ecj-3.9.0/0000755000175000001440000000000012251602362011136 5ustar dokousersecj-3.9.0/src/0000755000175000001440000000000012251575161011733 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/0000755000175000001440000000000012251602350015643 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/about.html0000644000175000001440000000263012212041344017641 0ustar dokousers About

About This Content

June 2, 2006

License

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available at http://www.eclipse.org/legal/epl-v10.html. For purposes of the EPL, "Program" will mean the Content.

If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party ("Redistributor") and different terms and conditions may apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise indicated below, the terms and conditions of the EPL still apply to any source code in the Content and such source code may be obtained at http://www.eclipse.org.

ecj-3.9.0/src/org.eclipse.jdt.core/build.xml0000644000175000001440000000351612251602350017471 0ustar dokousers ecj-3.9.0/src/org.eclipse.jdt.core/META-INF/0000755000175000001440000000000012251575161017014 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/META-INF/eclipse.inf0000644000175000001440000000014112212041344021116 0ustar dokousersjarprocessor.exclude.sign=true jarprocessor.exclude.children=true jarprocessor.exclude.pack=true ecj-3.9.0/src/org.eclipse.jdt.core/META-INF/services/0000755000175000001440000000000012251575161020637 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/META-INF/services/javax.tools.JavaCompiler0000644000175000001440000000011012251575161025375 0ustar dokousersorg.eclipse.jdt.internal.compiler.tool.EclipseCompiler #Eclipse compilerecj-3.9.0/src/org.eclipse.jdt.core/org/0000755000175000001440000000000012212041344016427 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/0000755000175000001440000000000012212041344020053 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/0000755000175000001440000000000012212041344020634 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/0000755000175000001440000000000012212041344022450 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/antadapter/0000755000175000001440000000000012212041344024573 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/antadapter/messages.properties0000644000175000001440000000302512212041344030520 0ustar dokousers############################################################################### # Copyright (c) 2000, 2011 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # # Contributors: # IBM Corporation - initial API and implementation ############################################################################### ### ant tasks messages. ant.jdtadapter.info.usingJDTCompiler=Using JDT compiler ant.jdtadapter.error.compilationFailed=Compilation failed. Compiler errors are available in {0} ant.jdtadapter.error.cannotFindJDTCompiler=Cannot find the JDT compiler ant.jdtadapter.info.ignoringMemoryInitialSize=Since fork is false, ignoring memoryInitialSize setting ant.jdtadapter.info.ignoringMemoryMaximumSize=Since fork is false, ignoring memoryMaximumSize setting checkDebugAttributes.file.argument.cannot.be.null=The file argument cannot be null checkDebugAttributes.property.argument.cannot.be.null=The property argument cannot be null checkDebugAttributes.ioexception.occured=IOException occurred while reading checkDebugAttributes.file.argument.must.be.a.classfile.or.a.jarfile=The file argument must be a .class or a .jar file buildJarIndex.jarFile.cannot.be.null=The jar file argument cannot be null buildJarIndex.indexFile.cannot.be.null=The index file argument cannot be null buildJarIndex.ioexception.occured=IOException - {0} ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/antadapter/AntAdapterMessages.java0000644000175000001440000000336512212041344031160 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.antadapter; import java.text.MessageFormat; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; public class AntAdapterMessages { private static final String BUNDLE_NAME = "org.eclipse.jdt.internal.antadapter.messages"; //$NON-NLS-1$ private static ResourceBundle RESOURCE_BUNDLE; static { try { RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault()); } catch(MissingResourceException e) { System.out.println("Missing resource : " + BUNDLE_NAME.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ throw e; } } private AntAdapterMessages() { // cannot be instantiated } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } public static String getString(String key, String argument) { try { String message = RESOURCE_BUNDLE.getString(key); MessageFormat messageFormat = new MessageFormat(message); return messageFormat.format(new String[] { argument } ); } catch (MissingResourceException e) { return '!' + key + '!'; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/0000755000175000001440000000000012212041344024262 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/0000755000175000001440000000000012212041344025666 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/ObjectCache.java0000644000175000001440000001104612212041344030665 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public class ObjectCache { public Object 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 ObjectCache() { this(13); } /** * Constructs a new, empty hashtable with the specified initial * capacity. * @param initialCapacity int * the initial number of buckets */ public ObjectCache(int initialCapacity) { this.elementSize = 0; this.threshold = (int) (initialCapacity * 0.66f); this.keyTable = new Object[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 = this.keyTable.length; --i >= 0;) { this.keyTable[i] = null; this.valueTable[i] = 0; } this.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(Object key) { int index = hashCode(key), length = this.keyTable.length; while (this.keyTable[index] != null) { if (this.keyTable[index] == key) return true; if (++index == length) { index = 0; } } return false; } /** 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(Object key) { int index = hashCode(key), length = this.keyTable.length; while (this.keyTable[index] != null) { if (this.keyTable[index] == key) return this.valueTable[index]; if (++index == length) { index = 0; } } return -1; } /** * Return the hashcode for the key parameter * * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding * @return int */ public int hashCode(Object key) { return (key.hashCode() & 0x7FFFFFFF) % this.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(Object key, int value) { int index = hashCode(key), length = this.keyTable.length; while (this.keyTable[index] != null) { if (this.keyTable[index] == key) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.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() { ObjectCache newHashtable = new ObjectCache(this.keyTable.length * 2); for (int i = this.keyTable.length; --i >= 0;) if (this.keyTable[i] != null) newHashtable.put(this.keyTable[i], this.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 this.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 (this.keyTable[i] != null) { buf.append(this.keyTable[i]).append("->").append(this.valueTable[i]); //$NON-NLS-1$ } if (i < max) { buf.append(", "); //$NON-NLS-1$ } } buf.append("}"); //$NON-NLS-1$ return buf.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/CharArrayCache.java0000644000175000001440000001500512212041344031332 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; import org.eclipse.jdt.core.compiler.CharOperation; public class CharArrayCache { // to avoid using Enumerations, walk the individual tables skipping nulls public char[] keyTable[]; public int valueTable[]; int elementSize; // number of elements in the table int threshold; /** * Constructs a new, empty hashtable. A default capacity is used. * Note that the hashtable will automatically grow when it gets full. */ public CharArrayCache() { this(9); } /** * Constructs a new, empty hashtable with the specified initial * capacity. * @param initialCapacity int * the initial number of buckets; must be less than Integer.MAX_VALUE / 2 */ public CharArrayCache(int initialCapacity) { this.elementSize = 0; this.threshold = (initialCapacity * 2) / 3; // faster than float operation this.keyTable = new char[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 = this.keyTable.length; --i >= 0;) { this.keyTable[i] = null; this.valueTable[i] = 0; } this.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(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (CharOperation.equals(this.keyTable[index], key)) return true; if (++index == length) { // faster than modulo index = 0; } } return false; } /** 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(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (CharOperation.equals(this.keyTable[index], key)) return this.valueTable[index]; if (++index == length) { // faster than modulo index = 0; } } return -1; } /** * Puts the specified element into the hashtable if it wasn't there already, * 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 the given key in the hashtable * @param value the given value * @return int the old value of the key, or -value if it did not have one. */ public int putIfAbsent(char[] key, int value) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (CharOperation.equals(this.keyTable[index], key)) return this.valueTable[index]; if (++index == length) { // faster than modulo index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return -value; // negative when added (value is assumed to be > 0) } /** * 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. */ private int put(char[] key, int value) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (CharOperation.equals(this.keyTable[index], key)) return this.valueTable[index] = value; if (++index == length) { // faster than modulo index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.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() { CharArrayCache newHashtable = new CharArrayCache(this.keyTable.length * 2); for (int i = this.keyTable.length; --i >= 0;) if (this.keyTable[i] != null) newHashtable.put(this.keyTable[i], this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } /** Remove the object associated with the specified key in the * hashtable. * @param key char[] the specified key */ public void remove(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (CharOperation.equals(this.keyTable[index], key)) { this.valueTable[index] = 0; this.keyTable[index] = null; return; } if (++index == length) { // faster than modulo index = 0; } } } /** * Returns the key corresponding to the value. Returns null if the * receiver doesn't contain the value. * @param value int the value that we are looking for * @return Object */ public char[] returnKeyFor(int value) { for (int i = this.keyTable.length; i-- > 0;) { if (this.valueTable[i] == value) { return this.keyTable[i]; } } return null; } /** * Returns the number of elements contained in the hashtable. * * @return int The size of the table */ public int size() { return this.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 (this.keyTable[i] != null) { buf.append(this.keyTable[i]).append("->").append(this.valueTable[i]); //$NON-NLS-1$ } if (i < max) { buf.append(", "); //$NON-NLS-1$ } } buf.append("}"); //$NON-NLS-1$ return buf.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/FloatCache.java0000644000175000001440000001123612212041344030525 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public class FloatCache { private float keyTable[]; private int valueTable[]; private int elementSize; /** * Constructs a new, empty hashtable. A default capacity and * load factor is used. Note that the hashtable will automatically * grow when it gets full. */ public FloatCache() { this(13); } /** * Constructs a new, empty hashtable with the specified initial * capacity. * @param initialCapacity int * the initial number of buckets */ public FloatCache(int initialCapacity) { this.elementSize = 0; this.keyTable = new float[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 = this.keyTable.length; --i >= 0;) { this.keyTable[i] = 0.0f; this.valueTable[i] = 0; } this.elementSize = 0; } /** Returns true if the collection contains an element for the key. * * @param key float the key that we are looking for * @return boolean */ public boolean containsKey(float key) { if (key == 0.0f) { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == 0.0f) { int value1 = Float.floatToIntBits(key); int value2 = Float.floatToIntBits(this.keyTable[i]); if (value1 == -2147483648 && value2 == -2147483648) return true; if (value1 == 0 && value2 == 0) return true; } } } else { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == key) { return true; } } } return false; } /** * Puts the specified element into the hashtable, using the specified * key. The element may be retrieved by doing a get() with the same key. * * @param key float the specified key in the hashtable * @param value int the specified element * @return int value */ public int put(float key, int value) { if (this.elementSize == this.keyTable.length) { // resize System.arraycopy(this.keyTable, 0, (this.keyTable = new float[this.elementSize * 2]), 0, this.elementSize); System.arraycopy(this.valueTable, 0, (this.valueTable = new int[this.elementSize * 2]), 0, this.elementSize); } this.keyTable[this.elementSize] = key; this.valueTable[this.elementSize] = value; this.elementSize++; return value; } /** * Puts the specified element into the hashtable, using the specified * key. The element may be retrieved by doing a get() with the same key. * * @param key float the specified key in the hashtable * @param value int the specified element * @return int value */ public int putIfAbsent(float key, int value) { if (key == 0.0f) { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == 0.0f) { int value1 = Float.floatToIntBits(key); int value2 = Float.floatToIntBits(this.keyTable[i]); if (value1 == -2147483648 && value2 == -2147483648) return this.valueTable[i]; if (value1 == 0 && value2 == 0) return this.valueTable[i]; } } } else { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == key) { return this.valueTable[i]; } } } if (this.elementSize == this.keyTable.length) { // resize System.arraycopy(this.keyTable, 0, (this.keyTable = new float[this.elementSize * 2]), 0, this.elementSize); System.arraycopy(this.valueTable, 0, (this.valueTable = new int[this.elementSize * 2]), 0, this.elementSize); } this.keyTable[this.elementSize] = key; this.valueTable[this.elementSize] = value; this.elementSize++; return -value; // negative when added, assumes value is > 0 } /** * Converts to a rather lengthy String. * * @return String the ascii representation of the receiver */ public String toString() { int max = this.elementSize; StringBuffer buf = new StringBuffer(); buf.append("{"); //$NON-NLS-1$ for (int i = 0; i < max; ++i) { if ((this.keyTable[i] != 0) || ((this.keyTable[i] == 0) && (this.valueTable[i] != 0))) { buf.append(this.keyTable[i]).append("->").append(this.valueTable[i]); //$NON-NLS-1$ } if (i < max) { buf.append(", "); //$NON-NLS-1$ } } buf.append("}"); //$NON-NLS-1$ return buf.toString(); } } ././@LongLink0000644000000000000000000000015312251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabe0000644000175000001440000000365112212041344032316 0ustar dokousers/******************************************************************************* * Copyright (c) 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class MultiCatchExceptionLabel extends ExceptionLabel { ExceptionLabel[] exceptionLabels; public MultiCatchExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) { super(codeStream, exceptionType); } public void initialize(UnionTypeReference typeReference) { TypeReference[] typeReferences = typeReference.typeReferences; int length = typeReferences.length; this.exceptionLabels = new ExceptionLabel[length]; for (int i = 0; i < length; i++) { this.exceptionLabels[i] = new ExceptionLabel(this.codeStream, typeReferences[i].resolvedType); } } public void place() { for (int i = 0, max = this.exceptionLabels.length; i < max; i++) { this.exceptionLabels[i].place(); } } public void placeEnd() { for (int i = 0, max = this.exceptionLabels.length; i < max; i++) { this.exceptionLabels[i].placeEnd(); } } public void placeStart() { for (int i = 0, max = this.exceptionLabels.length; i < max; i++) { this.exceptionLabels[i].placeStart(); } } public int getCount() { int temp = 0; for (int i = 0, max = this.exceptionLabels.length; i < max; i++) { temp += this.exceptionLabels[i].getCount(); } return temp; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java0000644000175000001440000000555512212041344031441 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.TypeBinding; public class ExceptionLabel extends Label { public int ranges[] = {POS_NOT_SET,POS_NOT_SET}; private int count = 0; // incremented each time placeStart or placeEnd is called public TypeBinding exceptionType; public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) { super(codeStream); this.exceptionType = exceptionType; } public int getCount() { return this.count; } public void place() { // register the handler inside the codeStream then normal place this.codeStream.registerExceptionHandler(this); this.position = this.codeStream.getPosition(); } public void placeEnd() { int endPosition = this.codeStream.position; if (this.ranges[this.count-1] == endPosition) { // start == end ? // discard empty exception handler this.count--; } else { this.ranges[this.count++] = endPosition; } } public void placeStart() { int startPosition = this.codeStream.position; if (this.count > 0 && this.ranges[this.count-1] == startPosition) { // start == previous end ? // reopen current handler this.count--; return; } // only need to grow on even additions (i.e. placeStart only) int length; if (this.count == (length = this.ranges.length)) { System.arraycopy(this.ranges, 0, this.ranges = new int[length*2], 0, length); } this.ranges[this.count++] = startPosition; } public String toString() { String basic = getClass().getName(); basic = basic.substring(basic.lastIndexOf('.')+1); StringBuffer buffer = new StringBuffer(basic); buffer.append('@').append(Integer.toHexString(hashCode())); buffer.append("(type=").append(this.exceptionType == null ? CharOperation.NO_CHAR : this.exceptionType.readableName()); //$NON-NLS-1$ buffer.append(", position=").append(this.position); //$NON-NLS-1$ buffer.append(", ranges = "); //$NON-NLS-1$ if (this.count == 0) { buffer.append("[]"); //$NON-NLS-1$ } else { for (int i = 0; i < this.count; i++) { if ((i & 1) == 0) { buffer.append("[").append(this.ranges[i]); //$NON-NLS-1$ } else { buffer.append(",").append(this.ranges[i]).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ } } if ((this.count & 1) == 1) { buffer.append(",?]"); //$NON-NLS-1$ } } buffer.append(')'); return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/LongCache.java0000644000175000001440000001210612212041344030354 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public class LongCache { public long keyTable[]; public int valueTable[]; int elementSize; int threshold; /** * Constructs a new, empty hashtable. A default capacity and * load factor is used. Note that the hashtable will automatically * grow when it gets full. */ public LongCache() { this(13); } /** * Constructs a new, empty hashtable with the specified initial * capacity. * @param initialCapacity int * the initial number of buckets */ public LongCache(int initialCapacity) { this.elementSize = 0; this.threshold = (int) (initialCapacity * 0.66); this.keyTable = new long[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 = this.keyTable.length; --i >= 0;) { this.keyTable[i] = 0; this.valueTable[i] = 0; } this.elementSize = 0; } /** Returns true if the collection contains an element for the key. * * @param key long the key that we are looking for * @return boolean */ public boolean containsKey(long key) { int index = hash(key), length = this.keyTable.length; while ((this.keyTable[index] != 0) || ((this.keyTable[index] == 0) &&(this.valueTable[index] != 0))) { if (this.keyTable[index] == key) return true; if (++index == length) { index = 0; } } return false; } /** * Return a hashcode for the value of the key parameter. * @param key long * @return int the hash code corresponding to the key value */ public int hash(long key) { return ((int) key & 0x7FFFFFFF) % this.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. * * @param key long the specified key in the hashtable * @param value int the specified element * @return int value */ public int put(long key, int value) { int index = hash(key), length = this.keyTable.length; while ((this.keyTable[index] != 0) || ((this.keyTable[index] == 0) && (this.valueTable[index] != 0))) { if (this.keyTable[index] == key) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) { rehash(); } return value; } /** * Puts the specified element into the hashtable, using the specified * key. The element may be retrieved by doing a get() with the same key. * * @param key long the specified key in the hashtable * @param value int the specified element * @return int value */ public int putIfAbsent(long key, int value) { int index = hash(key), length = this.keyTable.length; while ((this.keyTable[index] != 0) || ((this.keyTable[index] == 0) && (this.valueTable[index] != 0))) { if (this.keyTable[index] == key) return this.valueTable[index]; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) { rehash(); } return -value; // negative when added, assumes value is > 0 } /** * 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() { LongCache newHashtable = new LongCache(this.keyTable.length * 2); for (int i = this.keyTable.length; --i >= 0;) { long key = this.keyTable[i]; int value = this.valueTable[i]; if ((key != 0) || ((key == 0) && (value != 0))) { newHashtable.put(key, value); } } 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 this.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 ((this.keyTable[i] != 0) || ((this.keyTable[i] == 0) && (this.valueTable[i] != 0))) { buf.append(this.keyTable[i]).append("->").append(this.valueTable[i]); //$NON-NLS-1$ } if (i < max) { buf.append(", "); //$NON-NLS-1$ } } buf.append("}"); //$NON-NLS-1$ return buf.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java0000644000175000001440000062522612212041344030574 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.ClassFile; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; import org.eclipse.jdt.internal.compiler.util.Util; public class CodeStream { // It will be responsible for the following items. // -> Tracking Max Stack. public static FieldBinding[] ImplicitThis = new FieldBinding[] {}; public static final int LABELS_INCREMENT = 5; // local variable attributes output public static final int LOCALS_INCREMENT = 10; static ExceptionLabel[] noExceptionHandlers = new ExceptionLabel[LABELS_INCREMENT]; static BranchLabel[] noLabels = new BranchLabel[LABELS_INCREMENT]; static LocalVariableBinding[] noLocals = new LocalVariableBinding[LOCALS_INCREMENT]; static LocalVariableBinding[] noVisibleLocals = new LocalVariableBinding[LOCALS_INCREMENT]; public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0, 0); public static final CompilationResult RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE = new CompilationResult((char[])null, 0, 0, 0); public int allLocalsCounter; public byte[] bCodeStream; public ClassFile classFile; // The current classfile it is associated to. public int classFileOffset; public ConstantPool constantPool; // The constant pool used to generate bytecodes that need to store information into the constant pool public int countLabels; public ExceptionLabel[] exceptionLabels = new ExceptionLabel[LABELS_INCREMENT]; public int exceptionLabelsCounter; public int generateAttributes; // store all the labels placed at the current position to be able to optimize // a jump to the next bytecode. static final int L_UNKNOWN = 0, L_OPTIMIZABLE = 2, L_CANNOT_OPTIMIZE = 4; public BranchLabel[] labels = new BranchLabel[LABELS_INCREMENT]; public int lastEntryPC; // last entry recorded public int lastAbruptCompletion; // position of last instruction which abrupts completion: goto/return/athrow public int[] lineSeparatorPositions; // line number of the body start and the body end public int lineNumberStart; public int lineNumberEnd; public LocalVariableBinding[] locals = new LocalVariableBinding[LOCALS_INCREMENT]; public int maxFieldCount; public int maxLocals; public AbstractMethodDeclaration methodDeclaration; public int[] pcToSourceMap = new int[24]; public int pcToSourceMapSize; public int position; // So when first set can be incremented public boolean preserveUnusedLocals; public int stackDepth; // Use Ints to keep from using extra bc when adding public int stackMax; // Use Ints to keep from using extra bc when adding public int startingClassFileOffset; // I need to keep the starting point inside the byte array // target level to manage different code generation between different target levels protected long targetLevel; public LocalVariableBinding[] visibleLocals = new LocalVariableBinding[LOCALS_INCREMENT]; int visibleLocalsCount; // to handle goto_w public boolean wideMode = false; public CodeStream(ClassFile givenClassFile) { this.targetLevel = givenClassFile.targetJDK; this.generateAttributes = givenClassFile.produceAttributes; if ((givenClassFile.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { this.lineSeparatorPositions = givenClassFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.getLineSeparatorPositions(); } } /** * This methods searches for an existing entry inside the pcToSourceMap table with a pc equals to @pc. * If there is an existing entry it returns -1 (no insertion required). * Otherwise it returns the index where the entry for the pc has to be inserted. * This is based on the fact that the pcToSourceMap table is sorted according to the pc. * * @param pcToSourceMap the given pcToSourceMap array * @param length the given length * @param pc the given pc * @return int */ public static int insertionIndex(int[] pcToSourceMap, int length, int pc) { int g = 0; int d = length - 2; int m = 0; while (g <= d) { m = (g + d) / 2; // we search only on even indexes if ((m & 1) != 0) // faster than ((m % 2) != 0) m--; int currentPC = pcToSourceMap[m]; if (pc < currentPC) { d = m - 2; } else if (pc > currentPC) { g = m + 2; } else { return -1; } } if (pc < pcToSourceMap[m]) return m; return m + 2; } public static final void sort(int[] tab, int lo0, int hi0, int[] result) { int lo = lo0; int hi = hi0; int mid; if (hi0 > lo0) { /* Arbitrarily establishing partition element as the midpoint of * the array. */ mid = tab[lo0 + (hi0 - lo0) / 2]; // loop through the array until indices cross while (lo <= hi) { /* find the first element that is greater than or equal to * the partition element starting from the left Index. */ while ((lo < hi0) && (tab[lo] < mid)) ++lo; /* find an element that is smaller than or equal to * the partition element starting from the right Index. */ while ((hi > lo0) && (tab[hi] > mid)) --hi; // if the indexes have not crossed, swap if (lo <= hi) { swap(tab, lo, hi, result); ++lo; --hi; } } /* If the right index has not reached the left side of array * must now sort the left partition. */ if (lo0 < hi) sort(tab, lo0, hi, result); /* If the left index has not reached the right side of array * must now sort the right partition. */ if (lo < hi0) sort(tab, lo, hi0, result); } } private static final void swap(int a[], int i, int j, int result[]) { int T; T = a[i]; a[i] = a[j]; a[j] = T; T = result[j]; result[j] = result[i]; result[i] = T; } public void aaload() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aaload; } public void aastore() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aastore; } public void aconst_null() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) { this.stackMax = this.stackDepth; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aconst_null; } public void addDefinitelyAssignedVariables(Scope scope, int initStateIndex) { // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) == 0) return; for (int i = 0; i < this.visibleLocalsCount; i++) { LocalVariableBinding localBinding = this.visibleLocals[i]; if (localBinding != null) { // Check if the local is definitely assigned if (isDefinitelyAssigned(scope, initStateIndex, localBinding)) { if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) { /* There are two cases: * 1) there is no initialization interval opened ==> add an opened interval * 2) there is already some initialization intervals but the last one is closed ==> add an opened interval * An opened interval means that the value at localBinding.initializationPCs[localBinding.initializationCount - 1][1] * is equals to -1. * initializationPCs is a collection of pairs of int: * first value is the startPC and second value is the endPC. -1 one for the last value means that the interval * is not closed yet. */ localBinding.recordInitializationStartPC(this.position); } } } } } public void addLabel(BranchLabel aLabel) { if (this.countLabels == this.labels.length) System.arraycopy(this.labels, 0, this.labels = new BranchLabel[this.countLabels + LABELS_INCREMENT], 0, this.countLabels); this.labels[this.countLabels++] = aLabel; } public void addVariable(LocalVariableBinding localBinding) { /* do nothing */ } public void addVisibleLocalVariable(LocalVariableBinding localBinding) { if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) == 0) return; if (this.visibleLocalsCount >= this.visibleLocals.length) System.arraycopy(this.visibleLocals, 0, this.visibleLocals = new LocalVariableBinding[this.visibleLocalsCount * 2], 0, this.visibleLocalsCount); this.visibleLocals[this.visibleLocalsCount++] = localBinding; } public void aload(int iArg) { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals <= iArg) { this.maxLocals = iArg + 1; } if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aload; writeUnsignedShort(iArg); } else { // Don't need to use the wide bytecode if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aload; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void aload_0() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) { this.stackMax = this.stackDepth; } if (this.maxLocals == 0) { this.maxLocals = 1; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aload_0; } public void aload_1() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals <= 1) { this.maxLocals = 2; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aload_1; } public void aload_2() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals <= 2) { this.maxLocals = 3; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aload_2; } public void aload_3() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals <= 3) { this.maxLocals = 4; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_aload_3; } public void anewarray(TypeBinding typeBinding) { this.countLabels = 0; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_anewarray; writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding)); } public void areturn() { this.countLabels = 0; this.stackDepth--; // the stackDepth should be equal to 0 if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_areturn; this.lastAbruptCompletion = this.position; } public void arrayAt(int typeBindingID) { switch (typeBindingID) { case TypeIds.T_int : iaload(); break; case TypeIds.T_byte : case TypeIds.T_boolean : baload(); break; case TypeIds.T_short : saload(); break; case TypeIds.T_char : caload(); break; case TypeIds.T_long : laload(); break; case TypeIds.T_float : faload(); break; case TypeIds.T_double : daload(); break; default : aaload(); } } public void arrayAtPut(int elementTypeID, boolean valueRequired) { switch (elementTypeID) { case TypeIds.T_int : if (valueRequired) dup_x2(); iastore(); break; case TypeIds.T_byte : case TypeIds.T_boolean : if (valueRequired) dup_x2(); bastore(); break; case TypeIds.T_short : if (valueRequired) dup_x2(); sastore(); break; case TypeIds.T_char : if (valueRequired) dup_x2(); castore(); break; case TypeIds.T_long : if (valueRequired) dup2_x2(); lastore(); break; case TypeIds.T_float : if (valueRequired) dup_x2(); fastore(); break; case TypeIds.T_double : if (valueRequired) dup2_x2(); dastore(); break; default : if (valueRequired) dup_x2(); aastore(); } } public void arraylength() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_arraylength; } public void astore(int iArg) { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= iArg) { this.maxLocals = iArg + 1; } if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position+=2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_astore; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position+=2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_astore; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void astore_0() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals == 0) { this.maxLocals = 1; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_astore_0; } public void astore_1() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 1) { this.maxLocals = 2; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_astore_1; } public void astore_2() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 2) { this.maxLocals = 3; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_astore_2; } public void astore_3() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 3) { this.maxLocals = 4; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_astore_3; } public void athrow() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_athrow; this.lastAbruptCompletion = this.position; } public void baload() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_baload; } public void bastore() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_bastore; } public void bipush(byte b) { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_bipush; this.bCodeStream[this.classFileOffset++] = b; } public void caload() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_caload; } public void castore() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_castore; } public void checkcast(int baseId) { this.countLabels = 0; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_checkcast; switch (baseId) { case TypeIds.T_byte : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangByteConstantPoolName)); break; case TypeIds.T_short : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangShortConstantPoolName)); break; case TypeIds.T_char : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangCharacterConstantPoolName)); break; case TypeIds.T_int : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangIntegerConstantPoolName)); break; case TypeIds.T_long : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangLongConstantPoolName)); break; case TypeIds.T_float : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangFloatConstantPoolName)); break; case TypeIds.T_double : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangDoubleConstantPoolName)); break; case TypeIds.T_boolean : writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangBooleanConstantPoolName)); } } public void checkcast(TypeBinding typeBinding) { this.countLabels = 0; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_checkcast; writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding)); } public void d2f() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_d2f; } public void d2i() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_d2i; } public void d2l() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_d2l; } public void dadd() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dadd; } public void daload() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_daload; } public void dastore() { this.countLabels = 0; this.stackDepth -= 4; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dastore; } public void dcmpg() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dcmpg; } public void dcmpl() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dcmpl; } public void dconst_0() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dconst_0; } public void dconst_1() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dconst_1; } public void ddiv() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ddiv; } public void decrStackSize(int offset) { this.stackDepth -= offset; } public void dload(int iArg) { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals < iArg + 2) { this.maxLocals = iArg + 2; // + 2 because it is a double } if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dload; writeUnsignedShort(iArg); } else { // Don't need to use the wide bytecode if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dload; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void dload_0() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals < 2) { this.maxLocals = 2; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dload_0; } public void dload_1() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals < 3) { this.maxLocals = 3; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dload_1; } public void dload_2() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals < 4) { this.maxLocals = 4; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dload_2; } public void dload_3() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.maxLocals < 5) { this.maxLocals = 5; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dload_3; } public void dmul() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dmul; } public void dneg() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dneg; } public void drem() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_drem; } public void dreturn() { this.countLabels = 0; this.stackDepth -= 2; // the stackDepth should be equal to 0 if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dreturn; this.lastAbruptCompletion = this.position; } public void dstore(int iArg) { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals <= iArg + 1) { this.maxLocals = iArg + 2; } if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dstore; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dstore; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void dstore_0() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 2) { this.maxLocals = 2; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dstore_0; } public void dstore_1() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 3) { this.maxLocals = 3; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dstore_1; } public void dstore_2() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 4) { this.maxLocals = 4; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dstore_2; } public void dstore_3() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 5) { this.maxLocals = 5; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dstore_3; } public void dsub() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dsub; } public void dup() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) { this.stackMax = this.stackDepth; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dup; } public void dup_x1() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dup_x1; } public void dup_x2() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dup_x2; } public void dup2() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dup2; } public void dup2_x1() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dup2_x1; } public void dup2_x2() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_dup2_x2; } public void exitUserScope(BlockScope currentScope) { // mark all the scope's locals as losing their definite assignment if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) == 0) return; int index = this.visibleLocalsCount - 1; while (index >= 0) { LocalVariableBinding visibleLocal = this.visibleLocals[index]; if (visibleLocal == null || visibleLocal.declaringScope != currentScope) { // left currentScope index--; continue; } // there may be some preserved locals never initialized if (visibleLocal.initializationCount > 0) { visibleLocal.recordInitializationEndPC(this.position); } this.visibleLocals[index--] = null; // this variable is no longer visible afterwards } } public void exitUserScope(BlockScope currentScope, LocalVariableBinding binding) { // mark all the scope's locals as losing their definite assignment if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) == 0) return; int index = this.visibleLocalsCount - 1; while (index >= 0) { LocalVariableBinding visibleLocal = this.visibleLocals[index]; if (visibleLocal == null || visibleLocal.declaringScope != currentScope || visibleLocal == binding) { // left currentScope index--; continue; } // there may be some preserved locals never initialized if (visibleLocal.initializationCount > 0) { visibleLocal.recordInitializationEndPC(this.position); } this.visibleLocals[index--] = null; // this variable is no longer visible afterwards } } public void f2d() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_f2d; } public void f2i() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_f2i; } public void f2l() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_f2l; } public void fadd() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fadd; } public void faload() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_faload; } public void fastore() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fastore; } public void fcmpg() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fcmpg; } public void fcmpl() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fcmpl; } public void fconst_0() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fconst_0; } public void fconst_1() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fconst_1; } public void fconst_2() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fconst_2; } public void fdiv() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fdiv; } public void fieldAccess(byte opcode, FieldBinding fieldBinding, TypeBinding declaringClass) { if (declaringClass == null) declaringClass = fieldBinding.declaringClass; if ((declaringClass.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(this.classFile, declaringClass); } TypeBinding returnType = fieldBinding.type; int returnTypeSize; switch (returnType.id) { case TypeIds.T_long : case TypeIds.T_double : returnTypeSize = 2; break; default : returnTypeSize = 1; break; } this.fieldAccess(opcode, returnTypeSize, declaringClass.constantPoolName(), fieldBinding.name, returnType.signature()); } private void fieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] fieldName, char[] signature) { this.countLabels = 0; switch(opcode) { case Opcodes.OPC_getfield : if (returnTypeSize == 2) { this.stackDepth++; } break; case Opcodes.OPC_getstatic : if (returnTypeSize == 2) { this.stackDepth += 2; } else { this.stackDepth++; } break; case Opcodes.OPC_putfield : if (returnTypeSize == 2) { this.stackDepth -= 3; } else { this.stackDepth -= 2; } break; case Opcodes.OPC_putstatic : if (returnTypeSize == 2) { this.stackDepth -= 2; } else { this.stackDepth--; } } if (this.stackDepth > this.stackMax) { this.stackMax = this.stackDepth; } if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = opcode; writeUnsignedShort(this.constantPool.literalIndexForField(declaringClass, fieldName, signature)); } public void fload(int iArg) { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= iArg) { this.maxLocals = iArg + 1; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fload; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fload; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void fload_0() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals == 0) { this.maxLocals = 1; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fload_0; } public void fload_1() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= 1) { this.maxLocals = 2; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fload_1; } public void fload_2() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= 2) { this.maxLocals = 3; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fload_2; } public void fload_3() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= 3) { this.maxLocals = 4; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fload_3; } public void fmul() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fmul; } public void fneg() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fneg; } public void frem() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_frem; } public void freturn() { this.countLabels = 0; this.stackDepth--; // the stackDepth should be equal to 0 if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_freturn; this.lastAbruptCompletion = this.position; } public void fstore(int iArg) { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= iArg) { this.maxLocals = iArg + 1; } if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fstore; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fstore; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void fstore_0() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals == 0) { this.maxLocals = 1; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fstore_0; } public void fstore_1() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 1) { this.maxLocals = 2; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fstore_1; } public void fstore_2() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 2) { this.maxLocals = 3; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fstore_2; } public void fstore_3() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 3) { this.maxLocals = 4; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fstore_3; } public void fsub() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fsub; } public void generateBoxingConversion(int unboxedTypeID) { switch (unboxedTypeID) { case TypeIds.T_byte : if (this.targetLevel >= ClassFileConstants.JDK1_5) { // invokestatic: Byte.valueOf(byte) invoke( Opcodes.OPC_invokestatic, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangByteConstantPoolName, ConstantPool.ValueOf, ConstantPool.byteByteSignature); } else { // new Byte( byte ) newWrapperFor(unboxedTypeID); dup_x1(); swap(); invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangByteConstantPoolName, ConstantPool.Init, ConstantPool.ByteConstrSignature); } break; case TypeIds.T_short : if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) { // invokestatic: Short.valueOf(short) invoke( Opcodes.OPC_invokestatic, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangShortConstantPoolName, ConstantPool.ValueOf, ConstantPool.shortShortSignature); } else { // new Short(short) newWrapperFor(unboxedTypeID); dup_x1(); swap(); invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangShortConstantPoolName, ConstantPool.Init, ConstantPool.ShortConstrSignature); } break; case TypeIds.T_char : if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) { // invokestatic: Character.valueOf(char) invoke( Opcodes.OPC_invokestatic, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangCharacterConstantPoolName, ConstantPool.ValueOf, ConstantPool.charCharacterSignature); } else { // new Char( char ) newWrapperFor(unboxedTypeID); dup_x1(); swap(); invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangCharacterConstantPoolName, ConstantPool.Init, ConstantPool.CharConstrSignature); } break; case TypeIds.T_int : if (this.targetLevel >= ClassFileConstants.JDK1_5) { // invokestatic: Integer.valueOf(int) invoke( Opcodes.OPC_invokestatic, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangIntegerConstantPoolName, ConstantPool.ValueOf, ConstantPool.IntIntegerSignature); } else { // new Integer(int) newWrapperFor(unboxedTypeID); dup_x1(); swap(); invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangIntegerConstantPoolName, ConstantPool.Init, ConstantPool.IntConstrSignature); } break; case TypeIds.T_long : if (this.targetLevel >= ClassFileConstants.JDK1_5) { // invokestatic: Long.valueOf(long) invoke( Opcodes.OPC_invokestatic, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangLongConstantPoolName, ConstantPool.ValueOf, ConstantPool.longLongSignature); } else { // new Long( long ) newWrapperFor(unboxedTypeID); dup_x2(); dup_x2(); pop(); invoke( Opcodes.OPC_invokespecial, 3, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangLongConstantPoolName, ConstantPool.Init, ConstantPool.LongConstrSignature); } break; case TypeIds.T_float : if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) { // invokestatic: Float.valueOf(float) invoke( Opcodes.OPC_invokestatic, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangFloatConstantPoolName, ConstantPool.ValueOf, ConstantPool.floatFloatSignature); } else { // new Float(float) newWrapperFor(unboxedTypeID); dup_x1(); swap(); invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangFloatConstantPoolName, ConstantPool.Init, ConstantPool.FloatConstrSignature); } break; case TypeIds.T_double : if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) { // invokestatic: Double.valueOf(double) invoke( Opcodes.OPC_invokestatic, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangDoubleConstantPoolName, ConstantPool.ValueOf, ConstantPool.doubleDoubleSignature); } else { // new Double( double ) newWrapperFor(unboxedTypeID); dup_x2(); dup_x2(); pop(); invoke( Opcodes.OPC_invokespecial, 3, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangDoubleConstantPoolName, ConstantPool.Init, ConstantPool.DoubleConstrSignature); } break; case TypeIds.T_boolean : if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) { // invokestatic: Boolean.valueOf(boolean) invoke( Opcodes.OPC_invokestatic, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangBooleanConstantPoolName, ConstantPool.ValueOf, ConstantPool.booleanBooleanSignature); } else { // new Boolean(boolean) newWrapperFor(unboxedTypeID); dup_x1(); swap(); invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangBooleanConstantPoolName, ConstantPool.Init, ConstantPool.BooleanConstrSignature); } } } /** * Macro for building a class descriptor object */ public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBinding syntheticFieldBinding) { if (accessedType.isBaseType() && accessedType != TypeBinding.NULL) { getTYPE(accessedType.id); return; } if (this.targetLevel >= ClassFileConstants.JDK1_5) { // generation using the new ldc_w bytecode this.ldc(accessedType); } else { BranchLabel endLabel = new BranchLabel(this); if (syntheticFieldBinding != null) { // non interface case fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); dup(); ifnonnull(endLabel); 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 ExceptionLabel classNotFoundExceptionHandler = new ExceptionLabel(this, TypeBinding.NULL /*represents ClassNotFoundException*/); classNotFoundExceptionHandler.placeStart(); this.ldc(accessedType == TypeBinding.NULL ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$ 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. */ classNotFoundExceptionHandler.placeEnd(); if (syntheticFieldBinding != null) { // non interface case dup(); fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); } goto_(endLabel); int savedStackDepth = this.stackDepth; // Generate the body of the exception handler /* 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. */ pushExceptionOnStack(TypeBinding.NULL);/*represents ClassNotFoundException*/ classNotFoundExceptionHandler.place(); // Transform the current exception, and repush and throw a // NoClassDefFoundError(ClassNotFound.getMessage()) newNoClassDefFoundError(); dup_x1(); this.swap(); // Retrieve the message from the old exception invokeThrowableGetMessage(); // Send the constructor taking a message string as an argument invokeNoClassDefFoundErrorStringConstructor(); athrow(); endLabel.place(); this.stackDepth = savedStackDepth; } } /** * This method generates the code attribute bytecode */ final public void generateCodeAttributeForProblemMethod(String problemMessage) { newJavaLangError(); dup(); ldc(problemMessage); invokeJavaLangErrorConstructor(); athrow(); } public void generateConstant(Constant constant, int implicitConversionCode) { int targetTypeID = (implicitConversionCode & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; if (targetTypeID == 0) targetTypeID = constant.typeID(); // use default constant type switch (targetTypeID) { case TypeIds.T_boolean : generateInlinedValue(constant.booleanValue()); break; case TypeIds.T_char : generateInlinedValue(constant.charValue()); break; case TypeIds.T_byte : generateInlinedValue(constant.byteValue()); break; case TypeIds.T_short : generateInlinedValue(constant.shortValue()); break; case TypeIds.T_int : generateInlinedValue(constant.intValue()); break; case TypeIds.T_long : generateInlinedValue(constant.longValue()); break; case TypeIds.T_float : generateInlinedValue(constant.floatValue()); break; case TypeIds.T_double : generateInlinedValue(constant.doubleValue()); break; case TypeIds.T_JavaLangString : ldc(constant.stringValue()); } if ((implicitConversionCode & TypeIds.BOXING) != 0) { // need boxing generateBoxingConversion(targetTypeID); } } public void generateEmulatedReadAccessForField(FieldBinding fieldBinding) { generateEmulationForField(fieldBinding); // swap the field with the receiver this.swap(); invokeJavaLangReflectFieldGetter(fieldBinding.type.id); if (!fieldBinding.type.isBaseType()) { this.checkcast(fieldBinding.type); } } public void generateEmulatedWriteAccessForField(FieldBinding fieldBinding) { invokeJavaLangReflectFieldSetter(fieldBinding.type.id); } public void generateEmulationForConstructor(Scope scope, MethodBinding methodBinding) { // leave a java.lang.reflect.Field object on the stack this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); invokeClassForName(); int paramLength = methodBinding.parameters.length; this.generateInlinedValue(paramLength); newArray(scope.createArrayType(scope.getType(TypeConstants.JAVA_LANG_CLASS, 3), 1)); if (paramLength > 0) { dup(); for (int i = 0; i < paramLength; i++) { this.generateInlinedValue(i); TypeBinding parameter = methodBinding.parameters[i]; if (parameter.isBaseType()) { getTYPE(parameter.id); } else if (parameter.isArrayType()) { ArrayBinding array = (ArrayBinding)parameter; if (array.leafComponentType.isBaseType()) { getTYPE(array.leafComponentType.id); } else { this.ldc(String.valueOf(array.leafComponentType.constantPoolName()).replace('/', '.')); invokeClassForName(); } int dimensions = array.dimensions; this.generateInlinedValue(dimensions); newarray(TypeIds.T_int); invokeArrayNewInstance(); invokeObjectGetClass(); } else { // parameter is a reference binding this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); invokeClassForName(); } aastore(); if (i < paramLength - 1) { dup(); } } } invokeClassGetDeclaredConstructor(); dup(); iconst_1(); invokeAccessibleObjectSetAccessible(); } public void generateEmulationForField(FieldBinding fieldBinding) { // leave a java.lang.reflect.Field object on the stack this.ldc(String.valueOf(fieldBinding.declaringClass.constantPoolName()).replace('/', '.')); invokeClassForName(); this.ldc(String.valueOf(fieldBinding.name)); invokeClassGetDeclaredField(); dup(); iconst_1(); invokeAccessibleObjectSetAccessible(); } public void generateEmulationForMethod(Scope scope, MethodBinding methodBinding) { // leave a java.lang.reflect.Field object on the stack this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); invokeClassForName(); this.ldc(String.valueOf(methodBinding.selector)); int paramLength = methodBinding.parameters.length; this.generateInlinedValue(paramLength); newArray(scope.createArrayType(scope.getType(TypeConstants.JAVA_LANG_CLASS, 3), 1)); if (paramLength > 0) { dup(); for (int i = 0; i < paramLength; i++) { this.generateInlinedValue(i); TypeBinding parameter = methodBinding.parameters[i]; if (parameter.isBaseType()) { getTYPE(parameter.id); } else if (parameter.isArrayType()) { ArrayBinding array = (ArrayBinding)parameter; if (array.leafComponentType.isBaseType()) { getTYPE(array.leafComponentType.id); } else { this.ldc(String.valueOf(array.leafComponentType.constantPoolName()).replace('/', '.')); invokeClassForName(); } int dimensions = array.dimensions; this.generateInlinedValue(dimensions); newarray(TypeIds.T_int); invokeArrayNewInstance(); invokeObjectGetClass(); } else { // parameter is a reference binding this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.')); invokeClassForName(); } aastore(); if (i < paramLength - 1) { dup(); } } } invokeClassGetDeclaredMethod(); dup(); iconst_1(); invokeAccessibleObjectSetAccessible(); } /** * 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) { if ((implicitConversionCode & TypeIds.UNBOXING) != 0) { final int typeId = implicitConversionCode & TypeIds.COMPILE_TYPE_MASK; generateUnboxingConversion(typeId); // unboxing can further involve base type conversions } switch (implicitConversionCode & TypeIds.IMPLICIT_CONVERSION_MASK) { case TypeIds.Float2Char : f2i(); i2c(); break; case TypeIds.Double2Char : d2i(); i2c(); break; case TypeIds.Int2Char : case TypeIds.Short2Char : case TypeIds.Byte2Char : i2c(); break; case TypeIds.Long2Char : l2i(); i2c(); break; case TypeIds.Char2Float : case TypeIds.Short2Float : case TypeIds.Int2Float : case TypeIds.Byte2Float : i2f(); break; case TypeIds.Double2Float : d2f(); break; case TypeIds.Long2Float : l2f(); break; case TypeIds.Float2Byte : f2i(); i2b(); break; case TypeIds.Double2Byte : d2i(); i2b(); break; case TypeIds.Int2Byte : case TypeIds.Short2Byte : case TypeIds.Char2Byte : i2b(); break; case TypeIds.Long2Byte : l2i(); i2b(); break; case TypeIds.Byte2Double : case TypeIds.Char2Double : case TypeIds.Short2Double : case TypeIds.Int2Double : i2d(); break; case TypeIds.Float2Double : f2d(); break; case TypeIds.Long2Double : l2d(); break; case TypeIds.Byte2Short : case TypeIds.Char2Short : case TypeIds.Int2Short : i2s(); break; case TypeIds.Double2Short : d2i(); i2s(); break; case TypeIds.Long2Short : l2i(); i2s(); break; case TypeIds.Float2Short : f2i(); i2s(); break; case TypeIds.Double2Int : d2i(); break; case TypeIds.Float2Int : f2i(); break; case TypeIds.Long2Int : l2i(); break; case TypeIds.Int2Long : case TypeIds.Char2Long : case TypeIds.Byte2Long : case TypeIds.Short2Long : i2l(); break; case TypeIds.Double2Long : d2l(); break; case TypeIds.Float2Long : f2l(); break; case TypeIds.Object2boolean: case TypeIds.Object2byte: case TypeIds.Object2short: case TypeIds.Object2int: case TypeIds.Object2long: case TypeIds.Object2float: case TypeIds.Object2char: case TypeIds.Object2double: // see table 5.1 in JLS S5.5 // an Object to x conversion should have a check cast // and an unboxing conversion. int runtimeType = (implicitConversionCode & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; checkcast(runtimeType); generateUnboxingConversion(runtimeType); break; } if ((implicitConversionCode & TypeIds.BOXING) != 0) { // need to unbox/box the constant final int typeId = (implicitConversionCode & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; generateBoxingConversion(typeId); } } public void generateInlinedValue(boolean inlinedValue) { if (inlinedValue) iconst_1(); else iconst_0(); } public void generateInlinedValue(byte inlinedValue) { switch (inlinedValue) { case -1 : iconst_m1(); break; case 0 : iconst_0(); break; case 1 : iconst_1(); break; case 2 : iconst_2(); break; case 3 : iconst_3(); break; case 4 : iconst_4(); break; case 5 : iconst_5(); break; default : if ((-128 <= inlinedValue) && (inlinedValue <= 127)) { bipush(inlinedValue); return; } } } public void generateInlinedValue(char inlinedValue) { switch (inlinedValue) { case 0 : iconst_0(); break; case 1 : iconst_1(); break; case 2 : iconst_2(); break; case 3 : iconst_3(); break; case 4 : iconst_4(); break; case 5 : iconst_5(); break; default : if ((6 <= inlinedValue) && (inlinedValue <= 127)) { bipush((byte) inlinedValue); return; } if ((128 <= inlinedValue) && (inlinedValue <= 32767)) { sipush(inlinedValue); return; } this.ldc(inlinedValue); } } public void generateInlinedValue(double inlinedValue) { if (inlinedValue == 0.0) { if (Double.doubleToLongBits(inlinedValue) != 0L) this.ldc2_w(inlinedValue); else dconst_0(); return; } if (inlinedValue == 1.0) { dconst_1(); return; } this.ldc2_w(inlinedValue); } public void generateInlinedValue(float inlinedValue) { if (inlinedValue == 0.0f) { if (Float.floatToIntBits(inlinedValue) != 0) this.ldc(inlinedValue); else fconst_0(); return; } if (inlinedValue == 1.0f) { fconst_1(); return; } if (inlinedValue == 2.0f) { fconst_2(); return; } this.ldc(inlinedValue); } public void generateInlinedValue(int inlinedValue) { switch (inlinedValue) { case -1 : iconst_m1(); break; case 0 : iconst_0(); break; case 1 : iconst_1(); break; case 2 : iconst_2(); break; case 3 : iconst_3(); break; case 4 : iconst_4(); break; case 5 : iconst_5(); break; default : if ((-128 <= inlinedValue) && (inlinedValue <= 127)) { bipush((byte) inlinedValue); return; } if ((-32768 <= inlinedValue) && (inlinedValue <= 32767)) { sipush(inlinedValue); return; } this.ldc(inlinedValue); } } public void generateInlinedValue(long inlinedValue) { if (inlinedValue == 0) { lconst_0(); return; } if (inlinedValue == 1) { lconst_1(); return; } this.ldc2_w(inlinedValue); } public void generateInlinedValue(short inlinedValue) { switch (inlinedValue) { case -1 : iconst_m1(); break; case 0 : iconst_0(); break; case 1 : iconst_1(); break; case 2 : iconst_2(); break; case 3 : iconst_3(); break; case 4 : iconst_4(); break; case 5 : iconst_5(); break; default : if ((-128 <= inlinedValue) && (inlinedValue <= 127)) { bipush((byte) inlinedValue); return; } sipush(inlinedValue); } } public void generateOuterAccess(Object[] mappingSequence, ASTNode invocationSite, Binding target, Scope scope) { if (mappingSequence == null) { if (target instanceof LocalVariableBinding) { scope.problemReporter().needImplementation(invocationSite); //TODO (philippe) should improve local emulation failure reporting } else { scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, false); } return; } if (mappingSequence == BlockScope.NoEnclosingInstanceInConstructorCall) { scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, true); return; } else if (mappingSequence == BlockScope.NoEnclosingInstanceInStaticContext) { scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, false); return; } if (mappingSequence == BlockScope.EmulationPathToImplicitThis) { aload_0(); return; } else if (mappingSequence[0] instanceof FieldBinding) { FieldBinding fieldBinding = (FieldBinding) mappingSequence[0]; aload_0(); fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */); } else { load((LocalVariableBinding) mappingSequence[0]); } for (int i = 1, length = mappingSequence.length; i < length; i++) { if (mappingSequence[i] instanceof FieldBinding) { FieldBinding fieldBinding = (FieldBinding) mappingSequence[i]; fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */); } else { invoke(Opcodes.OPC_invokestatic, (MethodBinding) mappingSequence[i], null /* default declaringClass */); } } } public void generateReturnBytecode(Expression expression) { if (expression == null) { return_(); } else { final int implicitConversion = expression.implicitConversion; if ((implicitConversion & TypeIds.BOXING) != 0) { areturn(); return; } int runtimeType = (implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; switch (runtimeType) { case TypeIds.T_boolean : case TypeIds.T_int : ireturn(); break; case TypeIds.T_float : freturn(); break; case TypeIds.T_long : lreturn(); break; case TypeIds.T_double : dreturn(); break; default : areturn(); } } } /** * The equivalent code performs a string conversion: * * @param blockScope the given blockScope * @param oper1 the first expression * @param oper2 the second expression */ 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.*/ newStringContatenation(); dup_x1(); this.swap(); // If argument is reference type, need to transform it // into a string (handles null case) invokeStringValueOf(TypeIds.T_JavaLangObject); invokeStringConcatenationStringConstructor(); } else { pc = this.position; oper1.generateOptimizedStringConcatenationCreation(blockScope, this, oper1.implicitConversion & TypeIds.COMPILE_TYPE_MASK); this.recordPositionsFrom(pc, oper1.sourceStart); } pc = this.position; oper2.generateOptimizedStringConcatenation(blockScope, this, oper2.implicitConversion & TypeIds.COMPILE_TYPE_MASK); this.recordPositionsFrom(pc, oper2.sourceStart); invokeStringConcatenationToString(); } /** * @param accessBinding the access method binding to generate */ public void generateSyntheticBodyForConstructorAccess(SyntheticMethodBinding accessBinding) { initializeMaxLocals(accessBinding); MethodBinding constructorBinding = accessBinding.targetMethod; TypeBinding[] parameters = constructorBinding.parameters; int length = parameters.length; int resolvedPosition = 1; aload_0(); // special name&ordinal argument generation for enum constructors TypeBinding declaringClass = constructorBinding.declaringClass; if (declaringClass.erasure().id == TypeIds.T_JavaLangEnum || declaringClass.isEnum()) { aload_1(); // pass along name param as name arg iload_2(); // pass along ordinal param as ordinal arg resolvedPosition += 2; } if (declaringClass.isNestedType()) { NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass; SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticEnclosingInstances(); for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) { TypeBinding type; load((type = syntheticArguments[i].type), resolvedPosition); switch(type.id) { case TypeIds.T_long : case TypeIds.T_double : resolvedPosition += 2; break; default : resolvedPosition++; break; } } } for (int i = 0; i < length; i++) { TypeBinding parameter; load(parameter = parameters[i], resolvedPosition); switch(parameter.id) { case TypeIds.T_long : case TypeIds.T_double : resolvedPosition += 2; break; default : resolvedPosition++; break; } } if (declaringClass.isNestedType()) { NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass; SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables(); for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) { TypeBinding type; load(type = syntheticArguments[i].type, resolvedPosition); switch(type.id) { case TypeIds.T_long : case TypeIds.T_double : resolvedPosition += 2; break; default : resolvedPosition++; break; } } } invoke(Opcodes.OPC_invokespecial, constructorBinding, null /* default declaringClass */); return_(); } //static X valueOf(String name) { // return (X) Enum.valueOf(X.class, name); //} public void generateSyntheticBodyForEnumValueOf(SyntheticMethodBinding methodBinding) { initializeMaxLocals(methodBinding); final ReferenceBinding declaringClass = methodBinding.declaringClass; generateClassLiteralAccessForType(declaringClass, null); aload_0(); invokeJavaLangEnumvalueOf(declaringClass); this.checkcast(declaringClass); areturn(); } //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; initializeMaxLocals(methodBinding); TypeBinding enumArray = methodBinding.returnType; fieldAccess(Opcodes.OPC_getstatic, scope.referenceContext.enumValuesSyntheticfield, null /* default declaringClass */); dup(); astore_0(); iconst_0(); aload_0(); arraylength(); dup(); istore_1(); newArray((ArrayBinding) enumArray); dup(); astore_2(); iconst_0(); iload_1(); invokeSystemArraycopy(); aload_2(); areturn(); } public void generateSyntheticBodyForEnumInitializationMethod(SyntheticMethodBinding methodBinding) { // no local used this.maxLocals = 0; // generate all enum constants SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) methodBinding.declaringClass; TypeDeclaration typeDeclaration = sourceTypeBinding.scope.referenceContext; BlockScope staticInitializerScope = typeDeclaration.staticInitializerScope; FieldDeclaration[] fieldDeclarations = typeDeclaration.fields; for (int i = methodBinding.startIndex, max = methodBinding.endIndex; i < max; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; if (fieldDecl.isStatic()) { if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { fieldDecl.generateCode(staticInitializerScope, this); } } } return_(); } public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessMethod) { initializeMaxLocals(accessMethod); FieldBinding fieldBinding = accessMethod.targetReadField; // target method declaring class may not be accessible (247953); TypeBinding declaringClass = accessMethod.purpose == SyntheticMethodBinding.SuperFieldReadAccess ? accessMethod.declaringClass.superclass() : accessMethod.declaringClass; if (fieldBinding.isStatic()) { fieldAccess(Opcodes.OPC_getstatic, fieldBinding, declaringClass); } else { aload_0(); fieldAccess(Opcodes.OPC_getfield, fieldBinding, declaringClass); } switch (fieldBinding.type.id) { // case T_void : // this.return_(); // break; case TypeIds.T_boolean : case TypeIds.T_byte : case TypeIds.T_char : case TypeIds.T_short : case TypeIds.T_int : ireturn(); break; case TypeIds.T_long : lreturn(); break; case TypeIds.T_float : freturn(); break; case TypeIds.T_double : dreturn(); break; default : areturn(); } } public void generateSyntheticBodyForFieldWriteAccess(SyntheticMethodBinding accessMethod) { initializeMaxLocals(accessMethod); FieldBinding fieldBinding = accessMethod.targetWriteField; // target method declaring class may not be accessible (247953); TypeBinding declaringClass = accessMethod.purpose == SyntheticMethodBinding.SuperFieldWriteAccess ? accessMethod.declaringClass.superclass() : accessMethod.declaringClass; if (fieldBinding.isStatic()) { load(fieldBinding.type, 0); fieldAccess(Opcodes.OPC_putstatic, fieldBinding, declaringClass); } else { aload_0(); load(fieldBinding.type, 1); fieldAccess(Opcodes.OPC_putfield, fieldBinding, declaringClass); } return_(); } public void generateSyntheticBodyForMethodAccess(SyntheticMethodBinding accessMethod) { initializeMaxLocals(accessMethod); MethodBinding targetMethod = accessMethod.targetMethod; TypeBinding[] parameters = targetMethod.parameters; int length = parameters.length; TypeBinding[] arguments = accessMethod.purpose == SyntheticMethodBinding.BridgeMethod ? accessMethod.parameters : null; int resolvedPosition; if (targetMethod.isStatic()) resolvedPosition = 0; else { aload_0(); resolvedPosition = 1; } for (int i = 0; i < length; i++) { 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); } switch(parameter.id) { case TypeIds.T_long : case TypeIds.T_double : resolvedPosition += 2; break; default : resolvedPosition++; break; } } if (targetMethod.isStatic()) invoke(Opcodes.OPC_invokestatic, targetMethod, accessMethod.declaringClass); // target method declaring class may not be accessible (128563) else { if (targetMethod.isConstructor() || targetMethod.isPrivate() // qualified super "X.super.foo()" targets methods from superclass || accessMethod.purpose == SyntheticMethodBinding.SuperMethodAccess){ // target method declaring class may not be accessible (247953); TypeBinding declaringClass = accessMethod.purpose == SyntheticMethodBinding.SuperMethodAccess ? accessMethod.declaringClass.superclass() : accessMethod.declaringClass; invoke(Opcodes.OPC_invokespecial, targetMethod, declaringClass); } else { if (targetMethod.declaringClass.isInterface()) { // interface or annotation type invoke(Opcodes.OPC_invokeinterface, targetMethod, null /* default declaringClass */); } else { invoke(Opcodes.OPC_invokevirtual, targetMethod, accessMethod.declaringClass); // target method declaring class may not be accessible (128563) } } } switch (targetMethod.returnType.id) { case TypeIds.T_void : return_(); break; case TypeIds.T_boolean : case TypeIds.T_byte : case TypeIds.T_char : case TypeIds.T_short : case TypeIds.T_int : ireturn(); break; case TypeIds.T_long : lreturn(); break; case TypeIds.T_float : freturn(); break; case TypeIds.T_double : dreturn(); break; default : TypeBinding accessErasure = accessMethod.returnType.erasure(); TypeBinding match = targetMethod.returnType.findSuperTypeOriginatingFrom(accessErasure); if (match == null) { this.checkcast(accessErasure); // for bridge methods } areturn(); } } public void generateSyntheticBodyForSwitchTable(SyntheticMethodBinding methodBinding) { ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope; initializeMaxLocals(methodBinding); final BranchLabel nullLabel = new BranchLabel(this); FieldBinding syntheticFieldBinding = methodBinding.targetReadField; fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); dup(); ifnull(nullLabel); areturn(); pushOnStack(syntheticFieldBinding.type); nullLabel.place(); pop(); ReferenceBinding enumBinding = (ReferenceBinding) methodBinding.targetEnumType; ArrayBinding arrayBinding = scope.createArrayType(enumBinding, 1); invokeJavaLangEnumValues(enumBinding, arrayBinding); arraylength(); newarray(ClassFileConstants.INT_ARRAY); astore_0(); LocalVariableBinding localVariableBinding = new LocalVariableBinding(" tab".toCharArray(), scope.createArrayType(TypeBinding.INT, 1), 0, false); //$NON-NLS-1$ addVariable(localVariableBinding); final FieldBinding[] fields = enumBinding.fields(); if (fields != null) { for (int i = 0, max = fields.length; i < max; i++) { FieldBinding fieldBinding = fields[i]; if ((fieldBinding.getAccessFlags() & ClassFileConstants.AccEnum) != 0) { final BranchLabel endLabel = new BranchLabel(this); final ExceptionLabel anyExceptionHandler = new ExceptionLabel(this, TypeBinding.LONG /* represents NoSuchFieldError*/); anyExceptionHandler.placeStart(); aload_0(); fieldAccess(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */); invokeEnumOrdinal(enumBinding.constantPoolName()); this.generateInlinedValue(fieldBinding.id + 1); // zero should not be returned see bug 141810 iastore(); anyExceptionHandler.placeEnd(); goto_(endLabel); // Generate the body of the exception handler pushExceptionOnStack(TypeBinding.LONG /*represents NoSuchFieldError*/); anyExceptionHandler.place(); pop(); // we don't use it so we can pop it endLabel.place(); } } } aload_0(); dup(); fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); areturn(); removeVariable(localVariableBinding); } /** * Code responsible to generate the suitable code to supply values for the synthetic enclosing * instance arguments of a constructor invocation of a nested type. */ public void generateSyntheticEnclosingInstanceValues(BlockScope currentScope, ReferenceBinding targetType, Expression enclosingInstance, ASTNode invocationSite) { // supplying enclosing instance for the anonymous type's superclass ReferenceBinding checkedTargetType = targetType.isAnonymousType() ? (ReferenceBinding)targetType.superclass().erasure() : targetType; boolean hasExtraEnclosingInstance = enclosingInstance != null; if (hasExtraEnclosingInstance && (!checkedTargetType.isNestedType() || checkedTargetType.isStatic())) { currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); return; } // perform some emulation work in case there is some and we are inside a local type only ReferenceBinding[] syntheticArgumentTypes; if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) { ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType(); long compliance = currentScope.compilerOptions().complianceLevel; // deny access to enclosing instance argument for allocation and super constructor call (if 1.4) // always consider it if complying to 1.5 boolean denyEnclosingArgInConstructorCall; if (compliance <= ClassFileConstants.JDK1_3) { denyEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression; } else if (compliance == ClassFileConstants.JDK1_4){ denyEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression || invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess(); } else { //compliance >= JDK1_5 denyEnclosingArgInConstructorCall = (invocationSite instanceof AllocationExpression || invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess()) && !targetType.isLocalType(); } boolean complyTo14 = compliance >= ClassFileConstants.JDK1_4; for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { ReferenceBinding syntheticArgType = syntheticArgumentTypes[i]; if (hasExtraEnclosingInstance && syntheticArgType == targetEnclosingType) { hasExtraEnclosingInstance = false; enclosingInstance.generateCode(currentScope, this, true); if (complyTo14){ dup(); invokeObjectGetClass(); // will perform null check pop(); } } else { Object[] emulationPath = currentScope.getEmulationPath( syntheticArgType, false /*not only exact match (that is, allow compatible)*/, denyEnclosingArgInConstructorCall); generateOuterAccess(emulationPath, invocationSite, syntheticArgType, currentScope); } } if (hasExtraEnclosingInstance){ currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); } } } /** * Code responsible to generate the suitable code to supply values for the synthetic outer local * variable arguments of a constructor invocation of a nested type. * (bug 26122) - synthetic values for outer locals must be passed after user arguments, e.g. new X(i = 1){} */ public void generateSyntheticOuterArgumentValues(BlockScope currentScope, ReferenceBinding targetType, ASTNode invocationSite) { // generate the synthetic outer arguments then SyntheticArgumentBinding syntheticArguments[]; if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) { for (int i = 0, max = syntheticArguments.length; i < max; i++) { LocalVariableBinding targetVariable = syntheticArguments[i].actualOuterLocalVariable; VariableBinding[] emulationPath = currentScope.getEmulationPath(targetVariable); generateOuterAccess(emulationPath, invocationSite, targetVariable, currentScope); } } } public void generateUnboxingConversion(int unboxedTypeID) { switch (unboxedTypeID) { case TypeIds.T_byte : // invokevirtual: byteValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangByteConstantPoolName, ConstantPool.BYTEVALUE_BYTE_METHOD_NAME, ConstantPool.BYTEVALUE_BYTE_METHOD_SIGNATURE); break; case TypeIds.T_short : // invokevirtual: shortValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangShortConstantPoolName, ConstantPool.SHORTVALUE_SHORT_METHOD_NAME, ConstantPool.SHORTVALUE_SHORT_METHOD_SIGNATURE); break; case TypeIds.T_char : // invokevirtual: charValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangCharacterConstantPoolName, ConstantPool.CHARVALUE_CHARACTER_METHOD_NAME, ConstantPool.CHARVALUE_CHARACTER_METHOD_SIGNATURE); break; case TypeIds.T_int : // invokevirtual: intValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangIntegerConstantPoolName, ConstantPool.INTVALUE_INTEGER_METHOD_NAME, ConstantPool.INTVALUE_INTEGER_METHOD_SIGNATURE); break; case TypeIds.T_long : // invokevirtual: longValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 2, // return type size ConstantPool.JavaLangLongConstantPoolName, ConstantPool.LONGVALUE_LONG_METHOD_NAME, ConstantPool.LONGVALUE_LONG_METHOD_SIGNATURE); break; case TypeIds.T_float : // invokevirtual: floatValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangFloatConstantPoolName, ConstantPool.FLOATVALUE_FLOAT_METHOD_NAME, ConstantPool.FLOATVALUE_FLOAT_METHOD_SIGNATURE); break; case TypeIds.T_double : // invokevirtual: doubleValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 2, // return type size ConstantPool.JavaLangDoubleConstantPoolName, ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_NAME, ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE); break; case TypeIds.T_boolean : // invokevirtual: booleanValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangBooleanConstantPoolName, ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_NAME, ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE); } } /* * Wide conditional branch compare, improved by swapping comparison opcode * ifeq WideTarget * becomes * ifne Intermediate * gotow WideTarget * Intermediate: */ public void generateWideRevertedConditionalBranch(byte revertedOpcode, BranchLabel wideTarget) { BranchLabel intermediate = new BranchLabel(this); if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = revertedOpcode; intermediate.branch(); goto_w(wideTarget); intermediate.place(); } public void getBaseTypeValue(int baseTypeID) { switch (baseTypeID) { case TypeIds.T_byte : // invokevirtual: byteValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangByteConstantPoolName, ConstantPool.BYTEVALUE_BYTE_METHOD_NAME, ConstantPool.BYTEVALUE_BYTE_METHOD_SIGNATURE); break; case TypeIds.T_short : // invokevirtual: shortValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangShortConstantPoolName, ConstantPool.SHORTVALUE_SHORT_METHOD_NAME, ConstantPool.SHORTVALUE_SHORT_METHOD_SIGNATURE); break; case TypeIds.T_char : // invokevirtual: charValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangCharacterConstantPoolName, ConstantPool.CHARVALUE_CHARACTER_METHOD_NAME, ConstantPool.CHARVALUE_CHARACTER_METHOD_SIGNATURE); break; case TypeIds.T_int : // invokevirtual: intValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangIntegerConstantPoolName, ConstantPool.INTVALUE_INTEGER_METHOD_NAME, ConstantPool.INTVALUE_INTEGER_METHOD_SIGNATURE); break; case TypeIds.T_long : // invokevirtual: longValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 2, // return type size ConstantPool.JavaLangLongConstantPoolName, ConstantPool.LONGVALUE_LONG_METHOD_NAME, ConstantPool.LONGVALUE_LONG_METHOD_SIGNATURE); break; case TypeIds.T_float : // invokevirtual: floatValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangFloatConstantPoolName, ConstantPool.FLOATVALUE_FLOAT_METHOD_NAME, ConstantPool.FLOATVALUE_FLOAT_METHOD_SIGNATURE); break; case TypeIds.T_double : // invokevirtual: doubleValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 2, // return type size ConstantPool.JavaLangDoubleConstantPoolName, ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_NAME, ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE); break; case TypeIds.T_boolean : // invokevirtual: booleanValue() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangBooleanConstantPoolName, ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_NAME, ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE); } } final public byte[] getContents() { byte[] contents; System.arraycopy(this.bCodeStream, 0, contents = new byte[this.position], 0, this.position); return contents; } /** * Returns the type that should be substituted to original binding declaring class as the proper receiver type * @param currentScope * @param codegenBinding * @param actualReceiverType * @param isImplicitThisReceiver * @return the receiver type to use in constant pool */ public static TypeBinding getConstantPoolDeclaringClass(Scope currentScope, FieldBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver) { ReferenceBinding constantPoolDeclaringClass = codegenBinding.declaringClass; // 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 (constantPoolDeclaringClass != actualReceiverType.erasure() && !actualReceiverType.isArrayType() && constantPoolDeclaringClass != null // array.length && codegenBinding.constant() == Constant.NotAConstant) { CompilerOptions options = currentScope.compilerOptions(); if ((options.targetJDK >= ClassFileConstants.JDK1_2 && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic())) && constantPoolDeclaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields || !constantPoolDeclaringClass.canBeSeenBy(currentScope)) { return actualReceiverType.erasure(); } } return constantPoolDeclaringClass; } /** * Returns the type that should be substituted to original binding declaring class as the proper receiver type * @param currentScope * @param codegenBinding * @param actualReceiverType * @param isImplicitThisReceiver * @return the receiver type to use in constant pool */ public static TypeBinding getConstantPoolDeclaringClass(Scope currentScope, MethodBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver) { TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass; // 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) if (codegenBinding == currentScope.environment().arrayClone) { CompilerOptions options = currentScope.compilerOptions(); if (options.sourceLevel > ClassFileConstants.JDK1_4 ) { constantPoolDeclaringClass = actualReceiverType.erasure(); } } else { // 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 (constantPoolDeclaringClass != actualReceiverType.erasure() && !actualReceiverType.isArrayType()) { CompilerOptions options = currentScope.compilerOptions(); if ((options.targetJDK >= ClassFileConstants.JDK1_2 && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic())) && codegenBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods || !codegenBinding.declaringClass.canBeSeenBy(currentScope)) { constantPoolDeclaringClass = actualReceiverType.erasure(); } } } return constantPoolDeclaringClass; } protected int getPosition() { return this.position; } public void getTYPE(int baseTypeID) { this.countLabels = 0; switch (baseTypeID) { case TypeIds.T_byte : // getstatic: java.lang.Byte.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangByteConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_short : // getstatic: java.lang.Short.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangShortConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_char : // getstatic: java.lang.Character.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangCharacterConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_int : // getstatic: java.lang.Integer.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangIntegerConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_long : // getstatic: java.lang.Long.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangLongConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_float : // getstatic: java.lang.Float.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangFloatConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_double : // getstatic: java.lang.Double.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangDoubleConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_boolean : // getstatic: java.lang.Boolean.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangBooleanConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_void : // getstatic: java.lang.Void.TYPE fieldAccess( Opcodes.OPC_getstatic, 1, // return type size ConstantPool.JavaLangVoidConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; } } /** * We didn't call it goto, because there is a conflit with the goto keyword */ public void goto_(BranchLabel label) { if (this.wideMode) { goto_w(label); return; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } boolean chained = inlineForwardReferencesFromLabelsTargeting(label, this.position); /* Possible optimization for code such as: public Object foo() { boolean b = true; if (b) { if (b) return null; } else { if (b) { return null; } } return null; } The goto around the else block for the first if will be unreachable, because the thenClause of the second if returns. Also see 114894 }*/ if (chained && this.lastAbruptCompletion == this.position) { if (label.position != Label.POS_NOT_SET) { // ensure existing forward references are updated int[] forwardRefs = label.forwardReferences(); for (int i = 0, max = label.forwardReferenceCount(); i < max; i++) { this.writePosition(label, forwardRefs[i]); } this.countLabels = 0; // backward jump, no further chaining allowed } return; } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_goto; label.branch(); this.lastAbruptCompletion = this.position; } public void goto_w(BranchLabel label) { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_goto_w; label.branchWide(); this.lastAbruptCompletion = this.position; } public void i2b() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_i2b; } public void i2c() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_i2c; } public void i2d() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_i2d; } public void i2f() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_i2f; } public void i2l() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_i2l; } public void i2s() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_i2s; } public void iadd() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iadd; } public void iaload() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iaload; } public void iand() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iand; } public void iastore() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iastore; } public void iconst_0() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iconst_0; } public void iconst_1() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iconst_1; } public void iconst_2() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iconst_2; } public void iconst_3() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iconst_3; } public void iconst_4() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iconst_4; } public void iconst_5() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iconst_5; } public void iconst_m1() { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iconst_m1; } public void idiv() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_idiv; } public void if_acmpeq(BranchLabel lbl) { this.countLabels = 0; this.stackDepth-=2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_acmpne, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_acmpeq; lbl.branch(); } } public void if_acmpne(BranchLabel lbl) { this.countLabels = 0; this.stackDepth-=2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_acmpeq, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_acmpne; lbl.branch(); } } public void if_icmpeq(BranchLabel lbl) { this.countLabels = 0; this.stackDepth -= 2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_icmpne, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_icmpeq; lbl.branch(); } } public void if_icmpge(BranchLabel lbl) { this.countLabels = 0; this.stackDepth -= 2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_icmplt, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_icmpge; lbl.branch(); } } public void if_icmpgt(BranchLabel lbl) { this.countLabels = 0; this.stackDepth -= 2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_icmple, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_icmpgt; lbl.branch(); } } public void if_icmple(BranchLabel lbl) { this.countLabels = 0; this.stackDepth -= 2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_icmpgt, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_icmple; lbl.branch(); } } public void if_icmplt(BranchLabel lbl) { this.countLabels = 0; this.stackDepth -= 2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_icmpge, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_icmplt; lbl.branch(); } } public void if_icmpne(BranchLabel lbl) { this.countLabels = 0; this.stackDepth -= 2; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_if_icmpeq, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_if_icmpne; lbl.branch(); } } public void ifeq(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_ifne, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ifeq; lbl.branch(); } } public void ifge(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_iflt, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ifge; lbl.branch(); } } public void ifgt(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_ifle, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ifgt; lbl.branch(); } } public void ifle(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_ifgt, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ifle; lbl.branch(); } } public void iflt(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_ifge, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iflt; lbl.branch(); } } public void ifne(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_ifeq, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ifne; lbl.branch(); } } public void ifnonnull(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_ifnull, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ifnonnull; lbl.branch(); } } public void ifnull(BranchLabel lbl) { this.countLabels = 0; this.stackDepth--; if (this.wideMode) { generateWideRevertedConditionalBranch(Opcodes.OPC_ifnonnull, lbl); } else { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ifnull; lbl.branch(); } } final public void iinc(int index, int value) { this.countLabels = 0; if ((index > 255) || (value < -128 || value > 127)) { // have to widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iinc; writeUnsignedShort(index); writeSignedShort(value); } else { if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 3; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iinc; this.bCodeStream[this.classFileOffset++] = (byte) index; this.bCodeStream[this.classFileOffset++] = (byte) value; } } public void iload(int iArg) { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= iArg) { this.maxLocals = iArg + 1; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iload; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iload; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void iload_0() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= 0) { this.maxLocals = 1; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iload_0; } public void iload_1() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= 1) { this.maxLocals = 2; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iload_1; } public void iload_2() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= 2) { this.maxLocals = 3; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iload_2; } public void iload_3() { this.countLabels = 0; this.stackDepth++; if (this.maxLocals <= 3) { this.maxLocals = 4; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iload_3; } public void imul() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_imul; } public int indexOfSameLineEntrySincePC(int pc, int line) { for (int index = pc, max = this.pcToSourceMapSize; index < max; index+=2) { if (this.pcToSourceMap[index+1] == line) return index; } return -1; } public void ineg() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ineg; } public void init(ClassFile targetClassFile) { this.classFile = targetClassFile; this.constantPool = targetClassFile.constantPool; this.bCodeStream = targetClassFile.contents; this.classFileOffset = targetClassFile.contentsOffset; this.startingClassFileOffset = this.classFileOffset; this.pcToSourceMapSize = 0; this.lastEntryPC = 0; int length = this.visibleLocals.length; if (noVisibleLocals.length < length) { noVisibleLocals = new LocalVariableBinding[length]; } System.arraycopy(noVisibleLocals, 0, this.visibleLocals, 0, length); this.visibleLocalsCount = 0; length = this.locals.length; if (noLocals.length < length) { noLocals = new LocalVariableBinding[length]; } System.arraycopy(noLocals, 0, this.locals, 0, length); this.allLocalsCounter = 0; length = this.exceptionLabels.length; if (noExceptionHandlers.length < length) { noExceptionHandlers = new ExceptionLabel[length]; } System.arraycopy(noExceptionHandlers, 0, this.exceptionLabels, 0, length); this.exceptionLabelsCounter = 0; length = this.labels.length; if (noLabels.length < length) { noLabels = new BranchLabel[length]; } System.arraycopy(noLabels, 0, this.labels, 0, length); this.countLabels = 0; this.lastAbruptCompletion = -1; this.stackMax = 0; this.stackDepth = 0; this.maxLocals = 0; this.position = 0; } /** * @param methodBinding the given method binding to initialize the max locals */ public void initializeMaxLocals(MethodBinding methodBinding) { if (methodBinding == null) { this.maxLocals = 0; return; } this.maxLocals = methodBinding.isStatic() ? 0 : 1; ReferenceBinding declaringClass = methodBinding.declaringClass; // take into account enum constructor synthetic name+ordinal if (methodBinding.isConstructor() && declaringClass.isEnum()) { this.maxLocals += 2; // String and int (enum constant name+ordinal) } // take into account the synthetic parameters if (methodBinding.isConstructor() && declaringClass.isNestedType()) { this.maxLocals += declaringClass.getEnclosingInstancesSlotSize(); this.maxLocals += declaringClass.getOuterLocalVariablesSlotSize(); } TypeBinding[] parameterTypes; if ((parameterTypes = methodBinding.parameters) != null) { for (int i = 0, max = parameterTypes.length; i < max; i++) { switch (parameterTypes[i].id) { case TypeIds.T_long : case TypeIds.T_double : this.maxLocals += 2; break; default: this.maxLocals++; } } } } /** * Some placed labels might be branching to a goto bytecode which we can optimize better. */ public boolean inlineForwardReferencesFromLabelsTargeting(BranchLabel targetLabel, int gotoLocation) { if (targetLabel.delegate != null) return false; // already inlined int chaining = L_UNKNOWN; for (int i = this.countLabels - 1; i >= 0; i--) { BranchLabel currentLabel = this.labels[i]; if (currentLabel.position != gotoLocation) break; if (currentLabel == targetLabel) { chaining |= L_CANNOT_OPTIMIZE; // recursive continue; } if (currentLabel.isStandardLabel()) { if (currentLabel.delegate != null) continue; // ignore since already inlined targetLabel.becomeDelegateFor(currentLabel); chaining |= L_OPTIMIZABLE; // optimizable, providing no vetoing continue; } // case label chaining |= L_CANNOT_OPTIMIZE; } return (chaining & (L_OPTIMIZABLE|L_CANNOT_OPTIMIZE)) == L_OPTIMIZABLE; // check was some standards, and no case/recursive } /** * We didn't call it instanceof because there is a conflit with the * instanceof keyword */ public void instance_of(TypeBinding typeBinding) { this.countLabels = 0; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_instanceof; writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding)); } protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) { this.countLabels = 0; if (opcode == Opcodes.OPC_invokeinterface) { // invokeinterface if (this.classFileOffset + 4 >= this.bCodeStream.length) { resizeByteArray(); } this.position +=3; this.bCodeStream[this.classFileOffset++] = opcode; writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, true)); this.bCodeStream[this.classFileOffset++] = (byte) receiverAndArgsSize; this.bCodeStream[this.classFileOffset++] = 0; } else { // invokespecial // invokestatic // invokevirtual if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = opcode; writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, false)); } this.stackDepth += returnTypeSize - receiverAndArgsSize; if (this.stackDepth > this.stackMax) { this.stackMax = this.stackDepth; } } public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) { if (declaringClass == null) declaringClass = methodBinding.declaringClass; if ((declaringClass.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(this.classFile, declaringClass); } // compute receiverAndArgsSize int receiverAndArgsSize; switch(opcode) { case Opcodes.OPC_invokestatic : receiverAndArgsSize = 0; // no receiver break; case Opcodes.OPC_invokeinterface : case Opcodes.OPC_invokevirtual : receiverAndArgsSize = 1; // receiver break; case Opcodes.OPC_invokespecial : receiverAndArgsSize = 1; // receiver if (methodBinding.isConstructor()) { if (declaringClass.isNestedType()) { ReferenceBinding nestedType = (ReferenceBinding) declaringClass; // enclosing instances receiverAndArgsSize += nestedType.getEnclosingInstancesSlotSize(); // outer local variables SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables(); if (syntheticArguments != null) { for (int i = 0, max = syntheticArguments.length; i < max; i++) { switch (syntheticArguments[i].id) { case TypeIds.T_double : case TypeIds.T_long : receiverAndArgsSize += 2; break; default: receiverAndArgsSize++; break; } } } } if (declaringClass.isEnum()) { // adding String (name) and int (ordinal) receiverAndArgsSize += 2; } } break; default : return; // should not occur } for (int i = methodBinding.parameters.length - 1; i >= 0; i--) { switch (methodBinding.parameters[i].id) { case TypeIds.T_double : case TypeIds.T_long : receiverAndArgsSize += 2; break; default : receiverAndArgsSize ++; break; } } // compute return type size int returnTypeSize; switch (methodBinding.returnType.id) { case TypeIds.T_double : case TypeIds.T_long : returnTypeSize = 2; break; case TypeIds.T_void : returnTypeSize = 0; break; default : returnTypeSize = 1; break; } invoke( opcode, receiverAndArgsSize, returnTypeSize, declaringClass.constantPoolName(), methodBinding.selector, methodBinding.signature(this.classFile)); } protected void invokeAccessibleObjectSetAccessible() { // invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V; invoke( Opcodes.OPC_invokevirtual, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME, ConstantPool.SETACCESSIBLE_NAME, ConstantPool.SETACCESSIBLE_SIGNATURE); } protected void invokeArrayNewInstance() { // invokestatic: java.lang.reflect.Array.newInstance(Ljava.lang.Class;int[])Ljava.lang.Object; invoke( Opcodes.OPC_invokestatic, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JAVALANGREFLECTARRAY_CONSTANTPOOLNAME, ConstantPool.NewInstance, ConstantPool.NewInstanceSignature); } public void invokeClassForName() { // invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; invoke( Opcodes.OPC_invokestatic, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangClassConstantPoolName, ConstantPool.ForName, ConstantPool.ForNameSignature); } protected void invokeClassGetDeclaredConstructor() { // invokevirtual: java.lang.Class getDeclaredConstructor([Ljava.lang.Class)Ljava.lang.reflect.Constructor; invoke( Opcodes.OPC_invokevirtual, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangClassConstantPoolName, ConstantPool.GETDECLAREDCONSTRUCTOR_NAME, ConstantPool.GETDECLAREDCONSTRUCTOR_SIGNATURE); } protected void invokeClassGetDeclaredField() { // invokevirtual: java.lang.Class.getDeclaredField(Ljava.lang.String)Ljava.lang.reflect.Field; invoke( Opcodes.OPC_invokevirtual, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangClassConstantPoolName, ConstantPool.GETDECLAREDFIELD_NAME, ConstantPool.GETDECLAREDFIELD_SIGNATURE); } protected void invokeClassGetDeclaredMethod() { // invokevirtual: java.lang.Class getDeclaredMethod(Ljava.lang.String, [Ljava.lang.Class)Ljava.lang.reflect.Method; invoke( Opcodes.OPC_invokevirtual, 3, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangClassConstantPoolName, ConstantPool.GETDECLAREDMETHOD_NAME, ConstantPool.GETDECLAREDMETHOD_SIGNATURE); } public void invokeEnumOrdinal(char[] enumTypeConstantPoolName) { // invokevirtual: .ordinal() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size enumTypeConstantPoolName, ConstantPool.Ordinal, ConstantPool.OrdinalSignature); } public void invokeIterableIterator(TypeBinding iterableReceiverType) { // invokevirtual/interface: .iterator() if ((iterableReceiverType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(this.classFile, iterableReceiverType); } invoke( iterableReceiverType.isInterface() ? Opcodes.OPC_invokeinterface : Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // returnTypeSize iterableReceiverType.constantPoolName(), ConstantPool.ITERATOR_NAME, ConstantPool.ITERATOR_SIGNATURE); } public void invokeAutoCloseableClose(TypeBinding resourceType) { // invokevirtual/interface: .close() invoke( resourceType.erasure().isInterface() ? Opcodes.OPC_invokeinterface : Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 0, // returnTypeSize resourceType.constantPoolName(), ConstantPool.Close, ConstantPool.CloseSignature); } public void invokeThrowableAddSuppressed() { invoke(Opcodes.OPC_invokevirtual, 2, // receiverAndArgsSize 0, // returnTypeSize ConstantPool.JavaLangThrowableConstantPoolName, ConstantPool.AddSuppressed, ConstantPool.AddSuppressedSignature); } public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) { // invokespecial: java.lang.AssertionError.(typeBindingID)V int receiverAndArgsSize; char[] signature; switch (typeBindingID) { case TypeIds.T_int : case TypeIds.T_byte : case TypeIds.T_short : signature = ConstantPool.IntConstrSignature; receiverAndArgsSize = 2; break; case TypeIds.T_long : signature = ConstantPool.LongConstrSignature; receiverAndArgsSize = 3; break; case TypeIds.T_float : signature = ConstantPool.FloatConstrSignature; receiverAndArgsSize = 2; break; case TypeIds.T_double : signature = ConstantPool.DoubleConstrSignature; receiverAndArgsSize = 3; break; case TypeIds.T_char : signature = ConstantPool.CharConstrSignature; receiverAndArgsSize = 2; break; case TypeIds.T_boolean : signature = ConstantPool.BooleanConstrSignature; receiverAndArgsSize = 2; break; case TypeIds.T_JavaLangObject : case TypeIds.T_JavaLangString : case TypeIds.T_null : signature = ConstantPool.ObjectConstrSignature; receiverAndArgsSize = 2; break; default: return; // should not occur } invoke( Opcodes.OPC_invokespecial, receiverAndArgsSize, 0, // return type size ConstantPool.JavaLangAssertionErrorConstantPoolName, ConstantPool.Init, signature); } public void invokeJavaLangAssertionErrorDefaultConstructor() { // invokespecial: java.lang.AssertionError.()V invoke( Opcodes.OPC_invokespecial, 1, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangAssertionErrorConstantPoolName, ConstantPool.Init, ConstantPool.DefaultConstructorSignature); } public void invokeJavaLangClassDesiredAssertionStatus() { // invokevirtual: java.lang.Class.desiredAssertionStatus()Z; invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangClassConstantPoolName, ConstantPool.DesiredAssertionStatus, ConstantPool.DesiredAssertionStatusSignature); } public void invokeJavaLangEnumvalueOf(ReferenceBinding binding) { // invokestatic: java.lang.Enum.valueOf(Class,String) invoke( Opcodes.OPC_invokestatic, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangEnumConstantPoolName, ConstantPool.ValueOf, ConstantPool.ValueOfStringClassSignature); } public void invokeJavaLangEnumValues(TypeBinding enumBinding, ArrayBinding arrayBinding) { char[] signature = "()".toCharArray(); //$NON-NLS-1$ signature = CharOperation.concat(signature, arrayBinding.constantPoolName()); invoke( Opcodes.OPC_invokestatic, 0, // receiverAndArgsSize 1, // return type size enumBinding.constantPoolName(), TypeConstants.VALUES, signature); } public void invokeJavaLangErrorConstructor() { // invokespecial: java.lang.Error(Ljava.lang.String;)V invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangErrorConstantPoolName, ConstantPool.Init, ConstantPool.StringConstructorSignature); } public void invokeJavaLangReflectConstructorNewInstance() { // invokevirtual: java.lang.reflect.Constructor.newInstance([Ljava.lang.Object;)Ljava.lang.Object; invoke( Opcodes.OPC_invokevirtual, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangReflectConstructorConstantPoolName, ConstantPool.NewInstance, ConstantPool.JavaLangReflectConstructorNewInstanceSignature); } protected void invokeJavaLangReflectFieldGetter(int typeID) { char[] selector; char[] signature; int returnTypeSize; switch (typeID) { case TypeIds.T_int : selector = ConstantPool.GET_INT_METHOD_NAME; signature = ConstantPool.GET_INT_METHOD_SIGNATURE; returnTypeSize = 1; break; case TypeIds.T_byte : selector = ConstantPool.GET_BYTE_METHOD_NAME; signature = ConstantPool.GET_BYTE_METHOD_SIGNATURE; returnTypeSize = 1; break; case TypeIds.T_short : selector = ConstantPool.GET_SHORT_METHOD_NAME; signature = ConstantPool.GET_SHORT_METHOD_SIGNATURE; returnTypeSize = 1; break; case TypeIds.T_long : selector = ConstantPool.GET_LONG_METHOD_NAME; signature = ConstantPool.GET_LONG_METHOD_SIGNATURE; returnTypeSize = 2; break; case TypeIds.T_float : selector = ConstantPool.GET_FLOAT_METHOD_NAME; signature = ConstantPool.GET_FLOAT_METHOD_SIGNATURE; returnTypeSize = 1; break; case TypeIds.T_double : selector = ConstantPool.GET_DOUBLE_METHOD_NAME; signature = ConstantPool.GET_DOUBLE_METHOD_SIGNATURE; returnTypeSize = 2; break; case TypeIds.T_char : selector = ConstantPool.GET_CHAR_METHOD_NAME; signature = ConstantPool.GET_CHAR_METHOD_SIGNATURE; returnTypeSize = 1; break; case TypeIds.T_boolean : selector = ConstantPool.GET_BOOLEAN_METHOD_NAME; signature = ConstantPool.GET_BOOLEAN_METHOD_SIGNATURE; returnTypeSize = 1; break; default : selector = ConstantPool.GET_OBJECT_METHOD_NAME; signature = ConstantPool.GET_OBJECT_METHOD_SIGNATURE; returnTypeSize = 1; break; } invoke( Opcodes.OPC_invokevirtual, 2, // receiverAndArgsSize returnTypeSize, // return type size ConstantPool.JAVALANGREFLECTFIELD_CONSTANTPOOLNAME, selector, signature); } protected void invokeJavaLangReflectFieldSetter(int typeID) { char[] selector; char[] signature; int receiverAndArgsSize; switch (typeID) { case TypeIds.T_int : selector = ConstantPool.SET_INT_METHOD_NAME; signature = ConstantPool.SET_INT_METHOD_SIGNATURE; receiverAndArgsSize = 3; break; case TypeIds.T_byte : selector = ConstantPool.SET_BYTE_METHOD_NAME; signature = ConstantPool.SET_BYTE_METHOD_SIGNATURE; receiverAndArgsSize = 3; break; case TypeIds.T_short : selector = ConstantPool.SET_SHORT_METHOD_NAME; signature = ConstantPool.SET_SHORT_METHOD_SIGNATURE; receiverAndArgsSize = 3; break; case TypeIds.T_long : selector = ConstantPool.SET_LONG_METHOD_NAME; signature = ConstantPool.SET_LONG_METHOD_SIGNATURE; receiverAndArgsSize = 4; break; case TypeIds.T_float : selector = ConstantPool.SET_FLOAT_METHOD_NAME; signature = ConstantPool.SET_FLOAT_METHOD_SIGNATURE; receiverAndArgsSize = 3; break; case TypeIds.T_double : selector = ConstantPool.SET_DOUBLE_METHOD_NAME; signature = ConstantPool.SET_DOUBLE_METHOD_SIGNATURE; receiverAndArgsSize = 4; break; case TypeIds.T_char : selector = ConstantPool.SET_CHAR_METHOD_NAME; signature = ConstantPool.SET_CHAR_METHOD_SIGNATURE; receiverAndArgsSize = 3; break; case TypeIds.T_boolean : selector = ConstantPool.SET_BOOLEAN_METHOD_NAME; signature = ConstantPool.SET_BOOLEAN_METHOD_SIGNATURE; receiverAndArgsSize = 3; break; default : selector = ConstantPool.SET_OBJECT_METHOD_NAME; signature = ConstantPool.SET_OBJECT_METHOD_SIGNATURE; receiverAndArgsSize = 3; break; } invoke( Opcodes.OPC_invokevirtual, receiverAndArgsSize, 0, // return type size ConstantPool.JAVALANGREFLECTFIELD_CONSTANTPOOLNAME, selector, signature); } public void invokeJavaLangReflectMethodInvoke() { // invokevirtual: java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object; invoke( Opcodes.OPC_invokevirtual, 3, // receiverAndArgsSize 1, // return type size ConstantPool.JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME, ConstantPool.INVOKE_METHOD_METHOD_NAME, ConstantPool.INVOKE_METHOD_METHOD_SIGNATURE); } public void invokeJavaUtilIteratorHasNext() { // invokeinterface java.util.Iterator.hasNext()Z invoke( Opcodes.OPC_invokeinterface, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaUtilIteratorConstantPoolName, ConstantPool.HasNext, ConstantPool.HasNextSignature); } public void invokeJavaUtilIteratorNext() { // invokeinterface java.util.Iterator.next()java.lang.Object invoke( Opcodes.OPC_invokeinterface, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaUtilIteratorConstantPoolName, ConstantPool.Next, ConstantPool.NextSignature); } public void invokeNoClassDefFoundErrorStringConstructor() { // invokespecial: java.lang.NoClassDefFoundError.(Ljava.lang.String;)V invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName, ConstantPool.Init, ConstantPool.StringConstructorSignature); } public void invokeObjectGetClass() { // invokevirtual: java.lang.Object.getClass()Ljava.lang.Class; invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangObjectConstantPoolName, ConstantPool.GetClass, ConstantPool.GetClassSignature); } /** * The equivalent code performs a string conversion of the TOS * @param typeID int */ public void invokeStringConcatenationAppendForType(int typeID) { int receiverAndArgsSize; char[] declaringClass = null; char[] selector = ConstantPool.Append; char[] signature = null; switch (typeID) { case TypeIds.T_int : case TypeIds.T_byte : case TypeIds.T_short : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendIntSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendIntSignature; } receiverAndArgsSize = 2; break; case TypeIds.T_long : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendLongSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendLongSignature; } receiverAndArgsSize = 3; break; case TypeIds.T_float : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendFloatSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendFloatSignature; } receiverAndArgsSize = 2; break; case TypeIds.T_double : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendDoubleSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendDoubleSignature; } receiverAndArgsSize = 3; break; case TypeIds.T_char : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendCharSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendCharSignature; } receiverAndArgsSize = 2; break; case TypeIds.T_boolean : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendBooleanSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendBooleanSignature; } receiverAndArgsSize = 2; break; case TypeIds.T_JavaLangString : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendStringSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendStringSignature; } receiverAndArgsSize = 2; break; default : if (this.targetLevel >= ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; signature = ConstantPool.StringBuilderAppendObjectSignature; } else { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; signature = ConstantPool.StringBufferAppendObjectSignature; } receiverAndArgsSize = 2; break; } invoke( Opcodes.OPC_invokevirtual, receiverAndArgsSize, 1, // return type size declaringClass, selector, signature); } public void invokeStringConcatenationDefaultConstructor() { // invokespecial: java.lang.StringBuffer.()V // or invokespecial: java.lang.StringBuilder.()V char[] declaringClass; if (this.targetLevel < ClassFileConstants.JDK1_5) { declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; } else { declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; } invoke( Opcodes.OPC_invokespecial, 1, // receiverAndArgsSize 0, // return type size declaringClass, ConstantPool.Init, ConstantPool.DefaultConstructorSignature); } public void invokeStringConcatenationStringConstructor() { // invokespecial: java.lang.StringBuffer.(java.lang.String)V // or invokespecial: java.lang.StringBuilder.(java.lang.String)V char[] declaringClass; if (this.targetLevel < ClassFileConstants.JDK1_5) { // invokespecial: java.lang.StringBuffer.()V declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; } else { // invokespecial: java.lang.StringStringBuilder.(java.langString)V declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; } invoke( Opcodes.OPC_invokespecial, 2, // receiverAndArgsSize 0, // return type size declaringClass, ConstantPool.Init, ConstantPool.StringConstructorSignature); } public void invokeStringConcatenationToString() { // invokespecial: java.lang.StringBuffer.toString()java.lang.String // or invokespecial: java.lang.StringBuilder.toString()java.lang.String char[] declaringClass; if (this.targetLevel < ClassFileConstants.JDK1_5) { // invokespecial: java.lang.StringBuffer.()V declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName; } else { // invokespecial: java.lang.StringStringBuilder.(java.langString)V declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName; } invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size declaringClass, ConstantPool.ToString, ConstantPool.ToStringSignature); } public void invokeStringEquals() { // invokevirtual: java.lang.String.equals() invoke( Opcodes.OPC_invokevirtual, 2, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangStringConstantPoolName, ConstantPool.Equals, ConstantPool.EqualsSignature); } public void invokeStringHashCode() { // invokevirtual: java.lang.String.hashCode() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangStringConstantPoolName, ConstantPool.HashCode, ConstantPool.HashCodeSignature); } public void invokeStringIntern() { // invokevirtual: java.lang.String.intern() invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangStringConstantPoolName, ConstantPool.Intern, ConstantPool.InternSignature); } public void invokeStringValueOf(int typeID) { // invokestatic: java.lang.String.valueOf(argumentType) char[] signature; int receiverAndArgsSize; switch (typeID) { case TypeIds.T_int : case TypeIds.T_byte : case TypeIds.T_short : signature = ConstantPool.ValueOfIntSignature; receiverAndArgsSize = 1; break; case TypeIds.T_long : signature = ConstantPool.ValueOfLongSignature; receiverAndArgsSize = 2; break; case TypeIds.T_float : signature = ConstantPool.ValueOfFloatSignature; receiverAndArgsSize = 1; break; case TypeIds.T_double : signature = ConstantPool.ValueOfDoubleSignature; receiverAndArgsSize = 2; break; case TypeIds.T_char : signature = ConstantPool.ValueOfCharSignature; receiverAndArgsSize = 1; break; case TypeIds.T_boolean : signature = ConstantPool.ValueOfBooleanSignature; receiverAndArgsSize = 1; break; case TypeIds.T_JavaLangObject : case TypeIds.T_JavaLangString : case TypeIds.T_null : case TypeIds.T_undefined : signature = ConstantPool.ValueOfObjectSignature; receiverAndArgsSize = 1; break; default : return; // should not occur } invoke( Opcodes.OPC_invokestatic, receiverAndArgsSize, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangStringConstantPoolName, ConstantPool.ValueOf, signature); } public void invokeSystemArraycopy() { // invokestatic #21 invoke( Opcodes.OPC_invokestatic, 5, // receiverAndArgsSize 0, // return type size ConstantPool.JavaLangSystemConstantPoolName, ConstantPool.ArrayCopy, ConstantPool.ArrayCopySignature); } public void invokeThrowableGetMessage() { // invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String; invoke( Opcodes.OPC_invokevirtual, 1, // receiverAndArgsSize 1, // return type size ConstantPool.JavaLangThrowableConstantPoolName, ConstantPool.GetMessage, ConstantPool.GetMessageSignature); } public void ior() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ior; } public void irem() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_irem; } public void ireturn() { this.countLabels = 0; this.stackDepth--; // the stackDepth should be equal to 0 if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ireturn; this.lastAbruptCompletion = this.position; } public boolean isDefinitelyAssigned(Scope scope, int initStateIndex, LocalVariableBinding local) { // Mirror of UnconditionalFlowInfo.isDefinitelyAssigned(..) if ((local.tagBits & TagBits.IsArgument) != 0) { return true; } if (initStateIndex == -1) return false; int localPosition = local.id + this.maxFieldCount; MethodScope methodScope = scope.methodScope(); // id is zero-based if (localPosition < UnconditionalFlowInfo.BitCacheSize) { return (methodScope.definiteInits[initStateIndex] & (1L << localPosition)) != 0; // use bits } // use extra vector long[] extraInits = methodScope.extraDefiniteInits[initStateIndex]; if (extraInits == null) return false; // if vector not yet allocated, then not initialized int vectorIndex; if ((vectorIndex = (localPosition / UnconditionalFlowInfo.BitCacheSize) - 1) >= extraInits.length) return false; // if not enough room in vector, then not initialized return ((extraInits[vectorIndex]) & (1L << (localPosition % UnconditionalFlowInfo.BitCacheSize))) != 0; } public void ishl() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ishl; } public void ishr() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ishr; } public void istore(int iArg) { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= iArg) { this.maxLocals = iArg + 1; } if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_istore; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_istore; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void istore_0() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals == 0) { this.maxLocals = 1; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_istore_0; } public void istore_1() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 1) { this.maxLocals = 2; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_istore_1; } public void istore_2() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 2) { this.maxLocals = 3; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_istore_2; } public void istore_3() { this.countLabels = 0; this.stackDepth--; if (this.maxLocals <= 3) { this.maxLocals = 4; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_istore_3; } public void isub() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_isub; } public void iushr() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_iushr; } public void ixor() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ixor; } final public void jsr(BranchLabel lbl) { if (this.wideMode) { jsr_w(lbl); return; } this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_jsr; lbl.branch(); } final public void jsr_w(BranchLabel lbl) { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_jsr_w; lbl.branchWide(); } public void l2d() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_l2d; } public void l2f() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_l2f; } public void l2i() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_l2i; } public void ladd() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ladd; } public void laload() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_laload; } public void land() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_land; } public void lastore() { this.countLabels = 0; this.stackDepth -= 4; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lastore; } public void lcmp() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lcmp; } public void lconst_0() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lconst_0; } public void lconst_1() { this.countLabels = 0; this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lconst_1; } public void ldc(float constant) { this.countLabels = 0; int index = this.constantPool.literalIndex(constant); this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (index > 255) { // Generate a ldc_w if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc_w; writeUnsignedShort(index); } else { // Generate a ldc if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc; this.bCodeStream[this.classFileOffset++] = (byte) index; } } public void ldc(int constant) { this.countLabels = 0; int index = this.constantPool.literalIndex(constant); this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (index > 255) { // Generate a ldc_w if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc_w; writeUnsignedShort(index); } else { // Generate a ldc if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc; this.bCodeStream[this.classFileOffset++] = (byte) index; } } public void ldc(String constant) { this.countLabels = 0; int currentCodeStreamPosition = this.position; char[] constantChars = constant.toCharArray(); int index = this.constantPool.literalIndexForLdc(constantChars); if (index > 0) { // the string already exists inside the constant pool // we reuse the same index ldcForIndex(index); } else { // the string is too big to be utf8-encoded in one pass. // we have to split it into different pieces. // first we clean all side-effects due to the code above // this case is very rare, so we can afford to lose time to handle it this.position = currentCodeStreamPosition; int i = 0; int length = 0; int constantLength = constant.length(); byte[] utf8encoding = new byte[Math.min(constantLength + 100, 65535)]; int utf8encodingLength = 0; while ((length < 65532) && (i < constantLength)) { char current = constantChars[i]; // we resize the byte array immediately if necessary if (length + 3 > (utf8encodingLength = utf8encoding.length)) { System.arraycopy(utf8encoding, 0, utf8encoding = new byte[Math.min(utf8encodingLength + 100, 65535)], 0, length); } if ((current >= 0x0001) && (current <= 0x007F)) { // we only need one byte: ASCII table utf8encoding[length++] = (byte) current; } else { if (current > 0x07FF) { // we need 3 bytes utf8encoding[length++] = (byte) (0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000 utf8encoding[length++] = (byte) (0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000 utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 } else { // we can be 0 or between 0x0080 and 0x07FF // In that case we only need 2 bytes utf8encoding[length++] = (byte) (0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000 utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 } } i++; } // check if all the string is encoded (PR 1PR2DWJ) // the string is too big to be encoded in one pass newStringContatenation(); dup(); // write the first part char[] subChars = new char[i]; System.arraycopy(constantChars, 0, subChars, 0, i); System.arraycopy(utf8encoding, 0, utf8encoding = new byte[length], 0, length); index = this.constantPool.literalIndex(subChars, utf8encoding); ldcForIndex(index); // write the remaining part invokeStringConcatenationStringConstructor(); while (i < constantLength) { length = 0; utf8encoding = new byte[Math.min(constantLength - i + 100, 65535)]; int startIndex = i; while ((length < 65532) && (i < constantLength)) { char current = constantChars[i]; // we resize the byte array immediately if necessary if (length + 3 > (utf8encodingLength = utf8encoding.length)) { System.arraycopy(utf8encoding, 0, utf8encoding = new byte[Math.min(utf8encodingLength + 100, 65535)], 0, length); } if ((current >= 0x0001) && (current <= 0x007F)) { // we only need one byte: ASCII table utf8encoding[length++] = (byte) current; } else { if (current > 0x07FF) { // we need 3 bytes utf8encoding[length++] = (byte) (0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000 utf8encoding[length++] = (byte) (0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000 utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 } else { // we can be 0 or between 0x0080 and 0x07FF // In that case we only need 2 bytes utf8encoding[length++] = (byte) (0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000 utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 } } i++; } // the next part is done int newCharLength = i - startIndex; subChars = new char[newCharLength]; System.arraycopy(constantChars, startIndex, subChars, 0, newCharLength); System.arraycopy(utf8encoding, 0, utf8encoding = new byte[length], 0, length); index = this.constantPool.literalIndex(subChars, utf8encoding); ldcForIndex(index); // now on the stack it should be a StringBuffer and a string. invokeStringConcatenationAppendForType(TypeIds.T_JavaLangString); } invokeStringConcatenationToString(); invokeStringIntern(); } } public void ldc(TypeBinding typeBinding) { this.countLabels = 0; int index = this.constantPool.literalIndexForType(typeBinding); this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (index > 255) { // Generate a ldc_w if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc_w; writeUnsignedShort(index); } else { // Generate a ldc if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc; this.bCodeStream[this.classFileOffset++] = (byte) index; } } public void ldc2_w(double constant) { this.countLabels = 0; int index = this.constantPool.literalIndex(constant); this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; // Generate a ldc2_w if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc2_w; writeUnsignedShort(index); } public void ldc2_w(long constant) { this.countLabels = 0; int index = this.constantPool.literalIndex(constant); this.stackDepth += 2; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; // Generate a ldc2_w if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc2_w; writeUnsignedShort(index); } public void ldcForIndex(int index) { this.stackDepth++; if (this.stackDepth > this.stackMax) { this.stackMax = this.stackDepth; } if (index > 255) { // Generate a ldc_w if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc_w; writeUnsignedShort(index); } else { // Generate a ldc if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldc; this.bCodeStream[this.classFileOffset++] = (byte) index; } } public void ldiv() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ldiv; } public void lload(int iArg) { this.countLabels = 0; this.stackDepth += 2; if (this.maxLocals <= iArg + 1) { this.maxLocals = iArg + 2; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lload; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lload; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void lload_0() { this.countLabels = 0; this.stackDepth += 2; if (this.maxLocals < 2) { this.maxLocals = 2; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lload_0; } public void lload_1() { this.countLabels = 0; this.stackDepth += 2; if (this.maxLocals < 3) { this.maxLocals = 3; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lload_1; } public void lload_2() { this.countLabels = 0; this.stackDepth += 2; if (this.maxLocals < 4) { this.maxLocals = 4; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lload_2; } public void lload_3() { this.countLabels = 0; this.stackDepth += 2; if (this.maxLocals < 5) { this.maxLocals = 5; } if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lload_3; } public void lmul() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lmul; } public void lneg() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lneg; } public final void load(LocalVariableBinding localBinding) { load(localBinding.type, localBinding.resolvedPosition); } protected final void load(TypeBinding typeBinding, int resolvedPosition) { this.countLabels = 0; // Using dedicated int bytecode switch(typeBinding.id) { case TypeIds.T_int : case TypeIds.T_byte : case TypeIds.T_char : case TypeIds.T_boolean : case TypeIds.T_short : switch (resolvedPosition) { case 0 : iload_0(); break; case 1 : iload_1(); break; case 2 : iload_2(); break; case 3 : iload_3(); break; //case -1 : // internal failure: trying to load variable not supposed to be generated // break; default : iload(resolvedPosition); } break; case TypeIds.T_float : switch (resolvedPosition) { case 0 : fload_0(); break; case 1 : fload_1(); break; case 2 : fload_2(); break; case 3 : fload_3(); break; default : fload(resolvedPosition); } break; case TypeIds.T_long : switch (resolvedPosition) { case 0 : lload_0(); break; case 1 : lload_1(); break; case 2 : lload_2(); break; case 3 : lload_3(); break; default : lload(resolvedPosition); } break; case TypeIds.T_double : switch (resolvedPosition) { case 0 : dload_0(); break; case 1 : dload_1(); break; case 2 : dload_2(); break; case 3 : dload_3(); break; default : dload(resolvedPosition); } break; default : switch (resolvedPosition) { case 0 : aload_0(); break; case 1 : aload_1(); break; case 2 : aload_2(); break; case 3 : aload_3(); break; default : aload(resolvedPosition); } } } public void lookupswitch(CaseLabel defaultLabel, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) { this.countLabels = 0; this.stackDepth--; int length = keys.length; int pos = this.position; defaultLabel.placeInstruction(); for (int i = 0; i < length; i++) { casesLabel[i].placeInstruction(); } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lookupswitch; for (int i = (3 - (pos & 3)); i > 0; i--) { // faster than % 4 if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = 0; } defaultLabel.branch(); writeSignedWord(length); for (int i = 0; i < length; i++) { writeSignedWord(keys[sortedIndexes[i]]); casesLabel[sortedIndexes[i]].branch(); } } public void lor() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lor; } public void lrem() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lrem; } public void lreturn() { this.countLabels = 0; this.stackDepth -= 2; // the stackDepth should be equal to 0 if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lreturn; this.lastAbruptCompletion = this.position; } public void lshl() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lshl; } public void lshr() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lshr; } public void lstore(int iArg) { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals <= iArg + 1) { this.maxLocals = iArg + 2; } if (iArg > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lstore; writeUnsignedShort(iArg); } else { if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lstore; this.bCodeStream[this.classFileOffset++] = (byte) iArg; } } public void lstore_0() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 2) { this.maxLocals = 2; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lstore_0; } public void lstore_1() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 3) { this.maxLocals = 3; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lstore_1; } public void lstore_2() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 4) { this.maxLocals = 4; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lstore_2; } public void lstore_3() { this.countLabels = 0; this.stackDepth -= 2; if (this.maxLocals < 5) { this.maxLocals = 5; } if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lstore_3; } public void lsub() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lsub; } public void lushr() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lushr; } public void lxor() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_lxor; } public void monitorenter() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_monitorenter; } public void monitorexit() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_monitorexit; } public void multianewarray(TypeBinding typeBinding, int dimensions) { this.countLabels = 0; this.stackDepth += (1 - dimensions); if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_multianewarray; writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding)); this.bCodeStream[this.classFileOffset++] = (byte) dimensions; } // We didn't call it new, because there is a conflit with the new keyword public void new_(TypeBinding typeBinding) { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_new; writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding)); } public void newarray(int array_Type) { this.countLabels = 0; if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_newarray; this.bCodeStream[this.classFileOffset++] = (byte) array_Type; } public void newArray(ArrayBinding arrayBinding) { TypeBinding component = arrayBinding.elementsType(); switch (component.id) { case TypeIds.T_int : newarray(ClassFileConstants.INT_ARRAY); break; case TypeIds.T_byte : newarray(ClassFileConstants.BYTE_ARRAY); break; case TypeIds.T_boolean : newarray(ClassFileConstants.BOOLEAN_ARRAY); break; case TypeIds.T_short : newarray(ClassFileConstants.SHORT_ARRAY); break; case TypeIds.T_char : newarray(ClassFileConstants.CHAR_ARRAY); break; case TypeIds.T_long : newarray(ClassFileConstants.LONG_ARRAY); break; case TypeIds.T_float : newarray(ClassFileConstants.FLOAT_ARRAY); break; case TypeIds.T_double : newarray(ClassFileConstants.DOUBLE_ARRAY); break; default : anewarray(component); } } public void newJavaLangAssertionError() { // new: java.lang.AssertionError this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_new; writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangAssertionErrorConstantPoolName)); } public void newJavaLangError() { // new: java.lang.Error this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_new; writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangErrorConstantPoolName)); } public void newNoClassDefFoundError() { // new: java.lang.NoClassDefFoundError this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_new; writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName)); } public void newStringContatenation() { // new: java.lang.StringBuffer // new: java.lang.StringBuilder this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) { this.stackMax = this.stackDepth; } if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_new; if (this.targetLevel >= ClassFileConstants.JDK1_5) { writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangStringBuilderConstantPoolName)); } else { writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangStringBufferConstantPoolName)); } } public void newWrapperFor(int typeID) { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_new; switch (typeID) { case TypeIds.T_int : // new: java.lang.Integer writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangIntegerConstantPoolName)); break; case TypeIds.T_boolean : // new: java.lang.Boolean writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangBooleanConstantPoolName)); break; case TypeIds.T_byte : // new: java.lang.Byte writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangByteConstantPoolName)); break; case TypeIds.T_char : // new: java.lang.Character writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangCharacterConstantPoolName)); break; case TypeIds.T_float : // new: java.lang.Float writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangFloatConstantPoolName)); break; case TypeIds.T_double : // new: java.lang.Double writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangDoubleConstantPoolName)); break; case TypeIds.T_short : // new: java.lang.Short writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangShortConstantPoolName)); break; case TypeIds.T_long : // new: java.lang.Long writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangLongConstantPoolName)); break; case TypeIds.T_void : // new: java.lang.Void writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangVoidConstantPoolName)); } } public void nop() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_nop; } public void optimizeBranch(int oldPosition, BranchLabel lbl) { for (int i = 0; i < this.countLabels; i++) { BranchLabel label = this.labels[i]; if (oldPosition == label.position) { label.position = this.position; if (label instanceof CaseLabel) { int offset = this.position - ((CaseLabel) label).instructionPosition; int[] forwardRefs = label.forwardReferences(); for (int j = 0, length = label.forwardReferenceCount(); j < length; j++) { int forwardRef = forwardRefs[j]; this.writeSignedWord(forwardRef, offset); } } else { int[] forwardRefs = label.forwardReferences(); for (int j = 0, length = label.forwardReferenceCount(); j < length; j++) { final int forwardRef = forwardRefs[j]; this.writePosition(lbl, forwardRef); } } } } } public void pop() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_pop; } public void pop2() { this.countLabels = 0; this.stackDepth -= 2; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_pop2; } public void pushExceptionOnStack(TypeBinding binding) { this.stackDepth = 1; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; } public void pushOnStack(TypeBinding binding) { if (++this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; } public void record(LocalVariableBinding local) { if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) == 0) return; if (this.allLocalsCounter == this.locals.length) { // resize the collection System.arraycopy(this.locals, 0, this.locals = new LocalVariableBinding[this.allLocalsCounter + LOCALS_INCREMENT], 0, this.allLocalsCounter); } this.locals[this.allLocalsCounter++] = local; local.initializationPCs = new int[4]; local.initializationCount = 0; } public void recordExpressionType(TypeBinding typeBinding) { // nothing to do } public void recordPositionsFrom(int startPC, int sourcePos) { this.recordPositionsFrom(startPC, sourcePos, false); } public void recordPositionsFrom(int startPC, int sourcePos, boolean widen) { /* Record positions in the table, only if nothing has * already been recorded. Since we output them on the way * up (children first for more specific info) * The pcToSourceMap table is always sorted. */ if ((this.generateAttributes & ClassFileConstants.ATTR_LINES) == 0 || sourcePos == 0 || (startPC == this.position && !widen) || startPC > this.position) return; // Widening an existing entry that already has the same source positions if (this.pcToSourceMapSize + 4 > this.pcToSourceMap.length) { // resize the array pcToSourceMap System.arraycopy(this.pcToSourceMap, 0, this.pcToSourceMap = new int[this.pcToSourceMapSize << 1], 0, this.pcToSourceMapSize); } // lastEntryPC represents the endPC of the lastEntry. if (this.pcToSourceMapSize > 0) { int lineNumber; int previousLineNumber = this.pcToSourceMap[this.pcToSourceMapSize - 1]; if (this.lineNumberStart == this.lineNumberEnd) { // method on one line lineNumber = this.lineNumberStart; } else { // Check next line number if this is the one we are looking for int[] lineSeparatorPositions2 = this.lineSeparatorPositions; int length = lineSeparatorPositions2.length; if (previousLineNumber == 1) { if (sourcePos < lineSeparatorPositions2[0]) { lineNumber = 1; /* the last recorded entry is on the same line. But it could be relevant to widen this entry. we want to extend this entry forward in case we generated some bytecode before the last entry that are not related to any statement */ if (startPC < this.pcToSourceMap[this.pcToSourceMapSize - 2]) { int insertionIndex = insertionIndex(this.pcToSourceMap, this.pcToSourceMapSize, startPC); if (insertionIndex != -1) { // widen the existing entry // we have to figure out if we need to move the last entry at another location to keep a sorted table /* First we need to check if at the insertion position there is not an existing entry * that includes the one we want to insert. This is the case if pcToSourceMap[insertionIndex - 1] == newLine. * In this case we don't want to change the table. If not, we want to insert a new entry. Prior to insertion * we want to check if it is worth doing an arraycopy. If not we simply update the recorded pc. */ if (!((insertionIndex > 1) && (this.pcToSourceMap[insertionIndex - 1] == lineNumber))) { if ((this.pcToSourceMapSize > 4) && (this.pcToSourceMap[this.pcToSourceMapSize - 4] > startPC)) { System.arraycopy(this.pcToSourceMap, insertionIndex, this.pcToSourceMap, insertionIndex + 2, this.pcToSourceMapSize - 2 - insertionIndex); this.pcToSourceMap[insertionIndex++] = startPC; this.pcToSourceMap[insertionIndex] = lineNumber; } else { this.pcToSourceMap[this.pcToSourceMapSize - 2] = startPC; } } } } this.lastEntryPC = this.position; return; } else if (length == 1 || sourcePos < lineSeparatorPositions2[1]) { lineNumber = 2; if (startPC <= this.lastEntryPC) { // we forgot to add an entry. // search if an existing entry exists for startPC int insertionIndex = insertionIndex(this.pcToSourceMap, this.pcToSourceMapSize, startPC); if (insertionIndex != -1) { // there is no existing entry starting with startPC. int existingEntryIndex = indexOfSameLineEntrySincePC(startPC, lineNumber); // index for PC /* the existingEntryIndex corresponds to an entry with the same line and a PC >= startPC. in this case it is relevant to widen this entry instead of creating a new one. line1: this(a, b, c); with this code we generate each argument. We generate a aload0 to invoke the constructor. There is no entry for this aload0 bytecode. The first entry is the one for the argument a. But we want the constructor call to start at the aload0 pc and not just at the pc of the first argument. So we widen the existing entry (if there is one) or we create a new entry with the startPC. */ if (existingEntryIndex != -1) { // widen existing entry this.pcToSourceMap[existingEntryIndex] = startPC; } else if (insertionIndex < 1 || this.pcToSourceMap[insertionIndex - 1] != lineNumber) { // we have to add an entry that won't be sorted. So we sort the pcToSourceMap. System.arraycopy(this.pcToSourceMap, insertionIndex, this.pcToSourceMap, insertionIndex + 2, this.pcToSourceMapSize - insertionIndex); this.pcToSourceMap[insertionIndex++] = startPC; this.pcToSourceMap[insertionIndex] = lineNumber; this.pcToSourceMapSize += 2; } } else if (this.position != this.lastEntryPC) { // no bytecode since last entry pc if (this.lastEntryPC == startPC || this.lastEntryPC == this.pcToSourceMap[this.pcToSourceMapSize - 2]) { this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } else { this.pcToSourceMap[this.pcToSourceMapSize++] = this.lastEntryPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } } else if (this.pcToSourceMap[this.pcToSourceMapSize - 1] < lineNumber && widen) { // see if we can widen the existing entry this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } } else { // we can safely add the new entry. The endPC of the previous entry is not in conflit with the startPC of the new entry. this.pcToSourceMap[this.pcToSourceMapSize++] = startPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } this.lastEntryPC = this.position; return; } else { // since lineSeparatorPositions is zero-based, we pass this.lineNumberStart - 1 and this.lineNumberEnd - 1 lineNumber = Util.getLineNumber(sourcePos, this.lineSeparatorPositions, this.lineNumberStart - 1, this.lineNumberEnd - 1); } } else if (previousLineNumber < length) { if (lineSeparatorPositions2[previousLineNumber - 2] < sourcePos) { if (sourcePos < lineSeparatorPositions2[previousLineNumber - 1]) { lineNumber = previousLineNumber; /* the last recorded entry is on the same line. But it could be relevant to widen this entry. we want to extend this entry forward in case we generated some bytecode before the last entry that are not related to any statement */ if (startPC < this.pcToSourceMap[this.pcToSourceMapSize - 2]) { int insertionIndex = insertionIndex(this.pcToSourceMap, this.pcToSourceMapSize, startPC); if (insertionIndex != -1) { // widen the existing entry // we have to figure out if we need to move the last entry at another location to keep a sorted table /* First we need to check if at the insertion position there is not an existing entry * that includes the one we want to insert. This is the case if pcToSourceMap[insertionIndex - 1] == newLine. * In this case we don't want to change the table. If not, we want to insert a new entry. Prior to insertion * we want to check if it is worth doing an arraycopy. If not we simply update the recorded pc. */ if (!((insertionIndex > 1) && (this.pcToSourceMap[insertionIndex - 1] == lineNumber))) { if ((this.pcToSourceMapSize > 4) && (this.pcToSourceMap[this.pcToSourceMapSize - 4] > startPC)) { System.arraycopy(this.pcToSourceMap, insertionIndex, this.pcToSourceMap, insertionIndex + 2, this.pcToSourceMapSize - 2 - insertionIndex); this.pcToSourceMap[insertionIndex++] = startPC; this.pcToSourceMap[insertionIndex] = lineNumber; } else { this.pcToSourceMap[this.pcToSourceMapSize - 2] = startPC; } } } } this.lastEntryPC = this.position; return; } else if (sourcePos < lineSeparatorPositions2[previousLineNumber]) { lineNumber = previousLineNumber + 1; if (startPC <= this.lastEntryPC) { // we forgot to add an entry. // search if an existing entry exists for startPC int insertionIndex = insertionIndex(this.pcToSourceMap, this.pcToSourceMapSize, startPC); if (insertionIndex != -1) { // there is no existing entry starting with startPC. int existingEntryIndex = indexOfSameLineEntrySincePC(startPC, lineNumber); // index for PC /* the existingEntryIndex corresponds to an entry with the same line and a PC >= startPC. in this case it is relevant to widen this entry instead of creating a new one. line1: this(a, b, c); with this code we generate each argument. We generate a aload0 to invoke the constructor. There is no entry for this aload0 bytecode. The first entry is the one for the argument a. But we want the constructor call to start at the aload0 pc and not just at the pc of the first argument. So we widen the existing entry (if there is one) or we create a new entry with the startPC. */ if (existingEntryIndex != -1) { // widen existing entry this.pcToSourceMap[existingEntryIndex] = startPC; } else if (insertionIndex < 1 || this.pcToSourceMap[insertionIndex - 1] != lineNumber) { // we have to add an entry that won't be sorted. So we sort the pcToSourceMap. System.arraycopy(this.pcToSourceMap, insertionIndex, this.pcToSourceMap, insertionIndex + 2, this.pcToSourceMapSize - insertionIndex); this.pcToSourceMap[insertionIndex++] = startPC; this.pcToSourceMap[insertionIndex] = lineNumber; this.pcToSourceMapSize += 2; } } else if (this.position != this.lastEntryPC) { // no bytecode since last entry pc if (this.lastEntryPC == startPC || this.lastEntryPC == this.pcToSourceMap[this.pcToSourceMapSize - 2]) { this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } else { this.pcToSourceMap[this.pcToSourceMapSize++] = this.lastEntryPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } } else if (this.pcToSourceMap[this.pcToSourceMapSize - 1] < lineNumber && widen) { // see if we can widen the existing entry this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } } else { // we can safely add the new entry. The endPC of the previous entry is not in conflit with the startPC of the new entry. this.pcToSourceMap[this.pcToSourceMapSize++] = startPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } this.lastEntryPC = this.position; return; } else { // since lineSeparatorPositions is zero-based, we pass this.lineNumberStart - 1 and this.lineNumberEnd - 1 lineNumber = Util.getLineNumber(sourcePos, this.lineSeparatorPositions, this.lineNumberStart - 1, this.lineNumberEnd - 1); } } else { // since lineSeparatorPositions is zero-based, we pass this.lineNumberStart - 1 and this.lineNumberEnd - 1 lineNumber = Util.getLineNumber(sourcePos, this.lineSeparatorPositions, this.lineNumberStart - 1, this.lineNumberEnd - 1); } } else if (lineSeparatorPositions2[length - 1] < sourcePos) { lineNumber = length + 1; if (startPC <= this.lastEntryPC) { // we forgot to add an entry. // search if an existing entry exists for startPC int insertionIndex = insertionIndex(this.pcToSourceMap, this.pcToSourceMapSize, startPC); if (insertionIndex != -1) { // there is no existing entry starting with startPC. int existingEntryIndex = indexOfSameLineEntrySincePC(startPC, lineNumber); // index for PC /* the existingEntryIndex corresponds to an entry with the same line and a PC >= startPC. in this case it is relevant to widen this entry instead of creating a new one. line1: this(a, b, c); with this code we generate each argument. We generate a aload0 to invoke the constructor. There is no entry for this aload0 bytecode. The first entry is the one for the argument a. But we want the constructor call to start at the aload0 pc and not just at the pc of the first argument. So we widen the existing entry (if there is one) or we create a new entry with the startPC. */ if (existingEntryIndex != -1) { // widen existing entry this.pcToSourceMap[existingEntryIndex] = startPC; } else if (insertionIndex < 1 || this.pcToSourceMap[insertionIndex - 1] != lineNumber) { // we have to add an entry that won't be sorted. So we sort the pcToSourceMap. System.arraycopy(this.pcToSourceMap, insertionIndex, this.pcToSourceMap, insertionIndex + 2, this.pcToSourceMapSize - insertionIndex); this.pcToSourceMap[insertionIndex++] = startPC; this.pcToSourceMap[insertionIndex] = lineNumber; this.pcToSourceMapSize += 2; } } else if (this.position != this.lastEntryPC) { // no bytecode since last entry pc if (this.lastEntryPC == startPC || this.lastEntryPC == this.pcToSourceMap[this.pcToSourceMapSize - 2]) { this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } else { this.pcToSourceMap[this.pcToSourceMapSize++] = this.lastEntryPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } } else if (this.pcToSourceMap[this.pcToSourceMapSize - 1] < lineNumber && widen) { // see if we can widen the existing entry this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } } else { // we can safely add the new entry. The endPC of the previous entry is not in conflit with the startPC of the new entry. this.pcToSourceMap[this.pcToSourceMapSize++] = startPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } this.lastEntryPC = this.position; return; } else { // since lineSeparatorPositions is zero-based, we pass this.lineNumberStart - 1 and this.lineNumberEnd - 1 lineNumber = Util.getLineNumber(sourcePos, this.lineSeparatorPositions, this.lineNumberStart - 1, this.lineNumberEnd - 1); } } // in this case there is already an entry in the table if (previousLineNumber != lineNumber) { if (startPC <= this.lastEntryPC) { // we forgot to add an entry. // search if an existing entry exists for startPC int insertionIndex = insertionIndex(this.pcToSourceMap, this.pcToSourceMapSize, startPC); if (insertionIndex != -1) { // there is no existing entry starting with startPC. int existingEntryIndex = indexOfSameLineEntrySincePC(startPC, lineNumber); // index for PC /* the existingEntryIndex corresponds to an entry with the same line and a PC >= startPC. in this case it is relevant to widen this entry instead of creating a new one. line1: this(a, b, c); with this code we generate each argument. We generate a aload0 to invoke the constructor. There is no entry for this aload0 bytecode. The first entry is the one for the argument a. But we want the constructor call to start at the aload0 pc and not just at the pc of the first argument. So we widen the existing entry (if there is one) or we create a new entry with the startPC. */ if (existingEntryIndex != -1) { // widen existing entry this.pcToSourceMap[existingEntryIndex] = startPC; } else if (insertionIndex < 1 || this.pcToSourceMap[insertionIndex - 1] != lineNumber) { // we have to add an entry that won't be sorted. So we sort the pcToSourceMap. System.arraycopy(this.pcToSourceMap, insertionIndex, this.pcToSourceMap, insertionIndex + 2, this.pcToSourceMapSize - insertionIndex); this.pcToSourceMap[insertionIndex++] = startPC; this.pcToSourceMap[insertionIndex] = lineNumber; this.pcToSourceMapSize += 2; } } else if (this.position != this.lastEntryPC) { // no bytecode since last entry pc if (this.lastEntryPC == startPC || this.lastEntryPC == this.pcToSourceMap[this.pcToSourceMapSize - 2]) { this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } else { this.pcToSourceMap[this.pcToSourceMapSize++] = this.lastEntryPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } } else if (this.pcToSourceMap[this.pcToSourceMapSize - 1] < lineNumber && widen) { // see if we can widen the existing entry this.pcToSourceMap[this.pcToSourceMapSize - 1] = lineNumber; } } else { // we can safely add the new entry. The endPC of the previous entry is not in conflit with the startPC of the new entry. this.pcToSourceMap[this.pcToSourceMapSize++] = startPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; } } else { /* the last recorded entry is on the same line. But it could be relevant to widen this entry. we want to extend this entry forward in case we generated some bytecode before the last entry that are not related to any statement */ if (startPC < this.pcToSourceMap[this.pcToSourceMapSize - 2]) { int insertionIndex = insertionIndex(this.pcToSourceMap, this.pcToSourceMapSize, startPC); if (insertionIndex != -1) { // widen the existing entry // we have to figure out if we need to move the last entry at another location to keep a sorted table /* First we need to check if at the insertion position there is not an existing entry * that includes the one we want to insert. This is the case if pcToSourceMap[insertionIndex - 1] == newLine. * In this case we don't want to change the table. If not, we want to insert a new entry. Prior to insertion * we want to check if it is worth doing an arraycopy. If not we simply update the recorded pc. */ if (!((insertionIndex > 1) && (this.pcToSourceMap[insertionIndex - 1] == lineNumber))) { if ((this.pcToSourceMapSize > 4) && (this.pcToSourceMap[this.pcToSourceMapSize - 4] > startPC)) { System.arraycopy(this.pcToSourceMap, insertionIndex, this.pcToSourceMap, insertionIndex + 2, this.pcToSourceMapSize - 2 - insertionIndex); this.pcToSourceMap[insertionIndex++] = startPC; this.pcToSourceMap[insertionIndex] = lineNumber; } else { this.pcToSourceMap[this.pcToSourceMapSize - 2] = startPC; } } } } } this.lastEntryPC = this.position; } else { int lineNumber = 0; if (this.lineNumberStart == this.lineNumberEnd) { // method on one line lineNumber = this.lineNumberStart; } else { // since lineSeparatorPositions is zero-based, we pass this.lineNumberStart - 1 and this.lineNumberEnd - 1 lineNumber = Util.getLineNumber(sourcePos, this.lineSeparatorPositions, this.lineNumberStart - 1, this.lineNumberEnd - 1); } // record the first entry this.pcToSourceMap[this.pcToSourceMapSize++] = startPC; this.pcToSourceMap[this.pcToSourceMapSize++] = lineNumber; this.lastEntryPC = this.position; } } /** * @param anExceptionLabel org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel */ public void registerExceptionHandler(ExceptionLabel anExceptionLabel) { int length; if (this.exceptionLabelsCounter == (length = this.exceptionLabels.length)) { // resize the exception handlers table System.arraycopy(this.exceptionLabels, 0, this.exceptionLabels = new ExceptionLabel[length + LABELS_INCREMENT], 0, length); } // no need to resize. So just add the new exception label this.exceptionLabels[this.exceptionLabelsCounter++] = anExceptionLabel; } public void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) { // given some flow info, make sure we did not loose some variables initialization // if this happens, then we must update their pc entries to reflect it in debug attributes if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) == 0) return; for (int i = 0; i < this.visibleLocalsCount; i++) { LocalVariableBinding localBinding = this.visibleLocals[i]; if (localBinding != null && !isDefinitelyAssigned(scope, initStateIndex, localBinding) && localBinding.initializationCount > 0) { localBinding.recordInitializationEndPC(this.position); } } } /** * Remove all entries in pcToSourceMap table that are beyond this.position */ public void removeUnusedPcToSourceMapEntries() { if (this.pcToSourceMapSize != 0) { while (this.pcToSourceMapSize >= 2 && this.pcToSourceMap[this.pcToSourceMapSize - 2] > this.position) { this.pcToSourceMapSize -= 2; } } } public void removeVariable(LocalVariableBinding localBinding) { if (localBinding == null) return; if (localBinding.initializationCount > 0) { localBinding.recordInitializationEndPC(this.position); } for (int i = this.visibleLocalsCount - 1; i >= 0; i--) { LocalVariableBinding visibleLocal = this.visibleLocals[i]; if (visibleLocal == localBinding){ this.visibleLocals[i] = null; // this variable is no longer visible afterwards return; } } } /** * @param referenceMethod org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration * @param targetClassFile org.eclipse.jdt.internal.compiler.codegen.ClassFile */ public void reset(AbstractMethodDeclaration referenceMethod, ClassFile targetClassFile) { init(targetClassFile); this.methodDeclaration = referenceMethod; int[] lineSeparatorPositions2 = this.lineSeparatorPositions; if (lineSeparatorPositions2 != null) { int length = lineSeparatorPositions2.length; int lineSeparatorPositionsEnd = length - 1; if (referenceMethod.isClinit() || referenceMethod.isConstructor()) { this.lineNumberStart = 1; this.lineNumberEnd = length == 0 ? 1 : length; } else { int start = Util.getLineNumber(referenceMethod.bodyStart, lineSeparatorPositions2, 0, lineSeparatorPositionsEnd); this.lineNumberStart = start; if (start > lineSeparatorPositionsEnd) { this.lineNumberEnd = start; } else { int end = Util.getLineNumber(referenceMethod.bodyEnd, lineSeparatorPositions2, start - 1, lineSeparatorPositionsEnd); if (end >= lineSeparatorPositionsEnd) { end = length; } this.lineNumberEnd = end == 0 ? 1 : end; } } } this.preserveUnusedLocals = referenceMethod.scope.compilerOptions().preserveAllLocalVariables; initializeMaxLocals(referenceMethod.binding); } public void reset(ClassFile givenClassFile) { this.targetLevel = givenClassFile.targetJDK; int produceAttributes = givenClassFile.produceAttributes; this.generateAttributes = produceAttributes; if ((produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { this.lineSeparatorPositions = givenClassFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.getLineSeparatorPositions(); } else { this.lineSeparatorPositions = null; } } /** * @param targetClassFile The given classfile to reset the code stream */ public void resetForProblemClinit(ClassFile targetClassFile) { init(targetClassFile); initializeMaxLocals(null); } public void resetInWideMode() { this.wideMode = true; } public void resetForCodeGenUnusedLocals() { // nothing to do in standard code stream } private final void resizeByteArray() { int length = this.bCodeStream.length; int requiredSize = length + length; if (this.classFileOffset >= requiredSize) { // must be sure to grow enough requiredSize = this.classFileOffset + length; } System.arraycopy(this.bCodeStream, 0, this.bCodeStream = new byte[requiredSize], 0, length); } final public void ret(int index) { this.countLabels = 0; if (index > 255) { // Widen if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_wide; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ret; writeUnsignedShort(index); } else { // Don't Widen if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_ret; this.bCodeStream[this.classFileOffset++] = (byte) index; } } public void return_() { this.countLabels = 0; // the stackDepth should be equal to 0 if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_return; this.lastAbruptCompletion = this.position; } public void saload() { this.countLabels = 0; this.stackDepth--; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_saload; } public void sastore() { this.countLabels = 0; this.stackDepth -= 3; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_sastore; } /** * @param operatorConstant int * @param type_ID int */ public void sendOperator(int operatorConstant, int type_ID) { switch (type_ID) { case TypeIds.T_int : case TypeIds.T_boolean : case TypeIds.T_char : case TypeIds.T_byte : case TypeIds.T_short : switch (operatorConstant) { case OperatorIds.PLUS : iadd(); break; case OperatorIds.MINUS : isub(); break; case OperatorIds.MULTIPLY : imul(); break; case OperatorIds.DIVIDE : idiv(); break; case OperatorIds.REMAINDER : irem(); break; case OperatorIds.LEFT_SHIFT : ishl(); break; case OperatorIds.RIGHT_SHIFT : ishr(); break; case OperatorIds.UNSIGNED_RIGHT_SHIFT : iushr(); break; case OperatorIds.AND : iand(); break; case OperatorIds.OR : ior(); break; case OperatorIds.XOR : ixor(); break; } break; case TypeIds.T_long : switch (operatorConstant) { case OperatorIds.PLUS : ladd(); break; case OperatorIds.MINUS : lsub(); break; case OperatorIds.MULTIPLY : lmul(); break; case OperatorIds.DIVIDE : ldiv(); break; case OperatorIds.REMAINDER : lrem(); break; case OperatorIds.LEFT_SHIFT : lshl(); break; case OperatorIds.RIGHT_SHIFT : lshr(); break; case OperatorIds.UNSIGNED_RIGHT_SHIFT : lushr(); break; case OperatorIds.AND : land(); break; case OperatorIds.OR : lor(); break; case OperatorIds.XOR : lxor(); break; } break; case TypeIds.T_float : switch (operatorConstant) { case OperatorIds.PLUS : fadd(); break; case OperatorIds.MINUS : fsub(); break; case OperatorIds.MULTIPLY : fmul(); break; case OperatorIds.DIVIDE : fdiv(); break; case OperatorIds.REMAINDER : frem(); } break; case TypeIds.T_double : switch (operatorConstant) { case OperatorIds.PLUS : dadd(); break; case OperatorIds.MINUS : dsub(); break; case OperatorIds.MULTIPLY : dmul(); break; case OperatorIds.DIVIDE : ddiv(); break; case OperatorIds.REMAINDER : drem(); } } } public void sipush(int s) { this.countLabels = 0; this.stackDepth++; if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_sipush; writeSignedShort(s); } public void store(LocalVariableBinding localBinding, boolean valueRequired) { int localPosition = localBinding.resolvedPosition; // Using dedicated int bytecode switch(localBinding.type.id) { case TypeIds.T_int : case TypeIds.T_char : case TypeIds.T_byte : case TypeIds.T_short : case TypeIds.T_boolean : if (valueRequired) dup(); switch (localPosition) { case 0 : istore_0(); break; case 1 : istore_1(); break; case 2 : istore_2(); break; case 3 : istore_3(); break; //case -1 : // internal failure: trying to store into variable not supposed to be generated // break; default : istore(localPosition); } break; case TypeIds.T_float : if (valueRequired) dup(); switch (localPosition) { case 0 : fstore_0(); break; case 1 : fstore_1(); break; case 2 : fstore_2(); break; case 3 : fstore_3(); break; default : fstore(localPosition); } break; case TypeIds.T_double : if (valueRequired) dup2(); switch (localPosition) { case 0 : dstore_0(); break; case 1 : dstore_1(); break; case 2 : dstore_2(); break; case 3 : dstore_3(); break; default : dstore(localPosition); } break; case TypeIds.T_long : if (valueRequired) dup2(); switch (localPosition) { case 0 : lstore_0(); break; case 1 : lstore_1(); break; case 2 : lstore_2(); break; case 3 : lstore_3(); break; default : lstore(localPosition); } break; default: // Reference object if (valueRequired) dup(); switch (localPosition) { case 0 : astore_0(); break; case 1 : astore_1(); break; case 2 : astore_2(); break; case 3 : astore_3(); break; default : astore(localPosition); } } } public void swap() { this.countLabels = 0; if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_swap; } public void tableswitch(CaseLabel defaultLabel, int low, int high, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) { this.countLabels = 0; this.stackDepth--; int length = casesLabel.length; int pos = this.position; defaultLabel.placeInstruction(); for (int i = 0; i < length; i++) casesLabel[i].placeInstruction(); if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_tableswitch; // padding for (int i = (3 - (pos & 3)); i > 0; i--) { if (this.classFileOffset >= this.bCodeStream.length) { resizeByteArray(); } this.position++; this.bCodeStream[this.classFileOffset++] = 0; } defaultLabel.branch(); writeSignedWord(low); writeSignedWord(high); int i = low, j = low; // the index j is used to know if the index i is one of the missing entries in case of an // optimized tableswitch while (true) { int index; int key = keys[index = sortedIndexes[j - low]]; if (key == i) { casesLabel[index].branch(); j++; if (i == high) break; // if high is maxint, then avoids wrapping to minint. } else { defaultLabel.branch(); } i++; } } public void throwAnyException(LocalVariableBinding anyExceptionVariable) { this.load(anyExceptionVariable); athrow(); } public String toString() { StringBuffer buffer = new StringBuffer("( position:"); //$NON-NLS-1$ buffer.append(this.position); buffer.append(",\nstackDepth:"); //$NON-NLS-1$ buffer.append(this.stackDepth); buffer.append(",\nmaxStack:"); //$NON-NLS-1$ buffer.append(this.stackMax); buffer.append(",\nmaxLocals:"); //$NON-NLS-1$ buffer.append(this.maxLocals); buffer.append(")"); //$NON-NLS-1$ return buffer.toString(); } protected void writePosition(BranchLabel label) { int offset = label.position - this.position + 1; if (Math.abs(offset) > 0x7FFF && !this.wideMode) { throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE, null); } this.writeSignedShort(offset); int[] forwardRefs = label.forwardReferences(); for (int i = 0, max = label.forwardReferenceCount(); i < max; i++) { this.writePosition(label, forwardRefs[i]); } } protected void writePosition(BranchLabel label, int forwardReference) { final int offset = label.position - forwardReference + 1; if (Math.abs(offset) > 0x7FFF && !this.wideMode) { throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE, null); } if (this.wideMode) { if ((label.tagBits & BranchLabel.WIDE) != 0) { this.writeSignedWord(forwardReference, offset); } else { this.writeSignedShort(forwardReference, offset); } } else { this.writeSignedShort(forwardReference, offset); } } /** * Write a signed 16 bits value into the byte array * @param value the signed short */ private final void writeSignedShort(int value) { // we keep the resize in here because it is used outside the code stream if (this.classFileOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 2; this.bCodeStream[this.classFileOffset++] = (byte) (value >> 8); this.bCodeStream[this.classFileOffset++] = (byte) value; } private final void writeSignedShort(int pos, int value) { int currentOffset = this.startingClassFileOffset + pos; if (currentOffset + 1 >= this.bCodeStream.length) { resizeByteArray(); } this.bCodeStream[currentOffset] = (byte) (value >> 8); this.bCodeStream[currentOffset + 1] = (byte) value; } protected final void writeSignedWord(int value) { // we keep the resize in here because it is used outside the code stream if (this.classFileOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.position += 4; this.bCodeStream[this.classFileOffset++] = (byte) ((value & 0xFF000000) >> 24); this.bCodeStream[this.classFileOffset++] = (byte) ((value & 0xFF0000) >> 16); this.bCodeStream[this.classFileOffset++] = (byte) ((value & 0xFF00) >> 8); this.bCodeStream[this.classFileOffset++] = (byte) (value & 0xFF); } protected void writeSignedWord(int pos, int value) { int currentOffset = this.startingClassFileOffset + pos; if (currentOffset + 3 >= this.bCodeStream.length) { resizeByteArray(); } this.bCodeStream[currentOffset++] = (byte) ((value & 0xFF000000) >> 24); this.bCodeStream[currentOffset++] = (byte) ((value & 0xFF0000) >> 16); this.bCodeStream[currentOffset++] = (byte) ((value & 0xFF00) >> 8); this.bCodeStream[currentOffset++] = (byte) (value & 0xFF); } /** * Write a unsigned 16 bits value into the byte array * @param value the unsigned short */ private final void writeUnsignedShort(int value) { // no bound check since used only from within codestream where already checked this.position += 2; this.bCodeStream[this.classFileOffset++] = (byte) (value >>> 8); this.bCodeStream[this.classFileOffset++] = (byte) value; } protected void writeWidePosition(BranchLabel label) { int labelPos = label.position; int offset = labelPos - this.position + 1; this.writeSignedWord(offset); int[] forwardRefs = label.forwardReferences(); for (int i = 0, max = label.forwardReferenceCount(); i < max; i++) { int forward = forwardRefs[i]; offset = labelPos - forward + 1; this.writeSignedWord(forward, offset); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/IntegerCache.java0000644000175000001440000001212112212041344031047 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public class IntegerCache { public int keyTable[]; public int valueTable[]; int elementSize; int threshold; /** * Constructs a new, empty hashtable. A default capacity and * load factor is used. Note that the hashtable will automatically * grow when it gets full. */ public IntegerCache() { this(13); } /** * Constructs a new, empty hashtable with the specified initial * capacity. * @param initialCapacity int * the initial number of buckets */ public IntegerCache(int initialCapacity) { this.elementSize = 0; this.threshold = (int) (initialCapacity * 0.66); this.keyTable = new int[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 = this.keyTable.length; --i >= 0;) { this.keyTable[i] = 0; this.valueTable[i] = 0; } this.elementSize = 0; } /** Returns true if the collection contains an element for the key. * * @param key double the key that we are looking for * @return boolean */ public boolean containsKey(int key) { int index = hash(key), length = this.keyTable.length; while ((this.keyTable[index] != 0) || ((this.keyTable[index] == 0) &&(this.valueTable[index] != 0))) { if (this.keyTable[index] == key) return true; if (++index == length) { index = 0; } } return false; } /** * Return a hashcode for the value of the key parameter. * @param key int * @return int the hash code corresponding to the key value */ public int hash(int key) { return (key & 0x7FFFFFFF) % this.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. * * @param key int the specified key in the hashtable * @param value int the specified element * @return int value */ public int put(int key, int value) { int index = hash(key), length = this.keyTable.length; while ((this.keyTable[index] != 0) || ((this.keyTable[index] == 0) && (this.valueTable[index] != 0))) { if (this.keyTable[index] == key) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) { rehash(); } return value; } /** * Puts the specified element into the hashtable if absent, using the specified * key. The element may be retrieved by doing a get() with the same key. * * @param key int the specified key in the hashtable * @param value int the specified element * @return int value */ public int putIfAbsent(int key, int value) { int index = hash(key), length = this.keyTable.length; while ((this.keyTable[index] != 0) || ((this.keyTable[index] == 0) && (this.valueTable[index] != 0))) { if (this.keyTable[index] == key) return this.valueTable[index]; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) { rehash(); } return -value; // negative when added, assumes value is > 0 } /** * 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() { IntegerCache newHashtable = new IntegerCache(this.keyTable.length * 2); for (int i = this.keyTable.length; --i >= 0;) { int key = this.keyTable[i]; int value = this.valueTable[i]; if ((key != 0) || ((key == 0) && (value != 0))) { newHashtable.put(key, value); } } 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 this.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 ((this.keyTable[i] != 0) || ((this.keyTable[i] == 0) && (this.valueTable[i] != 0))) { buf.append(this.keyTable[i]).append("->").append(this.valueTable[i]); //$NON-NLS-1$ } if (i < max) { buf.append(", "); //$NON-NLS-1$ } } buf.append("}"); //$NON-NLS-1$ return buf.toString(); } } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/VerificationTypeInfo.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/VerificationTypeInfo.ja0000644000175000001440000001515412212041344032310 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public class VerificationTypeInfo { /** * The tag value representing top variable info * @since 3.2 */ public static final int ITEM_TOP = 0; /** * The tag value representing integer variable info * @since 3.2 */ public static final int ITEM_INTEGER = 1; /** * The tag value representing float variable info * @since 3.2 */ public static final int ITEM_FLOAT = 2; /** * The tag value representing double variable info * @since 3.2 */ public static final int ITEM_DOUBLE = 3; /** * The tag value representing long variable info * @since 3.2 */ public static final int ITEM_LONG = 4; /** * The tag value representing null variable info * @since 3.2 */ public static final int ITEM_NULL = 5; /** * The tag value representing uninitialized this variable info * @since 3.2 */ public static final int ITEM_UNINITIALIZED_THIS = 6; /** * The tag value representing object variable info * @since 3.2 */ public static final int ITEM_OBJECT = 7; /** * The tag value representing uninitialized variable info * @since 3.2 */ public static final int ITEM_UNINITIALIZED = 8; public int tag; private int id; private char[] constantPoolName; public int offset; private VerificationTypeInfo() { // for duplication } public VerificationTypeInfo(int id, char[] constantPoolName) { this(id, VerificationTypeInfo.ITEM_OBJECT, constantPoolName); } public VerificationTypeInfo(int id, int tag, char[] constantPoolName) { this.id = id; this.tag = tag; this.constantPoolName = constantPoolName; } public VerificationTypeInfo(int tag, TypeBinding binding) { this(binding); this.tag = tag; } public VerificationTypeInfo(TypeBinding binding) { this.id = binding.id; switch(binding.id) { case TypeIds.T_boolean : case TypeIds.T_byte : case TypeIds.T_char : case TypeIds.T_int : case TypeIds.T_short : this.tag = VerificationTypeInfo.ITEM_INTEGER; break; case TypeIds.T_float : this.tag = VerificationTypeInfo.ITEM_FLOAT; break; case TypeIds.T_long : this.tag = VerificationTypeInfo.ITEM_LONG; break; case TypeIds.T_double : this.tag = VerificationTypeInfo.ITEM_DOUBLE; break; case TypeIds.T_null : this.tag = VerificationTypeInfo.ITEM_NULL; break; default: this.tag = VerificationTypeInfo.ITEM_OBJECT; this.constantPoolName = binding.constantPoolName(); } } public void setBinding(TypeBinding binding) { this.constantPoolName = binding.constantPoolName(); final int typeBindingId = binding.id; this.id = typeBindingId; switch(typeBindingId) { case TypeIds.T_boolean : case TypeIds.T_byte : case TypeIds.T_char : case TypeIds.T_int : case TypeIds.T_short : this.tag = VerificationTypeInfo.ITEM_INTEGER; break; case TypeIds.T_float : this.tag = VerificationTypeInfo.ITEM_FLOAT; break; case TypeIds.T_long : this.tag = VerificationTypeInfo.ITEM_LONG; break; case TypeIds.T_double : this.tag = VerificationTypeInfo.ITEM_DOUBLE; break; case TypeIds.T_null : this.tag = VerificationTypeInfo.ITEM_NULL; break; default: this.tag = VerificationTypeInfo.ITEM_OBJECT; } } public int id() { return this.id; } public String toString() { StringBuffer buffer = new StringBuffer(); switch(this.tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED_THIS : buffer.append("uninitialized_this(").append(readableName()).append(")"); //$NON-NLS-1$//$NON-NLS-2$ break; case VerificationTypeInfo.ITEM_UNINITIALIZED : buffer.append("uninitialized(").append(readableName()).append(")"); //$NON-NLS-1$//$NON-NLS-2$ break; case VerificationTypeInfo.ITEM_OBJECT : buffer.append(readableName()); break; case VerificationTypeInfo.ITEM_DOUBLE : buffer.append('D'); break; case VerificationTypeInfo.ITEM_FLOAT : buffer.append('F'); break; case VerificationTypeInfo.ITEM_INTEGER : buffer.append('I'); break; case VerificationTypeInfo.ITEM_LONG : buffer.append('J'); break; case VerificationTypeInfo.ITEM_NULL : buffer.append("null"); //$NON-NLS-1$ break; case VerificationTypeInfo.ITEM_TOP : buffer.append("top"); //$NON-NLS-1$ break; } return String.valueOf(buffer); } public VerificationTypeInfo duplicate() { final VerificationTypeInfo verificationTypeInfo = new VerificationTypeInfo(); verificationTypeInfo.id = this.id; verificationTypeInfo.tag = this.tag; verificationTypeInfo.constantPoolName = this.constantPoolName; verificationTypeInfo.offset = this.offset; return verificationTypeInfo; } public boolean equals(Object obj) { if (obj instanceof VerificationTypeInfo) { VerificationTypeInfo info1 = (VerificationTypeInfo) obj; return info1.tag == this.tag && CharOperation.equals(info1.constantPoolName(), constantPoolName()); } return false; } public int hashCode() { return this.tag + this.id + this.constantPoolName.length + this.offset; } public char[] constantPoolName() { return this.constantPoolName; } public char[] readableName() { return this.constantPoolName; } public void replaceWithElementType() { if (this.constantPoolName[1] == 'L') { this.constantPoolName = CharOperation.subarray(this.constantPoolName, 2, this.constantPoolName.length - 1); } else { this.constantPoolName = CharOperation.subarray(this.constantPoolName, 1, this.constantPoolName.length); if (this.constantPoolName.length == 1) { switch(this.constantPoolName[0]) { case 'I' : this.id = TypeIds.T_int; break; case 'B' : this.id = TypeIds.T_byte; break; case 'S' : this.id = TypeIds.T_short; break; case 'C' : this.id = TypeIds.T_char; break; case 'J' : this.id = TypeIds.T_long; break; case 'F' : this.id = TypeIds.T_float; break; case 'D' : this.id = TypeIds.T_double; break; case 'Z' : this.id = TypeIds.T_boolean; break; case 'N' : this.id = TypeIds.T_null; break; case 'V' : this.id = TypeIds.T_void; break; } } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/StackMapFrame.java0000644000175000001440000003002012212041344031202 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; import java.text.MessageFormat; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public class StackMapFrame { public static final int USED = 1; public static final int SAME_FRAME = 0; public static final int CHOP_FRAME = 1; public static final int APPEND_FRAME = 2; public static final int SAME_FRAME_EXTENDED = 3; public static final int FULL_FRAME = 4; public static final int SAME_LOCALS_1_STACK_ITEMS = 5; public static final int SAME_LOCALS_1_STACK_ITEMS_EXTENDED = 6; public int pc; public int numberOfStackItems; private int numberOfLocals; public int localIndex; public VerificationTypeInfo[] locals; public VerificationTypeInfo[] stackItems; private int numberOfDifferentLocals = -1; public int tagBits; public StackMapFrame(int initialLocalSize) { this.locals = new VerificationTypeInfo[initialLocalSize]; this.numberOfLocals = -1; this.numberOfDifferentLocals = -1; } public int getFrameType(StackMapFrame prevFrame) { final int offsetDelta = getOffsetDelta(prevFrame); switch(this.numberOfStackItems) { case 0 : switch(numberOfDifferentLocals(prevFrame)) { case 0 : return offsetDelta <= 63 ? SAME_FRAME : SAME_FRAME_EXTENDED; case 1 : case 2 : case 3 : return APPEND_FRAME; case -1 : case -2 : case -3 : return CHOP_FRAME; } break; case 1 : switch(numberOfDifferentLocals(prevFrame)) { case 0 : return offsetDelta <= 63 ? SAME_LOCALS_1_STACK_ITEMS : SAME_LOCALS_1_STACK_ITEMS_EXTENDED; } } return FULL_FRAME; } public void addLocal(int resolvedPosition, VerificationTypeInfo info) { if (this.locals == null) { this.locals = new VerificationTypeInfo[resolvedPosition + 1]; this.locals[resolvedPosition] = info; } else { final int length = this.locals.length; if (resolvedPosition >= length) { System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length); } this.locals[resolvedPosition] = info; } } public void addStackItem(VerificationTypeInfo info) { if (info == null) { throw new IllegalArgumentException("info cannot be null"); //$NON-NLS-1$ } if (this.stackItems == null) { this.stackItems = new VerificationTypeInfo[1]; this.stackItems[0] = info; this.numberOfStackItems = 1; } else { final int length = this.stackItems.length; if (this.numberOfStackItems == length) { System.arraycopy(this.stackItems, 0, this.stackItems = new VerificationTypeInfo[length + 1], 0, length); } this.stackItems[this.numberOfStackItems++] = info; } } public void addStackItem(TypeBinding binding) { if (this.stackItems == null) { this.stackItems = new VerificationTypeInfo[1]; this.stackItems[0] = new VerificationTypeInfo(binding); this.numberOfStackItems = 1; } else { final int length = this.stackItems.length; if (this.numberOfStackItems == length) { System.arraycopy(this.stackItems, 0, this.stackItems = new VerificationTypeInfo[length + 1], 0, length); } this.stackItems[this.numberOfStackItems++] = new VerificationTypeInfo(binding); } } public StackMapFrame duplicate() { int length = this.locals.length; StackMapFrame result = new StackMapFrame(length); result.numberOfLocals = -1; result.numberOfDifferentLocals = -1; result.pc = this.pc; result.numberOfStackItems = this.numberOfStackItems; if (length != 0) { result.locals = new VerificationTypeInfo[length]; for (int i = 0; i < length; i++) { final VerificationTypeInfo verificationTypeInfo = this.locals[i]; if (verificationTypeInfo != null) { result.locals[i] = verificationTypeInfo.duplicate(); } } } length = this.numberOfStackItems; if (length != 0) { result.stackItems = new VerificationTypeInfo[length]; for (int i = 0; i < length; i++) { result.stackItems[i] = this.stackItems[i].duplicate(); } } return result; } public int numberOfDifferentLocals(StackMapFrame prevFrame) { if (this.numberOfDifferentLocals != -1) return this.numberOfDifferentLocals; if (prevFrame == null) { this.numberOfDifferentLocals = 0; return 0; } VerificationTypeInfo[] prevLocals = prevFrame.locals; VerificationTypeInfo[] currentLocals = this.locals; int prevLocalsLength = prevLocals == null ? 0 : prevLocals.length; int currentLocalsLength = currentLocals == null ? 0 : currentLocals.length; int prevNumberOfLocals = prevFrame.getNumberOfLocals(); int currentNumberOfLocals = getNumberOfLocals(); int result = 0; if (prevNumberOfLocals == 0) { if (currentNumberOfLocals != 0) { // need to check if there is a hole in the locals result = currentNumberOfLocals; // append if no hole and currentNumberOfLocals <= 3 int counter = 0; for(int i = 0; i < currentLocalsLength && counter < currentNumberOfLocals; i++) { if (currentLocals[i] != null) { switch(currentLocals[i].id()) { case TypeIds.T_double : case TypeIds.T_long : i++; } counter++; } else { result = Integer.MAX_VALUE; this.numberOfDifferentLocals = result; return result; } } } } else if (currentNumberOfLocals == 0) { // need to check if there is a hole in the prev locals int counter = 0; result = -prevNumberOfLocals; // chop frame if no hole and prevNumberOfLocals <= 3 for(int i = 0; i < prevLocalsLength && counter < prevNumberOfLocals; i++) { if (prevLocals[i] != null) { switch(prevLocals[i].id()) { case TypeIds.T_double : case TypeIds.T_long : i++; } counter++; } else { result = Integer.MAX_VALUE; this.numberOfDifferentLocals = result; return result; } } } else { // need to see if prevLocals matches with currentLocals int indexInPrevLocals = 0; int indexInCurrentLocals = 0; int currentLocalsCounter = 0; int prevLocalsCounter = 0; currentLocalsLoop: for (;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) { VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals]; if (currentLocal != null) { currentLocalsCounter++; switch(currentLocal.id()) { case TypeIds.T_double : case TypeIds.T_long : indexInCurrentLocals++; // next entry is null } } if (indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals) { VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals]; if (prevLocal != null) { prevLocalsCounter++; switch(prevLocal.id()) { case TypeIds.T_double : case TypeIds.T_long : indexInPrevLocals++; // next entry is null } } // now we need to check if prevLocal matches with currentLocal // the index must be the same if (equals(prevLocal, currentLocal) && indexInPrevLocals == indexInCurrentLocals) { if (result != 0) { result = Integer.MAX_VALUE; this.numberOfDifferentLocals = result; return result; } } else { // locals at the same location are not equals - this has to be a full frame result = Integer.MAX_VALUE; this.numberOfDifferentLocals = result; return result; } indexInPrevLocals++; continue currentLocalsLoop; } // process remaining current locals if (currentLocal != null) { result++; } else { result = Integer.MAX_VALUE; this.numberOfDifferentLocals = result; return result; } indexInCurrentLocals++; break currentLocalsLoop; } if (currentLocalsCounter < currentNumberOfLocals) { for(;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) { VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals]; if (currentLocal == null) { result = Integer.MAX_VALUE; this.numberOfDifferentLocals = result; return result; } result++; currentLocalsCounter++; switch(currentLocal.id()) { case TypeIds.T_double : case TypeIds.T_long : indexInCurrentLocals++; // next entry is null } } } else if (prevLocalsCounter < prevNumberOfLocals) { result = -result; // process possible remaining prev locals for(; indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals; indexInPrevLocals++) { VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals]; if (prevLocal == null) { result = Integer.MAX_VALUE; this.numberOfDifferentLocals = result; return result; } result--; prevLocalsCounter++; switch(prevLocal.id()) { case TypeIds.T_double : case TypeIds.T_long : indexInPrevLocals++; // next entry is null } } } } this.numberOfDifferentLocals = result; return result; } public int getNumberOfLocals() { if (this.numberOfLocals != -1) { return this.numberOfLocals; } int result = 0; final int length = this.locals == null ? 0 : this.locals.length; for(int i = 0; i < length; i++) { if (this.locals[i] != null) { switch(this.locals[i].id()) { case TypeIds.T_double : case TypeIds.T_long : i++; } result++; } } this.numberOfLocals = result; return result; } public int getOffsetDelta(StackMapFrame prevFrame) { if (prevFrame == null) return this.pc; return prevFrame.pc == -1 ? this.pc : this.pc - prevFrame.pc - 1; } public String toString() { StringBuffer buffer = new StringBuffer(); printFrame(buffer, this); return String.valueOf(buffer); } private void printFrame(StringBuffer buffer, StackMapFrame frame) { String pattern = "[pc : {0} locals: {1} stack items: {2}\nlocals: {3}\nstack: {4}\n]"; //$NON-NLS-1$ int localsLength = frame.locals == null ? 0 : frame.locals.length; buffer.append(MessageFormat.format( pattern, new String[] { Integer.toString(frame.pc), Integer.toString(frame.getNumberOfLocals()), Integer.toString(frame.numberOfStackItems), print(frame.locals, localsLength), print(frame.stackItems, frame.numberOfStackItems) } )); } private String print(VerificationTypeInfo[] infos, int length) { StringBuffer buffer = new StringBuffer(); buffer.append('['); if (infos != null) { for (int i = 0; i < length; i++) { if (i != 0) buffer.append(','); VerificationTypeInfo verificationTypeInfo = infos[i]; if (verificationTypeInfo == null) { buffer.append("top"); //$NON-NLS-1$ continue; } buffer.append(verificationTypeInfo); } } buffer.append(']'); return String.valueOf(buffer); } public void putLocal(int resolvedPosition, VerificationTypeInfo info) { if (this.locals == null) { this.locals = new VerificationTypeInfo[resolvedPosition + 1]; this.locals[resolvedPosition] = info; } else { final int length = this.locals.length; if (resolvedPosition >= length) { System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length); } this.locals[resolvedPosition] = info; } } public void replaceWithElementType() { VerificationTypeInfo info = this.stackItems[this.numberOfStackItems - 1]; VerificationTypeInfo info2 = info.duplicate(); info2.replaceWithElementType(); this.stackItems[this.numberOfStackItems - 1] = info2; } public int getIndexOfDifferentLocals(int differentLocalsCount) { for (int i = this.locals.length - 1; i >= 0; i--) { VerificationTypeInfo currentLocal = this.locals[i]; if (currentLocal == null) { // check the previous slot continue; } else { differentLocalsCount--; } if (differentLocalsCount == 0) { return i; } } return 0; } private boolean equals(VerificationTypeInfo info, VerificationTypeInfo info2) { if (info == null) { return info2 == null; } if (info2 == null) return false; return info.equals(info2); } } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream0000644000175000001440000004727612212041344032256 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; public class StackMapFrameCodeStream extends CodeStream { public static class ExceptionMarker implements Comparable { public char[] constantPoolName; public int pc; public ExceptionMarker(int pc, char[] constantPoolName) { this.pc = pc; this.constantPoolName = constantPoolName; } public int compareTo(Object o) { if (o instanceof ExceptionMarker) { return this.pc - ((ExceptionMarker) o).pc; } return 0; } public boolean equals(Object obj) { if (obj instanceof ExceptionMarker) { ExceptionMarker marker = (ExceptionMarker) obj; return this.pc == marker.pc && CharOperation.equals(this.constantPoolName, marker.constantPoolName); } return false; } public int hashCode() { return this.pc + this.constantPoolName.hashCode(); } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append('(').append(this.pc).append(',').append(this.constantPoolName).append(')'); return String.valueOf(buffer); } } public static class StackDepthMarker { public int pc; public int delta; public TypeBinding typeBinding; public StackDepthMarker(int pc, int delta, TypeBinding typeBinding) { this.pc = pc; this.typeBinding = typeBinding; this.delta = delta; } public StackDepthMarker(int pc, int delta) { this.pc = pc; this.delta = delta; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append('(').append(this.pc).append(',').append(this.delta); if (this.typeBinding != null) { buffer .append(',') .append(this.typeBinding.qualifiedPackageName()) .append(this.typeBinding.qualifiedSourceName()); } buffer.append(')'); return String.valueOf(buffer); } } public static class StackMarker { public int pc; public int destinationPC; public VerificationTypeInfo[] infos; public StackMarker(int pc, int destinationPC) { this.pc = pc; this.destinationPC = destinationPC; } public void setInfos(VerificationTypeInfo[] infos) { this.infos = infos; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer .append("[copy stack items from ") //$NON-NLS-1$ .append(this.pc) .append(" to ") //$NON-NLS-1$ .append(this.destinationPC); if (this.infos!= null) { for (int i = 0, max = this.infos.length; i < max; i++) { if (i > 0) buffer.append(','); buffer.append(this.infos[i]); } } buffer.append(']'); return String.valueOf(buffer); } } static class FramePosition { int counter; } public int[] stateIndexes; public int stateIndexesCounter; private HashMap framePositions; public Set exceptionMarkers; public ArrayList stackDepthMarkers; public ArrayList stackMarkers; public StackMapFrameCodeStream(ClassFile givenClassFile) { super(givenClassFile); this.generateAttributes |= ClassFileConstants.ATTR_STACK_MAP; } public void addDefinitelyAssignedVariables(Scope scope, int initStateIndex) { // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect loop: for (int i = 0; i < this.visibleLocalsCount; i++) { LocalVariableBinding localBinding = this.visibleLocals[i]; if (localBinding != null) { // Check if the local is definitely assigned boolean isDefinitelyAssigned = isDefinitelyAssigned(scope, initStateIndex, localBinding); if (!isDefinitelyAssigned) { if (this.stateIndexes != null) { for (int j = 0, max = this.stateIndexesCounter; j < max; j++) { if (isDefinitelyAssigned(scope, this.stateIndexes[j], localBinding)) { if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) { /* There are two cases: * 1) there is no initialization interval opened ==> add an opened interval * 2) there is already some initialization intervals but the last one is closed ==> add an opened interval * An opened interval means that the value at localBinding.initializationPCs[localBinding.initializationCount - 1][1] * is equals to -1. * initializationPCs is a collection of pairs of int: * first value is the startPC and second value is the endPC. -1 one for the last value means that the interval * is not closed yet. */ localBinding.recordInitializationStartPC(this.position); } continue loop; } } } } else { if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) { /* There are two cases: * 1) there is no initialization interval opened ==> add an opened interval * 2) there is already some initialization intervals but the last one is closed ==> add an opened interval * An opened interval means that the value at localBinding.initializationPCs[localBinding.initializationCount - 1][1] * is equals to -1. * initializationPCs is a collection of pairs of int: * first value is the startPC and second value is the endPC. -1 one for the last value means that the interval * is not closed yet. */ localBinding.recordInitializationStartPC(this.position); } } } } } public void addExceptionMarker(int pc, TypeBinding typeBinding) { if (this.exceptionMarkers == null) { this.exceptionMarkers = new HashSet(); } if (typeBinding == null) { this.exceptionMarkers.add(new ExceptionMarker(pc, ConstantPool.JavaLangThrowableConstantPoolName)); } else { switch(typeBinding.id) { case TypeIds.T_null : this.exceptionMarkers.add(new ExceptionMarker(pc, ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName)); break; case TypeIds.T_long : this.exceptionMarkers.add(new ExceptionMarker(pc, ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName)); break; default: this.exceptionMarkers.add(new ExceptionMarker(pc, typeBinding.constantPoolName())); } } } public void addFramePosition(int pc) { Integer newEntry = new Integer(pc); FramePosition value; if ((value = (FramePosition) this.framePositions.get(newEntry)) != null) { value.counter++; } else { this.framePositions.put(newEntry, new FramePosition()); } } public void optimizeBranch(int oldPosition, BranchLabel lbl) { super.optimizeBranch(oldPosition, lbl); removeFramePosition(oldPosition); } public void removeFramePosition(int pc) { Integer entry = new Integer(pc); FramePosition value; if ((value = (FramePosition) this.framePositions.get(entry)) != null) { value.counter--; if (value.counter <= 0) { this.framePositions.remove(entry); } } } public void addVariable(LocalVariableBinding localBinding) { if (localBinding.initializationPCs == null) { record(localBinding); } localBinding.recordInitializationStartPC(this.position); } private void addStackMarker(int pc, int destinationPC) { if (this.stackMarkers == null) { this.stackMarkers = new ArrayList(); this.stackMarkers.add(new StackMarker(pc, destinationPC)); } else { int size = this.stackMarkers.size(); if (size == 0 || ((StackMarker) this.stackMarkers.get(size - 1)).pc != this.position) { this.stackMarkers.add(new StackMarker(pc, destinationPC)); } } } private void addStackDepthMarker(int pc, int delta, TypeBinding typeBinding) { if (this.stackDepthMarkers == null) { this.stackDepthMarkers = new ArrayList(); this.stackDepthMarkers.add(new StackDepthMarker(pc, delta, typeBinding)); } else { int size = this.stackDepthMarkers.size(); if (size == 0) { this.stackDepthMarkers.add(new StackDepthMarker(pc, delta, typeBinding)); } else { StackDepthMarker stackDepthMarker = (StackDepthMarker) this.stackDepthMarkers.get(size - 1); if (stackDepthMarker.pc != this.position) { this.stackDepthMarkers.add(new StackDepthMarker(pc, delta, typeBinding)); } else { // We replace the recorded stack depth marker with a new value that contains the given typeBinding // This case can happen when multiple conditional expression are nested see bug 362591 this.stackDepthMarkers.set(size - 1, new StackDepthMarker(pc, delta, typeBinding)); } } } } public void decrStackSize(int offset) { super.decrStackSize(offset); addStackDepthMarker(this.position, -1, null); } public void recordExpressionType(TypeBinding typeBinding) { addStackDepthMarker(this.position, 0, typeBinding); } /** * Macro for building a class descriptor object */ public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBinding syntheticFieldBinding) { if (accessedType.isBaseType() && accessedType != TypeBinding.NULL) { getTYPE(accessedType.id); return; } if (this.targetLevel >= ClassFileConstants.JDK1_5) { // generation using the new ldc_w bytecode this.ldc(accessedType); } else { // use in CLDC mode BranchLabel endLabel = new BranchLabel(this); if (syntheticFieldBinding != null) { // non interface case fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); dup(); ifnonnull(endLabel); 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 ExceptionLabel classNotFoundExceptionHandler = new ExceptionLabel(this, TypeBinding.NULL /*represents ClassNotFoundException*/); classNotFoundExceptionHandler.placeStart(); this.ldc(accessedType == TypeBinding.NULL ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$ 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. */ classNotFoundExceptionHandler.placeEnd(); if (syntheticFieldBinding != null) { // non interface case dup(); fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); } int fromPC = this.position; goto_(endLabel); int savedStackDepth = this.stackDepth; // Generate the body of the exception handler /* 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. */ pushExceptionOnStack(TypeBinding.NULL);/*represents ClassNotFoundException*/ classNotFoundExceptionHandler.place(); // Transform the current exception, and repush and throw a // NoClassDefFoundError(ClassNotFound.getMessage()) newNoClassDefFoundError(); dup_x1(); swap(); // Retrieve the message from the old exception invokeThrowableGetMessage(); // Send the constructor taking a message string as an argument invokeNoClassDefFoundErrorStringConstructor(); athrow(); endLabel.place(); addStackMarker(fromPC, this.position); this.stackDepth = savedStackDepth; } } public void generateOuterAccess(Object[] mappingSequence, ASTNode invocationSite, Binding target, Scope scope) { int currentPosition = this.position; super.generateOuterAccess(mappingSequence, invocationSite, target, scope); if (currentPosition == this.position) { // no code has been generate during outer access => no enclosing instance is available throw new AbortMethod(scope.referenceCompilationUnit().compilationResult, null); } } public ExceptionMarker[] getExceptionMarkers() { Set exceptionMarkerSet = this.exceptionMarkers; if (this.exceptionMarkers == null) return null; int size = exceptionMarkerSet.size(); ExceptionMarker[] markers = new ExceptionMarker[size]; int n = 0; for (Iterator iterator = exceptionMarkerSet.iterator(); iterator.hasNext(); ) { markers[n++] = (ExceptionMarker) iterator.next(); } Arrays.sort(markers); // System.out.print('['); // for (int n = 0; n < size; n++) { // if (n != 0) System.out.print(','); // System.out.print(positions[n]); // } // System.out.println(']'); return markers; } public int[] getFramePositions() { Set set = this.framePositions.keySet(); int size = set.size(); int[] positions = new int[size]; int n = 0; for (Iterator iterator = set.iterator(); iterator.hasNext(); ) { positions[n++] = ((Integer) iterator.next()).intValue(); } Arrays.sort(positions); // System.out.print('['); // for (int n = 0; n < size; n++) { // if (n != 0) System.out.print(','); // System.out.print(positions[n]); // } // System.out.println(']'); return positions; } public StackDepthMarker[] getStackDepthMarkers() { if (this.stackDepthMarkers == null) return null; int length = this.stackDepthMarkers.size(); if (length == 0) return null; StackDepthMarker[] result = new StackDepthMarker[length]; this.stackDepthMarkers.toArray(result); return result; } public StackMarker[] getStackMarkers() { if (this.stackMarkers == null) return null; int length = this.stackMarkers.size(); if (length == 0) return null; StackMarker[] result = new StackMarker[length]; this.stackMarkers.toArray(result); return result; } public boolean hasFramePositions() { return this.framePositions.size() != 0; } public void init(ClassFile targetClassFile) { super.init(targetClassFile); this.stateIndexesCounter = 0; if (this.framePositions != null) { this.framePositions.clear(); } if (this.exceptionMarkers != null) { this.exceptionMarkers.clear(); } if (this.stackDepthMarkers != null) { this.stackDepthMarkers.clear(); } if (this.stackMarkers != null) { this.stackMarkers.clear(); } } public void initializeMaxLocals(MethodBinding methodBinding) { super.initializeMaxLocals(methodBinding); if (this.framePositions == null) { this.framePositions = new HashMap(); } else { this.framePositions.clear(); } } public void popStateIndex() { this.stateIndexesCounter--; } public void pushStateIndex(int naturalExitMergeInitStateIndex) { if (this.stateIndexes == null) { this.stateIndexes = new int[3]; } int length = this.stateIndexes.length; if (length == this.stateIndexesCounter) { // resize System.arraycopy(this.stateIndexes, 0, (this.stateIndexes = new int[length * 2]), 0, length); } this.stateIndexes[this.stateIndexesCounter++] = naturalExitMergeInitStateIndex; } public void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) { int index = this.visibleLocalsCount; loop : for (int i = 0; i < index; i++) { LocalVariableBinding localBinding = this.visibleLocals[i]; if (localBinding != null && localBinding.initializationCount > 0) { boolean isDefinitelyAssigned = isDefinitelyAssigned(scope, initStateIndex, localBinding); if (!isDefinitelyAssigned) { if (this.stateIndexes != null) { for (int j = 0, max = this.stateIndexesCounter; j < max; j++) { if (isDefinitelyAssigned(scope, this.stateIndexes[j], localBinding)) { continue loop; } } } localBinding.recordInitializationEndPC(this.position); } } } } public void reset(ClassFile givenClassFile) { super.reset(givenClassFile); this.stateIndexesCounter = 0; if (this.framePositions != null) { this.framePositions.clear(); } if (this.exceptionMarkers != null) { this.exceptionMarkers.clear(); } if (this.stackDepthMarkers != null) { this.stackDepthMarkers.clear(); } if (this.stackMarkers != null) { this.stackMarkers.clear(); } } protected void writePosition(BranchLabel label) { super.writePosition(label); addFramePosition(label.position); } protected void writePosition(BranchLabel label, int forwardReference) { super.writePosition(label, forwardReference); addFramePosition(label.position); } protected void writeSignedWord(int pos, int value) { super.writeSignedWord(pos, value); addFramePosition(this.position); } protected void writeWidePosition(BranchLabel label) { super.writeWidePosition(label); addFramePosition(label.position); } public void areturn() { super.areturn(); addFramePosition(this.position); } public void ireturn() { super.ireturn(); addFramePosition(this.position); } public void lreturn() { super.lreturn(); addFramePosition(this.position); } public void freturn() { super.freturn(); addFramePosition(this.position); } public void dreturn() { super.dreturn(); addFramePosition(this.position); } public void return_() { super.return_(); addFramePosition(this.position); } public void athrow() { super.athrow(); addFramePosition(this.position); } public void pushOnStack(TypeBinding binding) { super.pushOnStack(binding); addStackDepthMarker(this.position, 1, binding); } public void pushExceptionOnStack(TypeBinding binding) { super.pushExceptionOnStack(binding); addExceptionMarker(this.position, binding); } public void goto_(BranchLabel label) { super.goto_(label); addFramePosition(this.position); } public void goto_w(BranchLabel label) { super.goto_w(label); addFramePosition(this.position); } public void resetInWideMode() { this.resetSecretLocals(); super.resetInWideMode(); } public void resetForCodeGenUnusedLocals() { this.resetSecretLocals(); super.resetForCodeGenUnusedLocals(); } public void resetSecretLocals() { for (int i = 0, max = this.locals.length; i < max; i++) { LocalVariableBinding localVariableBinding = this.locals[i]; if (localVariableBinding != null && localVariableBinding.isSecret()) { // all other locals are reinitialized inside the computation of their resolved positions localVariableBinding.resetInitializations(); } } } } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants0000644000175000001440000000467012212041344032444 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public interface AttributeNamesConstants { 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$ final char[] StackMapTableName = "StackMapTable".toCharArray(); //$NON-NLS-1$ final char[] InconsistentHierarchy = "InconsistentHierarchy".toCharArray(); //$NON-NLS-1$ final char[] VarargsName = "Varargs".toCharArray(); //$NON-NLS-1$ final char[] StackMapName = "StackMap".toCharArray(); //$NON-NLS-1$ final char[] MissingTypesName = "MissingTypes".toCharArray(); //$NON-NLS-1$ } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/Opcodes.java0000644000175000001440000002327312212041344030134 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public interface Opcodes { public static final byte OPC_nop = 0; public static final byte OPC_aconst_null = 1; public static final byte OPC_iconst_m1 = 2; public static final byte OPC_iconst_0 = 3; public static final byte OPC_iconst_1 = 4; public static final byte OPC_iconst_2 = 5; public static final byte OPC_iconst_3 = 6; public static final byte OPC_iconst_4 = 7; public static final byte OPC_iconst_5 = 8; public static final byte OPC_lconst_0 = 9; public static final byte OPC_lconst_1 = 10; public static final byte OPC_fconst_0 = 11; public static final byte OPC_fconst_1 = 12; public static final byte OPC_fconst_2 = 13; public static final byte OPC_dconst_0 = 14; public static final byte OPC_dconst_1 = 15; public static final byte OPC_bipush = 16; public static final byte OPC_sipush = 17; public static final byte OPC_ldc = 18; public static final byte OPC_ldc_w = 19; public static final byte OPC_ldc2_w = 20; public static final byte OPC_iload = 21; public static final byte OPC_lload = 22; public static final byte OPC_fload = 23; public static final byte OPC_dload = 24; public static final byte OPC_aload = 25; public static final byte OPC_iload_0 = 26; public static final byte OPC_iload_1 = 27; public static final byte OPC_iload_2 = 28; public static final byte OPC_iload_3 = 29; public static final byte OPC_lload_0 = 30; public static final byte OPC_lload_1 = 31; public static final byte OPC_lload_2 = 32; public static final byte OPC_lload_3 = 33; public static final byte OPC_fload_0 = 34; public static final byte OPC_fload_1 = 35; public static final byte OPC_fload_2 = 36; public static final byte OPC_fload_3 = 37; public static final byte OPC_dload_0 = 38; public static final byte OPC_dload_1 = 39; public static final byte OPC_dload_2 = 40; public static final byte OPC_dload_3 = 41; public static final byte OPC_aload_0 = 42; public static final byte OPC_aload_1 = 43; public static final byte OPC_aload_2 = 44; public static final byte OPC_aload_3 = 45; public static final byte OPC_iaload = 46; public static final byte OPC_laload = 47; public static final byte OPC_faload = 48; public static final byte OPC_daload = 49; public static final byte OPC_aaload = 50; public static final byte OPC_baload = 51; public static final byte OPC_caload = 52; public static final byte OPC_saload = 53; public static final byte OPC_istore = 54; public static final byte OPC_lstore = 55; public static final byte OPC_fstore = 56; public static final byte OPC_dstore = 57; public static final byte OPC_astore = 58; public static final byte OPC_istore_0 = 59; public static final byte OPC_istore_1 = 60; public static final byte OPC_istore_2 = 61; public static final byte OPC_istore_3 = 62; public static final byte OPC_lstore_0 = 63; public static final byte OPC_lstore_1 = 64; public static final byte OPC_lstore_2 = 65; public static final byte OPC_lstore_3 = 66; public static final byte OPC_fstore_0 = 67; public static final byte OPC_fstore_1 = 68; public static final byte OPC_fstore_2 = 69; public static final byte OPC_fstore_3 = 70; public static final byte OPC_dstore_0 = 71; public static final byte OPC_dstore_1 = 72; public static final byte OPC_dstore_2 = 73; public static final byte OPC_dstore_3 = 74; public static final byte OPC_astore_0 = 75; public static final byte OPC_astore_1 = 76; public static final byte OPC_astore_2 = 77; public static final byte OPC_astore_3 = 78; public static final byte OPC_iastore = 79; public static final byte OPC_lastore = 80; public static final byte OPC_fastore = 81; public static final byte OPC_dastore = 82; public static final byte OPC_aastore = 83; public static final byte OPC_bastore = 84; public static final byte OPC_castore = 85; public static final byte OPC_sastore = 86; public static final byte OPC_pop = 87; public static final byte OPC_pop2 = 88; public static final byte OPC_dup = 89; public static final byte OPC_dup_x1 = 90; public static final byte OPC_dup_x2 = 91; public static final byte OPC_dup2 = 92; public static final byte OPC_dup2_x1 = 93; public static final byte OPC_dup2_x2 = 94; public static final byte OPC_swap = 95; public static final byte OPC_iadd = 96; public static final byte OPC_ladd = 97; public static final byte OPC_fadd = 98; public static final byte OPC_dadd = 99; public static final byte OPC_isub = 100; public static final byte OPC_lsub = 101; public static final byte OPC_fsub = 102; public static final byte OPC_dsub = 103; public static final byte OPC_imul = 104; public static final byte OPC_lmul = 105; public static final byte OPC_fmul = 106; public static final byte OPC_dmul = 107; public static final byte OPC_idiv = 108; public static final byte OPC_ldiv = 109; public static final byte OPC_fdiv = 110; public static final byte OPC_ddiv = 111; public static final byte OPC_irem = 112; public static final byte OPC_lrem = 113; public static final byte OPC_frem = 114; public static final byte OPC_drem = 115; public static final byte OPC_ineg = 116; public static final byte OPC_lneg = 117; public static final byte OPC_fneg = 118; public static final byte OPC_dneg = 119; public static final byte OPC_ishl = 120; public static final byte OPC_lshl = 121; public static final byte OPC_ishr = 122; public static final byte OPC_lshr = 123; public static final byte OPC_iushr = 124; public static final byte OPC_lushr = 125; public static final byte OPC_iand = 126; public static final byte OPC_land = 127; public static final byte OPC_ior = (byte) 128; public static final byte OPC_lor = (byte) 129; public static final byte OPC_ixor = (byte) 130; public static final byte OPC_lxor = (byte) 131; public static final byte OPC_iinc = (byte) 132; public static final byte OPC_i2l = (byte) 133; public static final byte OPC_i2f = (byte) 134; public static final byte OPC_i2d = (byte) 135; public static final byte OPC_l2i = (byte) 136; public static final byte OPC_l2f = (byte) 137; public static final byte OPC_l2d = (byte) 138; public static final byte OPC_f2i = (byte) 139; public static final byte OPC_f2l = (byte) 140; public static final byte OPC_f2d = (byte) 141; public static final byte OPC_d2i = (byte) 142; public static final byte OPC_d2l = (byte) 143; public static final byte OPC_d2f = (byte) 144; public static final byte OPC_i2b = (byte) 145; public static final byte OPC_i2c = (byte) 146; public static final byte OPC_i2s = (byte) 147; public static final byte OPC_lcmp = (byte) 148; public static final byte OPC_fcmpl = (byte) 149; public static final byte OPC_fcmpg = (byte) 150; public static final byte OPC_dcmpl = (byte) 151; public static final byte OPC_dcmpg = (byte) 152; public static final byte OPC_ifeq = (byte) 153; public static final byte OPC_ifne = (byte) 154; public static final byte OPC_iflt = (byte) 155; public static final byte OPC_ifge = (byte) 156; public static final byte OPC_ifgt = (byte) 157; public static final byte OPC_ifle = (byte) 158; public static final byte OPC_if_icmpeq = (byte) 159; public static final byte OPC_if_icmpne = (byte) 160; public static final byte OPC_if_icmplt = (byte) 161; public static final byte OPC_if_icmpge = (byte) 162; public static final byte OPC_if_icmpgt = (byte) 163; public static final byte OPC_if_icmple = (byte) 164; public static final byte OPC_if_acmpeq = (byte) 165; public static final byte OPC_if_acmpne = (byte) 166; public static final byte OPC_goto = (byte) 167; public static final byte OPC_jsr = (byte) 168; public static final byte OPC_ret = (byte) 169; public static final byte OPC_tableswitch = (byte) 170; public static final byte OPC_lookupswitch = (byte) 171; public static final byte OPC_ireturn = (byte) 172; public static final byte OPC_lreturn = (byte) 173; public static final byte OPC_freturn = (byte) 174; public static final byte OPC_dreturn = (byte) 175; public static final byte OPC_areturn = (byte) 176; public static final byte OPC_return = (byte) 177; public static final byte OPC_getstatic = (byte) 178; public static final byte OPC_putstatic = (byte) 179; public static final byte OPC_getfield = (byte) 180; public static final byte OPC_putfield = (byte) 181; public static final byte OPC_invokevirtual = (byte) 182; public static final byte OPC_invokespecial = (byte) 183; public static final byte OPC_invokestatic = (byte) 184; public static final byte OPC_invokeinterface = (byte) 185; public static final byte OPC_new = (byte) 187; public static final byte OPC_newarray = (byte) 188; public static final byte OPC_anewarray = (byte) 189; public static final byte OPC_arraylength = (byte) 190; public static final byte OPC_athrow = (byte) 191; public static final byte OPC_checkcast = (byte) 192; public static final byte OPC_instanceof = (byte) 193; public static final byte OPC_monitorenter = (byte) 194; public static final byte OPC_monitorexit = (byte) 195; public static final byte OPC_wide = (byte) 196; public static final byte OPC_multianewarray = (byte) 197; public static final byte OPC_ifnull = (byte) 198; public static final byte OPC_ifnonnull = (byte) 199; public static final byte OPC_goto_w = (byte) 200; public static final byte OPC_jsr_w = (byte) 201; } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/Label.java0000644000175000001440000000175112212041344027554 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public abstract class Label { public CodeStream codeStream; public int position = POS_NOT_SET; // position=POS_NOT_SET Then it's pos is not set. public final static int POS_NOT_SET = -1; public Label() { // for creating labels ahead of code generation } public Label(CodeStream codeStream) { this.codeStream = codeStream; } /* * Place the label target position. */ public abstract void place(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java0000644000175000001440000000466212212041344030354 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public class CaseLabel extends BranchLabel { public int instructionPosition = POS_NOT_SET; /** * CaseLabel constructor comment. * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream */ public CaseLabel(CodeStream codeStream) { super(codeStream); } /* * Put down a reference to the array at the location in the codestream. * #placeInstruction() must be performed prior to any #branch() */ void branch() { if (this.position == POS_NOT_SET) { addForwardReference(this.codeStream.position); // Leave 4 bytes free to generate the jump offset afterwards this.codeStream.position += 4; this.codeStream.classFileOffset += 4; } else { //Position is set. Write it! /* * Position is set. Write it if it is not a wide branch. */ this.codeStream.writeSignedWord(this.position - this.instructionPosition); } } /* * No support for wide branches yet */ void branchWide() { branch(); // case label branch is already wide } public boolean isCaseLabel() { return true; } public boolean isStandardLabel(){ return false; } /* * Put down a reference to the array at the location in the codestream. */ public void place() { if ((this.tagBits & USED) != 0) { this.position = this.codeStream.getPosition(); } else { this.position = this.codeStream.position; } if (this.instructionPosition != POS_NOT_SET) { int offset = this.position - this.instructionPosition; int[] forwardRefs = forwardReferences(); for (int i = 0, length = forwardReferenceCount(); i < length; i++) { this.codeStream.writeSignedWord(forwardRefs[i], offset); } // add the label in the codeStream labels collection this.codeStream.addLabel(this); } } /* * Put down a reference to the array at the location in the codestream. */ void placeInstruction() { if (this.instructionPosition == POS_NOT_SET) { this.instructionPosition = this.codeStream.position; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java0000644000175000001440000015177512212041344031174 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.ClassFile; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TagBits; 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; import org.eclipse.jdt.internal.compiler.util.Util; /** * This type is used to store all the constant pool entries. */ public class ConstantPool implements ClassFileConstants, TypeIds { public static final int DOUBLE_INITIAL_SIZE = 5; public static final int FLOAT_INITIAL_SIZE = 3; public static final int INT_INITIAL_SIZE = 248; 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 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; public static final int CONSTANTPOOL_GROW_SIZE = 6000; protected DoubleCache doubleCache; protected FloatCache floatCache; protected IntegerCache intCache; protected LongCache longCache; public CharArrayCache UTF8Cache; protected CharArrayCache stringCache; protected HashtableOfObject methodsAndFieldsCache; protected CharArrayCache classCache; protected HashtableOfObject nameAndTypeCacheForFieldsAndMethods; public byte[] poolContent; public int currentIndex = 1; public int currentOffset; public int[] offsets; 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[] Close = "close".toCharArray(); //$NON-NLS-1$ public static final char[] CloseSignature = "()V".toCharArray(); //$NON-NLS-1$ 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[] 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[] ITERATOR_NAME = "iterator".toCharArray(); //$NON-NLS-1$ public static final char[] ITERATOR_SIGNATURE = "()Ljava/util/Iterator;".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[] 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[] JavaLangEnumConstantPoolName = "java/lang/Enum".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[] 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[] JavaLangNoSuchFieldErrorConstantPoolName = "java/lang/NoSuchFieldError".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[] JavaLangReflectConstructorConstantPoolName = "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[] JavaLangObjectSignature = "Ljava/lang/Object;".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[] 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[] ObjectSignature = "Ljava/lang/Object;".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$ public static final char[] ValueOfStringClassSignature = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;".toCharArray(); //$NON-NLS-1$ public static final char[] JAVA_LANG_ANNOTATION_DOCUMENTED = "Ljava/lang/annotation/Documented;".toCharArray(); //$NON-NLS-1$ public static final char[] JAVA_LANG_ANNOTATION_ELEMENTTYPE = "Ljava/lang/annotation/ElementType;".toCharArray(); //$NON-NLS-1$ public static final char[] JAVA_LANG_ANNOTATION_RETENTION = "Ljava/lang/annotation/Retention;".toCharArray(); //$NON-NLS-1$ public static final char[] JAVA_LANG_ANNOTATION_RETENTIONPOLICY = "Ljava/lang/annotation/RetentionPolicy;".toCharArray(); //$NON-NLS-1$ public static final char[] JAVA_LANG_ANNOTATION_TARGET = "Ljava/lang/annotation/Target;".toCharArray(); //$NON-NLS-1$ public static final char[] JAVA_LANG_DEPRECATED = "Ljava/lang/Deprecated;".toCharArray(); //$NON-NLS-1$ public static final char[] JAVA_LANG_ANNOTATION_INHERITED = "Ljava/lang/annotation/Inherited;".toCharArray(); //$NON-NLS-1$ // java 7 java.lang.SafeVarargs public static final char[] JAVA_LANG_SAFEVARARGS = "Ljava/lang/SafeVarargs;".toCharArray(); //$NON-NLS-1$ // java 7 java.lang.invoke.MethodHandle.invokeExact(..)/invokeGeneric(..) public static final char[] JAVA_LANG_INVOKE_METHODHANDLE_POLYMORPHICSIGNATURE = "Ljava/lang/invoke/MethodHandle$PolymorphicSignature;".toCharArray(); //$NON-NLS-1$ public static final char[] HashCode = "hashCode".toCharArray(); //$NON-NLS-1$ public static final char[] HashCodeSignature = "()I".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[] AddSuppressed = "addSuppressed".toCharArray(); //$NON-NLS-1$; public static final char[] AddSuppressedSignature = "(Ljava/lang/Throwable;)V".toCharArray(); //$NON-NLS-1$ /** * ConstantPool constructor comment. */ public ConstantPool(ClassFile classFile) { this.UTF8Cache = new CharArrayCache(UTF8_INITIAL_SIZE); this.stringCache = new CharArrayCache(STRING_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.offsets = new int[5]; initialize(classFile); } public void initialize(ClassFile givenClassFile) { this.poolContent = givenClassFile.header; this.currentOffset = givenClassFile.headerOffset; // currentOffset is initialized to 0 by default this.currentIndex = 1; this.classFile = givenClassFile; } /** * Return the content of the receiver */ public byte[] dumpBytes() { System.arraycopy(this.poolContent, 0, (this.poolContent = new byte[this.currentOffset]), 0, this.currentOffset); return this.poolContent; } public int literalIndex(byte[] utf8encoding, char[] stringCharArray) { int index; if ((index = this.UTF8Cache.putIfAbsent(stringCharArray, this.currentIndex)) < 0) { // The entry doesn't exit yet if ((index = -index)> 0xFFFF) { this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } this.currentIndex++; // Write the tag first int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(Utf8Tag); int utf8encodingLength = utf8encoding.length; if (this.currentOffset + 2 + utf8encodingLength >= this.poolContent.length) { // we need to resize the poolContent array because we won't have // enough space to write the length resizePoolContents(2 + utf8encodingLength); } this.poolContent[this.currentOffset++] = (byte) (utf8encodingLength >> 8); this.poolContent[this.currentOffset++] = (byte) utf8encodingLength; // add in once the whole byte array System.arraycopy(utf8encoding, 0, this.poolContent, this.currentOffset, utf8encodingLength); this.currentOffset += utf8encodingLength; } return index; } public int literalIndex(TypeBinding binding) { TypeBinding typeBinding = binding.leafComponentType(); if ((typeBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(this.classFile, typeBinding); } return literalIndex(binding.signature()); } /** * This method returns the index into the constantPool corresponding to the type descriptor. * * @param utf8Constant char[] * @return int */ public int literalIndex(char[] utf8Constant) { int index; if ((index = this.UTF8Cache.putIfAbsent(utf8Constant, this.currentIndex)) < 0) { if ((index = -index)> 0xFFFF) { this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } // The entry doesn't exit yet // Write the tag first int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(Utf8Tag); // Then the size of the stringName array int savedCurrentOffset = this.currentOffset; if (this.currentOffset + 2 >= this.poolContent.length) { // we need to resize the poolContent array because we won't have // enough space to write the length resizePoolContents(2); } this.currentOffset += 2; length = 0; for (int i = 0; i < utf8Constant.length; i++) { char current = utf8Constant[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) { this.currentOffset = savedCurrentOffset - 1; this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceForConstant(this.classFile.referenceBinding.scope.referenceType()); } if (index > 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } this.currentIndex++; // Now we know the length that we have to write in the constant pool // we use savedCurrentOffset to do that this.poolContent[savedCurrentOffset] = (byte) (length >> 8); this.poolContent[savedCurrentOffset + 1] = (byte) length; } return index; } public int literalIndex(char[] stringCharArray, byte[] utf8encoding) { int index; if ((index = this.stringCache.putIfAbsent(stringCharArray, this.currentIndex)) < 0) { // The entry doesn't exit yet this.currentIndex++; if ((index = -index) > 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } // Write the tag first int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(StringTag); // Then the string index int stringIndexOffset = this.currentOffset; if (this.currentOffset + 2 >= this.poolContent.length) { resizePoolContents(2); } this.currentOffset+=2; final int stringIndex = literalIndex(utf8encoding, stringCharArray); this.poolContent[stringIndexOffset++] = (byte) (stringIndex >> 8); this.poolContent[stringIndexOffset] = (byte) stringIndex; } return index; } /** * This method returns the index into the constantPool corresponding to the double * value. If the double is not already present into the pool, it is added. The * double cache is updated and it returns the right index. * * @param key double * @return int */ public int literalIndex(double key) { //Retrieve the index from the cache // The double constant takes two indexes into the constant pool, but we only store // the first index into the long table int index; // lazy initialization for base type caches // If it is null, initialize it, otherwise use it if (this.doubleCache == null) { this.doubleCache = new DoubleCache(DOUBLE_INITIAL_SIZE); } if ((index = this.doubleCache.putIfAbsent(key, this.currentIndex)) < 0) { if ((index = -index)> 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } this.currentIndex += 2; // a double needs an extra place into the constant pool // Write the double into the constant pool // First add the tag int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(DoubleTag); // Then add the 8 bytes representing the double long temp = java.lang.Double.doubleToLongBits(key); length = this.poolContent.length; if (this.currentOffset + 8 >= length) { resizePoolContents(8); } this.poolContent[this.currentOffset++] = (byte) (temp >>> 56); this.poolContent[this.currentOffset++] = (byte) (temp >>> 48); this.poolContent[this.currentOffset++] = (byte) (temp >>> 40); this.poolContent[this.currentOffset++] = (byte) (temp >>> 32); this.poolContent[this.currentOffset++] = (byte) (temp >>> 24); this.poolContent[this.currentOffset++] = (byte) (temp >>> 16); this.poolContent[this.currentOffset++] = (byte) (temp >>> 8); this.poolContent[this.currentOffset++] = (byte) temp; } return index; } /** * This method returns the index into the constantPool corresponding to the float * value. If the float is not already present into the pool, it is added. The * int cache is updated and it returns the right index. * * @param key float * @return int */ public int literalIndex(float key) { //Retrieve the index from the cache int index; // lazy initialization for base type caches // If it is null, initialize it, otherwise use it if (this.floatCache == null) { this.floatCache = new FloatCache(FLOAT_INITIAL_SIZE); } if ((index = this.floatCache.putIfAbsent(key, this.currentIndex)) < 0) { if ((index = -index) > 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } this.currentIndex++; // Write the float constant entry into the constant pool // First add the tag int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(FloatTag); // Then add the 4 bytes representing the float int temp = java.lang.Float.floatToIntBits(key); if (this.currentOffset + 4 >= this.poolContent.length) { resizePoolContents(4); } this.poolContent[this.currentOffset++] = (byte) (temp >>> 24); this.poolContent[this.currentOffset++] = (byte) (temp >>> 16); this.poolContent[this.currentOffset++] = (byte) (temp >>> 8); this.poolContent[this.currentOffset++] = (byte) temp; } return index; } /** * This method returns the index into the constantPool corresponding to the int * value. If the int is not already present into the pool, it is added. The * int cache is updated and it returns the right index. * * @param key int * @return int */ public int literalIndex(int key) { //Retrieve the index from the cache int index; // lazy initialization for base type caches // If it is null, initialize it, otherwise use it if (this.intCache == null) { this.intCache = new IntegerCache(INT_INITIAL_SIZE); } if ((index = this.intCache.putIfAbsent(key, this.currentIndex)) < 0) { this.currentIndex++; if ((index = -index) > 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } // Write the integer constant entry into the constant pool // First add the tag int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(IntegerTag); // Then add the 4 bytes representing the int if (this.currentOffset + 4 >= this.poolContent.length) { resizePoolContents(4); } this.poolContent[this.currentOffset++] = (byte) (key >>> 24); this.poolContent[this.currentOffset++] = (byte) (key >>> 16); this.poolContent[this.currentOffset++] = (byte) (key >>> 8); this.poolContent[this.currentOffset++] = (byte) key; } return index; } /** * This method returns the index into the constantPool corresponding to the long * value. If the long is not already present into the pool, it is added. The * long cache is updated and it returns the right index. * * @param key long * @return int */ public int literalIndex(long key) { // Retrieve the index from the cache // The long constant takes two indexes into the constant pool, but we only store // the first index into the long table int index; // lazy initialization for base type caches // If it is null, initialize it, otherwise use it if (this.longCache == null) { this.longCache = new LongCache(LONG_INITIAL_SIZE); } if ((index = this.longCache.putIfAbsent(key, this.currentIndex)) < 0) { if ((index = -index) > 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } this.currentIndex+= 2; // long value need an extra place into thwe constant pool // Write the long into the constant pool // First add the tag int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(LongTag); // Then add the 8 bytes representing the long if (this.currentOffset + 8 >= this.poolContent.length) { resizePoolContents(8); } this.poolContent[this.currentOffset++] = (byte) (key >>> 56); this.poolContent[this.currentOffset++] = (byte) (key >>> 48); this.poolContent[this.currentOffset++] = (byte) (key >>> 40); this.poolContent[this.currentOffset++] = (byte) (key >>> 32); this.poolContent[this.currentOffset++] = (byte) (key >>> 24); this.poolContent[this.currentOffset++] = (byte) (key >>> 16); this.poolContent[this.currentOffset++] = (byte) (key >>> 8); this.poolContent[this.currentOffset++] = (byte) key; } return index; } /** * This method returns the index into the constantPool corresponding to the type descriptor. * * @param stringConstant java.lang.String * @return int */ public int literalIndex(String stringConstant) { int index; char[] stringCharArray = stringConstant.toCharArray(); if ((index = this.stringCache.putIfAbsent(stringCharArray, this.currentIndex)) < 0) { // The entry doesn't exit yet this.currentIndex++; if ((index = -index)> 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } // Write the tag first int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(StringTag); // Then the string index int stringIndexOffset = this.currentOffset; if (this.currentOffset + 2 >= this.poolContent.length) { resizePoolContents(2); } this.currentOffset+=2; final int stringIndex = literalIndex(stringCharArray); this.poolContent[stringIndexOffset++] = (byte) (stringIndex >> 8); this.poolContent[stringIndexOffset] = (byte) stringIndex; } return index; } public int literalIndexForType(final char[] constantPoolName) { int index; if ((index = this.classCache.putIfAbsent(constantPoolName, this.currentIndex)) < 0) { // The entry doesn't exit yet this.currentIndex++; if ((index = -index) > 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(ClassTag); // Then the name index int nameIndexOffset = this.currentOffset; if (this.currentOffset + 2 >= this.poolContent.length) { resizePoolContents(2); } this.currentOffset+=2; final int nameIndex = literalIndex(constantPoolName); this.poolContent[nameIndexOffset++] = (byte) (nameIndex >> 8); this.poolContent[nameIndexOffset] = (byte) nameIndex; } return index; } /* * This method returns the index into the constantPool corresponding to the type descriptor * corresponding to a type constant pool name * binding must not be an array type. */ public int literalIndexForType(final TypeBinding binding) { TypeBinding typeBinding = binding.leafComponentType(); if ((typeBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(this.classFile, typeBinding); } return this.literalIndexForType(binding.constantPoolName()); } public int literalIndexForMethod(char[] declaringClass, char[] selector, char[] signature, boolean isInterface) { int index; if ((index = putInCacheIfAbsent(declaringClass, selector, signature, this.currentIndex)) < 0) { // it doesn't exist yet this.currentIndex++; if ((index = -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 int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(isInterface ? InterfaceMethodRefTag : MethodRefTag); int classIndexOffset = this.currentOffset; if (this.currentOffset + 4 >= this.poolContent.length) { resizePoolContents(4); } this.currentOffset+=4; final int classIndex = literalIndexForType(declaringClass); final int nameAndTypeIndex = literalIndexForNameAndType(selector, signature); this.poolContent[classIndexOffset++] = (byte) (classIndex >> 8); this.poolContent[classIndexOffset++] = (byte) classIndex; this.poolContent[classIndexOffset++] = (byte) (nameAndTypeIndex >> 8); this.poolContent[classIndexOffset] = (byte) nameAndTypeIndex; } return index; } public int literalIndexForMethod(TypeBinding declaringClass, char[] selector, char[] signature, boolean isInterface) { if ((declaringClass.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(this.classFile, declaringClass); } return this.literalIndexForMethod(declaringClass.constantPoolName(), selector, signature, isInterface); } public int literalIndexForNameAndType(char[] name, char[] signature) { int index; if ((index = putInNameAndTypeCacheIfAbsent(name, signature, this.currentIndex)) < 0) { // The entry doesn't exit yet this.currentIndex++; if ((index = -index) > 0xFFFF){ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(NameAndTypeTag); int nameIndexOffset = this.currentOffset; if (this.currentOffset + 4 >= this.poolContent.length) { resizePoolContents(4); } this.currentOffset+=4; final int nameIndex = literalIndex(name); final int typeIndex = literalIndex(signature); this.poolContent[nameIndexOffset++] = (byte) (nameIndex >> 8); this.poolContent[nameIndexOffset++] = (byte) nameIndex; this.poolContent[nameIndexOffset++] = (byte) (typeIndex >> 8); this.poolContent[nameIndexOffset] = (byte) typeIndex; } return index; } public int literalIndexForField(char[] declaringClass, char[] name, char[] signature) { int index; if ((index = putInCacheIfAbsent(declaringClass, name, signature, this.currentIndex)) < 0) { this.currentIndex++; // doesn't exist yet if ((index = -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 int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(FieldRefTag); int classIndexOffset = this.currentOffset; if (this.currentOffset + 4 >= this.poolContent.length) { resizePoolContents(4); } this.currentOffset+=4; final int classIndex = literalIndexForType(declaringClass); final int nameAndTypeIndex = literalIndexForNameAndType(name, signature); this.poolContent[classIndexOffset++] = (byte) (classIndex >> 8); this.poolContent[classIndexOffset++] = (byte) classIndex; this.poolContent[classIndexOffset++] = (byte) (nameAndTypeIndex >> 8); this.poolContent[classIndexOffset] = (byte) 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 savedCurrentIndex = this.currentIndex; int savedCurrentOffset = this.currentOffset; int index; if ((index = this.stringCache.putIfAbsent(stringCharArray, this.currentIndex)) < 0) { if ((index = -index)> 0xFFFF) { this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } // The entry doesn't exit yet this.currentIndex++; // Write the tag first int length = this.offsets.length; if (length <= index) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); } this.offsets[index] = this.currentOffset; writeU1(StringTag); // Then the string index int stringIndexOffset = this.currentOffset; if (this.currentOffset + 2 >= this.poolContent.length) { resizePoolContents(2); } this.currentOffset+=2; int stringIndex; if ((stringIndex = this.UTF8Cache.putIfAbsent(stringCharArray, this.currentIndex)) < 0) { if ((stringIndex = -stringIndex)> 0xFFFF) { this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); } // The entry doesn't exit yet this.currentIndex++; // Write the tag first length = this.offsets.length; if (length <= stringIndex) { // resize System.arraycopy(this.offsets, 0, (this.offsets = new int[stringIndex * 2]), 0, length); } this.offsets[stringIndex] = this.currentOffset; writeU1(Utf8Tag); // Then the size of the stringName array int lengthOffset = this.currentOffset; if (this.currentOffset + 2 >= this.poolContent.length) { // we need to resize the poolContent array because we won't have // enough space to write the length resizePoolContents(2); } this.currentOffset += 2; 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 length++; if (this.currentOffset + 1 >= this.poolContent.length) { // we need to resize the poolContent array because we won't have // enough space to write the length resizePoolContents(1); } this.poolContent[this.currentOffset++] = (byte)(current); } else if (current > 0x07FF) { // we need 3 bytes length += 3; if (this.currentOffset + 3 >= this.poolContent.length) { // we need to resize the poolContent array because we won't have // enough space to write the length resizePoolContents(3); } this.poolContent[this.currentOffset++] = (byte) (0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000 this.poolContent[this.currentOffset++] = (byte) (0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000 this.poolContent[this.currentOffset++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 } else { if (this.currentOffset + 2 >= this.poolContent.length) { // we need to resize the poolContent array because we won't have // enough space to write the length resizePoolContents(2); } // we can be 0 or between 0x0080 and 0x07FF // In that case we only need 2 bytes length += 2; this.poolContent[this.currentOffset++] = (byte) (0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000 this.poolContent[this.currentOffset++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 } } if (length >= 65535) { this.currentOffset = savedCurrentOffset; this.currentIndex = savedCurrentIndex; this.stringCache.remove(stringCharArray); this.UTF8Cache.remove(stringCharArray); return 0; } this.poolContent[lengthOffset++] = (byte) (length >> 8); this.poolContent[lengthOffset] = (byte) length; } this.poolContent[stringIndexOffset++] = (byte) (stringIndex >> 8); this.poolContent[stringIndexOffset] = (byte) stringIndex; } return index; } /** * @param key1 the given name * @param key2 the given signature * @param value the given index * @return the new index */ private int putInNameAndTypeCacheIfAbsent(final char[] key1, final char[] key2, int value) { int index ; Object key1Value = this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); index = -value; this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } else if (key1Value instanceof CachedIndexEntry) { // adding a second entry CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); } return index; } /** * @param key1 the given declaring class name * @param key2 the given field name or method selector * @param key3 the given signature * @param value the new index * @return the given index */ private int putInCacheIfAbsent(final char[] key1, final char[] key2, final char[] key3, int value) { int index; HashtableOfObject key1Value = (HashtableOfObject) this.methodsAndFieldsCache.get(key1); if (key1Value == null) { key1Value = new HashtableOfObject(); this.methodsAndFieldsCache.put(key1, key1Value); CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key3, value); index = -value; key1Value.put(key2, cachedIndexEntry); } else { Object key2Value = key1Value.get(key2); if (key2Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key3, value); index = -value; key1Value.put(key2, cachedIndexEntry); } else if (key2Value instanceof CachedIndexEntry) { // adding a second entry CachedIndexEntry entry = (CachedIndexEntry) key2Value; if (CharOperation.equals(key3, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key3, value); key1Value.put(key2, charArrayCache); } } else { CharArrayCache charArrayCache = (CharArrayCache) key2Value; index = charArrayCache.putIfAbsent(key3, value); } } return index; } /** * This method is used to clean the receiver in case of a clinit header is generated, but the * clinit has no code. * This implementation assumes that the clinit is the first method to be generated. * @see org.eclipse.jdt.internal.compiler.ast.TypeDeclaration#addClinit() */ public void resetForClinit(int constantPoolIndex, int constantPoolOffset) { this.currentIndex = constantPoolIndex; this.currentOffset = constantPoolOffset; if (this.UTF8Cache.get(AttributeNamesConstants.CodeName) >= constantPoolIndex) { this.UTF8Cache.remove(AttributeNamesConstants.CodeName); } if (this.UTF8Cache.get(ConstantPool.ClinitSignature) >= constantPoolIndex) { this.UTF8Cache.remove(ConstantPool.ClinitSignature); } if (this.UTF8Cache.get(ConstantPool.Clinit) >= constantPoolIndex) { this.UTF8Cache.remove(ConstantPool.Clinit); } } /** * Resize the pool contents */ private final void resizePoolContents(int minimalSize) { int length = this.poolContent.length; int toAdd = length; if (toAdd < minimalSize) toAdd = minimalSize; System.arraycopy(this.poolContent, 0, this.poolContent = new byte[length + toAdd], 0, length); } /** * Write a unsigned byte into the byte array * * @param value int The value to write into the byte array */ protected final void writeU1(int value) { if (this.currentOffset + 1 >= this.poolContent.length) { resizePoolContents(1); } this.poolContent[this.currentOffset++] = (byte) value; } /** * Write a unsigned byte into the byte array * * @param value int The value to write into the byte array */ protected final void writeU2(int value) { if (this.currentOffset + 2 >= this.poolContent.length) { resizePoolContents(2); } this.poolContent[this.currentOffset++] = (byte) (value >>> 8); this.poolContent[this.currentOffset++] = (byte) value; } public void reset() { if (this.doubleCache != null) this.doubleCache.clear(); if (this.floatCache != null) this.floatCache.clear(); if (this.intCache != null) this.intCache.clear(); if (this.longCache != null) this.longCache.clear(); this.UTF8Cache.clear(); this.stringCache.clear(); this.methodsAndFieldsCache.clear(); this.classCache.clear(); this.nameAndTypeCacheForFieldsAndMethods.clear(); this.currentIndex = 1; this.currentOffset = 0; } public void resetForAttributeName(char[] attributeName, int constantPoolIndex, int constantPoolOffset) { this.currentIndex = constantPoolIndex; this.currentOffset = constantPoolOffset; if (this.UTF8Cache.get(attributeName) >= constantPoolIndex) { this.UTF8Cache.remove(attributeName); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/CachedIndexEntry.java0000644000175000001440000000142012212041344031707 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public class CachedIndexEntry { public char[] signature; public int index; public CachedIndexEntry(char[] signature, int index) { this.signature = signature; this.index = index; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/BranchLabel.java0000644000175000001440000002175712212041344030702 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; import java.util.Arrays; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; public class BranchLabel extends Label { private int[] forwardReferences = new int[10]; // Add an overflow check here. private int forwardReferenceCount = 0; BranchLabel delegate; // // Label tagbits public int tagBits; public final static int WIDE = 1; public final static int USED = 2; public BranchLabel() { // for creating labels ahead of code generation } /** * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream */ public BranchLabel(CodeStream codeStream) { super(codeStream); } /** * Add a forward refrence for the array. */ void addForwardReference(int pos) { if (this.delegate != null) { this.delegate.addForwardReference(pos); return; } final int count = this.forwardReferenceCount; if (count >= 1) { int previousValue = this.forwardReferences[count - 1]; if (previousValue < pos) { int length; if (count >= (length = this.forwardReferences.length)) System.arraycopy(this.forwardReferences, 0, (this.forwardReferences = new int[2*length]), 0, length); this.forwardReferences[this.forwardReferenceCount++] = pos; } else if (previousValue > pos) { int[] refs = this.forwardReferences; // check for duplicates for (int i = 0, max = this.forwardReferenceCount; i < max; i++) { if (refs[i] == pos) return; // already recorded } int length; if (count >= (length = refs.length)) System.arraycopy(refs, 0, (this.forwardReferences = new int[2*length]), 0, length); this.forwardReferences[this.forwardReferenceCount++] = pos; Arrays.sort(this.forwardReferences, 0, this.forwardReferenceCount); } } else { int length; if (count >= (length = this.forwardReferences.length)) System.arraycopy(this.forwardReferences, 0, (this.forwardReferences = new int[2*length]), 0, length); this.forwardReferences[this.forwardReferenceCount++] = pos; } } /** * Makes the current label inline all references to the other label */ public void becomeDelegateFor(BranchLabel otherLabel) { // other label is delegating to receiver from now on otherLabel.delegate = this; // all existing forward refs to other label are inlined into current label final int otherCount = otherLabel.forwardReferenceCount; if (otherCount == 0) return; // need to merge the two sorted arrays of forward references int[] mergedForwardReferences = new int[this.forwardReferenceCount + otherCount]; int indexInMerge = 0; int j = 0; int i = 0; int max = this.forwardReferenceCount; int max2 = otherLabel.forwardReferenceCount; loop1 : for (; i < max; i++) { final int value1 = this.forwardReferences[i]; for (; j < max2; j++) { final int value2 = otherLabel.forwardReferences[j]; if (value1 < value2) { mergedForwardReferences[indexInMerge++] = value1; continue loop1; } else if (value1 == value2) { mergedForwardReferences[indexInMerge++] = value1; j++; continue loop1; } else { mergedForwardReferences[indexInMerge++] = value2; } } mergedForwardReferences[indexInMerge++] = value1; } for (; j < max2; j++) { mergedForwardReferences[indexInMerge++] = otherLabel.forwardReferences[j]; } this.forwardReferences = mergedForwardReferences; this.forwardReferenceCount = indexInMerge; } /* * Put down a reference to the array at the location in the codestream. */ void branch() { this.tagBits |= BranchLabel.USED; if (this.delegate != null) { this.delegate.branch(); return; } if (this.position == Label.POS_NOT_SET) { addForwardReference(this.codeStream.position); // Leave two bytes free to generate the jump afterwards this.codeStream.position += 2; this.codeStream.classFileOffset += 2; } else { /* * Position is set. Write it if it is not a wide branch. */ this.codeStream.writePosition(this); } } /* * No support for wide branches yet */ void branchWide() { this.tagBits |= BranchLabel.USED; if (this.delegate != null) { this.delegate.branchWide(); return; } if (this.position == Label.POS_NOT_SET) { addForwardReference(this.codeStream.position); // Leave 4 bytes free to generate the jump offset afterwards this.tagBits |= BranchLabel.WIDE; this.codeStream.position += 4; this.codeStream.classFileOffset += 4; } else { //Position is set. Write it! this.codeStream.writeWidePosition(this); } } public int forwardReferenceCount() { if (this.delegate != null) this.delegate.forwardReferenceCount(); return this.forwardReferenceCount; } public int[] forwardReferences() { if (this.delegate != null) this.delegate.forwardReferences(); return this.forwardReferences; } public void initialize(CodeStream stream) { this.codeStream = stream; this.position = Label.POS_NOT_SET; this.forwardReferenceCount = 0; this.delegate = null; } public boolean isCaseLabel() { return false; } public boolean isStandardLabel(){ return true; } /* * Place the label. If we have forward references resolve them. */ public void place() { // Currently lacking wide support. // if ((this.tagBits & USED) == 0 && this.forwardReferenceCount == 0) { // return; // } //TODO how can position be set already ? cannot place more than once if (this.position == Label.POS_NOT_SET) { this.position = this.codeStream.position; this.codeStream.addLabel(this); int oldPosition = this.position; boolean isOptimizedBranch = false; if (this.forwardReferenceCount != 0) { isOptimizedBranch = (this.forwardReferences[this.forwardReferenceCount - 1] + 2 == this.position) && (this.codeStream.bCodeStream[this.codeStream.classFileOffset - 3] == Opcodes.OPC_goto); if (isOptimizedBranch) { if (this.codeStream.lastAbruptCompletion == this.position) { this.codeStream.lastAbruptCompletion = -1; } this.codeStream.position = (this.position -= 3); this.codeStream.classFileOffset -= 3; this.forwardReferenceCount--; if (this.codeStream.lastEntryPC == oldPosition) { this.codeStream.lastEntryPC = this.position; } // end of new code if ((this.codeStream.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) != 0) { LocalVariableBinding locals[] = this.codeStream.locals; for (int i = 0, max = locals.length; i < max; i++) { LocalVariableBinding local = locals[i]; if ((local != null) && (local.initializationCount > 0)) { if (local.initializationPCs[((local.initializationCount - 1) << 1) + 1] == oldPosition) { // we want to prevent interval of size 0 to have a negative size. // see PR 1GIRQLA: ITPJCORE:ALL - ClassFormatError for local variable attribute local.initializationPCs[((local.initializationCount - 1) << 1) + 1] = this.position; } if (local.initializationPCs[(local.initializationCount - 1) << 1] == oldPosition) { local.initializationPCs[(local.initializationCount - 1) << 1] = this.position; } } } } if ((this.codeStream.generateAttributes & ClassFileConstants.ATTR_LINES) != 0) { // we need to remove all entries that is beyond this.position inside the pcToSourcerMap table this.codeStream.removeUnusedPcToSourceMapEntries(); } } } for (int i = 0; i < this.forwardReferenceCount; i++) { this.codeStream.writePosition(this, this.forwardReferences[i]); } // For all labels placed at that position we check if we need to rewrite the jump // offset. It is the case each time a label had a forward reference to the current position. // Like we change the current position, we have to change the jump offset. See 1F4IRD9 for more details. if (isOptimizedBranch) { this.codeStream.optimizeBranch(oldPosition, this); } } } /** * Print out the receiver */ public String toString() { String basic = getClass().getName(); basic = basic.substring(basic.lastIndexOf('.')+1); StringBuffer buffer = new StringBuffer(basic); buffer.append('@').append(Integer.toHexString(hashCode())); buffer.append("(position=").append(this.position); //$NON-NLS-1$ if (this.delegate != null) buffer.append("delegate=").append(this.delegate); //$NON-NLS-1$ buffer.append(", forwards = ["); //$NON-NLS-1$ for (int i = 0; i < this.forwardReferenceCount - 1; i++) buffer.append(this.forwardReferences[i] + ", "); //$NON-NLS-1$ if (this.forwardReferenceCount >= 1) buffer.append(this.forwardReferences[this.forwardReferenceCount-1]); buffer.append("] )"); //$NON-NLS-1$ return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/codegen/DoubleCache.java0000644000175000001440000001133512212041344030672 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public class DoubleCache { private double keyTable[]; private int valueTable[]; private int elementSize; /** * Constructs a new, empty hashtable. A default capacity and * load factor is used. Note that the hashtable will automatically * grow when it gets full. */ public DoubleCache() { this(13); } /** * Constructs a new, empty hashtable with the specified initial * capacity. * @param initialCapacity int * the initial number of buckets */ public DoubleCache(int initialCapacity) { this.elementSize = 0; this.keyTable = new double[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 = this.keyTable.length; --i >= 0;) { this.keyTable[i] = 0.0; this.valueTable[i] = 0; } this.elementSize = 0; } /** Returns true if the collection contains an element for the key. * * @param key double the key that we are looking for * @return boolean */ public boolean containsKey(double key) { if (key == 0.0) { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == 0.0) { long value1 = Double.doubleToLongBits(key); long value2 = Double.doubleToLongBits(this.keyTable[i]); if (value1 == -9223372036854775808L && value2 == -9223372036854775808L) return true; if (value1 == 0 && value2 == 0) return true; } } } else { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == key) { return true; } } } return false; } /** * Puts the specified element into the hashtable, using the specified * key. The element may be retrieved by doing a get() with the same key. * * @param key double the specified key in the hashtable * @param value int the specified element * @return int value */ public int put(double key, int value) { if (this.elementSize == this.keyTable.length) { // resize System.arraycopy(this.keyTable, 0, (this.keyTable = new double[this.elementSize * 2]), 0, this.elementSize); System.arraycopy(this.valueTable, 0, (this.valueTable = new int[this.elementSize * 2]), 0, this.elementSize); } this.keyTable[this.elementSize] = key; this.valueTable[this.elementSize] = value; this.elementSize++; return value; } /** * Puts the specified element into the hashtable, using the specified * key. The element may be retrieved by doing a get() with the same key. * * @param key double the specified key in the hashtable * @param value int the specified element * @return int value */ public int putIfAbsent(double key, int value) { if (key == 0.0) { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == 0.0) { long value1 = Double.doubleToLongBits(key); long value2 = Double.doubleToLongBits(this.keyTable[i]); if (value1 == -9223372036854775808L && value2 == -9223372036854775808L) return this.valueTable[i]; if (value1 == 0 && value2 == 0) return this.valueTable[i]; } } } else { for (int i = 0, max = this.elementSize; i < max; i++) { if (this.keyTable[i] == key) { return this.valueTable[i]; } } } if (this.elementSize == this.keyTable.length) { // resize System.arraycopy(this.keyTable, 0, (this.keyTable = new double[this.elementSize * 2]), 0, this.elementSize); System.arraycopy(this.valueTable, 0, (this.valueTable = new int[this.elementSize * 2]), 0, this.elementSize); } this.keyTable[this.elementSize] = key; this.valueTable[this.elementSize] = value; this.elementSize++; return -value; // negative when added, assumes value is > 0 } /** * Converts to a rather lengthy String. * * @return String the ascii representation of the receiver */ public String toString() { int max = this.elementSize; StringBuffer buf = new StringBuffer(); buf.append("{"); //$NON-NLS-1$ for (int i = 0; i < max; ++i) { if ((this.keyTable[i] != 0) || ((this.keyTable[i] == 0) &&(this.valueTable[i] != 0))) { buf.append(this.keyTable[i]).append("->").append(this.valueTable[i]); //$NON-NLS-1$ } if (i < max) { buf.append(", "); //$NON-NLS-1$ } } buf.append("}"); //$NON-NLS-1$ return buf.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/messages.properties0000644000175000001440000000516712212041344030220 0ustar dokousers############################################################################### # Copyright (c) 2000, 2009 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # # Contributors: # IBM Corporation - initial API and implementation ############################################################################### ### compiler messages. ### compilation compilation_unresolvedProblem = Unresolved compilation problem: \n compilation_unresolvedProblems = Unresolved compilation problems: \n compilation_request = [parsing {2} - #{0}/{1}] compilation_loadBinary = [reading {0}.class] compilation_process = [analyzing {2} - #{0}/{1}] compilation_write = [writing {1} - #{0}] compilation_done = [completed {2} - #{0}/{1}] compilation_units = [{0} units compiled] compilation_unit = [{0} unit compiled] compilation_internalError = Internal compiler error: {0} compilation_beginningToCompile=Beginning to compile compilation_processing=Processing {0} ### output output_isFile = Regular file {0} cannot be used as output directory output_notValidAll = Could not create output directory {0} output_notValid = Could not create subdirectory {0} into output directory {1} ### problem problem_noSourceInformation = problem_atLine = (at line {0}) ### abort abort_invalidAttribute = SANITY CHECK: Invalid attribute for local variable {0} abort_invalidExceptionAttribute = SANITY CHECK: Invalid attribute for exception attribute for {0} abort_missingCode = Missing code implementation in the compiler abort_againstSourceModel = Cannot compile against source model {0} issued from {1} abort_invalidOpcode = SANITY CHECK: Invalid opcode {0} at pc {1} for stackmap table attribute for method {2} ### accept accept_cannot = Cannot accept the compilation unit: ### parser parser_incorrectPath = The path for the javadcl.java file is incorrect parser_moveFiles = MOVE FILES IN THE Runtime DIRECTORY OF Parser.class parser_syntaxRecovery = SYNTAX RECOVERY parser_regularParse = REGULAR PARSE parser_missingFile = missing file {0} parser_corruptedFile = corrupted file {0} parser_endOfFile = end of file parser_endOfConstructor = end of constructor parser_endOfMethod = end of method parser_endOfInitializer = end of initializer ### ast ast_missingCode = Missing code gen implementation ### constant constant_cannotCastedInto = {0} constant cannot be casted into {1} constant_cannotConvertedTo = {0} constant cannot be converted to {1} ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/0000755000175000001440000000000012212041344026076 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java0000644000175000001440000003327112212041344031675 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2012 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation * olivier_thomann@ca.ibm.com - add hashCode() and equals(..) methods *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import java.util.Arrays; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.env.*; import org.eclipse.jdt.internal.compiler.impl.*; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.util.Util; public class AnnotationInfo extends ClassFileStruct implements IBinaryAnnotation { /** The name of the annotation type */ private char[] typename; /** * null until this annotation is initialized * @see #getElementValuePairs() */ private ElementValuePairInfo[] pairs; long standardAnnotationTagBits = 0; int readOffset = 0; static Object[] EmptyValueArray = new Object[0]; AnnotationInfo(byte[] classFileBytes, int[] contantPoolOffsets, int offset) { super(classFileBytes, contantPoolOffsets, offset); } /** * @param classFileBytes * @param offset the offset into classFileBytes for the "type_index" of the annotation attribute. * @param populate true to indicate to build out the annotation structure. */ AnnotationInfo(byte[] classFileBytes, int[] contantPoolOffsets, int offset, boolean runtimeVisible, boolean populate) { this(classFileBytes, contantPoolOffsets, offset); if (populate) decodeAnnotation(); else this.readOffset = scanAnnotation(0, runtimeVisible, true); } private void decodeAnnotation() { this.readOffset = 0; int utf8Offset = this.constantPoolOffsets[u2At(0)] - this.structOffset; this.typename = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); int numberOfPairs = u2At(2); // u2 type_index + u2 num_member_value_pair this.readOffset += 4; this.pairs = numberOfPairs == 0 ? ElementValuePairInfo.NoMembers : new ElementValuePairInfo[numberOfPairs]; for (int i = 0; i < numberOfPairs; i++) { // u2 member_name_index; utf8Offset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; char[] membername = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); this.readOffset += 2; Object value = decodeDefaultValue(); this.pairs[i] = new ElementValuePairInfo(membername, value); } } Object decodeDefaultValue() { Object value = null; // u1 tag; int tag = u1At(this.readOffset); this.readOffset++; int constValueOffset = -1; switch (tag) { case 'Z': // boolean constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = BooleanConstant.fromValue(i4At(constValueOffset + 1) == 1); this.readOffset += 2; break; case 'I': // integer constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = IntConstant.fromValue(i4At(constValueOffset + 1)); this.readOffset += 2; break; case 'C': // char constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = CharConstant.fromValue((char) i4At(constValueOffset + 1)); this.readOffset += 2; break; case 'B': // byte constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = ByteConstant.fromValue((byte) i4At(constValueOffset + 1)); this.readOffset += 2; break; case 'S': // short constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = ShortConstant.fromValue((short) i4At(constValueOffset + 1)); this.readOffset += 2; break; case 'D': // double constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = DoubleConstant.fromValue(doubleAt(constValueOffset + 1)); this.readOffset += 2; break; case 'F': // float constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = FloatConstant.fromValue(floatAt(constValueOffset + 1)); this.readOffset += 2; break; case 'J': // long constant constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = LongConstant.fromValue(i8At(constValueOffset + 1)); this.readOffset += 2; break; case 's': // String constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; value = StringConstant.fromValue(String.valueOf(utf8At(constValueOffset + 3, u2At(constValueOffset + 1)))); this.readOffset += 2; break; case 'e': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; char[] typeName = utf8At(constValueOffset + 3, u2At(constValueOffset + 1)); this.readOffset += 2; constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; char[] constName = utf8At(constValueOffset + 3, u2At(constValueOffset + 1)); this.readOffset += 2; value = new EnumConstantSignature(typeName, constName); break; case 'c': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; char[] className = utf8At(constValueOffset + 3, u2At(constValueOffset + 1)); value = new ClassSignature(className); this.readOffset += 2; break; case '@': value = new AnnotationInfo(this.reference, this.constantPoolOffsets, this.readOffset + this.structOffset, false, true); this.readOffset += ((AnnotationInfo) value).readOffset; break; case '[': int numberOfValues = u2At(this.readOffset); this.readOffset += 2; if (numberOfValues == 0) { value = EmptyValueArray; } else { Object[] arrayElements = new Object[numberOfValues]; value = arrayElements; for (int i = 0; i < numberOfValues; i++) arrayElements[i] = decodeDefaultValue(); } break; default: throw new IllegalStateException("Unrecognized tag " + (char) tag); //$NON-NLS-1$ } return value; } public IBinaryElementValuePair[] getElementValuePairs() { if (this.pairs == null) initialize(); return this.pairs; } public char[] getTypeName() { return this.typename; } void initialize() { if (this.pairs == null) decodeAnnotation(); } private int readRetentionPolicy(int offset) { int currentOffset = offset; int tag = u1At(currentOffset); currentOffset++; switch (tag) { case 'e': int utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - this.structOffset; char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); currentOffset += 2; if (typeName.length == 38 && CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_RETENTIONPOLICY)) { utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - this.structOffset; char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); this.standardAnnotationTagBits |= Annotation.getRetentionPolicy(constName); } currentOffset += 2; break; case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': case 's': case 'c': currentOffset += 2; break; case '@': // none of the supported standard annotation are in the nested // level. currentOffset = scanAnnotation(currentOffset, false, false); break; case '[': int numberOfValues = u2At(currentOffset); currentOffset += 2; for (int i = 0; i < numberOfValues; i++) currentOffset = scanElementValue(currentOffset); break; default: throw new IllegalStateException(); } return currentOffset; } private int readTargetValue(int offset) { int currentOffset = offset; int tag = u1At(currentOffset); currentOffset++; switch (tag) { case 'e': int utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - this.structOffset; char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); currentOffset += 2; if (typeName.length == 34 && CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_ELEMENTTYPE)) { utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - this.structOffset; char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); this.standardAnnotationTagBits |= Annotation.getTargetElementType(constName); } currentOffset += 2; break; case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': case 's': case 'c': currentOffset += 2; break; case '@': // none of the supported standard annotation are in the nested // level. currentOffset = scanAnnotation(currentOffset, false, false); break; case '[': int numberOfValues = u2At(currentOffset); currentOffset += 2; if (numberOfValues == 0) { this.standardAnnotationTagBits |= TagBits.AnnotationTarget; } else { for (int i = 0; i < numberOfValues; i++) currentOffset = readTargetValue(currentOffset); } break; default: throw new IllegalStateException(); } return currentOffset; } /** * Read through this annotation in order to figure out the necessary tag * bits and the length of this annotation. The data structure will not be * flushed out. * * The tag bits are derived from the following (supported) standard * annotation. java.lang.annotation.Documented, * java.lang.annotation.Retention, java.lang.annotation.Target, and * java.lang.Deprecated * * @param expectRuntimeVisibleAnno * true to indicate that this is a runtime-visible annotation * @param toplevel false to indicate that an nested annotation is read. * true otherwise * @return the next offset to read. */ private int scanAnnotation(int offset, boolean expectRuntimeVisibleAnno, boolean toplevel) { int currentOffset = offset; int utf8Offset = this.constantPoolOffsets[u2At(offset)] - this.structOffset; char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (toplevel) this.typename = typeName; int numberOfPairs = u2At(offset + 2); // u2 type_index + u2 number_member_value_pair currentOffset += 4; if (expectRuntimeVisibleAnno && toplevel) { switch (typeName.length) { case 22: if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_DEPRECATED)) { this.standardAnnotationTagBits |= TagBits.AnnotationDeprecated; return currentOffset; } break; case 23: if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_SAFEVARARGS)) { this.standardAnnotationTagBits |= TagBits.AnnotationSafeVarargs; return currentOffset; } break; case 29: if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_TARGET)) { currentOffset += 2; return readTargetValue(currentOffset); } break; case 32: if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_RETENTION)) { currentOffset += 2; return readRetentionPolicy(currentOffset); } if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_INHERITED)) { this.standardAnnotationTagBits |= TagBits.AnnotationInherited; return currentOffset; } break; case 33: if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_DOCUMENTED)) { this.standardAnnotationTagBits |= TagBits.AnnotationDocumented; return currentOffset; } break; case 52: if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_INVOKE_METHODHANDLE_POLYMORPHICSIGNATURE)) { this.standardAnnotationTagBits |= TagBits.AnnotationPolymorphicSignature; return currentOffset; } break; } } for (int i = 0; i < numberOfPairs; i++) { // u2 member_name_index currentOffset += 2; currentOffset = scanElementValue(currentOffset); } return currentOffset; } /** * @param offset * the offset to start reading. * @return the next offset to read. */ private int scanElementValue(int offset) { int currentOffset = offset; int tag = u1At(currentOffset); currentOffset++; switch (tag) { case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': case 's': case 'c': currentOffset += 2; break; case 'e': currentOffset += 4; break; case '@': // none of the supported standard annotation are in the nested // level. currentOffset = scanAnnotation(currentOffset, false, false); break; case '[': int numberOfValues = u2At(currentOffset); currentOffset += 2; for (int i = 0; i < numberOfValues; i++) currentOffset = scanElementValue(currentOffset); break; default: throw new IllegalStateException(); } return currentOffset; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append('@'); buffer.append(this.typename); if (this.pairs != null) { buffer.append('('); buffer.append("\n\t"); //$NON-NLS-1$ for (int i = 0, len = this.pairs.length; i < len; i++) { if (i > 0) buffer.append(",\n\t"); //$NON-NLS-1$ buffer.append(this.pairs[i]); } buffer.append(')'); } return buffer.toString(); } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Util.hashCode(this.pairs); result = prime * result + CharOperation.hashCode(this.typename); return result; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } AnnotationInfo other = (AnnotationInfo) obj; if (!Arrays.equals(this.pairs, other.pairs)) { return false; } if (!Arrays.equals(this.typename, other.typename)) { return false; } return true; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java0000644000175000001440000004342112212041344031001 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; import org.eclipse.jdt.internal.compiler.util.Util; public class MethodInfo extends ClassFileStruct implements IBinaryMethod, Comparable { static private final char[][] noException = CharOperation.NO_CHAR_CHAR; static private final char[][] noArgumentNames = CharOperation.NO_CHAR_CHAR; protected int accessFlags; protected int attributeBytes; protected char[] descriptor; protected char[][] exceptionNames; protected char[] name; protected char[] signature; protected int signatureUtf8Offset; protected long tagBits; protected char[][] argumentNames; protected int argumentNamesIndex; public static MethodInfo createMethod(byte classFileBytes[], int offsets[], int offset) { MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset); int attributesCount = methodInfo.u2At(6); int readOffset = 8; AnnotationInfo[] annotations = null; AnnotationInfo[][] parameterAnnotations = null; for (int i = 0; i < attributesCount; i++) { // check the name of each attribute int utf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset)] - methodInfo.structOffset; char[] attributeName = methodInfo.utf8At(utf8Offset + 3, methodInfo.u2At(utf8Offset + 1)); if (attributeName.length > 0) { switch(attributeName[0]) { case 'S' : if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) methodInfo.signatureUtf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset + 6)] - methodInfo.structOffset; break; case 'R' : AnnotationInfo[] methodAnnotations = null; AnnotationInfo[][] paramAnnotations = null; if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) { methodAnnotations = decodeMethodAnnotations(readOffset, true, methodInfo); } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) { methodAnnotations = decodeMethodAnnotations(readOffset, false, methodInfo); } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName)) { paramAnnotations = decodeParamAnnotations(readOffset, true, methodInfo); } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName)) { paramAnnotations = decodeParamAnnotations(readOffset, false, methodInfo); } if (methodAnnotations != null) { if (annotations == null) { annotations = methodAnnotations; } else { int length = annotations.length; AnnotationInfo[] newAnnotations = new AnnotationInfo[length + methodAnnotations.length]; System.arraycopy(annotations, 0, newAnnotations, 0, length); System.arraycopy(methodAnnotations, 0, newAnnotations, length, methodAnnotations.length); annotations = newAnnotations; } } else if (paramAnnotations != null) { int numberOfParameters = paramAnnotations.length; if (parameterAnnotations == null) { parameterAnnotations = paramAnnotations; } else { for (int p = 0; p < numberOfParameters; p++) { int numberOfAnnotations = paramAnnotations[p] == null ? 0 : paramAnnotations[p].length; if (numberOfAnnotations > 0) { if (parameterAnnotations[p] == null) { parameterAnnotations[p] = paramAnnotations[p]; } else { int length = parameterAnnotations[p].length; AnnotationInfo[] newAnnotations = new AnnotationInfo[length + numberOfAnnotations]; System.arraycopy(parameterAnnotations[p], 0, newAnnotations, 0, length); System.arraycopy(paramAnnotations[p], 0, newAnnotations, length, numberOfAnnotations); parameterAnnotations[p] = newAnnotations; } } } } } break; } } readOffset += (6 + methodInfo.u4At(readOffset + 2)); } methodInfo.attributeBytes = readOffset; if (parameterAnnotations != null) return new MethodInfoWithParameterAnnotations(methodInfo, annotations, parameterAnnotations); if (annotations != null) return new MethodInfoWithAnnotations(methodInfo, annotations); return methodInfo; } static AnnotationInfo[] decodeAnnotations(int offset, boolean runtimeVisible, int numberOfAnnotations, MethodInfo methodInfo) { AnnotationInfo[] result = new AnnotationInfo[numberOfAnnotations]; int readOffset = offset; for (int i = 0; i < numberOfAnnotations; i++) { result[i] = new AnnotationInfo(methodInfo.reference, methodInfo.constantPoolOffsets, readOffset + methodInfo.structOffset, runtimeVisible, false); readOffset += result[i].readOffset; } return result; } static AnnotationInfo[] decodeMethodAnnotations(int offset, boolean runtimeVisible, MethodInfo methodInfo) { int numberOfAnnotations = methodInfo.u2At(offset + 6); if (numberOfAnnotations > 0) { AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations, methodInfo); if (runtimeVisible){ int numStandardAnnotations = 0; for( int i=0; i 0) { // u2 attribute_name_index + u4 attribute_length + u1 num_parameters int readOffset = offset + 7; for (int i=0 ; i < numberOfParameters; i++) { int numberOfAnnotations = methodInfo.u2At(readOffset); readOffset += 2; if (numberOfAnnotations > 0) { if (allParamAnnotations == null) allParamAnnotations = new AnnotationInfo[numberOfParameters][]; AnnotationInfo[] annos = decodeAnnotations(readOffset, runtimeVisible, numberOfAnnotations, methodInfo); allParamAnnotations[i] = annos; for (int aIndex = 0; aIndex < annos.length; aIndex++) readOffset += annos[aIndex].readOffset; } } } return allParamAnnotations; } /** * @param classFileBytes byte[] * @param offsets int[] * @param offset int */ protected MethodInfo (byte classFileBytes[], int offsets[], int offset) { super(classFileBytes, offsets, offset); this.accessFlags = -1; this.signatureUtf8Offset = -1; } public int compareTo(Object o) { MethodInfo otherMethod = (MethodInfo) o; int result = new String(getSelector()).compareTo(new String(otherMethod.getSelector())); if (result != 0) return result; return new String(getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor())); } public boolean equals(Object o) { if (!(o instanceof MethodInfo)) { return false; } MethodInfo otherMethod = (MethodInfo) o; return CharOperation.equals(getSelector(), otherMethod.getSelector()) && CharOperation.equals(getMethodDescriptor(), otherMethod.getMethodDescriptor()); } public int hashCode() { return CharOperation.hashCode(getSelector()) + CharOperation.hashCode(getMethodDescriptor()); } /** * @return the annotations or null if there is none. */ public IBinaryAnnotation[] getAnnotations() { return null; } /** * @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames() */ public char[][] getArgumentNames() { if (this.argumentNames == null) { readCodeAttribute(); } return this.argumentNames; } public Object getDefaultValue() { return null; } /** * Answer the resolved names of the exception types in the * class file format as specified in section 4.2 of the Java 2 VM spec * or null if the array is empty. * * For example, java.lang.String is java/lang/String. * @return char[][] */ public char[][] getExceptionTypeNames() { if (this.exceptionNames == null) { readExceptionAttributes(); } return this.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. * * For example: * - int foo(String) is (Ljava/lang/String;)I * - void foo(Object[]) is (I)[Ljava/lang/Object; * @return char[] */ public char[] getMethodDescriptor() { if (this.descriptor == null) { // read the name int utf8Offset = this.constantPoolOffsets[u2At(4)] - this.structOffset; this.descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } return this.descriptor; } /** * Answer an int whose bits are set according the access constants * defined by the VM spec. * Set the AccDeprecated and AccSynthetic bits if necessary * @return int */ public int getModifiers() { if (this.accessFlags == -1) { // compute the accessflag. Don't forget the deprecated attribute this.accessFlags = u2At(0); readModifierRelatedAttributes(); } return this.accessFlags; } public IBinaryAnnotation[] getParameterAnnotations(int index) { return null; } public int getAnnotatedParametersCount() { return 0; } /** * Answer the name of the method. * * For a constructor, answer & for a clinit method. * @return char[] */ public char[] getSelector() { if (this.name == null) { // read the name int utf8Offset = this.constantPoolOffsets[u2At(2)] - this.structOffset; this.name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } return this.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. */ protected void initialize() { getModifiers(); getSelector(); getMethodDescriptor(); getExceptionTypeNames(); getGenericSignature(); getArgumentNames(); reset(); } /** * Answer true if the method is a class initializer, false otherwise. * @return boolean */ public boolean isClinit() { char[] selector = getSelector(); return selector[0] == '<' && selector.length == 8; // Can only match } /** * Answer true if the method is a constructor, false otherwise. * @return boolean */ public boolean isConstructor() { char[] selector = getSelector(); return selector[0] == '<' && selector.length == 6; // Can only match } /** * Return true if the field is a synthetic method, false otherwise. * @return boolean */ public boolean isSynthetic() { return (getModifiers() & ClassFileConstants.AccSynthetic) != 0; } private void readExceptionAttributes() { int attributesCount = u2At(6); int readOffset = 8; for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.structOffset; char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (CharOperation.equals(attributeName, AttributeNamesConstants.ExceptionsName)) { // read the number of exception entries int entriesNumber = u2At(readOffset + 6); // place the readOffset at the beginning of the exceptions table readOffset += 8; if (entriesNumber == 0) { this.exceptionNames = noException; } else { this.exceptionNames = new char[entriesNumber][]; for (int j = 0; j < entriesNumber; j++) { utf8Offset = this.constantPoolOffsets[u2At( this.constantPoolOffsets[u2At(readOffset)] - this.structOffset + 1)] - this.structOffset; this.exceptionNames[j] = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); readOffset += 2; } } } else { readOffset += (6 + u4At(readOffset + 2)); } } if (this.exceptionNames == null) { this.exceptionNames = noException; } } private void readModifierRelatedAttributes() { int attributesCount = u2At(6); int readOffset = 8; for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.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, AttributeNamesConstants.DeprecatedName)) this.accessFlags |= ClassFileConstants.AccDeprecated; break; case 'S' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName)) this.accessFlags |= ClassFileConstants.AccSynthetic; break; case 'A' : if (CharOperation.equals(attributeName, AttributeNamesConstants.AnnotationDefaultName)) this.accessFlags |= ClassFileConstants.AccAnnotationDefault; break; case 'V' : if (CharOperation.equals(attributeName, AttributeNamesConstants.VarargsName)) this.accessFlags |= ClassFileConstants.AccVarargs; } } readOffset += (6 + u4At(readOffset + 2)); } } /** * Answer the size of the receiver in bytes. * * @return int */ public int sizeInBytes() { return this.attributeBytes; } public String toString() { StringBuffer buffer = new StringBuffer(); toString(buffer); return buffer.toString(); } void toString(StringBuffer buffer) { buffer.append(getClass().getName()); toStringContent(buffer); } protected void toStringContent(StringBuffer buffer) { int modifiers = getModifiers(); char[] desc = getGenericSignature(); if (desc == null) desc = getMethodDescriptor(); buffer .append('{') .append( ((modifiers & ClassFileConstants.AccDeprecated) != 0 ? "deprecated " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0001) == 1 ? "public " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0002) == 0x0002 ? "private " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0004) == 0x0004 ? "protected " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0008) == 0x000008 ? "static " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0010) == 0x0010 ? "final " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0040) == 0x0040 ? "bridge " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0080) == 0x0080 ? "varargs " : Util.EMPTY_STRING)) //$NON-NLS-1$ .append(getSelector()) .append(desc) .append('}'); } private void readCodeAttribute() { int attributesCount = u2At(6); int readOffset = 8; if (attributesCount != 0) { for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.structOffset; char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (CharOperation.equals(attributeName, AttributeNamesConstants.CodeName)) { decodeCodeAttribute(readOffset); if (this.argumentNames == null) { this.argumentNames = noArgumentNames; } return; } else { readOffset += (6 + u4At(readOffset + 2)); } } } this.argumentNames = noArgumentNames; } private void decodeCodeAttribute(int offset) { int readOffset = offset + 10; int codeLength = (int) u4At(readOffset); readOffset += (4 + codeLength); int exceptionTableLength = u2At(readOffset); readOffset += 2; if (exceptionTableLength != 0) { for (int i = 0; i < exceptionTableLength; i++) { readOffset += 8; } } int attributesCount = u2At(readOffset); readOffset += 2; for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.structOffset; char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (CharOperation.equals(attributeName, AttributeNamesConstants.LocalVariableTableName)) { decodeLocalVariableAttribute(readOffset, codeLength); } readOffset += (6 + u4At(readOffset + 2)); } } private void decodeLocalVariableAttribute(int offset, int codeLength) { int readOffset = offset + 6; final int length = u2At(readOffset); if (length != 0) { readOffset += 2; this.argumentNames = new char[length][]; this.argumentNamesIndex = 0; for (int i = 0; i < length; i++) { int startPC = u2At(readOffset); if (startPC == 0) { int nameIndex = u2At(4 + readOffset); int utf8Offset = this.constantPoolOffsets[nameIndex] - this.structOffset; char[] localVariableName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (!CharOperation.equals(localVariableName, ConstantPool.This)) { this.argumentNames[this.argumentNamesIndex++] = localVariableName; } } else { break; } readOffset += 10; } if (this.argumentNamesIndex != this.argumentNames.length) { // resize System.arraycopy(this.argumentNames, 0, (this.argumentNames = new char[this.argumentNamesIndex][]), 0, this.argumentNamesIndex); } } } } ././@LongLink0000644000000000000000000000016612251602427011646 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithParameterAnnotations.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithParamete0000644000175000001440000000462612212041344032400 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2013 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation * IBM Corporation - fix for bug 342757 * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; class MethodInfoWithParameterAnnotations extends MethodInfoWithAnnotations { private AnnotationInfo[][] parameterAnnotations; MethodInfoWithParameterAnnotations(MethodInfo methodInfo, AnnotationInfo[] annotations, AnnotationInfo[][] parameterAnnotations) { super(methodInfo, annotations); this.parameterAnnotations = parameterAnnotations; } public IBinaryAnnotation[] getParameterAnnotations(int index) { return this.parameterAnnotations[index]; } public int getAnnotatedParametersCount() { return this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length; } protected void initialize() { for (int i = 0, l = this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length; i < l; i++) { AnnotationInfo[] infos = this.parameterAnnotations[i]; for (int j = 0, k = infos == null ? 0 : infos.length; j < k; j++) infos[j].initialize(); } super.initialize(); } protected void reset() { for (int i = 0, l = this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length; i < l; i++) { AnnotationInfo[] infos = this.parameterAnnotations[i]; for (int j = 0, k = infos == null ? 0 : infos.length; j < k; j++) infos[j].reset(); } super.reset(); } protected void toStringContent(StringBuffer buffer) { super.toStringContent(buffer); for (int i = 0, l = this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length; i < l; i++) { buffer.append("param" + (i - 1)); //$NON-NLS-1$ buffer.append('\n'); AnnotationInfo[] infos = this.parameterAnnotations[i]; for (int j = 0, k = infos == null ? 0 : infos.length; j < k; j++) { buffer.append(infos[j]); buffer.append('\n'); } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java0000644000175000001440000012557112212041344031744 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 365992 - [builder] [null] Change of nullness for a parameter doesn't trigger a build for the files that call the method *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import org.eclipse.jdt.core.compiler.CharOperation; 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.TypeIds; import org.eclipse.jdt.internal.compiler.util.Util; public class ClassFileReader extends ClassFileStruct implements IBinaryType { private int accessFlags; private char[] classFileName; private char[] className; private int classNameIndex; private int constantPoolCount; private AnnotationInfo[] annotations; private FieldInfo[] fields; private int fieldsCount; // initialized in case the .class file is a nested type private InnerClassInfo innerInfo; private int innerInfoIndex; private InnerClassInfo[] innerInfos; private char[][] interfaceNames; private int interfacesCount; private MethodInfo[] methods; private int methodsCount; private char[] signature; private char[] sourceName; private char[] sourceFileName; private char[] superclassName; private long tagBits; private long version; private char[] enclosingTypeName; private char[][][] missingTypeNames; private int enclosingNameAndTypeIndex; private char[] enclosingMethod; private static String printTypeModifiers(int modifiers) { java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); java.io.PrintWriter print = new java.io.PrintWriter(out); if ((modifiers & ClassFileConstants.AccPublic) != 0) print.print("public "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccPrivate) != 0) print.print("private "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccFinal) != 0) print.print("final "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccSuper) != 0) print.print("super "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccInterface) != 0) print.print("interface "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccAbstract) != 0) print.print("abstract "); //$NON-NLS-1$ print.flush(); return out.toString(); } 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(InputStream stream, String fileName) throws ClassFormatException, IOException { return read(stream, fileName, false); } public static ClassFileReader read(InputStream stream, String fileName, boolean fullyInitialize) throws ClassFormatException, IOException { byte classFileBytes[] = Util.getInputStreamAsByteArray(stream, -1); ClassFileReader classFileReader = new ClassFileReader(classFileBytes, fileName.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); } /** * @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 * * @param fileName char[] * Actual name of the file that contains the bytes, can be null * * @param fullyInitialize boolean * Flag to fully initialize the new object * @exception ClassFormatException */ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInitialize) throws ClassFormatException { // This method looks ugly but is actually quite simple, the constantPool is constructed // in 3 passes. All non-primitive constant pool members that usually refer to other members // by index are tweaked to have their value in inst vars, this minor cost at read-time makes // all subsequent uses of the constant pool element faster. super(classFileBytes, null, 0); this.classFileName = fileName; int readOffset = 10; try { this.version = ((long)u2At(6) << 16) + u2At(4); // major<<16 + minor this.constantPoolCount = u2At(8); // Pass #1 - Fill in all primitive constants this.constantPoolOffsets = new int[this.constantPoolCount]; for (int i = 1; i < this.constantPoolCount; i++) { int tag = u1At(readOffset); switch (tag) { case ClassFileConstants.Utf8Tag : this.constantPoolOffsets[i] = readOffset; readOffset += u2At(readOffset + 1); readOffset += ClassFileConstants.ConstantUtf8FixedSize; break; case ClassFileConstants.IntegerTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantIntegerFixedSize; break; case ClassFileConstants.FloatTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantFloatFixedSize; break; case ClassFileConstants.LongTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantLongFixedSize; i++; break; case ClassFileConstants.DoubleTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantDoubleFixedSize; i++; break; case ClassFileConstants.ClassTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantClassFixedSize; break; case ClassFileConstants.StringTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantStringFixedSize; break; case ClassFileConstants.FieldRefTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantFieldRefFixedSize; break; case ClassFileConstants.MethodRefTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantMethodRefFixedSize; break; case ClassFileConstants.InterfaceMethodRefTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantInterfaceMethodRefFixedSize; break; case ClassFileConstants.NameAndTypeTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantNameAndTypeFixedSize; break; case ClassFileConstants.MethodHandleTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantMethodHandleFixedSize; break; case ClassFileConstants.MethodTypeTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantMethodTypeFixedSize; break; case ClassFileConstants.InvokeDynamicTag : this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantInvokeDynamicFixedSize; break; } } // Read and validate access flags this.accessFlags = u2At(readOffset); readOffset += 2; // Read the classname, use exception handlers to catch bad format this.classNameIndex = u2At(readOffset); this.className = getConstantClassNameAt(this.classNameIndex); readOffset += 2; // Read the superclass name, can be null for java.lang.Object int superclassNameIndex = u2At(readOffset); readOffset += 2; // if superclassNameIndex is equals to 0 there is no need to set a value for the // field this.superclassName. null is fine. if (superclassNameIndex != 0) { this.superclassName = getConstantClassNameAt(superclassNameIndex); } // Read the interfaces, use exception handlers to catch bad format this.interfacesCount = u2At(readOffset); readOffset += 2; if (this.interfacesCount != 0) { this.interfaceNames = new char[this.interfacesCount][]; for (int i = 0; i < this.interfacesCount; i++) { this.interfaceNames[i] = getConstantClassNameAt(u2At(readOffset)); readOffset += 2; } } // Read the fields, use exception handlers to catch bad format this.fieldsCount = u2At(readOffset); readOffset += 2; if (this.fieldsCount != 0) { FieldInfo field; this.fields = new FieldInfo[this.fieldsCount]; for (int i = 0; i < this.fieldsCount; i++) { field = FieldInfo.createField(this.reference, this.constantPoolOffsets, readOffset); this.fields[i] = field; readOffset += field.sizeInBytes(); } } // Read the methods this.methodsCount = u2At(readOffset); readOffset += 2; if (this.methodsCount != 0) { this.methods = new MethodInfo[this.methodsCount]; boolean isAnnotationType = (this.accessFlags & ClassFileConstants.AccAnnotation) != 0; for (int i = 0; i < this.methodsCount; i++) { this.methods[i] = isAnnotationType ? AnnotationMethodInfo.createAnnotationMethod(this.reference, this.constantPoolOffsets, readOffset) : MethodInfo.createMethod(this.reference, this.constantPoolOffsets, readOffset); readOffset += this.methods[i].sizeInBytes(); } } // Read the attributes int attributesCount = u2At(readOffset); readOffset += 2; for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)]; char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (attributeName.length == 0) { readOffset += (6 + u4At(readOffset + 2)); continue; } switch(attributeName[0] ) { case 'E' : if (CharOperation.equals(attributeName, AttributeNamesConstants.EnclosingMethodName)) { utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[u2At(readOffset + 6)] + 1)]; this.enclosingTypeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); this.enclosingNameAndTypeIndex = u2At(readOffset + 8); } break; case 'D' : if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName)) { this.accessFlags |= ClassFileConstants.AccDeprecated; } break; case 'I' : if (CharOperation.equals(attributeName, AttributeNamesConstants.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(this.reference, this.constantPoolOffsets, innerOffset); if (this.classNameIndex == this.innerInfos[j].innerClassNameIndex) { this.innerInfo = this.innerInfos[j]; this.innerInfoIndex = j; } innerOffset += 8; } if (this.innerInfo != null) { char[] enclosingType = this.innerInfo.getEnclosingTypeName(); if (enclosingType != null) { this.enclosingTypeName = enclosingType; } } } } else if (CharOperation.equals(attributeName, AttributeNamesConstants.InconsistentHierarchy)) { this.tagBits |= TagBits.HierarchyHasProblems; } break; case 'S' : if (attributeName.length > 2) { switch(attributeName[1]) { case 'o' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SourceName)) { utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)]; this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } break; case 'y' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName)) { this.accessFlags |= ClassFileConstants.AccSynthetic; } break; case 'i' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SignatureName)) { utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)]; this.signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } } } break; case 'R' : if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) { decodeAnnotations(readOffset, true); } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) { decodeAnnotations(readOffset, false); } break; case 'M' : if (CharOperation.equals(attributeName, AttributeNamesConstants.MissingTypesName)) { // decode the missing types int missingTypeOffset = readOffset + 6; int numberOfMissingTypes = u2At(missingTypeOffset); if (numberOfMissingTypes != 0) { this.missingTypeNames = new char[numberOfMissingTypes][][]; missingTypeOffset += 2; for (int j = 0; j < numberOfMissingTypes; j++) { utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[u2At(missingTypeOffset)] + 1)]; char[] missingTypeConstantPoolName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); this.missingTypeNames[j] = CharOperation.splitOn('/', missingTypeConstantPoolName); missingTypeOffset += 2; } } } } readOffset += (6 + u4At(readOffset + 2)); } if (fullyInitialize) { initialize(); } } catch(ClassFormatException e) { throw e; } catch (Exception e) { throw new ClassFormatException( ClassFormatException.ErrTruncatedInput, readOffset); } } /** * 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 */ public int accessFlags() { return this.accessFlags; } private void decodeAnnotations(int offset, boolean runtimeVisible) { int numberOfAnnotations = u2At(offset + 6); if (numberOfAnnotations > 0) { int readOffset = offset + 8; AnnotationInfo[] newInfos = null; int newInfoCount = 0; for (int i = 0; i < numberOfAnnotations; i++) { // With the last parameter being 'false', the data structure will not be flushed out AnnotationInfo newInfo = new AnnotationInfo(this.reference, this.constantPoolOffsets, readOffset, runtimeVisible, false); readOffset += newInfo.readOffset; long standardTagBits = newInfo.standardAnnotationTagBits; if (standardTagBits != 0) { this.tagBits |= standardTagBits; } else { if (newInfos == null) newInfos = new AnnotationInfo[numberOfAnnotations - i]; newInfos[newInfoCount++] = newInfo; } } if (newInfos == null) return; // nothing to record in this.annotations if (this.annotations == null) { if (newInfoCount != newInfos.length) System.arraycopy(newInfos, 0, newInfos = new AnnotationInfo[newInfoCount], 0, newInfoCount); this.annotations = newInfos; } else { int length = this.annotations.length; AnnotationInfo[] temp = new AnnotationInfo[length + newInfoCount]; System.arraycopy(this.annotations, 0, temp, 0, length); System.arraycopy(newInfos, 0, temp, length, newInfoCount); this.annotations = temp; } } } /** * @return the annotations or null if there is none. */ public IBinaryAnnotation[] getAnnotations() { return this.annotations; } /** * 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. * * @param constantPoolIndex int * @return char[] */ private char[] getConstantClassNameAt(int constantPoolIndex) { int utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[constantPoolIndex] + 1)]; return utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } /** * Answer the int array that corresponds to all the offsets of each entry in the constant pool * * @return int[] */ public int[] getConstantPoolOffsets() { return this.constantPoolOffsets; } public char[] getEnclosingMethod() { if (this.enclosingNameAndTypeIndex <= 0) { return null; } if (this.enclosingMethod == null) { // read the name StringBuffer buffer = new StringBuffer(); int nameAndTypeOffset = this.constantPoolOffsets[this.enclosingNameAndTypeIndex]; int utf8Offset = this.constantPoolOffsets[u2At(nameAndTypeOffset + 1)]; buffer.append(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); utf8Offset = this.constantPoolOffsets[u2At(nameAndTypeOffset + 3)]; buffer.append(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); this.enclosingMethod = String.valueOf(buffer).toCharArray(); } return this.enclosingMethod; } /* * Answer the resolved compoundName of the enclosing type * or null if the receiver is a top level type. */ public char[] getEnclosingTypeName() { return this.enclosingTypeName; } /** * Answer the receiver's this.fields or null if the array is empty. * @return org.eclipse.jdt.internal.compiler.api.IBinaryField[] */ public IBinaryField[] getFields() { return this.fields; } /** * @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. * public class A { * public class B { * } * public void foo() { * class C {} * } * public Runnable bar() { * return new Runnable() { * public void run() {} * }; * } * } * It returns {'B'} for the member A$B * It returns null for A * It returns {'C'} for the local class A$1$C * It returns null for the anonymous A$1 * @return char[] */ public char[] getInnerSourceName() { if (this.innerInfo != null) return this.innerInfo.getSourceName(); return null; } /** * Answer the resolved names of the receiver's interfaces in the * class file format as specified in section 4.2 of the Java 2 VM spec * or null if the array is empty. * * For example, java.lang.String is java/lang/String. * @return char[][] */ public char[][] getInterfaceNames() { return this.interfaceNames; } /** * 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 * * @return org.eclipse.jdt.internal.compiler.api.IBinaryNestedType[] */ public IBinaryNestedType[] getMemberTypes() { // we might have some member types of the current type if (this.innerInfos == null) return null; int length = this.innerInfos.length; int startingIndex = this.innerInfo != null ? this.innerInfoIndex + 1 : 0; if (length != startingIndex) { IBinaryNestedType[] memberTypes = new IBinaryNestedType[length - this.innerInfoIndex]; int memberTypeIndex = 0; for (int i = startingIndex; i < length; i++) { InnerClassInfo currentInnerInfo = this.innerInfos[i]; int outerClassNameIdx = currentInnerInfo.outerClassNameIndex; int innerNameIndex = currentInnerInfo.innerNameIndex; /* * Checking that outerClassNameIDx is different from 0 should be enough to determine if an inner class * attribute entry is a member class, but due to the bug: * http://dev.eclipse.org/bugs/show_bug.cgi?id=14592 * we needed to add an extra check. So we check that innerNameIndex is different from 0 as well. * * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49879 * From JavaMail 1.2, the class javax.mail.Folder contains an anonymous class in the * terminateQueue() method for which the inner attribute is boggus. * outerClassNameIdx is not 0, innerNameIndex is not 0, but the sourceName length is 0. * So I added this extra check to filter out this anonymous class from the * member types. */ if (outerClassNameIdx != 0 && innerNameIndex != 0 && outerClassNameIdx == this.classNameIndex && currentInnerInfo.getSourceName().length != 0) { memberTypes[memberTypeIndex++] = currentInnerInfo; } } if (memberTypeIndex == 0) return null; if (memberTypeIndex != memberTypes.length) { // we need to resize the memberTypes array. Some local or anonymous classes // are present in the current class. System.arraycopy( memberTypes, 0, (memberTypes = new IBinaryNestedType[memberTypeIndex]), 0, memberTypeIndex); } return memberTypes; } return null; } /** * Answer the receiver's this.methods or null if the array is empty. * @return org.eclipse.jdt.internal.compiler.api.env.IBinaryMethod[] */ public IBinaryMethod[] getMethods() { return this.methods; } /* public static void main(String[] args) throws ClassFormatException, IOException { if (args == null || args.length != 1) { System.err.println("ClassFileReader "); //$NON-NLS-1$ System.exit(1); } File file = new File(args[0]); ClassFileReader reader = read(file, true); if (reader.annotations != null) { System.err.println(); for (int i = 0; i < reader.annotations.length; i++) System.err.println(reader.annotations[i]); } System.err.print("class "); //$NON-NLS-1$ System.err.print(reader.getName()); char[] superclass = reader.getSuperclassName(); if (superclass != null) { System.err.print(" extends "); //$NON-NLS-1$ System.err.print(superclass); } System.err.println(); char[][] interfaces = reader.getInterfaceNames(); if (interfaces != null && interfaces.length > 0) { System.err.print(" implements "); //$NON-NLS-1$ for (int i = 0; i < interfaces.length; i++) { if (i != 0) System.err.print(", "); //$NON-NLS-1$ System.err.println(interfaces[i]); } } System.err.println(); System.err.println('{'); if (reader.fields != null) { for (int i = 0; i < reader.fields.length; i++) { System.err.println(reader.fields[i]); System.err.println(); } } if (reader.methods != null) { for (int i = 0; i < reader.methods.length; i++) { System.err.println(reader.methods[i]); System.err.println(); } } System.err.println(); System.err.println('}'); } */ public char[][][] getMissingTypeNames() { return this.missingTypeNames; } /** * Answer an int whose bits are set according the access constants * defined by the VM spec. * Set the AccDeprecated and AccSynthetic bits if necessary * @return int */ public int getModifiers() { int modifiers; if (this.innerInfo != null) { modifiers = this.innerInfo.getModifiers() | (this.accessFlags & ClassFileConstants.AccDeprecated) | (this.accessFlags & ClassFileConstants.AccSynthetic); } else { modifiers = this.accessFlags; } return modifiers; } /** * Answer the resolved name of the type in the * class file format as specified in section 4.2 of the Java 2 VM spec. * * For example, java.lang.String is java/lang/String. * @return char[] */ public char[] getName() { return this.className; } public char[] getSourceName() { if (this.sourceName != null) return this.sourceName; char[] name = getInnerSourceName(); // member or local scenario if (name == null) { name = getName(); // extract from full name int start; if (isAnonymous()) { start = CharOperation.indexOf('$', name, CharOperation.lastIndexOf('/', name) + 1) + 1; } else { start = CharOperation.lastIndexOf('/', name) + 1; } if (start > 0) { char[] newName = new char[name.length - start]; System.arraycopy(name, start, newName, 0, newName.length); name = newName; } } return this.sourceName = name; } /** * 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 * or null if it does not have one. * * For example, java.lang.String is java/lang/String. * @return char[] */ 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 * @return the major/minor version found */ public long getVersion() { return this.version; } 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 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; } /** * Check if the receiver has structural changes compare to the byte array in argument. * Structural changes are: * - modifiers changes for the class, the this.fields or the this.methods * - signature changes for this.fields or this.methods. * - changes in the number of this.fields or this.methods * - changes for field constants * - changes for thrown exceptions * - change for the super class or any super interfaces. * - changes for member types name or modifiers * If any of these changes occurs, the method returns true. false otherwise. * The synthetic fields are included and the members are not required to be sorted. * @param newBytes the bytes of the .class file we want to compare the receiver to * @return boolean Returns true is there is a structural change between the two .class files, false otherwise */ public boolean hasStructuralChanges(byte[] newBytes) { return hasStructuralChanges(newBytes, true, true); } /** * Check if the receiver has structural changes compare to the byte array in argument. * Structural changes are: * - modifiers changes for the class, the this.fields or the this.methods * - signature changes for this.fields or this.methods. * - changes in the number of this.fields or this.methods * - changes for field constants * - changes for thrown exceptions * - change for the super class or any super interfaces. * - changes for member types name or modifiers * If any of these changes occurs, the method returns true. false otherwise. * @param newBytes the bytes of the .class file we want to compare the receiver to * @param orderRequired a boolean indicating whether the members should be sorted or not * @param excludesSynthetic a boolean indicating whether the synthetic members should be used in the comparison * @return boolean Returns true is there is a structural change between the two .class files, false otherwise */ public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, boolean excludesSynthetic) { try { ClassFileReader newClassFile = new ClassFileReader(newBytes, this.classFileName); // type level comparison // modifiers if (getModifiers() != newClassFile.getModifiers()) return true; // only consider a portion of the tagbits which indicate a structural change for dependents // e.g. @Override change has no influence outside long OnlyStructuralTagBits = TagBits.AnnotationTargetMASK // different @Target status ? | TagBits.AnnotationDeprecated // different @Deprecated status ? | TagBits.AnnotationRetentionMASK // different @Retention status ? | TagBits.HierarchyHasProblems; // different hierarchy status ? // meta-annotations if ((getTagBits() & OnlyStructuralTagBits) != (newClassFile.getTagBits() & OnlyStructuralTagBits)) return true; // annotations if (hasStructuralAnnotationChanges(getAnnotations(), newClassFile.getAnnotations())) return true; // generic signature if (!CharOperation.equals(getGenericSignature(), newClassFile.getGenericSignature())) return true; // superclass if (!CharOperation.equals(getSuperclassName(), newClassFile.getSuperclassName())) return true; // interfaces char[][] newInterfacesNames = newClassFile.getInterfaceNames(); if (this.interfaceNames != newInterfacesNames) { // TypeConstants.NoSuperInterfaces int newInterfacesLength = newInterfacesNames == null ? 0 : newInterfacesNames.length; if (newInterfacesLength != this.interfacesCount) return true; for (int i = 0, max = this.interfacesCount; i < max; i++) if (!CharOperation.equals(this.interfaceNames[i], newInterfacesNames[i])) return true; } // member types IBinaryNestedType[] currentMemberTypes = getMemberTypes(); IBinaryNestedType[] otherMemberTypes = newClassFile.getMemberTypes(); if (currentMemberTypes != otherMemberTypes) { // TypeConstants.NoMemberTypes int currentMemberTypeLength = currentMemberTypes == null ? 0 : currentMemberTypes.length; int otherMemberTypeLength = otherMemberTypes == null ? 0 : otherMemberTypes.length; if (currentMemberTypeLength != otherMemberTypeLength) return true; for (int i = 0; i < currentMemberTypeLength; i++) if (!CharOperation.equals(currentMemberTypes[i].getName(), otherMemberTypes[i].getName()) || currentMemberTypes[i].getModifiers() != otherMemberTypes[i].getModifiers()) return true; } // fields FieldInfo[] otherFieldInfos = (FieldInfo[]) newClassFile.getFields(); int otherFieldInfosLength = otherFieldInfos == null ? 0 : otherFieldInfos.length; boolean compareFields = true; if (this.fieldsCount == otherFieldInfosLength) { int i = 0; for (; i < this.fieldsCount; i++) if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i])) break; if ((compareFields = i != this.fieldsCount) && !orderRequired && !excludesSynthetic) return true; } if (compareFields) { if (this.fieldsCount != otherFieldInfosLength && !excludesSynthetic) return true; if (orderRequired) { if (this.fieldsCount != 0) Arrays.sort(this.fields); if (otherFieldInfosLength != 0) Arrays.sort(otherFieldInfos); } if (excludesSynthetic) { if (hasNonSyntheticFieldChanges(this.fields, otherFieldInfos)) return true; } else { for (int i = 0; i < this.fieldsCount; i++) if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i])) return true; } } // methods MethodInfo[] otherMethodInfos = (MethodInfo[]) newClassFile.getMethods(); int otherMethodInfosLength = otherMethodInfos == null ? 0 : otherMethodInfos.length; boolean compareMethods = true; if (this.methodsCount == otherMethodInfosLength) { int i = 0; for (; i < this.methodsCount; i++) if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i])) break; if ((compareMethods = i != this.methodsCount) && !orderRequired && !excludesSynthetic) return true; } if (compareMethods) { if (this.methodsCount != otherMethodInfosLength && !excludesSynthetic) return true; if (orderRequired) { if (this.methodsCount != 0) Arrays.sort(this.methods); if (otherMethodInfosLength != 0) Arrays.sort(otherMethodInfos); } if (excludesSynthetic) { if (hasNonSyntheticMethodChanges(this.methods, otherMethodInfos)) return true; } else { for (int i = 0; i < this.methodsCount; i++) if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i])) return true; } } // missing types char[][][] missingTypes = getMissingTypeNames(); char[][][] newMissingTypes = newClassFile.getMissingTypeNames(); if (missingTypes != null) { if (newMissingTypes == null) { return true; } int length = missingTypes.length; if (length != newMissingTypes.length) { return true; } for (int i = 0; i < length; i++) { if (!CharOperation.equals(missingTypes[i], newMissingTypes[i])) { return true; } } } else if (newMissingTypes != null) { return true; } return false; } catch (ClassFormatException e) { return true; } } private boolean hasStructuralAnnotationChanges(IBinaryAnnotation[] currentAnnotations, IBinaryAnnotation[] otherAnnotations) { if (currentAnnotations == otherAnnotations) return false; int currentAnnotationsLength = currentAnnotations == null ? 0 : currentAnnotations.length; int otherAnnotationsLength = otherAnnotations == null ? 0 : otherAnnotations.length; if (currentAnnotationsLength != otherAnnotationsLength) return true; for (int i = 0; i < currentAnnotationsLength; i++) { if (!CharOperation.equals(currentAnnotations[i].getTypeName(), otherAnnotations[i].getTypeName())) return true; IBinaryElementValuePair[] currentPairs = currentAnnotations[i].getElementValuePairs(); IBinaryElementValuePair[] otherPairs = otherAnnotations[i].getElementValuePairs(); int currentPairsLength = currentPairs == null ? 0 : currentPairs.length; int otherPairsLength = otherPairs == null ? 0 : otherPairs.length; if (currentPairsLength != otherPairsLength) return true; for (int j = 0; j < currentPairsLength; j++) { if (!CharOperation.equals(currentPairs[j].getName(), otherPairs[j].getName())) return true; final Object value = currentPairs[j].getValue(); final Object value2 = otherPairs[j].getValue(); if (value instanceof Object[]) { Object[] currentValues = (Object[]) value; if (value2 instanceof Object[]) { Object[] currentValues2 = (Object[]) value2; final int length = currentValues.length; if (length != currentValues2.length) { return true; } for (int n = 0; n < length; n++) { if (!currentValues[n].equals(currentValues2[n])) { return true; } } return false; } return true; } else if (!value.equals(value2)) { return true; } } } return false; } private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfo, FieldInfo otherFieldInfo) { // generic signature if (!CharOperation.equals(currentFieldInfo.getGenericSignature(), otherFieldInfo.getGenericSignature())) return true; if (currentFieldInfo.getModifiers() != otherFieldInfo.getModifiers()) return true; if ((currentFieldInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherFieldInfo.getTagBits() & TagBits.AnnotationDeprecated)) return true; if (hasStructuralAnnotationChanges(currentFieldInfo.getAnnotations(), otherFieldInfo.getAnnotations())) return true; if (!CharOperation.equals(currentFieldInfo.getName(), otherFieldInfo.getName())) return true; if (!CharOperation.equals(currentFieldInfo.getTypeName(), otherFieldInfo.getTypeName())) return true; if (currentFieldInfo.hasConstant() != otherFieldInfo.hasConstant()) return true; if (currentFieldInfo.hasConstant()) { Constant currentConstant = currentFieldInfo.getConstant(); Constant otherConstant = otherFieldInfo.getConstant(); if (currentConstant.typeID() != otherConstant.typeID()) return true; if (!currentConstant.getClass().equals(otherConstant.getClass())) return true; switch (currentConstant.typeID()) { case TypeIds.T_int : return currentConstant.intValue() != otherConstant.intValue(); case TypeIds.T_byte : return currentConstant.byteValue() != otherConstant.byteValue(); case TypeIds.T_short : return currentConstant.shortValue() != otherConstant.shortValue(); case TypeIds.T_char : return currentConstant.charValue() != otherConstant.charValue(); case TypeIds.T_long : return currentConstant.longValue() != otherConstant.longValue(); case TypeIds.T_float : return currentConstant.floatValue() != otherConstant.floatValue(); case TypeIds.T_double : return currentConstant.doubleValue() != otherConstant.doubleValue(); case TypeIds.T_boolean : return currentConstant.booleanValue() != otherConstant.booleanValue(); case TypeIds.T_JavaLangString : return !currentConstant.stringValue().equals(otherConstant.stringValue()); } } return false; } private boolean hasStructuralMethodChanges(MethodInfo currentMethodInfo, MethodInfo otherMethodInfo) { // generic signature if (!CharOperation.equals(currentMethodInfo.getGenericSignature(), otherMethodInfo.getGenericSignature())) return true; if (currentMethodInfo.getModifiers() != otherMethodInfo.getModifiers()) return true; if ((currentMethodInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherMethodInfo.getTagBits() & TagBits.AnnotationDeprecated)) return true; if (hasStructuralAnnotationChanges(currentMethodInfo.getAnnotations(), otherMethodInfo.getAnnotations())) return true; // parameter annotations: int currentAnnotatedParamsCount = currentMethodInfo.getAnnotatedParametersCount(); int otherAnnotatedParamsCount = otherMethodInfo.getAnnotatedParametersCount(); if (currentAnnotatedParamsCount != otherAnnotatedParamsCount) return true; for (int i=0; iboolean */ public boolean isAnonymous() { if (this.innerInfo == null) return false; char[] innerSourceName = this.innerInfo.getSourceName(); return (innerSourceName == null || innerSourceName.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[] innerSourceName = this.innerInfo.getSourceName(); return (innerSourceName != null && innerSourceName.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[] innerSourceName = this.innerInfo.getSourceName(); return (innerSourceName != null && innerSourceName.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; } /** * 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(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: " + printTypeModifiers(accessFlags()) + "(" + accessFlags() + ")"); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$ print.flush(); return out.toString(); } } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.j0000644000175000001440000001112612212041344032341 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2009 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; public class AnnotationMethodInfo extends MethodInfo { protected Object defaultValue = null; public static MethodInfo createAnnotationMethod(byte classFileBytes[], int offsets[], int offset) { MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset); int attributesCount = methodInfo.u2At(6); int readOffset = 8; AnnotationInfo[] annotations = null; Object defaultValue = null; for (int i = 0; i < attributesCount; i++) { // check the name of each attribute int utf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset)] - methodInfo.structOffset; char[] attributeName = methodInfo.utf8At(utf8Offset + 3, methodInfo.u2At(utf8Offset + 1)); if (attributeName.length > 0) { switch(attributeName[0]) { case 'A': if (CharOperation.equals(attributeName, AttributeNamesConstants.AnnotationDefaultName)) { // readOffset + 6 so the offset is at the start of the 'member_value' entry // u2 attribute_name_index + u4 attribute_length = + 6 AnnotationInfo info = new AnnotationInfo(methodInfo.reference, methodInfo.constantPoolOffsets, readOffset + 6 + methodInfo.structOffset); defaultValue = info.decodeDefaultValue(); } break; case 'S' : if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) methodInfo.signatureUtf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset + 6)] - methodInfo.structOffset; break; case 'R' : AnnotationInfo[] methodAnnotations = null; if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) { methodAnnotations = decodeMethodAnnotations(readOffset, true, methodInfo); } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) { methodAnnotations = decodeMethodAnnotations(readOffset, false, methodInfo); } if (methodAnnotations != null) { if (annotations == null) { annotations = methodAnnotations; } else { int length = annotations.length; AnnotationInfo[] newAnnotations = new AnnotationInfo[length + methodAnnotations.length]; System.arraycopy(annotations, 0, newAnnotations, 0, length); System.arraycopy(methodAnnotations, 0, newAnnotations, length, methodAnnotations.length); annotations = newAnnotations; } } break; } } readOffset += (6 + methodInfo.u4At(readOffset + 2)); } methodInfo.attributeBytes = readOffset; if (defaultValue != null) { if (annotations != null) { return new AnnotationMethodInfoWithAnnotations(methodInfo, defaultValue, annotations); } return new AnnotationMethodInfo(methodInfo, defaultValue); } if (annotations != null) return new MethodInfoWithAnnotations(methodInfo, annotations); return methodInfo; } AnnotationMethodInfo(MethodInfo methodInfo, Object defaultValue) { super(methodInfo.reference, methodInfo.constantPoolOffsets, methodInfo.structOffset); this.defaultValue = defaultValue; this.accessFlags = methodInfo.accessFlags; this.attributeBytes = methodInfo.attributeBytes; this.descriptor = methodInfo.descriptor; this.exceptionNames = methodInfo.exceptionNames; this.name = methodInfo.name; this.signature = methodInfo.signature; this.signatureUtf8Offset = methodInfo.signatureUtf8Offset; this.tagBits = methodInfo.tagBits; } public Object getDefaultValue() { return this.defaultValue; } protected void toStringContent(StringBuffer buffer) { super.toStringContent(buffer); if (this.defaultValue != null) { buffer.append(" default "); //$NON-NLS-1$ if (this.defaultValue instanceof Object[]) { buffer.append('{'); Object[] elements = (Object[]) this.defaultValue; for (int i = 0, len = elements.length; i < len; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append(elements[i]); } buffer.append('}'); } else { buffer.append(this.defaultValue); } buffer.append('\n'); } } } ././@LongLink0000644000000000000000000000015312251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/FieldInfoWithAnnotation.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/FieldInfoWithAnnotatio0000644000175000001440000000373212212041344032376 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2009 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; public final class FieldInfoWithAnnotation extends FieldInfo { private AnnotationInfo[] annotations; FieldInfoWithAnnotation(FieldInfo info, AnnotationInfo[] annos) { super(info.reference, info.constantPoolOffsets, info.structOffset); this.accessFlags = info.accessFlags; this.attributeBytes = info.attributeBytes; this.constant = info.constant; this.constantPoolOffsets = info.constantPoolOffsets; this.descriptor = info.descriptor; this.name = info.name; this.signature = info.signature; this.signatureUtf8Offset = info.signatureUtf8Offset; this.tagBits = info.tagBits; this.wrappedConstantValue = info.wrappedConstantValue; this.annotations = annos; } public org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation[] getAnnotations() { return this.annotations; } protected void initialize() { for (int i = 0, max = this.annotations.length; i < max; i++) this.annotations[i].initialize(); super.initialize(); } protected void reset() { if (this.annotations != null) for (int i = 0, max = this.annotations.length; i < max; i++) this.annotations[i].reset(); super.reset(); } public String toString() { StringBuffer buffer = new StringBuffer(getClass().getName()); if (this.annotations != null) { buffer.append('\n'); for (int i = 0; i < this.annotations.length; i++) { buffer.append(this.annotations[i]); buffer.append('\n'); } } toStringContent(buffer); return buffer.toString(); } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.jav0000644000175000001440000001135212212041344032344 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.internal.compiler.ast.ASTNode; public interface ClassFileConstants { int AccDefault = 0; /* * Modifiers */ 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 AccAnnotation = 0x2000; int AccEnum = 0x4000; /** * Other VM flags. */ int AccSuper = 0x0020; /** * Extra flags for types and members attributes. */ int AccAnnotationDefault = ASTNode.Bit18; // indicate presence of an attribute "DefaultValue" (annotation method) int AccDeprecated = ASTNode.Bit21; // indicate presence of an attribute "Deprecated" int Utf8Tag = 1; int IntegerTag = 3; int FloatTag = 4; int LongTag = 5; int DoubleTag = 6; int ClassTag = 7; int StringTag = 8; int FieldRefTag = 9; int MethodRefTag = 10; int InterfaceMethodRefTag = 11; int NameAndTypeTag = 12; int MethodHandleTag = 15; int MethodTypeTag = 16; int InvokeDynamicTag = 18; int ConstantMethodRefFixedSize = 5; int ConstantClassFixedSize = 3; int ConstantDoubleFixedSize = 9; int ConstantFieldRefFixedSize = 5; int ConstantFloatFixedSize = 5; int ConstantIntegerFixedSize = 5; int ConstantInterfaceMethodRefFixedSize = 5; int ConstantLongFixedSize = 9; int ConstantStringFixedSize = 3; int ConstantUtf8FixedSize = 3; int ConstantNameAndTypeFixedSize = 5; int ConstantMethodHandleFixedSize = 4; int ConstantMethodTypeFixedSize = 3; int ConstantInvokeDynamicFixedSize = 5; int MAJOR_VERSION_1_1 = 45; int MAJOR_VERSION_1_2 = 46; int MAJOR_VERSION_1_3 = 47; int MAJOR_VERSION_1_4 = 48; int MAJOR_VERSION_1_5 = 49; int MAJOR_VERSION_1_6 = 50; int MAJOR_VERSION_1_7 = 51; int MAJOR_VERSION_1_8 = 52; // Oracle has not updated this as of JDK8b39, i.e it still says 51. int MINOR_VERSION_0 = 0; int MINOR_VERSION_1 = 1; int MINOR_VERSION_2 = 2; int MINOR_VERSION_3 = 3; int MINOR_VERSION_4 = 4; // JDK 1.1 -> 1.8, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0 // 16 unsigned bits for major, then 16 bits for minor long JDK1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3; // 1.1. is 45.3 long JDK1_2 = ((long)ClassFileConstants.MAJOR_VERSION_1_2 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_3 = ((long)ClassFileConstants.MAJOR_VERSION_1_3 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_4 = ((long)ClassFileConstants.MAJOR_VERSION_1_4 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_5 = ((long)ClassFileConstants.MAJOR_VERSION_1_5 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_6 = ((long)ClassFileConstants.MAJOR_VERSION_1_6 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_7 = ((long)ClassFileConstants.MAJOR_VERSION_1_7 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_8 = ((long)ClassFileConstants.MAJOR_VERSION_1_8 << 16) + ClassFileConstants.MINOR_VERSION_0; /* * cldc1.1 is 45.3, but we modify it to be different from JDK1_1. * In the code gen, we will generate the same target value as JDK1_1 */ long CLDC_1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_4; // 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; 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; // Debug attributes int ATTR_SOURCE = 0x1; // SourceFileAttribute int ATTR_LINES = 0x2; // LineNumberAttribute int ATTR_VARS = 0x4; // LocalVariableTableAttribute int ATTR_STACK_MAP_TABLE = 0x8; // Stack map table attribute int ATTR_STACK_MAP = 0x10; // Stack map attribute: cldc } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ElementValuePairInfo.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ElementValuePairInfo.j0000644000175000001440000000436312212041344032275 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2010 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation * olivier_thomann@ca.ibm.com - add hashCode() and equals(..) methods *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import java.util.Arrays; import org.eclipse.jdt.core.compiler.CharOperation; public class ElementValuePairInfo implements org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair { static final ElementValuePairInfo[] NoMembers = new ElementValuePairInfo[0]; private char[] name; private Object value; ElementValuePairInfo(char[] name, Object value) { this.name = name; this.value = value; } public char[] getName() { return this.name; } public Object getValue() { return this.value; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(this.name); buffer.append('='); if (this.value instanceof Object[]) { final Object[] values = (Object[]) this.value; buffer.append('{'); for (int i = 0, l = values.length; i < l; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append(values[i]); } buffer.append('}'); } else { buffer.append(this.value); } return buffer.toString(); } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + CharOperation.hashCode(this.name); result = prime * result + ((this.value == null) ? 0 : this.value.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ElementValuePairInfo other = (ElementValuePairInfo) obj; if (!Arrays.equals(this.name, other.name)) { return false; } if (this.value == null) { if (other.value != null) { return false; } } else if (!this.value.equals(other.value)) { return false; } return true; } } ././@LongLink0000644000000000000000000000015512251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotati0000644000175000001440000000376512212041344032422 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2007 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; public class MethodInfoWithAnnotations extends MethodInfo { protected AnnotationInfo[] annotations; MethodInfoWithAnnotations(MethodInfo methodInfo, AnnotationInfo[] annotations) { super(methodInfo.reference, methodInfo.constantPoolOffsets, methodInfo.structOffset); this.annotations = annotations; this.accessFlags = methodInfo.accessFlags; this.attributeBytes = methodInfo.attributeBytes; this.descriptor = methodInfo.descriptor; this.exceptionNames = methodInfo.exceptionNames; this.name = methodInfo.name; this.signature = methodInfo.signature; this.signatureUtf8Offset = methodInfo.signatureUtf8Offset; this.tagBits = methodInfo.tagBits; } public IBinaryAnnotation[] getAnnotations() { return this.annotations; } protected void initialize() { for (int i = 0, l = this.annotations == null ? 0 : this.annotations.length; i < l; i++) if (this.annotations[i] != null) this.annotations[i].initialize(); super.initialize(); } protected void reset() { for (int i = 0, l = this.annotations == null ? 0 : this.annotations.length; i < l; i++) if (this.annotations[i] != null) this.annotations[i].reset(); super.reset(); } protected void toStringContent(StringBuffer buffer) { super.toStringContent(buffer); for (int i = 0, l = this.annotations == null ? 0 : this.annotations.length; i < l; i++) { buffer.append(this.annotations[i]); buffer.append('\n'); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java0000644000175000001440000000637312212041344032024 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; abstract public class ClassFileStruct { byte[] reference; int[] constantPoolOffsets; int structOffset; public ClassFileStruct(byte[] classFileBytes, int[] offsets, int offset) { this.reference = classFileBytes; this.constantPoolOffsets = offsets; this.structOffset = offset; } public double doubleAt(int relativeOffset) { return (Double.longBitsToDouble(i8At(relativeOffset))); } public float floatAt(int relativeOffset) { return (Float.intBitsToFloat(i4At(relativeOffset))); } public int i4At(int relativeOffset) { int position = relativeOffset + this.structOffset; return ((this.reference[position++] & 0xFF) << 24) | ((this.reference[position++] & 0xFF) << 16) | ((this.reference[position++] & 0xFF) << 8) + (this.reference[position] & 0xFF); } public long i8At(int relativeOffset) { int position = relativeOffset + this.structOffset; return (((long) (this.reference[position++] & 0xFF)) << 56) | (((long) (this.reference[position++] & 0xFF)) << 48) | (((long) (this.reference[position++] & 0xFF)) << 40) | (((long) (this.reference[position++] & 0xFF)) << 32) | (((long) (this.reference[position++] & 0xFF)) << 24) | (((long) (this.reference[position++] & 0xFF)) << 16) | (((long) (this.reference[position++] & 0xFF)) << 8) | (this.reference[position++] & 0xFF); } protected void reset() { this.reference = null; this.constantPoolOffsets = null; } public int u1At(int relativeOffset) { return (this.reference[relativeOffset + this.structOffset] & 0xFF); } public int u2At(int relativeOffset) { int position = relativeOffset + this.structOffset; return ((this.reference[position++] & 0xFF) << 8) | (this.reference[position] & 0xFF); } public long u4At(int relativeOffset) { int position = relativeOffset + this.structOffset; return (((this.reference[position++] & 0xFFL) << 24) | ((this.reference[position++] & 0xFF) << 16) | ((this.reference[position++] & 0xFF) << 8) | (this.reference[position] & 0xFF)); } public char[] utf8At(int relativeOffset, int bytesAvailable) { int length = bytesAvailable; char outputBuf[] = new char[bytesAvailable]; int outputPos = 0; int readOffset = this.structOffset + relativeOffset; while (length != 0) { int x = this.reference[readOffset++] & 0xFF; length--; if ((0x80 & x) != 0) { if ((x & 0x20) != 0) { length-=2; x = ((x & 0xF) << 12) | ((this.reference[readOffset++] & 0x3F) << 6) | (this.reference[readOffset++] & 0x3F); } else { length--; x = ((x & 0x1F) << 6) | (this.reference[readOffset++] & 0x3F); } } outputBuf[outputPos++] = (char) x; } if (outputPos != bytesAvailable) { System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]), 0, outputPos); } return outputBuf; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java0000644000175000001440000003237312212041344030610 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryField; import org.eclipse.jdt.internal.compiler.impl.*; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.util.Util; public class FieldInfo extends ClassFileStruct implements IBinaryField, Comparable { protected int accessFlags; protected int attributeBytes; protected Constant constant; protected char[] descriptor; protected char[] name; protected char[] signature; protected int signatureUtf8Offset; protected long tagBits; protected Object wrappedConstantValue; public static FieldInfo createField(byte classFileBytes[], int offsets[], int offset) { FieldInfo fieldInfo = new FieldInfo(classFileBytes, offsets, offset); AnnotationInfo[] annotations = fieldInfo.readAttributes(); if (annotations == null) return fieldInfo; return new FieldInfoWithAnnotation(fieldInfo, annotations); } /** * @param classFileBytes byte[] * @param offsets int[] * @param offset int */ protected FieldInfo (byte classFileBytes[], int offsets[], int offset) { super(classFileBytes, offsets, offset); this.accessFlags = -1; this.signatureUtf8Offset = -1; } private AnnotationInfo[] decodeAnnotations(int offset, boolean runtimeVisible) { int numberOfAnnotations = u2At(offset + 6); if (numberOfAnnotations > 0) { int readOffset = offset + 8; AnnotationInfo[] newInfos = null; int newInfoCount = 0; for (int i = 0; i < numberOfAnnotations; i++) { // With the last parameter being 'false', the data structure will not be flushed out AnnotationInfo newInfo = new AnnotationInfo(this.reference, this.constantPoolOffsets, readOffset + this.structOffset, runtimeVisible, false); readOffset += newInfo.readOffset; long standardTagBits = newInfo.standardAnnotationTagBits; if (standardTagBits != 0) { this.tagBits |= standardTagBits; } else { if (newInfos == null) newInfos = new AnnotationInfo[numberOfAnnotations - i]; newInfos[newInfoCount++] = newInfo; } } if (newInfos != null) { if (newInfoCount != newInfos.length) System.arraycopy(newInfos, 0, newInfos = new AnnotationInfo[newInfoCount], 0, newInfoCount); return newInfos; } } return null; // nothing to record } public int compareTo(Object o) { return new String(getName()).compareTo(new String(((FieldInfo) o).getName())); } public boolean equals(Object o) { if (!(o instanceof FieldInfo)) { return false; } return CharOperation.equals(getName(), ((FieldInfo) o).getName()); } public int hashCode() { return CharOperation.hashCode(getName()); } /** * Return the constant of the field. * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none. * @return org.eclipse.jdt.internal.compiler.impl.Constant */ public Constant getConstant() { if (this.constant == null) { // read constant readConstantAttribute(); } return this.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. * Set the AccDeprecated and AccSynthetic bits if necessary * @return int */ public int getModifiers() { if (this.accessFlags == -1) { // compute the accessflag. Don't forget the deprecated attribute this.accessFlags = u2At(0); readModifierRelatedAttributes(); } return this.accessFlags; } /** * Answer the name of the field. * @return char[] */ public char[] getName() { if (this.name == null) { // read the name int utf8Offset = this.constantPoolOffsets[u2At(2)] - this.structOffset; this.name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } return this.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. * * For example: * - java.lang.String is Ljava/lang/String; * - an int is I * - a 2 dimensional array of strings is [[Ljava/lang/String; * - an array of floats is [F * @return char[] */ public char[] getTypeName() { if (this.descriptor == null) { // read the signature int utf8Offset = this.constantPoolOffsets[u2At(4)] - this.structOffset; this.descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } return this.descriptor; } /** * @return the annotations or null if there is none. */ public IBinaryAnnotation[] getAnnotations() { return null; } /** * Return a wrapper that contains the constant of the field. * @return java.lang.Object */ public Object getWrappedConstantValue() { if (this.wrappedConstantValue == null) { if (hasConstant()) { Constant fieldConstant = getConstant(); switch (fieldConstant.typeID()) { case TypeIds.T_int : this.wrappedConstantValue = new Integer(fieldConstant.intValue()); break; case TypeIds.T_byte : this.wrappedConstantValue = new Byte(fieldConstant.byteValue()); break; case TypeIds.T_short : this.wrappedConstantValue = new Short(fieldConstant.shortValue()); break; case TypeIds.T_char : this.wrappedConstantValue = new Character(fieldConstant.charValue()); break; case TypeIds.T_float : this.wrappedConstantValue = new Float(fieldConstant.floatValue()); break; case TypeIds.T_double : this.wrappedConstantValue = new Double(fieldConstant.doubleValue()); break; case TypeIds.T_boolean : this.wrappedConstantValue = Util.toBoolean(fieldConstant.booleanValue()); break; case TypeIds.T_long : this.wrappedConstantValue = new Long(fieldConstant.longValue()); break; case TypeIds.T_JavaLangString : this.wrappedConstantValue = fieldConstant.stringValue(); } } } return this.wrappedConstantValue; } /** * Return true if the field has a constant value attribute, false otherwise. * @return boolean */ 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. */ protected void initialize() { getModifiers(); getName(); getConstant(); getTypeName(); getGenericSignature(); reset(); } /** * Return true if the field is a synthetic field, false otherwise. * @return boolean */ public boolean isSynthetic() { return (getModifiers() & ClassFileConstants.AccSynthetic) != 0; } private AnnotationInfo[] readAttributes() { int attributesCount = u2At(6); int readOffset = 8; AnnotationInfo[] annotations = null; for (int i = 0; i < attributesCount; i++) { // check the name of each attribute int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.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 = this.constantPoolOffsets[u2At(readOffset + 6)] - this.structOffset; break; case 'R' : AnnotationInfo[] decodedAnnotations = null; if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) { decodedAnnotations = decodeAnnotations(readOffset, true); } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) { decodedAnnotations = decodeAnnotations(readOffset, false); } if (decodedAnnotations != null) { if (annotations == null) { annotations = decodedAnnotations; } else { int length = annotations.length; AnnotationInfo[] combined = new AnnotationInfo[length + decodedAnnotations.length]; System.arraycopy(annotations, 0, combined, 0, length); System.arraycopy(decodedAnnotations, 0, combined, length, decodedAnnotations.length); annotations = combined; } } } } readOffset += (6 + u4At(readOffset + 2)); } this.attributeBytes = readOffset; return annotations; } private void readConstantAttribute() { int attributesCount = u2At(6); int readOffset = 8; boolean isConstant = false; for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.structOffset; char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (CharOperation .equals(attributeName, AttributeNamesConstants.ConstantValueName)) { isConstant = true; // read the right constant int relativeOffset = this.constantPoolOffsets[u2At(readOffset + 6)] - this.structOffset; switch (u1At(relativeOffset)) { case ClassFileConstants.IntegerTag : char[] sign = getTypeName(); if (sign.length == 1) { switch (sign[0]) { case 'Z' : // boolean constant this.constant = BooleanConstant.fromValue(i4At(relativeOffset + 1) == 1); break; case 'I' : // integer constant this.constant = IntConstant.fromValue(i4At(relativeOffset + 1)); break; case 'C' : // char constant this.constant = CharConstant.fromValue((char) i4At(relativeOffset + 1)); break; case 'B' : // byte constant this.constant = ByteConstant.fromValue((byte) i4At(relativeOffset + 1)); break; case 'S' : // short constant this.constant = ShortConstant.fromValue((short) i4At(relativeOffset + 1)); break; default: this.constant = Constant.NotAConstant; } } else { this.constant = Constant.NotAConstant; } break; case ClassFileConstants.FloatTag : this.constant = FloatConstant.fromValue(floatAt(relativeOffset + 1)); break; case ClassFileConstants.DoubleTag : this.constant = DoubleConstant.fromValue(doubleAt(relativeOffset + 1)); break; case ClassFileConstants.LongTag : this.constant = LongConstant.fromValue(i8At(relativeOffset + 1)); break; case ClassFileConstants.StringTag : utf8Offset = this.constantPoolOffsets[u2At(relativeOffset + 1)] - this.structOffset; this.constant = StringConstant.fromValue( String.valueOf(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)))); break; } } readOffset += (6 + u4At(readOffset + 2)); } if (!isConstant) { this.constant = Constant.NotAConstant; } } private void readModifierRelatedAttributes() { int attributesCount = u2At(6); int readOffset = 8; for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.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, AttributeNamesConstants.DeprecatedName)) this.accessFlags |= ClassFileConstants.AccDeprecated; break; case 'S' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName)) this.accessFlags |= ClassFileConstants.AccSynthetic; break; } } readOffset += (6 + u4At(readOffset + 2)); } } /** * Answer the size of the receiver in bytes. * * @return int */ public int sizeInBytes() { return this.attributeBytes; } public void throwFormatException() throws ClassFormatException { throw new ClassFormatException(ClassFormatException.ErrBadFieldInfo); } public String toString() { StringBuffer buffer = new StringBuffer(getClass().getName()); toStringContent(buffer); return buffer.toString(); } protected void toStringContent(StringBuffer buffer) { int modifiers = getModifiers(); buffer .append('{') .append( ((modifiers & ClassFileConstants.AccDeprecated) != 0 ? "deprecated " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0001) == 1 ? "public " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0002) == 0x0002 ? "private " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0004) == 0x0004 ? "protected " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0008) == 0x000008 ? "static " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0010) == 0x0010 ? "final " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0040) == 0x0040 ? "volatile " : Util.EMPTY_STRING) //$NON-NLS-1$ + ((modifiers & 0x0080) == 0x0080 ? "transient " : Util.EMPTY_STRING)) //$NON-NLS-1$ .append(getTypeName()) .append(' ') .append(getName()) .append(' ') .append(getConstant()) .append('}') .toString(); } } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.j0000644000175000001440000001063012212041344032346 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ 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; public static final int ErrBadConstantClass = 4; public static final int ErrBadConstantString = 5; public static final int ErrBadConstantNameAndType = 6; public static final int ErrBadConstantFieldRef = 7; public static final int ErrBadConstantMethodRef = 8; public static final int ErrBadConstantInterfaceMethodRef = 9; public static final int ErrBadConstantPoolIndex = 10; public static final int ErrBadSuperclassName = 11; public static final int ErrInterfaceCannotBeFinal = 12; public static final int ErrInterfaceMustBeAbstract = 13; public static final int ErrBadModifiers = 14; public static final int ErrClassCannotBeAbstractFinal = 15; public static final int ErrBadClassname = 16; public static final int ErrBadFieldInfo = 17; public static final int ErrBadMethodInfo = 17; public static final int ErrEmptyConstantPool = 18; public static final int ErrMalformedUtf8 = 19; public static final int ErrUnknownConstantTag = 20; public static final int ErrTruncatedInput = 21; public static final int ErrMethodMustBeAbstract = 22; public static final int ErrMalformedAttribute = 23; public static final int ErrBadInterface = 24; public static final int ErrInterfaceMustSubclassObject = 25; public static final int ErrIncorrectInterfaceMethods = 26; public static final int ErrInvalidMethodName = 27; public static final int ErrInvalidMethodSignature = 28; private static final long serialVersionUID = 6667458511042774540L; // backward compatible private int errorCode; private int bufferPosition; private RuntimeException nestedException; private char[] fileName; public ClassFormatException(RuntimeException e, char[] fileName) { this.nestedException = e; this.fileName = fileName; } public ClassFormatException(int code) { this.errorCode = code; } public ClassFormatException(int code, int bufPos) { this.errorCode = code; this.bufferPosition = bufPos; } /** * @return int */ public int getErrorCode() { return this.errorCode; } /** * @return int */ public int getBufferPosition() { return this.bufferPosition; } /** * Returns the underlying Throwable that caused the failure. * * @return the wrappered Throwable, or null * if the direct case of the failure was at the Java model layer */ public Throwable getException() { return this.nestedException; } public void printStackTrace() { printStackTrace(System.err); } /** * Prints this exception's stack trace to the given print stream. * * @param output * the print stream * @since 3.0 */ public void printStackTrace(PrintStream output) { synchronized (output) { super.printStackTrace(output); Throwable throwable = getException(); if (throwable != null) { if (this.fileName != null) { output.print("Caused in "); //$NON-NLS-1$ output.print(this.fileName); output.print(" by: "); //$NON-NLS-1$ } else { output.print("Caused by: "); //$NON-NLS-1$ } throwable.printStackTrace(output); } } } /** * Prints this exception's stack trace to the given print writer. * * @param output * the print writer * @since 3.0 */ public void printStackTrace(PrintWriter output) { synchronized (output) { super.printStackTrace(output); Throwable throwable = getException(); if (throwable != null) { if (this.fileName != null) { output.print("Caused in "); //$NON-NLS-1$ output.print(this.fileName); output.print(" by: "); //$NON-NLS-1$ } else { output.print("Caused by: "); //$NON-NLS-1$ } throwable.printStackTrace(output); } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java0000644000175000001440000001016112212041344031615 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; /** * Describes one entry in the classes table of the InnerClasses attribute. * See the inner class specification (The class file attribute "InnerClasses"). */ public class InnerClassInfo extends ClassFileStruct implements IBinaryNestedType { int innerClassNameIndex = -1; int outerClassNameIndex = -1; int innerNameIndex = -1; private char[] innerClassName; private char[] outerClassName; private char[] innerName; private int accessFlags = -1; private boolean readInnerClassName = false; private boolean readOuterClassName = false; private boolean readInnerName = false; public InnerClassInfo(byte classFileBytes[], int offsets[], int offset) { super(classFileBytes, offsets, offset); this.innerClassNameIndex = u2At(0); this.outerClassNameIndex = u2At(2); this.innerNameIndex = u2At(4); } /** * Answer the resolved name of the enclosing type in the * class file format as specified in section 4.2 of the Java 2 VM spec. * * For example, java.lang.String is java/lang/String. * @return char[] */ public char[] getEnclosingTypeName() { if (!this.readOuterClassName) { // read outer class name this.readOuterClassName = true; if (this.outerClassNameIndex != 0) { int utf8Offset = this.constantPoolOffsets[u2At( this.constantPoolOffsets[this.outerClassNameIndex] - this.structOffset + 1)] - this.structOffset; this.outerClassName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } } return this.outerClassName; } /** * Answer an int whose bits are set according the access constants * defined by the VM spec. * @return int */ public int getModifiers() { if (this.accessFlags == -1) { // read access flag this.accessFlags = u2At(6); } return this.accessFlags; } /** * Answer the resolved name of the member type in the * class file format as specified in section 4.2 of the Java 2 VM spec. * * For example, p1.p2.A.M is p1/p2/A$M. * @return char[] */ public char[] getName() { if (!this.readInnerClassName) { // read the inner class name this.readInnerClassName = true; if (this.innerClassNameIndex != 0) { int classOffset = this.constantPoolOffsets[this.innerClassNameIndex] - this.structOffset; int utf8Offset = this.constantPoolOffsets[u2At(classOffset + 1)] - this.structOffset; this.innerClassName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } } return this.innerClassName; } /** * Answer the source name of the member type. * * For example, p1.p2.A.M is M. * @return char[] */ public char[] getSourceName() { if (!this.readInnerName) { this.readInnerName = true; if (this.innerNameIndex != 0) { int utf8Offset = this.constantPoolOffsets[this.innerNameIndex] - this.structOffset; this.innerName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } } return this.innerName; } /** * Answer the string representation of the receiver * @return java.lang.String */ public String toString() { StringBuffer buffer = new StringBuffer(); if (getName() != null) { buffer.append(getName()); } buffer.append("\n"); //$NON-NLS-1$ if (getEnclosingTypeName() != null) { buffer.append(getEnclosingTypeName()); } buffer.append("\n"); //$NON-NLS-1$ if (getSourceName() != null) { buffer.append(getSourceName()); } return buffer.toString(); } /** * 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(); getSourceName(); getEnclosingTypeName(); reset(); } } ././@LongLink0000644000000000000000000000016712251602427011647 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfoWithAnnotations.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfoWi0000644000175000001440000000322012212041344032405 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2007 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; public class AnnotationMethodInfoWithAnnotations extends AnnotationMethodInfo { private AnnotationInfo[] annotations; AnnotationMethodInfoWithAnnotations(MethodInfo methodInfo, Object defaultValue, AnnotationInfo[] annotations) { super(methodInfo, defaultValue); this.annotations = annotations; } public IBinaryAnnotation[] getAnnotations() { return this.annotations; } protected void initialize() { for (int i = 0, l = this.annotations == null ? 0 : this.annotations.length; i < l; i++) if (this.annotations[i] != null) this.annotations[i].initialize(); super.initialize(); } protected void reset() { for (int i = 0, l = this.annotations == null ? 0 : this.annotations.length; i < l; i++) if (this.annotations[i] != null) this.annotations[i].reset(); super.reset(); } protected void toStringContent(StringBuffer buffer) { super.toStringContent(buffer); for (int i = 0, l = this.annotations == null ? 0 : this.annotations.length; i < l; i++) { buffer.append(this.annotations[i]); buffer.append('\n'); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/CompilationResult.java0000644000175000001440000003731512212041344030613 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; /** * A compilation result consists of all information returned by the compiler for * a single compiled compilation source unit. This includes: *
    *
  • the compilation unit that was compiled *
  • for each type produced by compiling the compilation unit, its binary and optionally its principal structure *
  • any problems (errors or warnings) produced *
  • dependency info *
* * The principle structure and binary may be null if the compiler could not produce them. * If neither could be produced, there is no corresponding entry for the type. * * The dependency info includes type references such as supertypes, field types, method * parameter and return types, local variable types, types of intermediate expressions, etc. * It also includes the namespaces (packages) in which names were looked up. * It does not include finer grained dependencies such as information about * specific fields and methods which were referenced, but does contain their * declaring types and any other types used to locate such fields or methods. */ import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData; import org.eclipse.jdt.internal.compiler.util.Util; public class CompilationResult { public CategorizedProblem problems[]; public CategorizedProblem tasks[]; public int problemCount; public int taskCount; public ICompilationUnit compilationUnit; private Map problemsMap; private Set firstErrors; private int maxProblemPerUnit; public char[][][] qualifiedReferences; public char[][] simpleNameReferences; public char[][] rootReferences; public boolean hasAnnotations = false; public int lineSeparatorPositions[]; public RecoveryScannerData recoveryScannerData; public Map compiledTypes = new Hashtable(11); 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 boolean hasSyntaxError = false; public char[][] packageName; public boolean checkSecondaryTypes = false; // check for secondary types which were created after the initial buildTypeBindings call private int numberOfErrors; private boolean hasMandatoryErrors; private static final int[] EMPTY_LINE_ENDS = Util.EMPTY_INT_ARRAY; private static final Comparator PROBLEM_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { return ((CategorizedProblem) o1).getSourceStart() - ((CategorizedProblem) o2).getSourceStart(); } }; public CompilationResult(char[] fileName, int unitIndex, int totalUnitsKnown, int maxProblemPerUnit){ this.fileName = fileName; this.unitIndex = unitIndex; this.totalUnitsKnown = totalUnitsKnown; this.maxProblemPerUnit = maxProblemPerUnit; } public CompilationResult(ICompilationUnit compilationUnit, int unitIndex, int totalUnitsKnown, int maxProblemPerUnit){ this.fileName = compilationUnit.getFileName(); this.compilationUnit = compilationUnit; this.unitIndex = unitIndex; this.totalUnitsKnown = totalUnitsKnown; this.maxProblemPerUnit = maxProblemPerUnit; } private int computePriority(CategorizedProblem problem){ final int P_STATIC = 10000; final int P_OUTSIDE_METHOD = 40000; final int P_FIRST_ERROR = 20000; final int P_ERROR = 100000; int priority = 10000 - problem.getSourceLineNumber(); // early problems first if (priority < 0) priority = 0; if (problem.isError()){ priority += P_ERROR; } ReferenceContext context = this.problemsMap == null ? null : (ReferenceContext) this.problemsMap.get(problem); if (context != null){ if (context instanceof AbstractMethodDeclaration){ AbstractMethodDeclaration method = (AbstractMethodDeclaration) context; if (method.isStatic()) { priority += P_STATIC; } } else { priority += P_OUTSIDE_METHOD; } if (this.firstErrors.contains(problem)){ // if context is null, firstErrors is null too priority += P_FIRST_ERROR; } } else { priority += P_OUTSIDE_METHOD; } return priority; } public CategorizedProblem[] getAllProblems() { CategorizedProblem[] onlyProblems = getProblems(); int onlyProblemCount = onlyProblems != null ? onlyProblems.length : 0; CategorizedProblem[] onlyTasks = getTasks(); int onlyTaskCount = onlyTasks != null ? onlyTasks.length : 0; if (onlyTaskCount == 0) { return onlyProblems; } if (onlyProblemCount == 0) { return onlyTasks; } int totalNumberOfProblem = onlyProblemCount + onlyTaskCount; CategorizedProblem[] allProblems = new CategorizedProblem[totalNumberOfProblem]; int allProblemIndex = 0; int taskIndex = 0; int problemIndex = 0; while (taskIndex + problemIndex < totalNumberOfProblem) { CategorizedProblem nextTask = null; CategorizedProblem nextProblem = null; if (taskIndex < onlyTaskCount) { nextTask = onlyTasks[taskIndex]; } if (problemIndex < onlyProblemCount) { nextProblem = onlyProblems[problemIndex]; } // select the next problem CategorizedProblem currentProblem = null; if (nextProblem != null) { if (nextTask != null) { if (nextProblem.getSourceStart() < nextTask.getSourceStart()) { currentProblem = nextProblem; problemIndex++; } else { currentProblem = nextTask; taskIndex++; } } else { currentProblem = nextProblem; problemIndex++; } } else { if (nextTask != null) { currentProblem = nextTask; taskIndex++; } } allProblems[allProblemIndex++] = currentProblem; } return allProblems; } public ClassFile[] getClassFiles() { ClassFile[] classFiles = new ClassFile[this.compiledTypes.size()]; this.compiledTypes.values().toArray(classFiles); return classFiles; } /** * Answer the initial compilation unit corresponding to the present compilation result */ public ICompilationUnit getCompilationUnit(){ return this.compilationUnit; } /** * Answer the errors encountered during compilation. */ public CategorizedProblem[] getErrors() { CategorizedProblem[] reportedProblems = getProblems(); int errorCount = 0; for (int i = 0; i < this.problemCount; i++) { if (reportedProblems[i].isError()) errorCount++; } if (errorCount == this.problemCount) return reportedProblems; CategorizedProblem[] errors = new CategorizedProblem[errorCount]; int index = 0; for (int i = 0; i < this.problemCount; i++) { if (reportedProblems[i].isError()) errors[index++] = reportedProblems[i]; } return errors; } /** * Answer the initial file name */ public char[] getFileName(){ return this.fileName; } public int[] getLineSeparatorPositions() { return this.lineSeparatorPositions == null ? CompilationResult.EMPTY_LINE_ENDS : this.lineSeparatorPositions; } /** * Answer the problems (errors and warnings) encountered during compilation. * * This is not a compiler internal API - it has side-effects ! * It is intended to be used only once all problems have been detected, * and makes sure the problems slot as the exact size of the number of * problems. */ public CategorizedProblem[] getProblems() { // Re-adjust the size of the problems if necessary. if (this.problems != null) { if (this.problemCount != this.problems.length) { System.arraycopy(this.problems, 0, (this.problems = new CategorizedProblem[this.problemCount]), 0, this.problemCount); } if (this.maxProblemPerUnit > 0 && this.problemCount > this.maxProblemPerUnit){ quickPrioritize(this.problems, 0, this.problemCount - 1); this.problemCount = this.maxProblemPerUnit; System.arraycopy(this.problems, 0, (this.problems = new CategorizedProblem[this.problemCount]), 0, this.problemCount); } // Stable sort problems per source positions. Arrays.sort(this.problems, 0, this.problems.length, CompilationResult.PROBLEM_COMPARATOR); //quickSort(problems, 0, problems.length-1); } return this.problems; } /** * Same as getProblems() but don't answer problems that actually concern the enclosing package. */ public CategorizedProblem[] getCUProblems() { // Re-adjust the size of the problems if necessary and filter package problems if (this.problems != null) { CategorizedProblem[] filteredProblems = new CategorizedProblem[this.problemCount]; int keep = 0; for (int i=0; i< this.problemCount; i++) { CategorizedProblem problem = this.problems[i]; if (problem.getID() != IProblem.MissingNonNullByDefaultAnnotationOnPackage) { filteredProblems[keep++] = problem; } else if (this.compilationUnit != null) { if (CharOperation.equals(this.compilationUnit.getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME)) { filteredProblems[keep++] = problem; } } } if (keep < this.problemCount) { System.arraycopy(filteredProblems, 0, filteredProblems = new CategorizedProblem[keep], 0, keep); this.problemCount = keep; } this.problems = filteredProblems; if (this.maxProblemPerUnit > 0 && this.problemCount > this.maxProblemPerUnit){ quickPrioritize(this.problems, 0, this.problemCount - 1); this.problemCount = this.maxProblemPerUnit; System.arraycopy(this.problems, 0, (this.problems = new CategorizedProblem[this.problemCount]), 0, this.problemCount); } // Stable sort problems per source positions. Arrays.sort(this.problems, 0, this.problems.length, CompilationResult.PROBLEM_COMPARATOR); //quickSort(problems, 0, problems.length-1); } return this.problems; } /** * Answer the tasks (TO-DO, ...) encountered during compilation. * * This is not a compiler internal API - it has side-effects ! * It is intended to be used only once all problems have been detected, * and makes sure the problems slot as the exact size of the number of * problems. */ public CategorizedProblem[] getTasks() { // Re-adjust the size of the tasks if necessary. if (this.tasks != null) { if (this.taskCount != this.tasks.length) { System.arraycopy(this.tasks, 0, (this.tasks = new CategorizedProblem[this.taskCount]), 0, this.taskCount); } // Stable sort problems per source positions. Arrays.sort(this.tasks, 0, this.tasks.length, CompilationResult.PROBLEM_COMPARATOR); //quickSort(tasks, 0, tasks.length-1); } return this.tasks; } public boolean hasErrors() { return this.numberOfErrors != 0; } public boolean hasMandatoryErrors() { return this.hasMandatoryErrors; } public boolean hasProblems() { return this.problemCount != 0; } public boolean hasTasks() { return this.taskCount != 0; } public boolean hasWarnings() { if (this.problems != null) for (int i = 0; i < this.problemCount; i++) { if (this.problems[i].isWarning()) return true; } return false; } private void quickPrioritize(CategorizedProblem[] problemList, int left, int right) { if (left >= right) return; // sort the problems by their priority... starting with the highest priority int original_left = left; int original_right = right; int mid = computePriority(problemList[left + (right - left) / 2]); do { while (computePriority(problemList[right]) < mid) right--; while (mid < computePriority(problemList[left])) left++; if (left <= right) { CategorizedProblem tmp = problemList[left]; problemList[left] = problemList[right]; problemList[right] = tmp; left++; right--; } } while (left <= right); if (original_left < right) quickPrioritize(problemList, original_left, right); if (left < original_right) quickPrioritize(problemList, left, original_right); } /* * Record the compilation unit result's package name */ public void recordPackageName(char[][] packName) { this.packageName = packName; } public void record(CategorizedProblem newProblem, ReferenceContext referenceContext) { record(newProblem, referenceContext, true); return; } public void record(CategorizedProblem newProblem, ReferenceContext referenceContext, boolean mandatoryError) { //new Exception("VERBOSE PROBLEM REPORTING").printStackTrace(); if(newProblem.getID() == IProblem.Task) { recordTask(newProblem); return; } if (this.problemCount == 0) { this.problems = new CategorizedProblem[5]; } else if (this.problemCount == this.problems.length) { System.arraycopy(this.problems, 0, (this.problems = new CategorizedProblem[this.problemCount * 2]), 0, this.problemCount); } this.problems[this.problemCount++] = newProblem; if (referenceContext != null){ if (this.problemsMap == null) this.problemsMap = new HashMap(5); if (this.firstErrors == null) this.firstErrors = new HashSet(5); if (newProblem.isError() && !referenceContext.hasErrors()) this.firstErrors.add(newProblem); this.problemsMap.put(newProblem, referenceContext); } if (newProblem.isError()) { this.numberOfErrors++; if (mandatoryError) this.hasMandatoryErrors = true; if ((newProblem.getID() & IProblem.Syntax) != 0) { this.hasSyntaxError = true; } } } /** * For now, remember the compiled type using its compound name. */ public void record(char[] typeName, ClassFile classFile) { SourceTypeBinding sourceType = classFile.referenceBinding; if (!sourceType.isLocalType() && sourceType.isHierarchyInconsistent()) { this.hasInconsistentToplevelHierarchies = true; } this.compiledTypes.put(typeName, classFile); } private void recordTask(CategorizedProblem newProblem) { if (this.taskCount == 0) { this.tasks = new CategorizedProblem[5]; } else if (this.taskCount == this.tasks.length) { System.arraycopy(this.tasks, 0, (this.tasks = new CategorizedProblem[this.taskCount * 2]), 0, this.taskCount); } this.tasks[this.taskCount++] = newProblem; } public void removeProblem(CategorizedProblem problem) { if (this.problemsMap != null) this.problemsMap.remove(problem); if (this.firstErrors != null) this.firstErrors.remove(problem); if (problem.isError()) { this.numberOfErrors--; } this.problemCount--; } public CompilationResult tagAsAccepted(){ this.hasBeenAccepted = true; this.problemsMap = null; // flush this.firstErrors = null; // flush return this; } public String toString(){ StringBuffer buffer = new StringBuffer(); if (this.fileName != null){ buffer.append("Filename : ").append(this.fileName).append('\n'); //$NON-NLS-1$ } if (this.compiledTypes != null){ buffer.append("COMPILED type(s) \n"); //$NON-NLS-1$ Iterator keys = this.compiledTypes.keySet().iterator(); while (keys.hasNext()) { char[] typeName = (char[]) keys.next(); buffer.append("\t - ").append(typeName).append('\n'); //$NON-NLS-1$ } } else { buffer.append("No COMPILED type\n"); //$NON-NLS-1$ } if (this.problems != null){ buffer.append(this.problemCount).append(" PROBLEM(s) detected \n"); //$NON-NLS-1$ for (int i = 0; i < this.problemCount; i++){ buffer.append("\t - ").append(this.problems[i]).append('\n'); //$NON-NLS-1$ } } else { buffer.append("No PROBLEM\n"); //$NON-NLS-1$ } return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/IDebugRequestor.java0000644000175000001440000000222112212041344030173 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; public interface IDebugRequestor { /* * Debug callback method allowing to take into account a new compilation result. * Any side-effect performed on the actual result might interfere with the * original compiler requestor, and should be prohibited. */ void acceptDebugResult(CompilationResult result); /* * Answers true when in active mode */ boolean isActive(); /* * Activate debug callbacks */ void activate(); /* * Deactivate debug callbacks */ void deactivate(); /* * Reset debug requestor after compilation has finished */ void reset(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java0000644000175000001440000000215012212041344031152 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; /* * Handler policy is responsible to answer the 2 following * questions: * 1. should the handler stop on first problem which appears * to be a real error (that is, not a warning), * 2. should it proceed once it has gathered all problems * * The intent is that one can supply its own policy to implement * some interactive error handling strategy where some UI would * display problems and ask user if he wants to proceed or not. */ public interface IErrorHandlingPolicy { boolean proceedOnErrors(); boolean stopOnFirstError(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/0000755000175000001440000000000012212041344025231 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java0000644000175000001440000010063012212041344031700 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - contributions for * bug 336428 - [compiler][null] bogus warning "redundant null check" in condition of do {} while() loop * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 385626 - @NonNull fails across loop boundaries * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 376263 - Bogus "Potential null pointer access" warning * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking * bug 406384 - Internal error with I20130413 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import java.util.ArrayList; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; import org.eclipse.jdt.internal.compiler.ast.Reference; import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 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; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class LoopingFlowContext extends SwitchFlowContext { public BranchLabel continueLabel; public UnconditionalFlowInfo initsOnContinue = FlowInfo.DEAD_END; private UnconditionalFlowInfo upstreamNullFlowInfo; private LoopingFlowContext innerFlowContexts[] = null; private UnconditionalFlowInfo innerFlowInfos[] = null; private int innerFlowContextsCount = 0; private LabelFlowContext breakTargetContexts[] = null; private int breakTargetsCount = 0; Reference finalAssignments[]; VariableBinding finalVariables[]; int assignCount = 0; // the following three arrays are in sync regarding their indices: LocalVariableBinding[] nullLocals; // slots can be null for checkType == IN_UNBOXING ASTNode[] nullReferences; // Expressions for null checking, Statements for resource analysis // cast to Expression is safe if corresponding nullCheckType != EXIT_RESOURCE int[] nullCheckTypes; int nullCount; // see also the related field FlowContext#expectedTypes // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321926 static private class EscapingExceptionCatchSite { final ReferenceBinding caughtException; final ExceptionHandlingFlowContext catchingContext; public EscapingExceptionCatchSite(ExceptionHandlingFlowContext catchingContext, ReferenceBinding caughtException) { this.catchingContext = catchingContext; this.caughtException = caughtException; } void simulateThrowAfterLoopBack(FlowInfo flowInfo) { this.catchingContext.recordHandlingException(this.caughtException, flowInfo.unconditionalInits(), null, // raised exception, irrelevant here, null, null, /* invocation site, irrelevant here */ true // we have no business altering the needed status. ); } } private ArrayList escapingExceptionCatchSites = null; Scope associatedScope; public LoopingFlowContext( FlowContext parent, FlowInfo upstreamNullFlowInfo, ASTNode associatedNode, BranchLabel breakLabel, BranchLabel continueLabel, Scope associatedScope, boolean isPreTest) { super(parent, associatedNode, breakLabel, isPreTest); this.tagBits |= FlowContext.PREEMPT_NULL_DIAGNOSTIC; // children will defer to this, which may defer to its own parent this.continueLabel = continueLabel; this.associatedScope = associatedScope; this.upstreamNullFlowInfo = upstreamNullFlowInfo.unconditionalCopy(); } /** * Perform deferred checks relative to final variables duplicate initialization * of lack of initialization. * @param scope the scope to which this context is associated * @param flowInfo the flow info against which checks must be performed */ public void complainOnDeferredFinalChecks(BlockScope scope, FlowInfo flowInfo) { // complain on final assignments in loops for (int i = 0; i < this.assignCount; i++) { VariableBinding variable = this.finalVariables[i]; if (variable == null) continue; boolean complained = false; // remember if have complained on this final assignment if (variable instanceof FieldBinding) { if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) { complained = true; scope.problemReporter().duplicateInitializationOfBlankFinalField( (FieldBinding) variable, this.finalAssignments[i]); } } else { if (flowInfo.isPotentiallyAssigned((LocalVariableBinding)variable)) { complained = true; scope.problemReporter().duplicateInitializationOfFinalLocal( (LocalVariableBinding) variable, this.finalAssignments[i]); } } // any reference reported at this level is removed from the parent context where it // could also be reported again if (complained) { FlowContext context = this.getLocalParent(); while (context != null) { context.removeFinalAssignmentIfAny(this.finalAssignments[i]); context = context.getLocalParent(); } } } } /** * Perform deferred checks relative to the null status of local variables. * @param scope the scope to which this context is associated * @param callerFlowInfo the flow info against which checks must be performed */ public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowInfo) { for (int i = 0 ; i < this.innerFlowContextsCount ; i++) { this.upstreamNullFlowInfo. addPotentialNullInfoFrom( this.innerFlowContexts[i].upstreamNullFlowInfo). addPotentialNullInfoFrom(this.innerFlowInfos[i]); } this.innerFlowContextsCount = 0; FlowInfo upstreamCopy = this.upstreamNullFlowInfo.copy(); UnconditionalFlowInfo flowInfo = this.upstreamNullFlowInfo. addPotentialNullInfoFrom(callerFlowInfo.unconditionalInitsWithoutSideEffect()); if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // check only immutable null checks on innermost looping context for (int i = 0; i < this.nullCount; i++) { LocalVariableBinding local = this.nullLocals[i]; ASTNode location = this.nullReferences[i]; // final local variable switch (this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) { case CAN_ONLY_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NON_NULL | IN_COMPARISON_NON_NULL: if (flowInfo.isDefinitelyNonNull(local)) { this.nullReferences[i] = null; if ((this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) == (CAN_ONLY_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, location); } } else { scope.problemReporter().localVariableNonNullComparedToNull(local, location); } continue; } break; case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: if (flowInfo.isDefinitelyNonNull(local)) { this.nullReferences[i] = null; if ((this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, location); } } else { scope.problemReporter().localVariableNonNullComparedToNull(local, location); } continue; } if (flowInfo.isDefinitelyNull(local)) { this.nullReferences[i] = null; if ((this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) { if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, location); } } else { scope.problemReporter().localVariableNullComparedToNonNull(local, location); } continue; } break; case CAN_ONLY_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_ASSIGNMENT: case CAN_ONLY_NULL | IN_INSTANCEOF: Expression expression = (Expression)location; if (flowInfo.isDefinitelyNull(local)) { this.nullReferences[i] = null; switch(this.nullCheckTypes[i] & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, expression); continue; } if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, expression); } continue; case FlowContext.IN_COMPARISON_NON_NULL: if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, expression); continue; } scope.problemReporter().localVariableNullComparedToNonNull(local, expression); continue; case FlowContext.IN_ASSIGNMENT: scope.problemReporter().localVariableRedundantNullAssignment(local, expression); continue; case FlowContext.IN_INSTANCEOF: scope.problemReporter().localVariableNullInstanceof(local, expression); continue; } } else if (flowInfo.isPotentiallyNull(local)) { switch(this.nullCheckTypes[i] & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: this.nullReferences[i] = null; if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, expression); continue; } break; case FlowContext.IN_COMPARISON_NON_NULL: this.nullReferences[i] = null; if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, expression); continue; } break; } } break; case MAY_NULL: if (flowInfo.isDefinitelyNull(local)) { this.nullReferences[i] = null; scope.problemReporter().localVariableNullReference(local, location); continue; } break; case ASSIGN_TO_NONNULL: int nullStatus = flowInfo.nullStatus(local); if (nullStatus != FlowInfo.NON_NULL) { this.parent.recordNullityMismatch(scope, (Expression)location, this.providedExpectedTypes[i][0], this.providedExpectedTypes[i][1], nullStatus); } break; case EXIT_RESOURCE: FakedTrackingVariable trackingVar = local.closeTracker; if (trackingVar != null) { if (trackingVar.hasDefinitelyNoResource(flowInfo)) { continue; // no resource - no warning. } if (trackingVar.isClosedInFinallyOfEnclosing(scope)) { continue; } if (this.parent.recordExitAgainstResource(scope, flowInfo, trackingVar, location)) { this.nullReferences[i] = null; continue; } } break; case IN_UNBOXING: checkUnboxing(scope, (Expression) location, flowInfo); continue; // delegation to parent already handled in the above. default: // never happens } // https://bugs.eclipse.org/376263: avoid further deferring if the upstream info // already has definite information (which might get lost for deferred checking). if (!(this.nullCheckTypes[i] == MAY_NULL && upstreamCopy.isDefinitelyNonNull(local))) { this.parent.recordUsingNullReference(scope, local, location, this.nullCheckTypes[i], flowInfo); } } } else { // check inconsistent null checks on outermost looping context for (int i = 0; i < this.nullCount; i++) { ASTNode location = this.nullReferences[i]; // final local variable LocalVariableBinding local = this.nullLocals[i]; switch (this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: if (flowInfo.isDefinitelyNonNull(local)) { this.nullReferences[i] = null; if ((this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, location); } } else { scope.problemReporter().localVariableNonNullComparedToNull(local, location); } continue; } //$FALL-THROUGH$ case CAN_ONLY_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_ASSIGNMENT: case CAN_ONLY_NULL | IN_INSTANCEOF: Expression expression = (Expression) location; if (flowInfo.isDefinitelyNull(local)) { this.nullReferences[i] = null; switch(this.nullCheckTypes[i] & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, expression); continue; } if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, expression); } continue; case FlowContext.IN_COMPARISON_NON_NULL: if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, expression); continue; } scope.problemReporter().localVariableNullComparedToNonNull(local, expression); continue; case FlowContext.IN_ASSIGNMENT: scope.problemReporter().localVariableRedundantNullAssignment(local, expression); continue; case FlowContext.IN_INSTANCEOF: scope.problemReporter().localVariableNullInstanceof(local, expression); continue; } } else if (flowInfo.isPotentiallyNull(local)) { switch(this.nullCheckTypes[i] & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: this.nullReferences[i] = null; if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, expression); continue; } break; case FlowContext.IN_COMPARISON_NON_NULL: this.nullReferences[i] = null; if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, expression); continue; } break; } } break; case MAY_NULL: if (flowInfo.isDefinitelyNull(local)) { this.nullReferences[i] = null; scope.problemReporter().localVariableNullReference(local, location); continue; } if (flowInfo.isPotentiallyNull(local)) { this.nullReferences[i] = null; scope.problemReporter().localVariablePotentialNullReference(local, location); continue; } break; case ASSIGN_TO_NONNULL: int nullStatus = flowInfo.nullStatus(local); if (nullStatus != FlowInfo.NON_NULL) { char[][] annotationName = scope.environment().getNonNullAnnotationName(); scope.problemReporter().nullityMismatch((Expression) location, this.providedExpectedTypes[i][0], this.providedExpectedTypes[i][1], nullStatus, annotationName); } break; case EXIT_RESOURCE: nullStatus = flowInfo.nullStatus(local); if (nullStatus != FlowInfo.NON_NULL) { FakedTrackingVariable closeTracker = local.closeTracker; if (closeTracker != null) { if (closeTracker.hasDefinitelyNoResource(flowInfo)) { continue; // no resource - no warning. } if (closeTracker.isClosedInFinallyOfEnclosing(scope)) { continue; } nullStatus = closeTracker.findMostSpecificStatus(flowInfo, scope, null); closeTracker.recordErrorLocation(this.nullReferences[i], nullStatus); closeTracker.reportRecordedErrors(scope, nullStatus); this.nullReferences[i] = null; continue; } } break; case IN_UNBOXING: checkUnboxing(scope, (Expression) location, flowInfo); break; default: // never happens } } } // propagate breaks this.initsOnBreak.addPotentialNullInfoFrom(flowInfo); for (int i = 0; i < this.breakTargetsCount; i++) { this.breakTargetContexts[i].initsOnBreak.addPotentialNullInfoFrom(flowInfo); } } public BranchLabel continueLabel() { return this.continueLabel; } public String individualToString() { StringBuffer buffer = new StringBuffer("Looping flow context"); //$NON-NLS-1$ buffer.append("[initsOnBreak - ").append(this.initsOnBreak.toString()).append(']'); //$NON-NLS-1$ buffer.append("[initsOnContinue - ").append(this.initsOnContinue.toString()).append(']'); //$NON-NLS-1$ buffer.append("[finalAssignments count - ").append(this.assignCount).append(']'); //$NON-NLS-1$ buffer.append("[nullReferences count - ").append(this.nullCount).append(']'); //$NON-NLS-1$ return buffer.toString(); } public boolean isContinuable() { return true; } public boolean isContinuedTo() { return this.initsOnContinue != FlowInfo.DEAD_END; } public void recordBreakTo(FlowContext targetContext) { if (targetContext instanceof LabelFlowContext) { int current; if ((current = this.breakTargetsCount++) == 0) { this.breakTargetContexts = new LabelFlowContext[2]; } else if (current == this.breakTargetContexts.length) { System.arraycopy(this.breakTargetContexts, 0, this.breakTargetContexts = new LabelFlowContext[current + 2], 0, current); } this.breakTargetContexts[current] = (LabelFlowContext) targetContext; } } public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { if ((this.initsOnContinue.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.initsOnContinue = this.initsOnContinue. mergedWith(flowInfo.unconditionalInitsWithoutSideEffect()); } else { this.initsOnContinue = flowInfo.unconditionalCopy(); } FlowContext inner = innerFlowContext; while (inner != this && !(inner instanceof LoopingFlowContext)) { inner = inner.parent; // we know that inner is reachable from this without crossing a type boundary } if (inner == this) { this.upstreamNullFlowInfo. addPotentialNullInfoFrom( flowInfo.unconditionalInitsWithoutSideEffect()); } else { int length = 0; if (this.innerFlowContexts == null) { this.innerFlowContexts = new LoopingFlowContext[5]; this.innerFlowInfos = new UnconditionalFlowInfo[5]; } else if (this.innerFlowContextsCount == (length = this.innerFlowContexts.length) - 1) { System.arraycopy(this.innerFlowContexts, 0, (this.innerFlowContexts = new LoopingFlowContext[length + 5]), 0, length); System.arraycopy(this.innerFlowInfos, 0, (this.innerFlowInfos= new UnconditionalFlowInfo[length + 5]), 0, length); } this.innerFlowContexts[this.innerFlowContextsCount] = (LoopingFlowContext) inner; this.innerFlowInfos[this.innerFlowContextsCount++] = flowInfo.unconditionalInitsWithoutSideEffect(); } } } protected boolean recordFinalAssignment( VariableBinding binding, Reference finalAssignment) { // do not consider variables which are defined inside this loop if (binding instanceof LocalVariableBinding) { Scope scope = ((LocalVariableBinding) binding).declaringScope; while ((scope = scope.parent) != null) { if (scope == this.associatedScope) return false; } } if (this.assignCount == 0) { this.finalAssignments = new Reference[5]; this.finalVariables = new VariableBinding[5]; } else { if (this.assignCount == this.finalAssignments.length) System.arraycopy( this.finalAssignments, 0, (this.finalAssignments = new Reference[this.assignCount * 2]), 0, this.assignCount); System.arraycopy( this.finalVariables, 0, (this.finalVariables = new VariableBinding[this.assignCount * 2]), 0, this.assignCount); } this.finalAssignments[this.assignCount] = finalAssignment; this.finalVariables[this.assignCount++] = binding; return true; } protected void recordNullReference(LocalVariableBinding local, ASTNode expression, int checkType) { if (this.nullCount == 0) { this.nullLocals = new LocalVariableBinding[5]; this.nullReferences = new ASTNode[5]; this.nullCheckTypes = new int[5]; } else if (this.nullCount == this.nullLocals.length) { System.arraycopy(this.nullLocals, 0, this.nullLocals = new LocalVariableBinding[this.nullCount * 2], 0, this.nullCount); System.arraycopy(this.nullReferences, 0, this.nullReferences = new ASTNode[this.nullCount * 2], 0, this.nullCount); System.arraycopy(this.nullCheckTypes, 0, this.nullCheckTypes = new int[this.nullCount * 2], 0, this.nullCount); } this.nullLocals[this.nullCount] = local; this.nullReferences[this.nullCount] = expression; this.nullCheckTypes[this.nullCount++] = checkType; } public void recordUnboxing(Scope scope, Expression expression, int nullStatus, FlowInfo flowInfo) { if (nullStatus == FlowInfo.NULL) super.recordUnboxing(scope, expression, nullStatus, flowInfo); else // defer checking: recordNullReference(null, expression, IN_UNBOXING); } /** Record the fact that we see an early exit (in 'reference') while 'trackingVar' is in scope and may be unclosed. */ public boolean recordExitAgainstResource(BlockScope scope, FlowInfo flowInfo, FakedTrackingVariable trackingVar, ASTNode reference) { LocalVariableBinding local = trackingVar.binding; if (flowInfo.isDefinitelyNonNull(local)) { return false; } if (flowInfo.isDefinitelyNull(local)) { scope.problemReporter().unclosedCloseable(trackingVar, reference); return true; // handled } if (flowInfo.isPotentiallyNull(local)) { scope.problemReporter().potentiallyUnclosedCloseable(trackingVar, reference); return true; // handled } recordNullReference(trackingVar.binding, reference, EXIT_RESOURCE); return true; // handled } public void recordUsingNullReference(Scope scope, LocalVariableBinding local, ASTNode location, int checkType, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 || flowInfo.isDefinitelyUnknown(local)) { return; } // if reference is being recorded inside an assert, we will not raise redundant null check warnings checkType |= (this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING); int checkTypeWithoutHideNullWarning = checkType & ~FlowContext.HIDE_NULL_COMPARISON_WARNING_MASK; switch (checkTypeWithoutHideNullWarning) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: Expression reference = (Expression)location; if (flowInfo.isDefinitelyNonNull(local)) { if (checkTypeWithoutHideNullWarning == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } else { scope.problemReporter().localVariableNonNullComparedToNull(local, reference); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } } else if (flowInfo.isDefinitelyNull(local)) { if (checkTypeWithoutHideNullWarning == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) { if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } else { scope.problemReporter().localVariableNullComparedToNonNull(local, reference); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } } else if (this.upstreamNullFlowInfo.isDefinitelyNonNull(local) && !flowInfo.isPotentiallyNull(local) && !flowInfo.isPotentiallyUnknown(local)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291418 flowInfo.markAsDefinitelyNonNull(local); recordNullReference(local, reference, checkType); } else if (flowInfo.cannotBeDefinitelyNullOrNonNull(local)) { return; // no reason to complain, since there is definitely some uncertainty making the comparison relevant. } else { // note: pot non-null & pot null is already captured by cannotBeDefinitelyNullOrNonNull() if (flowInfo.isPotentiallyNonNull(local)) { // knowing 'local' can be non-null, we're only interested in seeing whether it can *only* be non-null recordNullReference(local, reference, CAN_ONLY_NON_NULL | checkType & (CONTEXT_MASK|HIDE_NULL_COMPARISON_WARNING_MASK)); } else if (flowInfo.isPotentiallyNull(local)) { // knowing 'local' can be null, we're only interested in seeing whether it can *only* be null recordNullReference(local, reference, CAN_ONLY_NULL | checkType & (CONTEXT_MASK|HIDE_NULL_COMPARISON_WARNING_MASK)); } else { recordNullReference(local, reference, checkType); } } return; case CAN_ONLY_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_ASSIGNMENT: case CAN_ONLY_NULL | IN_INSTANCEOF: reference = (Expression)location; if (flowInfo.isPotentiallyNonNull(local) || flowInfo.isPotentiallyUnknown(local) || flowInfo.isProtectedNonNull(local)) { // if variable is not null, we are not interested in recording null reference for deferred checks. // This is because CAN_ONLY_NULL means we're only interested in cases when variable can be null. return; } if (flowInfo.isDefinitelyNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } scope.problemReporter().localVariableNullComparedToNonNull(local, reference); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_ASSIGNMENT: scope.problemReporter().localVariableRedundantNullAssignment(local, reference); return; case FlowContext.IN_INSTANCEOF: scope.problemReporter().localVariableNullInstanceof(local, reference); return; } } else if (flowInfo.isPotentiallyNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; } } recordNullReference(local, reference, checkType); return; case MAY_NULL : if (flowInfo.isDefinitelyNonNull(local)) { return; } if (flowInfo.isDefinitelyNull(local)) { scope.problemReporter().localVariableNullReference(local, location); return; } if (flowInfo.isPotentiallyNull(local)) { scope.problemReporter().localVariablePotentialNullReference(local, location); return; } recordNullReference(local, location, checkType); return; default: // never happens } } void removeFinalAssignmentIfAny(Reference reference) { for (int i = 0; i < this.assignCount; i++) { if (this.finalAssignments[i] == reference) { this.finalAssignments[i] = null; this.finalVariables[i] = null; return; } } } /* Simulate a throw of an exception from inside a loop in its second or subsequent iteration. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=321926 */ public void simulateThrowAfterLoopBack(FlowInfo flowInfo) { if (this.escapingExceptionCatchSites != null) { for (int i = 0, exceptionCount = this.escapingExceptionCatchSites.size(); i < exceptionCount; i++) { ((EscapingExceptionCatchSite) this.escapingExceptionCatchSites.get(i)).simulateThrowAfterLoopBack(flowInfo); } this.escapingExceptionCatchSites = null; // don't care for it anymore. } } /* Record the fact that some exception thrown by code within this loop is caught by an outer catch block. This is used to propagate data flow along the edge back to the next iteration. See simulateThrowAfterLoopBack */ public void recordCatchContextOfEscapingException(ExceptionHandlingFlowContext catchingContext, ReferenceBinding caughtException) { if (this.escapingExceptionCatchSites == null) { this.escapingExceptionCatchSites = new ArrayList(5); } this.escapingExceptionCatchSites.add(new EscapingExceptionCatchSite(catchingContext, caughtException)); } public boolean hasEscapingExceptions() { return this.escapingExceptionCatchSites != null; } protected boolean internalRecordNullityMismatch(Expression expression, TypeBinding providedType, int nullStatus, TypeBinding expectedType, int checkType) { recordProvidedExpectedTypes(providedType, expectedType, this.nullCount); recordNullReference(expression.localVariableBinding(), expression, checkType); return true; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java0000644000175000001440000000373412212041344031541 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class SwitchFlowContext extends FlowContext { public BranchLabel breakLabel; public UnconditionalFlowInfo initsOnBreak = FlowInfo.DEAD_END; public SwitchFlowContext(FlowContext parent, ASTNode associatedNode, BranchLabel breakLabel, boolean isPreTest) { super(parent, associatedNode); this.breakLabel = breakLabel; if (isPreTest && parent.conditionalLevel > -1) { this.conditionalLevel++; } } public BranchLabel breakLabel() { return this.breakLabel; } public String individualToString() { StringBuffer buffer = new StringBuffer("Switch flow context"); //$NON-NLS-1$ buffer.append("[initsOnBreak -").append(this.initsOnBreak.toString()).append(']'); //$NON-NLS-1$ return buffer.toString(); } public boolean isBreakable() { return true; } public void recordBreakFrom(FlowInfo flowInfo) { if ((this.initsOnBreak.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.initsOnBreak = this.initsOnBreak.mergedWith(flowInfo.unconditionalInits()); } else { this.initsOnBreak = flowInfo.unconditionalCopy(); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java0000644000175000001440000005177412212041344031705 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 385626 - @NonNull fails across loop boundaries * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class FinallyFlowContext extends TryFlowContext { Reference[] finalAssignments; VariableBinding[] finalVariables; int assignCount; // the following three arrays are in sync regarding their indices: LocalVariableBinding[] nullLocals; // slots can be null for checkType == IN_UNBOXING ASTNode[] nullReferences; // Expressions for null checking, Statements for resource analysis // cast to Expression is safe if corresponding nullCheckType != EXIT_RESOURCE int[] nullCheckTypes; int nullCount; // see also the related field FlowContext#expectedTypes // back reference to the flow context of the corresponding try statement public FlowContext tryContext; public FinallyFlowContext(FlowContext parent, ASTNode associatedNode, ExceptionHandlingFlowContext tryContext) { super(parent, associatedNode); this.tryContext = tryContext; } /** * Given some contextual initialization info (derived from a try block or a catch block), this * code will check that the subroutine context does not also initialize a final variable potentially set * redundantly. */ public void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope) { // check redundant final assignments for (int i = 0; i < this.assignCount; i++) { VariableBinding variable = this.finalVariables[i]; if (variable == null) continue; boolean complained = false; // remember if have complained on this final assignment if (variable instanceof FieldBinding) { // final field if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) { complained = true; scope.problemReporter().duplicateInitializationOfBlankFinalField((FieldBinding)variable, this.finalAssignments[i]); } } else { // final local variable if (flowInfo.isPotentiallyAssigned((LocalVariableBinding)variable)) { complained = true; scope.problemReporter().duplicateInitializationOfFinalLocal( (LocalVariableBinding) variable, this.finalAssignments[i]); } } // any reference reported at this level is removed from the parent context // where it could also be reported again if (complained) { FlowContext currentContext = this.getLocalParent(); while (currentContext != null) { //if (currentContext.isSubRoutine()) { currentContext.removeFinalAssignmentIfAny(this.finalAssignments[i]); //} currentContext = currentContext.getLocalParent(); } } } // check inconsistent null checks if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative for (int i = 0; i < this.nullCount; i++) { ASTNode location = this.nullReferences[i]; switch (this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) { case ASSIGN_TO_NONNULL: int nullStatus = flowInfo.nullStatus(this.nullLocals[i]); if (nullStatus != FlowInfo.NON_NULL) { this.parent.recordNullityMismatch(scope, (Expression) location, this.providedExpectedTypes[i][0], this.providedExpectedTypes[i][1], nullStatus); } break; case IN_UNBOXING: checkUnboxing(scope, (Expression) location, flowInfo); break; default: this.parent.recordUsingNullReference(scope, this.nullLocals[i], this.nullReferences[i], this.nullCheckTypes[i], flowInfo); } } } else { // no enclosing loop, be as precise as possible right now for (int i = 0; i < this.nullCount; i++) { ASTNode location = this.nullReferences[i]; // final local variable LocalVariableBinding local = this.nullLocals[i]; switch (this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: if (flowInfo.isDefinitelyNonNull(local)) { if ((this.nullCheckTypes[i] & ~HIDE_NULL_COMPARISON_WARNING_MASK) == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, location); } } else { scope.problemReporter().localVariableNonNullComparedToNull(local, location); } continue; } //$FALL-THROUGH$ case CAN_ONLY_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_ASSIGNMENT: case CAN_ONLY_NULL | IN_INSTANCEOF: Expression expression = (Expression) location; if (flowInfo.isDefinitelyNull(local)) { switch(this.nullCheckTypes[i] & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, expression); continue; } if ((this.nullCheckTypes[i] & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, expression); } continue; case FlowContext.IN_COMPARISON_NON_NULL: if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, expression); continue; } scope.problemReporter().localVariableNullComparedToNonNull(local, expression); continue; case FlowContext.IN_ASSIGNMENT: scope.problemReporter().localVariableRedundantNullAssignment(local, expression); continue; case FlowContext.IN_INSTANCEOF: scope.problemReporter().localVariableNullInstanceof(local, expression); continue; } } else if (flowInfo.isPotentiallyNull(local)) { switch(this.nullCheckTypes[i] & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: this.nullReferences[i] = null; if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, expression); continue; } break; case FlowContext.IN_COMPARISON_NON_NULL: this.nullReferences[i] = null; if (((this.nullCheckTypes[i] & CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, expression); continue; } break; } } break; case MAY_NULL: if (flowInfo.isDefinitelyNull(local)) { scope.problemReporter().localVariableNullReference(local, location); continue; } if (flowInfo.isPotentiallyNull(local)) { scope.problemReporter().localVariablePotentialNullReference(local, location); } break; case ASSIGN_TO_NONNULL: int nullStatus = flowInfo.nullStatus(local); if (nullStatus != FlowInfo.NON_NULL) { char[][] annotationName = scope.environment().getNonNullAnnotationName(); scope.problemReporter().nullityMismatch((Expression) location, this.providedExpectedTypes[i][0], this.providedExpectedTypes[i][1], nullStatus, annotationName); } break; case IN_UNBOXING: checkUnboxing(scope, (Expression) location, flowInfo); break; default: // should not happen } } } } public String individualToString() { StringBuffer buffer = new StringBuffer("Finally flow context"); //$NON-NLS-1$ buffer.append("[finalAssignments count - ").append(this.assignCount).append(']'); //$NON-NLS-1$ buffer.append("[nullReferences count - ").append(this.nullCount).append(']'); //$NON-NLS-1$ return buffer.toString(); } public boolean isSubRoutine() { return true; } protected boolean recordFinalAssignment( VariableBinding binding, Reference finalAssignment) { if (this.assignCount == 0) { this.finalAssignments = new Reference[5]; this.finalVariables = new VariableBinding[5]; } else { if (this.assignCount == this.finalAssignments.length) System.arraycopy( this.finalAssignments, 0, (this.finalAssignments = new Reference[this.assignCount * 2]), 0, this.assignCount); System.arraycopy( this.finalVariables, 0, (this.finalVariables = new VariableBinding[this.assignCount * 2]), 0, this.assignCount); } this.finalAssignments[this.assignCount] = finalAssignment; this.finalVariables[this.assignCount++] = binding; return true; } public void recordUsingNullReference(Scope scope, LocalVariableBinding local, ASTNode location, int checkType, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && !flowInfo.isDefinitelyUnknown(local)) { // if reference is being recorded inside an assert, we will not raise redundant null check warnings checkType |= (this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING); int checkTypeWithoutHideNullWarning = checkType & ~FlowContext.HIDE_NULL_COMPARISON_WARNING_MASK; if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative switch (checkTypeWithoutHideNullWarning) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_ASSIGNMENT: case CAN_ONLY_NULL | IN_INSTANCEOF: Expression reference = (Expression) location; if (flowInfo.cannotBeNull(local)) { if (checkTypeWithoutHideNullWarning == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } else if (checkTypeWithoutHideNullWarning == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) { scope.problemReporter().localVariableNonNullComparedToNull(local, reference); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } return; } if (flowInfo.canOnlyBeNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } scope.problemReporter().localVariableNullComparedToNonNull(local, reference); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_ASSIGNMENT: scope.problemReporter().localVariableRedundantNullAssignment(local, reference); return; case FlowContext.IN_INSTANCEOF: scope.problemReporter().localVariableNullInstanceof(local, reference); return; } } else if (flowInfo.isPotentiallyNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; } } break; case MAY_NULL : if (flowInfo.cannotBeNull(local)) { return; } if (flowInfo.canOnlyBeNull(local)) { scope.problemReporter().localVariableNullReference(local, location); return; } break; default: // never happens } } else { // no enclosing loop, be as precise as possible right now switch (checkTypeWithoutHideNullWarning) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: if (flowInfo.isDefinitelyNonNull(local)) { if (checkTypeWithoutHideNullWarning == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, location); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } else { scope.problemReporter().localVariableNonNullComparedToNull(local, location); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } return; } //$FALL-THROUGH$ case CAN_ONLY_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_ASSIGNMENT: case CAN_ONLY_NULL | IN_INSTANCEOF: Expression reference = (Expression) location; if (flowInfo.isDefinitelyNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } scope.problemReporter().localVariableNullComparedToNonNull(local, reference); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_ASSIGNMENT: scope.problemReporter().localVariableRedundantNullAssignment(local, reference); return; case FlowContext.IN_INSTANCEOF: scope.problemReporter().localVariableNullInstanceof(local, reference); return; } } else if (flowInfo.isPotentiallyNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; } } break; case MAY_NULL : if (flowInfo.isDefinitelyNull(local)) { scope.problemReporter().localVariableNullReference(local, location); return; } if (flowInfo.isPotentiallyNull(local)) { scope.problemReporter().localVariablePotentialNullReference(local, location); return; } if (flowInfo.isDefinitelyNonNull(local)) { return; // shortcut: cannot be null } break; default: // never happens } } recordNullReference(local, location, checkType); // prepare to re-check with try/catch flow info } } void removeFinalAssignmentIfAny(Reference reference) { for (int i = 0; i < this.assignCount; i++) { if (this.finalAssignments[i] == reference) { this.finalAssignments[i] = null; this.finalVariables[i] = null; return; } } } protected void recordNullReference(LocalVariableBinding local, ASTNode expression, int checkType) { if (this.nullCount == 0) { this.nullLocals = new LocalVariableBinding[5]; this.nullReferences = new ASTNode[5]; this.nullCheckTypes = new int[5]; } else if (this.nullCount == this.nullLocals.length) { int newLength = this.nullCount * 2; System.arraycopy(this.nullLocals, 0, this.nullLocals = new LocalVariableBinding[newLength], 0, this.nullCount); System.arraycopy(this.nullReferences, 0, this.nullReferences = new ASTNode[newLength], 0, this.nullCount); System.arraycopy(this.nullCheckTypes, 0, this.nullCheckTypes = new int[newLength], 0, this.nullCount); } this.nullLocals[this.nullCount] = local; this.nullReferences[this.nullCount] = expression; this.nullCheckTypes[this.nullCount++] = checkType; } public void recordUnboxing(Scope scope, Expression expression, int nullStatus, FlowInfo flowInfo) { if (nullStatus == FlowInfo.NULL) super.recordUnboxing(scope, expression, nullStatus, flowInfo); else // defer checking: recordNullReference(null, expression, IN_UNBOXING); } protected boolean internalRecordNullityMismatch(Expression expression, TypeBinding providedType, int nullStatus, TypeBinding expectedType, int checkType) { // cf. decision structure inside FinallyFlowContext.recordUsingNullReference(..) if (nullStatus == FlowInfo.UNKNOWN || ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0 && nullStatus != FlowInfo.NULL)) { recordProvidedExpectedTypes(providedType, expectedType, this.nullCount); recordNullReference(expression.localVariableBinding(), expression, checkType); return true; } return false; } } ././@LongLink0000644000000000000000000000015112251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.0000644000175000001440000000653112212041344032423 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class InitializationFlowContext extends ExceptionHandlingFlowContext { public int exceptionCount; public TypeBinding[] thrownExceptions = new TypeBinding[5]; public ASTNode[] exceptionThrowers = new ASTNode[5]; public FlowInfo[] exceptionThrowerFlowInfos = new FlowInfo[5]; public FlowInfo initsBeforeContext; public InitializationFlowContext(FlowContext parent, ASTNode associatedNode, FlowInfo initsBeforeContext, FlowContext initializationParent, BlockScope scope) { super( parent, associatedNode, Binding.NO_EXCEPTIONS, // no exception allowed by default initializationParent, scope, FlowInfo.DEAD_END); this.initsBeforeContext = initsBeforeContext; } public void checkInitializerExceptions( BlockScope currentScope, FlowContext initializerContext, FlowInfo flowInfo) { for (int i = 0; i < this.exceptionCount; i++) { initializerContext.checkExceptionHandlers( this.thrownExceptions[i], this.exceptionThrowers[i], this.exceptionThrowerFlowInfos[i], currentScope); } } public String individualToString() { StringBuffer buffer = new StringBuffer("Initialization flow context"); //$NON-NLS-1$ for (int i = 0; i < this.exceptionCount; i++) { buffer.append('[').append(this.thrownExceptions[i].readableName()); buffer.append('-').append(this.exceptionThrowerFlowInfos[i].toString()).append(']'); } return buffer.toString(); } public void recordHandlingException( ReferenceBinding exceptionType, UnconditionalFlowInfo flowInfo, TypeBinding raisedException, TypeBinding caughtException, ASTNode invocationSite, boolean wasMasked) { // even if unreachable code, need to perform unhandled exception diagnosis int size = this.thrownExceptions.length; if (this.exceptionCount == size) { System.arraycopy( this.thrownExceptions, 0, (this.thrownExceptions = new TypeBinding[size * 2]), 0, size); System.arraycopy( this.exceptionThrowers, 0, (this.exceptionThrowers = new ASTNode[size * 2]), 0, size); System.arraycopy( this.exceptionThrowerFlowInfos, 0, (this.exceptionThrowerFlowInfos = new FlowInfo[size * 2]), 0, size); } this.thrownExceptions[this.exceptionCount] = raisedException; this.exceptionThrowers[this.exceptionCount] = invocationSite; this.exceptionThrowerFlowInfos[this.exceptionCount++] = flowInfo.copy(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java0000644000175000001440000002041412212041344032004 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 332637 - Dead Code detection removing code that isn't dead * bug 391517 - java.lang.VerifyError on code that runs correctly in Eclipse 3.7 and eclipse 3.6 * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; /** * Record conditional initialization status during definite assignment analysis * */ public class ConditionalFlowInfo extends FlowInfo { public FlowInfo initsWhenTrue; public FlowInfo initsWhenFalse; ConditionalFlowInfo(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){ this.initsWhenTrue = initsWhenTrue; this.initsWhenFalse = initsWhenFalse; this.tagBits = initsWhenTrue.tagBits & initsWhenFalse.tagBits & UNREACHABLE; } public FlowInfo addInitializationsFrom(FlowInfo otherInits) { this.initsWhenTrue.addInitializationsFrom(otherInits); this.initsWhenFalse.addInitializationsFrom(otherInits); return this; } public FlowInfo addNullInfoFrom(FlowInfo otherInits) { this.initsWhenTrue.addNullInfoFrom(otherInits); this.initsWhenFalse.addNullInfoFrom(otherInits); return this; } public FlowInfo addPotentialInitializationsFrom(FlowInfo otherInits) { this.initsWhenTrue.addPotentialInitializationsFrom(otherInits); this.initsWhenFalse.addPotentialInitializationsFrom(otherInits); return this; } public FlowInfo asNegatedCondition() { FlowInfo extra = this.initsWhenTrue; this.initsWhenTrue = this.initsWhenFalse; this.initsWhenFalse = extra; return this; } public FlowInfo copy() { return new ConditionalFlowInfo(this.initsWhenTrue.copy(), this.initsWhenFalse.copy()); } public FlowInfo initsWhenFalse() { return this.initsWhenFalse; } public FlowInfo initsWhenTrue() { return this.initsWhenTrue; } public boolean isDefinitelyAssigned(FieldBinding field) { return this.initsWhenTrue.isDefinitelyAssigned(field) && this.initsWhenFalse.isDefinitelyAssigned(field); } public boolean isDefinitelyAssigned(LocalVariableBinding local) { return this.initsWhenTrue.isDefinitelyAssigned(local) && this.initsWhenFalse.isDefinitelyAssigned(local); } public boolean isDefinitelyNonNull(LocalVariableBinding local) { return this.initsWhenTrue.isDefinitelyNonNull(local) && this.initsWhenFalse.isDefinitelyNonNull(local); } public boolean isDefinitelyNull(LocalVariableBinding local) { return this.initsWhenTrue.isDefinitelyNull(local) && this.initsWhenFalse.isDefinitelyNull(local); } public boolean isDefinitelyUnknown(LocalVariableBinding local) { return this.initsWhenTrue.isDefinitelyUnknown(local) && this.initsWhenFalse.isDefinitelyUnknown(local); } public boolean hasNullInfoFor(LocalVariableBinding local) { return this.initsWhenTrue.hasNullInfoFor(local) || this.initsWhenFalse.hasNullInfoFor(local); } public boolean isPotentiallyAssigned(FieldBinding field) { return this.initsWhenTrue.isPotentiallyAssigned(field) || this.initsWhenFalse.isPotentiallyAssigned(field); } public boolean isPotentiallyAssigned(LocalVariableBinding local) { return this.initsWhenTrue.isPotentiallyAssigned(local) || this.initsWhenFalse.isPotentiallyAssigned(local); } public boolean isPotentiallyNonNull(LocalVariableBinding local) { return this.initsWhenTrue.isPotentiallyNonNull(local) || this.initsWhenFalse.isPotentiallyNonNull(local); } public boolean isPotentiallyNull(LocalVariableBinding local) { return this.initsWhenTrue.isPotentiallyNull(local) || this.initsWhenFalse.isPotentiallyNull(local); } public boolean isPotentiallyUnknown(LocalVariableBinding local) { return this.initsWhenTrue.isPotentiallyUnknown(local) || this.initsWhenFalse.isPotentiallyUnknown(local); } public boolean isProtectedNonNull(LocalVariableBinding local) { return this.initsWhenTrue.isProtectedNonNull(local) && this.initsWhenFalse.isProtectedNonNull(local); } public boolean isProtectedNull(LocalVariableBinding local) { return this.initsWhenTrue.isProtectedNull(local) && this.initsWhenFalse.isProtectedNull(local); } public void markAsComparedEqualToNonNull(LocalVariableBinding local) { this.initsWhenTrue.markAsComparedEqualToNonNull(local); this.initsWhenFalse.markAsComparedEqualToNonNull(local); } public void markAsComparedEqualToNull(LocalVariableBinding local) { this.initsWhenTrue.markAsComparedEqualToNull(local); this.initsWhenFalse.markAsComparedEqualToNull(local); } public void markAsDefinitelyAssigned(FieldBinding field) { this.initsWhenTrue.markAsDefinitelyAssigned(field); this.initsWhenFalse.markAsDefinitelyAssigned(field); } public void markAsDefinitelyAssigned(LocalVariableBinding local) { this.initsWhenTrue.markAsDefinitelyAssigned(local); this.initsWhenFalse.markAsDefinitelyAssigned(local); } public void markAsDefinitelyNonNull(LocalVariableBinding local) { this.initsWhenTrue.markAsDefinitelyNonNull(local); this.initsWhenFalse.markAsDefinitelyNonNull(local); } public void markAsDefinitelyNull(LocalVariableBinding local) { this.initsWhenTrue.markAsDefinitelyNull(local); this.initsWhenFalse.markAsDefinitelyNull(local); } public void resetNullInfo(LocalVariableBinding local) { this.initsWhenTrue.resetNullInfo(local); this.initsWhenFalse.resetNullInfo(local); } public void markPotentiallyNullBit(LocalVariableBinding local) { this.initsWhenTrue.markPotentiallyNullBit(local); this.initsWhenFalse.markPotentiallyNullBit(local); } public void markPotentiallyNonNullBit(LocalVariableBinding local) { this.initsWhenTrue.markPotentiallyNonNullBit(local); this.initsWhenFalse.markPotentiallyNonNullBit(local); } public void markAsDefinitelyUnknown(LocalVariableBinding local) { this.initsWhenTrue.markAsDefinitelyUnknown(local); this.initsWhenFalse.markAsDefinitelyUnknown(local); } public void markPotentiallyUnknownBit(LocalVariableBinding local) { this.initsWhenTrue.markPotentiallyUnknownBit(local); this.initsWhenFalse.markPotentiallyUnknownBit(local); } public FlowInfo setReachMode(int reachMode) { if (reachMode == REACHABLE) { this.tagBits &= ~UNREACHABLE; } else { this.tagBits |= reachMode; } this.initsWhenTrue.setReachMode(reachMode); this.initsWhenFalse.setReachMode(reachMode); return this; } public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) { return unconditionalInits().mergedWith(otherInits); } public UnconditionalFlowInfo nullInfoLessUnconditionalCopy() { return unconditionalInitsWithoutSideEffect(). nullInfoLessUnconditionalCopy(); } public String toString() { return "FlowInfo"; //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$ } public FlowInfo safeInitsWhenTrue() { return this.initsWhenTrue; } public UnconditionalFlowInfo unconditionalCopy() { return this.initsWhenTrue.unconditionalCopy(). mergedWith(this.initsWhenFalse.unconditionalInits()); } public UnconditionalFlowInfo unconditionalFieldLessCopy() { return this.initsWhenTrue.unconditionalFieldLessCopy(). mergedWith(this.initsWhenFalse.unconditionalFieldLessCopy()); // should never happen, hence suboptimal does not hurt } public UnconditionalFlowInfo unconditionalInits() { return this.initsWhenTrue.unconditionalInits(). mergedWith(this.initsWhenFalse.unconditionalInits()); } public UnconditionalFlowInfo unconditionalInitsWithoutSideEffect() { // cannot do better here than unconditionalCopy - but still a different // operation for UnconditionalFlowInfo return this.initsWhenTrue.unconditionalCopy(). mergedWith(this.initsWhenFalse.unconditionalInits()); } public void resetAssignmentInfo(LocalVariableBinding local) { this.initsWhenTrue.resetAssignmentInfo(local); this.initsWhenFalse.resetAssignmentInfo(local); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/TryFlowContext.java0000644000175000001440000000307512212041344031054 0ustar dokousers/******************************************************************************* * Copyright (c) 2013 GK Software AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stephan Herrmann - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; /** * Shared implementation for try-statement-related flow contexts. */ public abstract class TryFlowContext extends FlowContext { /** * For a try statement nested inside a finally block this reference * points to the flow context of the outer try block, for access to its initsOnFinally. */ public FlowContext outerTryContext; public TryFlowContext(FlowContext parent, ASTNode associatedNode) { super(parent, associatedNode); } public void markFinallyNullStatus(LocalVariableBinding local, int nullStatus) { if (this.outerTryContext != null) { this.outerTryContext.markFinallyNullStatus(local, nullStatus); } super.markFinallyNullStatus(local, nullStatus); } public void mergeFinallyNullInfo(FlowInfo flowInfo) { if (this.outerTryContext != null) { this.outerTryContext.mergeFinallyNullInfo(flowInfo); } super.mergeFinallyNullInfo(flowInfo); } } ././@LongLink0000644000000000000000000000015312251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContex0000644000175000001440000000367212212041344032430 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class InsideSubRoutineFlowContext extends TryFlowContext { public UnconditionalFlowInfo initsOnReturn; public InsideSubRoutineFlowContext( FlowContext parent, ASTNode associatedNode) { super(parent, associatedNode); this.initsOnReturn = FlowInfo.DEAD_END; } public String individualToString() { StringBuffer buffer = new StringBuffer("Inside SubRoutine flow context"); //$NON-NLS-1$ buffer.append("[initsOnReturn -").append(this.initsOnReturn.toString()).append(']'); //$NON-NLS-1$ return buffer.toString(); } public UnconditionalFlowInfo initsOnReturn(){ return this.initsOnReturn; } public boolean isNonReturningContext() { return ((SubRoutineStatement) this.associatedNode).isSubRoutineEscaping(); } public void recordReturnFrom(UnconditionalFlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { if (this.initsOnReturn == FlowInfo.DEAD_END) { this.initsOnReturn = (UnconditionalFlowInfo) flowInfo.copy(); } else { this.initsOnReturn = this.initsOnReturn.mergedWith(flowInfo); } } } public SubRoutineStatement subroutine() { return (SubRoutineStatement) this.associatedNode; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java0000644000175000001440000005643712212041344027636 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 292478 - Report potentially null across variable assignment * bug 332637 - Dead Code detection removing code that isn't dead * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.IfStatement; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; public abstract class FlowInfo { public int tagBits; // REACHABLE by default public final static int REACHABLE = 0; /* unreachable code * eg. while (true); * i++; --> unreachable code */ public final static int UNREACHABLE_OR_DEAD = 1; /* unreachable code as inferred by null analysis * eg. str = null; * if (str != null) { * // dead code * } */ public final static int UNREACHABLE_BY_NULLANALYSIS = 2; /* * code unreachable in any fashion */ public final static int UNREACHABLE = UNREACHABLE_OR_DEAD | UNREACHABLE_BY_NULLANALYSIS; public final static int NULL_FLAG_MASK = 4; public final static int UNKNOWN = 1; public final static int NULL = 2; public final static int NON_NULL = 4; public final static int POTENTIALLY_UNKNOWN = 8; public final static int POTENTIALLY_NULL = 16; public final static int POTENTIALLY_NON_NULL = 32; public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization static { DEAD_END = new UnconditionalFlowInfo(); DEAD_END.tagBits = UNREACHABLE; } /** * Add other inits to this flow info, then return this. The operation semantics * are to match as closely as possible the application to this flow info of all * the operations that resulted into otherInits. * @param otherInits other inits to add to this * @return this, modified according to otherInits information */ abstract public FlowInfo addInitializationsFrom(FlowInfo otherInits); /** * Add all null information from otherInits to this flow info and return this. * The operation models the effect of an unconditional sequence of this flow info * and otherInits. */ abstract public FlowInfo addNullInfoFrom(FlowInfo otherInits); /** * Compose other inits over this flow info, then return this. The operation * semantics are to wave into this flow info the consequences of a possible * path into the operations that resulted into otherInits. The fact that this * path may be left unexecuted under peculiar conditions results into less * specific results than {@link #addInitializationsFrom(FlowInfo) * addInitializationsFrom}. * @param otherInits other inits to compose over this * @return this, modified according to otherInits information */ abstract public FlowInfo addPotentialInitializationsFrom(FlowInfo otherInits); public FlowInfo asNegatedCondition() { return this; } public static FlowInfo conditional(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){ if (initsWhenTrue == initsWhenFalse) return initsWhenTrue; // if (initsWhenTrue.equals(initsWhenFalse)) return initsWhenTrue; -- could optimize if #equals is defined return new ConditionalFlowInfo(initsWhenTrue, initsWhenFalse); } /** * Check whether a given local variable is known to be unable to gain a definite * non null or definite null status by the use of an enclosing flow info. The * semantics are that if the current flow info marks the variable as potentially * unknown or else as being both potentially null and potentially non null, * then it won't ever be promoted as definitely null or definitely non null. (It * could still get promoted to definite unknown). * @param local the variable to check * @return true iff this flow info prevents local from being promoted to * definite non null or definite null against an enclosing flow info */ public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) { return isPotentiallyUnknown(local) || isPotentiallyNonNull(local) && isPotentiallyNull(local); } /** * Check whether a given local variable is known to be non null, either because * it is definitely non null, or because is has been tested against non null. * @param local the variable to ckeck * @return true iff local cannot be null for this flow info */ public boolean cannotBeNull(LocalVariableBinding local) { return isDefinitelyNonNull(local) || isProtectedNonNull(local); } /** * Check whether a given local variable is known to be null, either because it * is definitely null, or because is has been tested against null. * @param local the variable to ckeck * @return true iff local can only be null for this flow info */ public boolean canOnlyBeNull(LocalVariableBinding local) { return isDefinitelyNull(local) || isProtectedNull(local); } /** * Return a deep copy of the current instance. * @return a deep copy of this flow info */ abstract public FlowInfo copy(); public static UnconditionalFlowInfo initial(int maxFieldCount) { UnconditionalFlowInfo info = new UnconditionalFlowInfo(); info.maxFieldCount = maxFieldCount; return info; } /** * Return the flow info that would result from the path associated to the * value false for the condition expression that generated this flow info. * May be this flow info if it is not an instance of {@link * ConditionalFlowInfo}. May have a side effect on subparts of this flow * info (subtrees get merged). * @return the flow info associated to the false branch of the condition * that generated this flow info */ abstract public FlowInfo initsWhenFalse(); /** * Return the flow info that would result from the path associated to the * value true for the condition expression that generated this flow info. * May be this flow info if it is not an instance of {@link * ConditionalFlowInfo}. May have a side effect on subparts of this flow * info (subtrees get merged). * @return the flow info associated to the true branch of the condition * that generated this flow info */ abstract public FlowInfo initsWhenTrue(); /** * Check status of definite assignment for a field. */ abstract public boolean isDefinitelyAssigned(FieldBinding field); /** * Check status of definite assignment for a local. */ public abstract boolean isDefinitelyAssigned(LocalVariableBinding local); /** * Check status of definite non-null value for a given local variable. * @param local the variable to ckeck * @return true iff local is definitely non null for this flow info */ public abstract boolean isDefinitelyNonNull(LocalVariableBinding local); /** * Check status of definite null value for a given local variable. * @param local the variable to ckeck * @return true iff local is definitely null for this flow info */ public abstract boolean isDefinitelyNull(LocalVariableBinding local); /** * Check status of definite unknown value for a given local variable. * @param local the variable to ckeck * @return true iff local is definitely unknown for this flow info */ public abstract boolean isDefinitelyUnknown(LocalVariableBinding local); /** * Check if any null info has been recorded for a given local variable. * Here even recording of 'UNKNOWN' is considered as null info. */ public abstract boolean hasNullInfoFor(LocalVariableBinding local); /** * Check status of potential assignment for a field. */ abstract public boolean isPotentiallyAssigned(FieldBinding field); /** * Check status of potential assignment for a local variable. */ abstract public boolean isPotentiallyAssigned(LocalVariableBinding field); /** * Check status of potential null assignment for a local. Return true if there * is a reasonable expectation that the variable be non null at this point. * @param local LocalVariableBinding - the binding for the checked local * @return true if there is a reasonable expectation that local be non null at * this point */ public abstract boolean isPotentiallyNonNull(LocalVariableBinding local); /** * Check status of potential null assignment for a local. Return true if there * is a reasonable expectation that the variable be null at this point. This * includes the protected null case, so as to augment diagnostics, but does not * really check that someone deliberately assigned to null on any specific * path * @param local LocalVariableBinding - the binding for the checked local * @return true if there is a reasonable expectation that local be null at * this point */ public abstract boolean isPotentiallyNull(LocalVariableBinding local); /** * Return true if the given local may have been assigned to an unknown value. * @param local the local to check * @return true if the given local may have been assigned to an unknown value */ public abstract boolean isPotentiallyUnknown(LocalVariableBinding local); /** * Return true if the given local is protected by a test against a non null * value. * @param local the local to check * @return true if the given local is protected by a test against a non null */ public abstract boolean isProtectedNonNull(LocalVariableBinding local); /** * Return true if the given local is protected by a test against null. * @param local the local to check * @return true if the given local is protected by a test against null */ public abstract boolean isProtectedNull(LocalVariableBinding local); /** * Record that a local variable got checked to be non null. * @param local the checked local variable */ abstract public void markAsComparedEqualToNonNull(LocalVariableBinding local); /** * Record that a local variable got checked to be null. * @param local the checked local variable */ abstract public void markAsComparedEqualToNull(LocalVariableBinding local); /** * Record a field got definitely assigned. */ 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 local got definitely assigned to null. */ abstract public void markAsDefinitelyNull(LocalVariableBinding local); /** * Reset all null-information about a given local. */ abstract public void resetNullInfo(LocalVariableBinding local); /** * Record a local may have got assigned to unknown (set the bit on existing info). */ abstract public void markPotentiallyUnknownBit(LocalVariableBinding local); /** * Record a local may have got assigned to null (set the bit on existing info). */ abstract public void markPotentiallyNullBit(LocalVariableBinding local); /** * Record a local may have got assigned to non-null (set the bit on existing info). */ abstract public void markPotentiallyNonNullBit(LocalVariableBinding local); /** * Record a local got definitely assigned. */ abstract public void markAsDefinitelyAssigned(LocalVariableBinding local); /** * Record a local got definitely assigned to an unknown value. */ abstract public void markAsDefinitelyUnknown(LocalVariableBinding local); /** * Mark the null status of the given local according to the given status * @param local * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL */ public void markNullStatus(LocalVariableBinding local, int nullStatus) { switch(nullStatus) { // definite status? case FlowInfo.UNKNOWN : markAsDefinitelyUnknown(local); break; case FlowInfo.NULL : markAsDefinitelyNull(local); break; case FlowInfo.NON_NULL : markAsDefinitelyNonNull(local); break; default: // collect potential status: resetNullInfo(local); if ((nullStatus & FlowInfo.POTENTIALLY_UNKNOWN) != 0) markPotentiallyUnknownBit(local); if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) markPotentiallyNullBit(local); if ((nullStatus & FlowInfo.POTENTIALLY_NON_NULL) != 0) markPotentiallyNonNullBit(local); if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL|FlowInfo.POTENTIALLY_UNKNOWN)) == 0) markAsDefinitelyUnknown(local); } } /** * Answer the null status of the given local * @param local * @return bitset of FlowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL */ public int nullStatus(LocalVariableBinding local) { if (isDefinitelyUnknown(local)) return FlowInfo.UNKNOWN; if (isDefinitelyNull(local)) return FlowInfo.NULL; if (isDefinitelyNonNull(local)) return FlowInfo.NON_NULL; int status = 0; if (isPotentiallyUnknown(local)) status |= FlowInfo.POTENTIALLY_UNKNOWN; if (isPotentiallyNull(local)) status |= FlowInfo.POTENTIALLY_NULL; if (isPotentiallyNonNull(local)) status |= FlowInfo.POTENTIALLY_NON_NULL; if (status > 0) return status; return FlowInfo.UNKNOWN; } /** * Merge two single bits (NULL, NON_NULL, POTENTIALLY*..) into one. * This method implements a simpler logic than the 4-bit encoding used in FlowInfo instances. */ public static int mergeNullStatus(int nullStatus1, int nullStatus2) { boolean canBeNull = false; boolean canBeNonNull = false; switch (nullStatus1) { case POTENTIALLY_NULL: canBeNonNull = true; //$FALL-THROUGH$ case NULL: canBeNull = true; break; case POTENTIALLY_NON_NULL: canBeNull = true; //$FALL-THROUGH$ case NON_NULL: canBeNonNull = true; break; } switch (nullStatus2) { case POTENTIALLY_NULL: canBeNonNull = true; //$FALL-THROUGH$ case NULL: canBeNull = true; break; case POTENTIALLY_NON_NULL: canBeNull = true; //$FALL-THROUGH$ case NON_NULL: canBeNonNull = true; break; } if (canBeNull) { if (canBeNonNull) return POTENTIALLY_NULL; else return NULL; } else { if (canBeNonNull) return NON_NULL; else return UNKNOWN; } } /** * Merge branches using optimized boolean conditions */ public static UnconditionalFlowInfo mergedOptimizedBranches( FlowInfo initsWhenTrue, boolean isOptimizedTrue, FlowInfo initsWhenFalse, boolean isOptimizedFalse, boolean allowFakeDeadBranch) { UnconditionalFlowInfo mergedInfo; if (isOptimizedTrue){ if (initsWhenTrue == FlowInfo.DEAD_END && allowFakeDeadBranch) { mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD). unconditionalInits(); } else { mergedInfo = initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse. nullInfoLessUnconditionalCopy()). unconditionalInits(); } } else if (isOptimizedFalse) { if (initsWhenFalse == FlowInfo.DEAD_END && allowFakeDeadBranch) { mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD). unconditionalInits(); } else { mergedInfo = initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue. nullInfoLessUnconditionalCopy()). unconditionalInits(); } } else { mergedInfo = initsWhenTrue. mergedWith(initsWhenFalse.unconditionalInits()); } return mergedInfo; } /** * Merge if-else branches using optimized boolean conditions */ public static UnconditionalFlowInfo mergedOptimizedBranchesIfElse( FlowInfo initsWhenTrue, boolean isOptimizedTrue, FlowInfo initsWhenFalse, boolean isOptimizedFalse, boolean allowFakeDeadBranch, FlowInfo flowInfo, IfStatement ifStatement, boolean reportDeadCodeInKnownPattern) { UnconditionalFlowInfo mergedInfo; if (isOptimizedTrue){ if (initsWhenTrue == FlowInfo.DEAD_END && allowFakeDeadBranch) { if (!reportDeadCodeInKnownPattern) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=256796 // do not report code even after if-else as dead as a consequence of analysis done in known dead code pattern // when the CompilerOptions$reportDeadCodeInTrivialIfStatement option is disabled if (ifStatement.elseStatement == null) { mergedInfo = flowInfo.unconditionalInits(); } else { mergedInfo = initsWhenFalse.unconditionalInits(); if (initsWhenFalse != FlowInfo.DEAD_END) { // let the definitely true status of known dead code pattern not affect the reachability mergedInfo.setReachMode(flowInfo.reachMode()); } } } else { mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD). unconditionalInits(); } } else { mergedInfo = initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse. nullInfoLessUnconditionalCopy()). unconditionalInits(); } } else if (isOptimizedFalse) { if (initsWhenFalse == FlowInfo.DEAD_END && allowFakeDeadBranch) { if (!reportDeadCodeInKnownPattern) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=256796 // do not report code even after if-else as dead as a consequence of analysis done in known dead code pattern // when the CompilerOptions$reportDeadCodeInTrivialIfStatement option is disabled if (ifStatement.thenStatement == null) { mergedInfo = flowInfo.unconditionalInits(); } else { mergedInfo = initsWhenTrue.unconditionalInits(); if (initsWhenTrue != FlowInfo.DEAD_END) { // let the definitely false status of known dead code pattern not affect the reachability mergedInfo.setReachMode(flowInfo.reachMode()); } } } else { mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD). unconditionalInits(); } } else { mergedInfo = initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue. nullInfoLessUnconditionalCopy()). unconditionalInits(); } } else if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && (ifStatement.bits & ASTNode.IsElseStatementUnreachable) != 0 && initsWhenTrue != FlowInfo.DEAD_END && initsWhenFalse != FlowInfo.DEAD_END) { // Done when the then branch will always be executed but the condition does not have a boolean // true or false (i.e if(true), etc) for sure // We don't do this if both if and else branches themselves are in an unreachable code // or if any of them is a DEAD_END (e.g. contains 'return' or 'throws') mergedInfo = initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse. nullInfoLessUnconditionalCopy()). unconditionalInits(); // if a variable is only initialized in one branch and not initialized in the other, // then we need to cast a doubt on its initialization in the merged info mergedInfo.definiteInits &= initsWhenFalse.unconditionalCopy().definiteInits; } else if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && (ifStatement.bits & ASTNode.IsThenStatementUnreachable) != 0 && initsWhenTrue != FlowInfo.DEAD_END && initsWhenFalse != FlowInfo.DEAD_END) { // Done when the else branch will always be executed but the condition does not have a boolean // true or false (i.e if(true), etc) for sure // We don't do this if both if and else branches themselves are in an unreachable code // or if any of them is a DEAD_END (e.g. contains 'return' or 'throws') mergedInfo = initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue. nullInfoLessUnconditionalCopy()). unconditionalInits(); // if a variable is only initialized in one branch and not initialized in the other, // then we need to cast a doubt on its initialization in the merged info mergedInfo.definiteInits &= initsWhenTrue.unconditionalCopy().definiteInits; } else { mergedInfo = initsWhenTrue. mergedWith(initsWhenFalse.unconditionalInits()); } return mergedInfo; } /** * Find out the reachability mode of this flowInfo. * @return REACHABLE if this flow info is reachable, otherwise * either UNREACHABLE_OR_DEAD or UNREACHABLE_BY_NULLANALYSIS. */ public int reachMode() { return this.tagBits & UNREACHABLE; } /** * Return a flow info that carries the same information as the result of * {@link #initsWhenTrue() initsWhenTrue}, but warrantied to be different * from this.
* Caveat: side effects on the result may affect components of this. * @return the result of initsWhenTrue or a copy of it */ abstract public FlowInfo safeInitsWhenTrue(); /** * Set this flow info reach mode and return this. * @param reachMode one of {@link #REACHABLE REACHABLE}, {@link #UNREACHABLE_OR_DEAD UNREACHABLE_OR_DEAD}, * {@link #UNREACHABLE_BY_NULLANALYSIS UNREACHABLE_BY_NULLANALYSIS} or {@link #UNREACHABLE UNREACHABLE} * @return this, with the reach mode set to reachMode */ abstract public FlowInfo setReachMode(int reachMode); /** * Return the intersection of this and otherInits, that is * one of:
    *
  • the receiver updated in the following way:
      *
    • intersection of definitely assigned variables, *
    • union of potentially assigned variables, *
    • similar operations for null,
    *
  • or the receiver or otherInits if the other one is non * reachable.
* otherInits is not affected, and is not returned either (no * need to protect the result). * @param otherInits the flow info to merge with this * @return the intersection of this and otherInits. */ abstract public UnconditionalFlowInfo mergedWith( UnconditionalFlowInfo otherInits); /** * Return a copy of this unconditional flow info, deprived from its null * info. {@link #DEAD_END DEAD_END} is returned unmodified. * @return a copy of this unconditional flow info deprived from its null info */ abstract public UnconditionalFlowInfo nullInfoLessUnconditionalCopy(); public String toString(){ if (this == DEAD_END){ return "FlowInfo.DEAD_END"; //$NON-NLS-1$ } return super.toString(); } /** * Return a new flow info that holds the same information as this would after * a call to unconditionalInits, but leaving this info unaffected. Moreover, * the result can be modified without affecting this. * @return a new flow info carrying this unconditional flow info */ abstract public UnconditionalFlowInfo unconditionalCopy(); /** * Return a new flow info that holds the same information as this would after * a call to {@link #unconditionalInits() unconditionalInits} followed by the * erasure of fields specific information, but leaving this flow info unaffected. * @return a new flow info carrying the unconditional flow info for local variables */ abstract public UnconditionalFlowInfo unconditionalFieldLessCopy(); /** * Return a flow info that merges the possible paths of execution described by * this flow info. In case of an unconditional flow info, return this. In case * of a conditional flow info, merge branches recursively. Caveat: this may * be affected, and modifying the result may affect this. * @return a flow info that merges the possible paths of execution described by * this */ abstract public UnconditionalFlowInfo unconditionalInits(); /** * Return a new flow info that holds the same information as this would after * a call to {@link #unconditionalInits() unconditionalInits}, but leaving * this info unaffected. Side effects on the result might affect this though * (consider it as read only). * @return a flow info carrying this unconditional flow info */ abstract public UnconditionalFlowInfo unconditionalInitsWithoutSideEffect(); /** * Resets the definite and potential initialization info for the given local variable * @param local */ abstract public void resetAssignmentInfo(LocalVariableBinding local); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java0000644000175000001440000000401112212041344031304 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class LabelFlowContext extends SwitchFlowContext { public char[] labelName; public LabelFlowContext(FlowContext parent, ASTNode associatedNode, char[] labelName, BranchLabel breakLabel, BlockScope scope) { super(parent, associatedNode, breakLabel, false); this.labelName = labelName; checkLabelValidity(scope); } void checkLabelValidity(BlockScope scope) { // check if label was already defined above FlowContext current = this.getLocalParent(); while (current != null) { char[] currentLabelName; if (((currentLabelName = current.labelName()) != null) && CharOperation.equals(currentLabelName, this.labelName)) { scope.problemReporter().alreadyDefinedLabel(this.labelName, this.associatedNode); } current = current.getLocalParent(); } } public String individualToString() { return "Label flow context [label:" + String.valueOf(this.labelName) + "]"; //$NON-NLS-2$ //$NON-NLS-1$ } public char[] labelName() { return this.labelName; } } ././@LongLink0000644000000000000000000000015412251602427011643 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowConte0000644000175000001440000003110112212041344032374 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import java.util.ArrayList; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement; import org.eclipse.jdt.internal.compiler.ast.TryStatement; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.codegen.ObjectCache; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class ExceptionHandlingFlowContext extends FlowContext { public final static int BitCacheSize = 32; // 32 bits per int public ReferenceBinding[] handledExceptions; int[] isReached; int[] isNeeded; // WARNING: This is an array that maps to catch blocks, not caught exceptions (which could be more than catch blocks in a multi-catch block) UnconditionalFlowInfo[] initsOnExceptions; ObjectCache indexes = new ObjectCache(); boolean isMethodContext; public UnconditionalFlowInfo initsOnReturn; public FlowContext initializationParent; // special parent relationship only for initialization purpose // for dealing with anonymous constructor thrown exceptions public ArrayList extendedExceptions; private static final Argument[] NO_ARGUMENTS = new Argument[0]; public Argument [] catchArguments; private int[] exceptionToCatchBlockMap; public ExceptionHandlingFlowContext( FlowContext parent, ASTNode associatedNode, ReferenceBinding[] handledExceptions, FlowContext initializationParent, BlockScope scope, UnconditionalFlowInfo flowInfo) { this(parent, associatedNode, handledExceptions, null, NO_ARGUMENTS, initializationParent, scope, flowInfo); } public ExceptionHandlingFlowContext( FlowContext parent, TryStatement tryStatement, ReferenceBinding[] handledExceptions, int [] exceptionToCatchBlockMap, FlowContext initializationParent, BlockScope scope, FlowInfo flowInfo) { this(parent, tryStatement, handledExceptions, exceptionToCatchBlockMap, tryStatement.catchArguments, initializationParent, scope, flowInfo.unconditionalInits()); this.initsOnFinally = flowInfo.unconditionalCopy(); } ExceptionHandlingFlowContext( FlowContext parent, ASTNode associatedNode, ReferenceBinding[] handledExceptions, int [] exceptionToCatchBlockMap, Argument [] catchArguments, FlowContext initializationParent, BlockScope scope, UnconditionalFlowInfo flowInfo) { super(parent, associatedNode); this.isMethodContext = scope == scope.methodScope(); this.handledExceptions = handledExceptions; this.catchArguments = catchArguments; this.exceptionToCatchBlockMap = exceptionToCatchBlockMap; int count = handledExceptions.length, cacheSize = (count / ExceptionHandlingFlowContext.BitCacheSize) + 1; this.isReached = new int[cacheSize]; // none is reached by default this.isNeeded = new int[cacheSize]; // none is needed by default this.initsOnExceptions = new UnconditionalFlowInfo[count]; boolean markExceptionsAndThrowableAsReached = !this.isMethodContext || scope.compilerOptions().reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable; for (int i = 0; i < count; i++) { ReferenceBinding handledException = handledExceptions[i]; int catchBlock = this.exceptionToCatchBlockMap != null? this.exceptionToCatchBlockMap[i] : i; this.indexes.put(handledException, i); // key type -> value index if (handledException.isUncheckedException(true)) { if (markExceptionsAndThrowableAsReached || handledException.id != TypeIds.T_JavaLangThrowable && handledException.id != TypeIds.T_JavaLangException) { this.isReached[i / ExceptionHandlingFlowContext.BitCacheSize] |= 1 << (i % ExceptionHandlingFlowContext.BitCacheSize); } this.initsOnExceptions[catchBlock] = flowInfo.unconditionalCopy(); } else { this.initsOnExceptions[catchBlock] = FlowInfo.DEAD_END; } } if (!this.isMethodContext) { System.arraycopy(this.isReached, 0, this.isNeeded, 0, cacheSize); } this.initsOnReturn = FlowInfo.DEAD_END; this.initializationParent = initializationParent; } public void complainIfUnusedExceptionHandlers(AbstractMethodDeclaration method) { MethodScope scope = method.scope; // can optionally skip overriding methods if ((method.binding.modifiers & (ExtraCompilerModifiers.AccOverriding | ExtraCompilerModifiers.AccImplementing)) != 0 && !scope.compilerOptions().reportUnusedDeclaredThrownExceptionWhenOverriding) { return; } // report errors for unreachable exception handlers TypeBinding[] docCommentReferences = null; int docCommentReferencesLength = 0; if (scope.compilerOptions(). reportUnusedDeclaredThrownExceptionIncludeDocCommentReference && method.javadoc != null && method.javadoc.exceptionReferences != null && (docCommentReferencesLength = method.javadoc.exceptionReferences.length) > 0) { docCommentReferences = new TypeBinding[docCommentReferencesLength]; for (int i = 0; i < docCommentReferencesLength; i++) { docCommentReferences[i] = method.javadoc.exceptionReferences[i].resolvedType; } } nextHandledException: for (int i = 0, count = this.handledExceptions.length; i < count; i++) { int index = this.indexes.get(this.handledExceptions[i]); if ((this.isReached[index / ExceptionHandlingFlowContext.BitCacheSize] & 1 << (index % ExceptionHandlingFlowContext.BitCacheSize)) == 0) { for (int j = 0; j < docCommentReferencesLength; j++) { if (docCommentReferences[j] == this.handledExceptions[i]) { continue nextHandledException; } } scope.problemReporter().unusedDeclaredThrownException( this.handledExceptions[index], method, method.thrownExceptions[index]); } } } public void complainIfUnusedExceptionHandlers(BlockScope scope,TryStatement tryStatement) { // report errors for unreachable exception handlers for (int index = 0, count = this.handledExceptions.length; index < count; index++) { int cacheIndex = index / ExceptionHandlingFlowContext.BitCacheSize; int bitMask = 1 << (index % ExceptionHandlingFlowContext.BitCacheSize); if ((this.isReached[cacheIndex] & bitMask) == 0) { scope.problemReporter().unreachableCatchBlock( this.handledExceptions[index], getExceptionType(index)); } else { if ((this.isNeeded[cacheIndex] & bitMask) == 0) { scope.problemReporter().hiddenCatchBlock( this.handledExceptions[index], getExceptionType(index)); } } } } private ASTNode getExceptionType(int index) { if (this.exceptionToCatchBlockMap == null) { return this.catchArguments[index].type; } int catchBlock = this.exceptionToCatchBlockMap[index]; ASTNode node = this.catchArguments[catchBlock].type; if (node instanceof UnionTypeReference) { TypeReference[] typeRefs = ((UnionTypeReference)node).typeReferences; for (int i = 0, len = typeRefs.length; i < len; i++) { TypeReference typeRef = typeRefs[i]; if (typeRef.resolvedType == this.handledExceptions[index]) return typeRef; } } return node; } public String individualToString() { StringBuffer buffer = new StringBuffer("Exception flow context"); //$NON-NLS-1$ int length = this.handledExceptions.length; for (int i = 0; i < length; i++) { int cacheIndex = i / ExceptionHandlingFlowContext.BitCacheSize; int bitMask = 1 << (i % ExceptionHandlingFlowContext.BitCacheSize); buffer.append('[').append(this.handledExceptions[i].readableName()); if ((this.isReached[cacheIndex] & bitMask) != 0) { if ((this.isNeeded[cacheIndex] & bitMask) == 0) { buffer.append("-masked"); //$NON-NLS-1$ } else { buffer.append("-reached"); //$NON-NLS-1$ } } else { buffer.append("-not reached"); //$NON-NLS-1$ } int catchBlock = this.exceptionToCatchBlockMap != null? this.exceptionToCatchBlockMap[i] : i; buffer.append('-').append(this.initsOnExceptions[catchBlock].toString()).append(']'); } buffer.append("[initsOnReturn -").append(this.initsOnReturn.toString()).append(']'); //$NON-NLS-1$ return buffer.toString(); } // WARNING: index is the catch block index as in the program order, before any normalization is // applied for multi catch public UnconditionalFlowInfo initsOnException(int index) { return this.initsOnExceptions[index]; } public UnconditionalFlowInfo initsOnReturn(){ return this.initsOnReturn; } /* * Compute a merged list of unhandled exception types (keeping only the most generic ones). * This is necessary to add synthetic thrown exceptions for anonymous type constructors (JLS 8.6). */ public void mergeUnhandledException(TypeBinding newException){ if (this.extendedExceptions == null){ this.extendedExceptions = new ArrayList(5); for (int i = 0; i < this.handledExceptions.length; i++){ this.extendedExceptions.add(this.handledExceptions[i]); } } boolean isRedundant = false; for(int i = this.extendedExceptions.size()-1; i >= 0; i--){ switch(Scope.compareTypes(newException, (TypeBinding)this.extendedExceptions.get(i))){ case Scope.MORE_GENERIC : this.extendedExceptions.remove(i); break; case Scope.EQUAL_OR_MORE_SPECIFIC : isRedundant = true; break; case Scope.NOT_RELATED : break; } } if (!isRedundant){ this.extendedExceptions.add(newException); } } public void recordHandlingException( ReferenceBinding exceptionType, UnconditionalFlowInfo flowInfo, TypeBinding raisedException, TypeBinding caughtException, ASTNode invocationSite, boolean wasAlreadyDefinitelyCaught) { int index = this.indexes.get(exceptionType); int cacheIndex = index / ExceptionHandlingFlowContext.BitCacheSize; int bitMask = 1 << (index % ExceptionHandlingFlowContext.BitCacheSize); if (!wasAlreadyDefinitelyCaught) { this.isNeeded[cacheIndex] |= bitMask; } this.isReached[cacheIndex] |= bitMask; int catchBlock = this.exceptionToCatchBlockMap != null? this.exceptionToCatchBlockMap[index] : index; if (caughtException != null && this.catchArguments != null && this.catchArguments.length > 0 && !wasAlreadyDefinitelyCaught) { CatchParameterBinding catchParameter = (CatchParameterBinding) this.catchArguments[catchBlock].binding; catchParameter.setPreciseType(caughtException); } this.initsOnExceptions[catchBlock] = (this.initsOnExceptions[catchBlock].tagBits & FlowInfo.UNREACHABLE) == 0 ? this.initsOnExceptions[catchBlock].mergedWith(flowInfo): flowInfo.unconditionalCopy(); } public void recordReturnFrom(UnconditionalFlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { if ((this.initsOnReturn.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.initsOnReturn = this.initsOnReturn.mergedWith(flowInfo); } else { this.initsOnReturn = (UnconditionalFlowInfo) flowInfo.copy(); } } } /** * Exception handlers (with no finally block) are also included with subroutine * only once (in case parented with true InsideSubRoutineFlowContext). * Standard management of subroutines need to also operate on intermediate * exception handlers. * @see org.eclipse.jdt.internal.compiler.flow.FlowContext#subroutine() */ public SubRoutineStatement subroutine() { if (this.associatedNode instanceof SubRoutineStatement) { // exception handler context may be child of InsideSubRoutineFlowContext, which maps to same handler if (this.parent.subroutine() == this.associatedNode) return null; return (SubRoutineStatement) this.associatedNode; } return null; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java0000644000175000001440000020725412212041344032360 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 325755 - [compiler] wrong initialization state after conditional expression * bug 320170 - [compiler] [null] Whitebox issues in null analysis * bug 292478 - Report potentially null across variable assignment * bug 332637 - Dead Code detection removing code that isn't dead * bug 341499 - [compiler][null] allocate extra bits in all methods of UnconditionalFlowInfo * bug 349326 - [1.7] new warning for missing try-with-resources * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 386181 - [compiler][null] wrong transition in UnconditionalFlowInfo.mergedWith() * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import org.eclipse.jdt.internal.compiler.ast.ASTNode; 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; import org.eclipse.jdt.internal.compiler.lookup.TagBits; /** * Record initialization status during definite assignment analysis * * No caching of pre-allocated instances. */ public class UnconditionalFlowInfo extends FlowInfo { /** * Exception raised when unexpected behavior is detected. */ public static class AssertionFailedException extends RuntimeException { private static final long serialVersionUID = 1827352841030089703L; public AssertionFailedException(String message) { super(message); } } // Coverage tests need that the code be instrumented. The following flag // controls whether the instrumented code is compiled in or not, and whether // the coverage tests methods run or not. public final static boolean COVERAGE_TEST_FLAG = false; // never release with the coverageTestFlag set to true public static int CoverageTestId; // assignment bits - first segment public long definiteInits; public long potentialInits; // null bits - first segment public long nullBit1, nullBit2, nullBit3, nullBit4; /* nullBit1 nullBit2... 0000 start 0001 pot. unknown 0010 pot. non null 0011 pot. nn & pot. un 0100 pot. null 0101 pot. n & pot. un 0110 pot. n & pot. nn 0111 pot. n & pot. nn & pot. un 1001 def. unknown 1010 def. non null 1011 pot. nn & prot. nn 1100 def. null 1101 pot. n & prot. n 1110 prot. null 1111 prot. non null */ // extra segments public static final int extraLength = 6; public long extra[][]; // extra bit fields for larger numbers of fields/variables // extra[0] holds definiteInits values, extra[1] potentialInits, etc. // lifecycle is extra == null or else all extra[]'s are allocated // arrays which have the same size public int maxFieldCount; // limit between fields and locals // Constants public static final int BitCacheSize = 64; // 64 bits in a long. public FlowInfo addInitializationsFrom(FlowInfo inits) { return addInfoFrom(inits, true); } public FlowInfo addNullInfoFrom(FlowInfo inits) { return addInfoFrom(inits, false); } private FlowInfo addInfoFrom(FlowInfo inits, boolean handleInits) { if (this == DEAD_END) return this; if (inits == DEAD_END) return this; UnconditionalFlowInfo otherInits = inits.unconditionalInits(); if (handleInits) { // union of definitely assigned variables, this.definiteInits |= otherInits.definiteInits; // union of potentially set ones this.potentialInits |= otherInits.potentialInits; } // combine null information boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0, otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0; long a1, a2, a3, a4, na1, na2, na3, na4, b1, b2, b3, b4, nb1, nb2, nb3, nb4; if (otherHasNulls) { if (!thisHadNulls) { this.nullBit1 = otherInits.nullBit1; this.nullBit2 = otherInits.nullBit2; this.nullBit3 = otherInits.nullBit3; this.nullBit4 = otherInits.nullBit4; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 1) { this.nullBit4 = ~0; } } } else { this.nullBit1 = (b1 = otherInits.nullBit1) | (a1 = this.nullBit1) & ((a3 = this.nullBit3) & (a4 = this.nullBit4) & (nb2 = ~(b2 = otherInits.nullBit2)) & (nb4 = ~(b4 = otherInits.nullBit4)) | ((na4 = ~a4) | (na3 = ~a3)) & ((na2 = ~(a2 = this.nullBit2)) & nb2 | a2 & (nb3 = ~(b3 = otherInits.nullBit3)) & nb4)); this.nullBit2 = b2 & (nb4 | nb3) | na3 & na4 & b2 | a2 & (nb3 & nb4 | (nb1 = ~b1) & (na3 | (na1 = ~a1)) | a1 & b2); this.nullBit3 = b3 & (nb1 & (b2 | a2 | na1) | b1 & (b4 | nb2 | a1 & a3) | na1 & na2 & na4) | a3 & nb2 & nb4 | nb1 & ((na2 & a4 | na1) & a3 | a1 & na2 & na4 & b2); this.nullBit4 = nb1 & (a4 & (na3 & nb3 | (a3 | na2) & nb2) | a1 & (a3 & nb2 & b4 | a2 & b2 & (b4 | a3 & na4 & nb3))) | b1 & (a3 & a4 & b4 | na2 & na4 & nb3 & b4 | a2 & ((b3 | a4) & b4 | na3 & a4 & b2 & b3) | na1 & (b4 | (a4 | a2) & b2 & b3)) | (na1 & (na3 & nb3 | na2 & nb2) | a1 & (nb2 & nb3 | a2 & a3)) & b4; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 2) { this.nullBit4 = ~0; } } } this.tagBits |= NULL_FLAG_MASK; // in all cases - avoid forgetting extras } // treating extra storage if (this.extra != null || otherInits.extra != null) { int mergeLimit = 0, copyLimit = 0; if (this.extra != null) { if (otherInits.extra != null) { // both sides have extra storage int length, otherLength; if ((length = this.extra[0].length) < (otherLength = otherInits.extra[0].length)) { // current storage is shorter -> grow current for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[otherLength]), 0, length); } mergeLimit = length; copyLimit = otherLength; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 3) { throw new AssertionFailedException("COVERAGE 3"); //$NON-NLS-1$ } } } else { // current storage is longer mergeLimit = otherLength; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 4) { throw new AssertionFailedException("COVERAGE 4"); //$NON-NLS-1$ } } } } } else if (otherInits.extra != null) { // no storage here, but other has extra storage. // shortcut regular copy because array copy is better int otherLength; this.extra = new long[extraLength][]; System.arraycopy(otherInits.extra[0], 0, (this.extra[0] = new long[otherLength = otherInits.extra[0].length]), 0, otherLength); System.arraycopy(otherInits.extra[1], 0, (this.extra[1] = new long[otherLength]), 0, otherLength); if (otherHasNulls) { for (int j = 2; j < extraLength; j++) { System.arraycopy(otherInits.extra[j], 0, (this.extra[j] = new long[otherLength]), 0, otherLength); } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 5) { this.extra[5][otherLength - 1] = ~0; } } } else { for (int j = 2; j < extraLength; j++) { this.extra[j] = new long[otherLength]; } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 6) { throw new AssertionFailedException("COVERAGE 6"); //$NON-NLS-1$ } } } } int i; if (handleInits) { // manage definite assignment info for (i = 0; i < mergeLimit; i++) { this.extra[0][i] |= otherInits.extra[0][i]; this.extra[1][i] |= otherInits.extra[1][i]; } for (; i < copyLimit; i++) { this.extra[0][i] = otherInits.extra[0][i]; this.extra[1][i] = otherInits.extra[1][i]; } } // tweak limits for nulls if (!thisHadNulls) { if (copyLimit < mergeLimit) { copyLimit = mergeLimit; } mergeLimit = 0; } if (!otherHasNulls) { copyLimit = 0; mergeLimit = 0; } for (i = 0; i < mergeLimit; i++) { this.extra[1 + 1][i] = (b1 = otherInits.extra[1 + 1][i]) | (a1 = this.extra[1 + 1][i]) & ((a3 = this.extra[3 + 1][i]) & (a4 = this.extra[4 + 1][i]) & (nb2 = ~(b2 = otherInits.extra[2 + 1][i])) & (nb4 = ~(b4 = otherInits.extra[4 + 1][i])) | ((na4 = ~a4) | (na3 = ~a3)) & ((na2 = ~(a2 = this.extra[2 + 1][i])) & nb2 | a2 & (nb3 = ~(b3 = otherInits.extra[3 + 1][i])) & nb4)); this.extra[2 + 1][i] = b2 & (nb4 | nb3) | na3 & na4 & b2 | a2 & (nb3 & nb4 | (nb1 = ~b1) & (na3 | (na1 = ~a1)) | a1 & b2); this.extra[3 + 1][i] = b3 & (nb1 & (b2 | a2 | na1) | b1 & (b4 | nb2 | a1 & a3) | na1 & na2 & na4) | a3 & nb2 & nb4 | nb1 & ((na2 & a4 | na1) & a3 | a1 & na2 & na4 & b2); this.extra[4 + 1][i] = nb1 & (a4 & (na3 & nb3 | (a3 | na2) & nb2) | a1 & (a3 & nb2 & b4 | a2 & b2 & (b4 | a3 & na4 & nb3))) | b1 & (a3 & a4 & b4 | na2 & na4 & nb3 & b4 | a2 & ((b3 | a4) & b4 | na3 & a4 & b2 & b3) | na1 & (b4 | (a4 | a2) & b2 & b3)) | (na1 & (na3 & nb3 | na2 & nb2) | a1 & (nb2 & nb3 | a2 & a3)) & b4; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 7) { this.extra[5][i] = ~0; } } } for (; i < copyLimit; i++) { for (int j = 2; j < extraLength; j++) { this.extra[j][i] = otherInits.extra[j][i]; } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 8) { this.extra[5][i] = ~0; } } } } return this; } public FlowInfo addPotentialInitializationsFrom(FlowInfo inits) { if (this == DEAD_END){ return this; } if (inits == DEAD_END){ return this; } UnconditionalFlowInfo otherInits = inits.unconditionalInits(); // union of potentially set ones this.potentialInits |= otherInits.potentialInits; // treating extra storage if (this.extra != null) { if (otherInits.extra != null) { // both sides have extra storage int i = 0, length, otherLength; if ((length = this.extra[0].length) < (otherLength = otherInits.extra[0].length)) { // current storage is shorter -> grow current for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[otherLength]), 0, length); } for (; i < length; i++) { this.extra[1][i] |= otherInits.extra[1][i]; } for (; i < otherLength; i++) { this.extra[1][i] = otherInits.extra[1][i]; } } else { // current storage is longer for (; i < otherLength; i++) { this.extra[1][i] |= otherInits.extra[1][i]; } } } } else if (otherInits.extra != null) { // no storage here, but other has extra storage. int otherLength = otherInits.extra[0].length; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[otherLength]; } System.arraycopy(otherInits.extra[1], 0, this.extra[1], 0, otherLength); } addPotentialNullInfoFrom(otherInits); return this; } /** * Compose other inits over this flow info, then return this. The operation * semantics are to wave into this flow info the consequences upon null * information of a possible path into the operations that resulted into * otherInits. The fact that this path may be left unexecuted under peculiar * conditions results into less specific results than * {@link #addInitializationsFrom(FlowInfo) addInitializationsFrom}; moreover, * only the null information is affected. * @param otherInits other null inits to compose over this * @return this, modified according to otherInits information */ public UnconditionalFlowInfo addPotentialNullInfoFrom( UnconditionalFlowInfo otherInits) { if ((this.tagBits & UNREACHABLE) != 0 || (otherInits.tagBits & UNREACHABLE) != 0 || (otherInits.tagBits & NULL_FLAG_MASK) == 0) { return this; } // if we get here, otherInits has some null info boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0, thisHasNulls = false; long a1, a2, a3, a4, na1, na2, na3, na4, b1, b2, b3, b4, nb1, nb2, nb3, nb4; if (thisHadNulls) { this.nullBit1 = (a1 = this.nullBit1) & ((a3 = this.nullBit3) & (a4 = this.nullBit4) & ((nb2 = ~(b2 = otherInits.nullBit2)) & (nb4 = ~(b4 = otherInits.nullBit4)) | (b1 = otherInits.nullBit1) & (b3 = otherInits.nullBit3)) | (na2 = ~(a2 = this.nullBit2)) & (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2) | a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2))); this.nullBit2 = b2 & (nb3 | (nb1 = ~b1)) | a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1)); this.nullBit3 = b3 & (nb1 & b2 | a2 & (nb2 | a3) | na1 & nb2 | a1 & na2 & na4 & b1) | a3 & (nb2 & nb4 | na2 & a4 | na1) | a1 & na2 & na4 & b2; this.nullBit4 = na3 & (nb1 & nb3 & b4 | a4 & (nb3 | b1 & b2)) | nb2 & (na3 & b1 & nb3 | na2 & (nb1 & b4 | b1 & nb3 | a4)) | a3 & (a4 & (nb2 | b1 & b3) | a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3)); if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 9) { this.nullBit4 = ~0; } } if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { // bit1 is redundant thisHasNulls = true; } } else { this.nullBit1 = 0; this.nullBit2 = (b2 = otherInits.nullBit2) & ((nb3 = ~(b3 = otherInits.nullBit3)) | (nb1 = ~(b1 = otherInits.nullBit1))); this.nullBit3 = b3 & (nb1 | (nb2 = ~b2)); this.nullBit4 = ~b1 & ~b3 & (b4 = otherInits.nullBit4) | ~b2 & (b1 & ~b3 | ~b1 & b4); if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 10) { this.nullBit4 = ~0; } } if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { // bit1 is redundant thisHasNulls = true; } } // extra storage management if (otherInits.extra != null) { int mergeLimit = 0, copyLimit = otherInits.extra[0].length; if (this.extra == null) { this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[copyLimit]; } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 11) { throw new AssertionFailedException("COVERAGE 11"); //$NON-NLS-1$ } } } else { mergeLimit = copyLimit; if (mergeLimit > this.extra[0].length) { mergeLimit = this.extra[0].length; for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, this.extra[j] = new long[copyLimit], 0, mergeLimit); } if (! thisHadNulls) { mergeLimit = 0; // will do with a copy -- caveat: only valid because definite assignment bits copied above if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 12) { throw new AssertionFailedException("COVERAGE 12"); //$NON-NLS-1$ } } } } } // PREMATURE skip operations for fields int i; for (i = 0 ; i < mergeLimit ; i++) { this.extra[1 + 1][i] = (a1 = this.extra[1 + 1][i]) & ((a3 = this.extra[3 + 1][i]) & (a4 = this.extra[4 + 1][i]) & ((nb2 = ~(b2 = otherInits.extra[2 + 1][i])) & (nb4 = ~(b4 = otherInits.extra[4 + 1][i])) | (b1 = otherInits.extra[1 + 1][i]) & (b3 = otherInits.extra[3 + 1][i])) | (na2 = ~(a2 = this.extra[2 + 1][i])) & (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2) | a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2))); this.extra[2 + 1][i] = b2 & (nb3 | (nb1 = ~b1)) | a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1)); this.extra[3 + 1][i] = b3 & (nb1 & b2 | a2 & (nb2 | a3) | na1 & nb2 | a1 & na2 & na4 & b1) | a3 & (nb2 & nb4 | na2 & a4 | na1) | a1 & na2 & na4 & b2; this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4 | a4 & (nb3 | b1 & b2)) | nb2 & (na3 & b1 & nb3 | na2 & (nb1 & b4 | b1 & nb3 | a4)) | a3 & (a4 & (nb2 | b1 & b3) | a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3)); if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { // bit1 is redundant thisHasNulls = true; } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 13) { this.nullBit4 = ~0; } } } for (; i < copyLimit; i++) { this.extra[1 + 1][i] = 0; this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i]) & ((nb3 = ~(b3 = otherInits.extra[3 + 1][i])) | (nb1 = ~(b1 = otherInits.extra[1 + 1][i]))); this.extra[3 + 1][i] = b3 & (nb1 | (nb2 = ~b2)); this.extra[4 + 1][i] = ~b1 & ~b3 & (b4 = otherInits.extra[4 + 1][i]) | ~b2 & (b1 & ~b3 | ~b1 & b4); if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { // bit1 is redundant thisHasNulls = true; } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 14) { this.extra[5][i] = ~0; } } } } if (thisHasNulls) { this.tagBits |= NULL_FLAG_MASK; } else { this.tagBits &= NULL_FLAG_MASK; } return this; } final public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits return ( (~this.nullBit1 & (this.nullBit2 & this.nullBit3 | this.nullBit4) | ~this.nullBit2 & ~this.nullBit3 & this.nullBit4) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } long a2, a3, a4; return ( (~this.extra[2][vectorIndex] & ((a2 = this.extra[3][vectorIndex]) & (a3 = this.extra[4][vectorIndex]) | (a4 = this.extra[5][vectorIndex])) | ~a2 & ~a3 & a4) & (1L << (position % BitCacheSize))) != 0; } final public boolean cannotBeNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits return (this.nullBit1 & this.nullBit3 & ((this.nullBit2 & this.nullBit4) | ~this.nullBit2) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } return (this.extra[2][vectorIndex] & this.extra[4][vectorIndex] & ((this.extra[3][vectorIndex] & this.extra[5][vectorIndex]) | ~this.extra[3][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } final public boolean canOnlyBeNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits return (this.nullBit1 & this.nullBit2 & (~this.nullBit3 | ~this.nullBit4) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } return (this.extra[2][vectorIndex] & this.extra[3][vectorIndex] & (~this.extra[4][vectorIndex] | ~this.extra[5][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } public FlowInfo copy() { // do not clone the DeadEnd if (this == DEAD_END) { return this; } UnconditionalFlowInfo copy = new UnconditionalFlowInfo(); // copy slots copy.definiteInits = this.definiteInits; copy.potentialInits = this.potentialInits; boolean hasNullInfo = (this.tagBits & NULL_FLAG_MASK) != 0; if (hasNullInfo) { copy.nullBit1 = this.nullBit1; copy.nullBit2 = this.nullBit2; copy.nullBit3 = this.nullBit3; copy.nullBit4 = this.nullBit4; } copy.tagBits = this.tagBits; copy.maxFieldCount = this.maxFieldCount; if (this.extra != null) { int length; copy.extra = new long[extraLength][]; System.arraycopy(this.extra[0], 0, (copy.extra[0] = new long[length = this.extra[0].length]), 0, length); System.arraycopy(this.extra[1], 0, (copy.extra[1] = new long[length]), 0, length); if (hasNullInfo) { for (int j = 2; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (copy.extra[j] = new long[length]), 0, length); } } else { for (int j = 2; j < extraLength; j++) { copy.extra[j] = new long[length]; } } } return copy; } /** * Discard definite inits and potential inits from this, then return this. * The returned flow info only holds null related information. * @return this flow info, minus definite inits and potential inits */ public UnconditionalFlowInfo discardInitializationInfo() { if (this == DEAD_END) { return this; } this.definiteInits = this.potentialInits = 0; if (this.extra != null) { for (int i = 0, length = this.extra[0].length; i < length; i++) { this.extra[0][i] = this.extra[1][i] = 0; } } return this; } /** * Remove local variables information from this flow info and return this. * @return this, deprived from any local variable information */ public UnconditionalFlowInfo discardNonFieldInitializations() { int limit = this.maxFieldCount; if (limit < BitCacheSize) { long mask = (1L << limit)-1; this.definiteInits &= mask; this.potentialInits &= mask; this.nullBit1 &= mask; this.nullBit2 &= mask; this.nullBit3 &= mask; this.nullBit4 &= mask; } // use extra vector if (this.extra == null) { return this; // if vector not yet allocated, then not initialized } int vectorIndex, length = this.extra[0].length; if ((vectorIndex = (limit / BitCacheSize) - 1) >= length) { return this; // not enough room yet } if (vectorIndex >= 0) { // else we only have complete non field array items left long mask = (1L << (limit % BitCacheSize))-1; for (int j = 0; j < extraLength; j++) { this.extra[j][vectorIndex] &= mask; } } for (int i = vectorIndex + 1; i < length; i++) { for (int j = 0; j < extraLength; j++) { this.extra[j][i] = 0; } } return this; } public FlowInfo initsWhenFalse() { return this; } public FlowInfo initsWhenTrue() { return this; } /** * Check status of definite 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 isDefinitelyAssigned(int position) { if (position < BitCacheSize) { // use bits return (this.definiteInits & (1L << position)) != 0; } // use extra vector if (this.extra == null) return false; // if vector not yet allocated, then not initialized int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[0][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } final public boolean isDefinitelyAssigned(FieldBinding field) { // Mirrored in CodeStream.isDefinitelyAssigned(..) // do not want to complain in unreachable code if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0) { return true; } return isDefinitelyAssigned(field.id); } final public boolean isDefinitelyAssigned(LocalVariableBinding local) { // do not want to complain in unreachable code if local declared in reachable code if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0 && (local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0) { return true; } return isDefinitelyAssigned(local.id + this.maxFieldCount); } final public boolean isDefinitelyNonNull(LocalVariableBinding local) { // do not want to complain in unreachable code if ((this.tagBits & UNREACHABLE) != 0 || (this.tagBits & NULL_FLAG_MASK) == 0) { return false; } if ((local.type.tagBits & TagBits.IsBaseType) != 0 || local.constant() != Constant.NotAConstant) { // String instances return true; } int position = local.id + this.maxFieldCount; if (position < BitCacheSize) { // use bits return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4)) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex] & (~this.extra[3][vectorIndex] | this.extra[5][vectorIndex])) & (1L << (position % BitCacheSize))) != 0; } final public boolean isDefinitelyNull(LocalVariableBinding local) { // do not want to complain in unreachable code if ((this.tagBits & UNREACHABLE) != 0 || (this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position = local.id + this.maxFieldCount; if (position < BitCacheSize) { // use bits return ((this.nullBit1 & this.nullBit2 & (~this.nullBit3 | ~this.nullBit4)) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex] & (~this.extra[4][vectorIndex] | ~this.extra[5][vectorIndex])) & (1L << (position % BitCacheSize))) != 0; } final public boolean isDefinitelyUnknown(LocalVariableBinding local) { // do not want to complain in unreachable code if ((this.tagBits & UNREACHABLE) != 0 || (this.tagBits & NULL_FLAG_MASK) == 0) { return false; } int position = local.id + this.maxFieldCount; if (position < BitCacheSize) { // use bits return ((this.nullBit1 & this.nullBit4 & ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex] & ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } final public boolean hasNullInfoFor(LocalVariableBinding local) { // do not want to complain in unreachable code if ((this.tagBits & UNREACHABLE) != 0 || (this.tagBits & NULL_FLAG_MASK) == 0) { return false; } int position = local.id + this.maxFieldCount; if (position < BitCacheSize) { // use bits return ((this.nullBit1 | this.nullBit2 | this.nullBit3 | this.nullBit4) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[2][vectorIndex] | this.extra[3][vectorIndex] | this.extra[4][vectorIndex] | this.extra[5][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } /** * Check status of potential assignment at a given position. */ final private boolean isPotentiallyAssigned(int position) { // id is zero-based if (position < BitCacheSize) { // use bits return (this.potentialInits & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[1][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } final public boolean isPotentiallyAssigned(FieldBinding field) { return isPotentiallyAssigned(field.id); } final public boolean isPotentiallyAssigned(LocalVariableBinding local) { // final constants are inlined, and thus considered as always initialized if (local.constant() != Constant.NotAConstant) { return true; } return isPotentiallyAssigned(local.id + this.maxFieldCount); } // TODO (Ayush) Check why this method does not return true for protected non null (1111) final public boolean isPotentiallyNonNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2)) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[4][vectorIndex] & (~this.extra[2][vectorIndex] | ~this.extra[3][vectorIndex])) & (1L << (position % BitCacheSize))) != 0; } // TODO (Ayush) Check why this method does not return true for protected null final public boolean isPotentiallyNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3)) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return ((this.extra[3][vectorIndex] & (~this.extra[2][vectorIndex] | ~this.extra[4][vectorIndex])) & (1L << (position % BitCacheSize))) != 0; } final public boolean isPotentiallyUnknown(LocalVariableBinding local) { // do not want to complain in unreachable code if ((this.tagBits & UNREACHABLE) != 0 || (this.tagBits & NULL_FLAG_MASK) == 0) { return false; } int position = local.id + this.maxFieldCount; if (position < BitCacheSize) { // use bits return (this.nullBit4 & (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[2].length) { return false; // if not enough room in vector, then not initialized } return (this.extra[5][vectorIndex] & (~this.extra[2][vectorIndex] | ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } final public boolean isProtectedNonNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } return (this.extra[2][vectorIndex] & this.extra[4][vectorIndex] & this.extra[5][vectorIndex] & (1L << (position % BitCacheSize))) != 0; } final public boolean isProtectedNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits return (this.nullBit1 & this.nullBit2 & (this.nullBit3 ^ this.nullBit4) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { return false; // if vector not yet allocated, then not initialized } int vectorIndex; if ((vectorIndex = (position / BitCacheSize) - 1) >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } return (this.extra[2][vectorIndex] & this.extra[3][vectorIndex] & (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex]) & (1L << (position % BitCacheSize))) != 0; } /** Asserts that the given boolean is true. If this * is not the case, some kind of unchecked exception is thrown. * The given message is included in that exception, to aid debugging. * * @param expression the outcome of the check * @param message the message to include in the exception * @return true if the check passes (does not return * if the check fails) */ protected static boolean isTrue(boolean expression, String message) { if (!expression) throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$ return expression; } public void markAsComparedEqualToNonNull(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; int position; long mask; long a1, a2, a3, a4, na2; // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits if (((mask = 1L << position) & (a1 = this.nullBit1) & (na2 = ~(a2 = this.nullBit2)) & ~(a3 = this.nullBit3) & (a4 = this.nullBit4)) != 0) { this.nullBit4 &= ~mask; } else if ((mask & a1 & na2 & a3) == 0) { this.nullBit4 |= mask; if ((mask & a1) == 0) { if ((mask & a2 & (a3 ^ a4)) != 0) { this.nullBit2 &= ~mask; } else if ((mask & (a2 | a3 | a4)) == 0) { this.nullBit2 |= mask; } } } this.nullBit1 |= mask; this.nullBit3 |= mask; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 15) { this.nullBit4 = ~0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 16) { throw new AssertionFailedException("COVERAGE 16"); //$NON-NLS-1$ } } } else { int oldLength; if (vectorIndex >= (oldLength = this.extra[0].length)) { int newLength = vectorIndex + 1; for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[newLength]), 0, oldLength); } if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 17) { throw new AssertionFailedException("COVERAGE 17"); //$NON-NLS-1$ } } } } // MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][vectorIndex]/gc if (((mask = 1L << (position % BitCacheSize)) & (a1 = this.extra[1 + 1][vectorIndex]) & (na2 = ~(a2 = this.extra[2 + 1][vectorIndex])) & ~(a3 = this.extra[3 + 1][vectorIndex]) & (a4 = this.extra[4 + 1][vectorIndex])) != 0) { this.extra[4 + 1][vectorIndex] &= ~mask; } else if ((mask & a1 & na2 & a3) == 0) { this.extra[4 + 1][vectorIndex] |= mask; if ((mask & a1) == 0) { if ((mask & a2 & (a3 ^ a4)) != 0) { this.extra[2 + 1][vectorIndex] &= ~mask; } else if ((mask & (a2 | a3 | a4)) == 0) { this.extra[2 + 1][vectorIndex] |= mask; } } } this.extra[1 + 1][vectorIndex] |= mask; this.extra[3 + 1][vectorIndex] |= mask; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 18) { this.extra[5][vectorIndex] = ~0; } } } } } public void markAsComparedEqualToNull(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; int position; long mask; // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits if (((mask = 1L << position) & this.nullBit1) != 0) { if ((mask & (~this.nullBit2 | this.nullBit3 | ~this.nullBit4)) != 0) { this.nullBit4 &= ~mask; } } else if ((mask & this.nullBit4) != 0) { this.nullBit3 &= ~mask; } else { if ((mask & this.nullBit2) != 0) { this.nullBit3 &= ~mask; this.nullBit4 |= mask; } else { this.nullBit3 |= mask; } } this.nullBit1 |= mask; this.nullBit2 |= mask; if (COVERAGE_TEST_FLAG) { if (CoverageTestId == 19) { this.nullBit4 = ~0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; mask = 1L << (position % BitCacheSize); if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length ]; } if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 20) { throw new AssertionFailedException("COVERAGE 20"); //$NON-NLS-1$ } } } else { int oldLength; if (vectorIndex >= (oldLength = this.extra[0].length)) { int newLength = vectorIndex + 1; for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[newLength]), 0, oldLength); } if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 21) { throw new AssertionFailedException("COVERAGE 21"); //$NON-NLS-1$ } } } } if ((mask & this.extra[1 + 1][vectorIndex]) != 0) { if ((mask & (~this.extra[2 + 1][vectorIndex] | this.extra[3 + 1][vectorIndex] | ~this.extra[4 + 1][vectorIndex])) != 0) { this.extra[4 + 1][vectorIndex] &= ~mask; } } else if ((mask & this.extra[4 + 1][vectorIndex]) != 0) { this.extra[3 + 1][vectorIndex] &= ~mask; } else { if ((mask & this.extra[2 + 1][vectorIndex]) != 0) { this.extra[3 + 1][vectorIndex] &= ~mask; this.extra[4 + 1][vectorIndex] |= mask; } else { this.extra[3 + 1][vectorIndex] |= mask; } } this.extra[1 + 1][vectorIndex] |= mask; this.extra[2 + 1][vectorIndex] |= mask; } } } /** * Record a definite assignment at a given position. */ final private void markAsDefinitelyAssigned(int position) { if (this != DEAD_END) { // position is zero-based if (position < BitCacheSize) { // use bits long mask; this.definiteInits |= (mask = 1L << position); this.potentialInits |= mask; } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } } else { int oldLength; // might need to grow the arrays if (vectorIndex >= (oldLength = this.extra[0].length)) { for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[vectorIndex + 1]), 0, oldLength); } } } long mask; this.extra[0][vectorIndex] |= (mask = 1L << (position % BitCacheSize)); this.extra[1][vectorIndex] |= mask; } } } public void markAsDefinitelyAssigned(FieldBinding field) { if (this != DEAD_END) markAsDefinitelyAssigned(field.id); } public void markAsDefinitelyAssigned(LocalVariableBinding local) { if (this != DEAD_END) markAsDefinitelyAssigned(local.id + this.maxFieldCount); } public void markAsDefinitelyNonNull(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; long mask; int position; // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits // set assigned non null this.nullBit1 |= (mask = 1L << position); this.nullBit3 |= mask; // clear others this.nullBit2 &= (mask = ~mask); this.nullBit4 &= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 22) { this.nullBit1 = 0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } } else { int oldLength; // might need to grow the arrays if (vectorIndex >= (oldLength = this.extra[0].length)) { for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[vectorIndex + 1]), 0, oldLength); } } } this.extra[2][vectorIndex] |= (mask = 1L << (position % BitCacheSize)); this.extra[4][vectorIndex] |= mask; this.extra[3][vectorIndex] &= (mask = ~mask); this.extra[5][vectorIndex] &= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 23) { this.extra[2][vectorIndex] = 0; } } } } } public void markAsDefinitelyNull(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; long mask; int position; // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits // mark assigned null this.nullBit1 |= (mask = 1L << position); this.nullBit2 |= mask; // clear others this.nullBit3 &= (mask = ~mask); this.nullBit4 &= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 24) { this.nullBit4 = ~0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } } else { int oldLength; // might need to grow the arrays if (vectorIndex >= (oldLength = this.extra[0].length)) { for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[vectorIndex + 1]), 0, oldLength); } } } this.extra[2][vectorIndex] |= (mask = 1L << (position % BitCacheSize)); this.extra[3][vectorIndex] |= mask; this.extra[4][vectorIndex] &= (mask = ~mask); this.extra[5][vectorIndex] &= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 25) { this.extra[5][vectorIndex] = ~0; } } } } } /** * Mark a local as having been assigned to an unknown value. * @param local the local to mark */ // PREMATURE may try to get closer to markAsDefinitelyAssigned, but not // obvious public void markAsDefinitelyUnknown(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; long mask; int position; // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits // mark assigned null this.nullBit1 |= (mask = 1L << position); this.nullBit4 |= mask; // clear others this.nullBit2 &= (mask = ~mask); this.nullBit3 &= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 26) { this.nullBit4 = 0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } } else { int oldLength; // might need to grow the arrays if (vectorIndex >= (oldLength = this.extra[0].length)) { for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[vectorIndex + 1]), 0, oldLength); } } } this.extra[2][vectorIndex] |= (mask = 1L << (position % BitCacheSize)); this.extra[5][vectorIndex] |= mask; this.extra[3][vectorIndex] &= (mask = ~mask); this.extra[4][vectorIndex] &= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 27) { this.extra[5][vectorIndex] = 0; } } } } } public void resetNullInfo(LocalVariableBinding local) { if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; int position; long mask; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits this.nullBit1 &= (mask = ~(1L << position)); this.nullBit2 &= mask; this.nullBit3 &= mask; this.nullBit4 &= mask; } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null || vectorIndex >= this.extra[2].length) { // in case we attempt to reset the null info of a variable that has not been encountered // before and for which no null bits exist. return; } this.extra[2][vectorIndex] &= (mask = ~(1L << (position % BitCacheSize))); this.extra[3][vectorIndex] &= mask; this.extra[4][vectorIndex] &= mask; this.extra[5][vectorIndex] &= mask; } } } /** * Mark a local as potentially having been assigned to an unknown value. * @param local the local to mark */ public void markPotentiallyUnknownBit(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; int position; long mask; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits mask = 1L << position; isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$ this.nullBit4 |= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 44) { this.nullBit4 = 0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } } else { int oldLength; // might need to grow the arrays if (vectorIndex >= (oldLength = this.extra[0].length)) { for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[vectorIndex + 1]), 0, oldLength); } } } mask = 1L << (position % BitCacheSize); isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$ this.extra[5][vectorIndex] |= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 45) { this.extra[2][vectorIndex] = ~0; this.extra[3][vectorIndex] = ~0; this.extra[4][vectorIndex] = 0; this.extra[5][vectorIndex] = 0; } } } } } public void markPotentiallyNullBit(LocalVariableBinding local) { if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; int position; long mask; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits mask = 1L << position; isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$ this.nullBit2 |= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 40) { this.nullBit2 = 0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } } else { int oldLength; // might need to grow the arrays if (vectorIndex >= (oldLength = this.extra[0].length)) { for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[vectorIndex + 1]), 0, oldLength); } } } mask = 1L << (position % BitCacheSize); this.extra[3][vectorIndex] |= mask; isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$ if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 41) { this.extra[3][vectorIndex] = 0; } } } } } public void markPotentiallyNonNullBit(LocalVariableBinding local) { if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; int position; long mask; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits mask = 1L << position; isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$ this.nullBit3 |= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 42) { this.nullBit1 = ~0; this.nullBit2 = 0; this.nullBit3 = ~0; this.nullBit4 = 0; } } } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null) { int length = vectorIndex + 1; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } } else { int oldLength; // might need to grow the arrays if (vectorIndex >= (oldLength = this.extra[0].length)) { for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[vectorIndex + 1]), 0, oldLength); } } } mask = 1L << (position % BitCacheSize); isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$ this.extra[4][vectorIndex] |= mask; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 43) { this.extra[2][vectorIndex] = ~0; this.extra[3][vectorIndex] = 0; this.extra[4][vectorIndex] = ~0; this.extra[5][vectorIndex] = 0; } } } } } public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) { if ((otherInits.tagBits & UNREACHABLE_OR_DEAD) != 0 && this != DEAD_END) { if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 28) { throw new AssertionFailedException("COVERAGE 28"); //$NON-NLS-1$ } } return this; } if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0) { if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 29) { throw new AssertionFailedException("COVERAGE 29"); //$NON-NLS-1$ } } return (UnconditionalFlowInfo) otherInits.copy(); // make sure otherInits won't be affected } // intersection of definitely assigned variables, this.definiteInits &= otherInits.definiteInits; // union of potentially set ones this.potentialInits |= otherInits.potentialInits; // null combinations boolean thisHasNulls = (this.tagBits & NULL_FLAG_MASK) != 0, otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0, thisHadNulls = thisHasNulls; long a1, a2, a3, a4, na1, na2, na3, na4, nb1, nb2, nb3, nb4, b1, b2, b3, b4; if ((otherInits.tagBits & FlowInfo.UNREACHABLE_BY_NULLANALYSIS) != 0) { otherHasNulls = false; // skip merging, otherInits is unreachable by null analysis } else if ((this.tagBits & FlowInfo.UNREACHABLE_BY_NULLANALYSIS) != 0) { // directly copy if this is unreachable by null analysis this.nullBit1 = otherInits.nullBit1; this.nullBit2 = otherInits.nullBit2; this.nullBit3 = otherInits.nullBit3; this.nullBit4 = otherInits.nullBit4; thisHadNulls = false; thisHasNulls = otherHasNulls; this.tagBits = otherInits.tagBits; } else if (thisHadNulls) { if (otherHasNulls) { this.nullBit1 = (a1 = this.nullBit1) & (b1 = otherInits.nullBit1) & ( ((a2 = this.nullBit2) & (((b2 = otherInits.nullBit2) & ~(((a3=this.nullBit3) & (a4=this.nullBit4)) ^ ((b3=otherInits.nullBit3) & (b4=otherInits.nullBit4)))) |(a3 & a4 & (nb2 = ~b2)))) |((na2 = ~a2) & ((b2 & b3 & b4) |(nb2 & ((na3 = ~a3) ^ b3))))); this.nullBit2 = b2 & ((nb3 = ~b3) | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & (nb4 = ~b4)) | a2 & (b2 | (na4 = ~a4) & b3 & (b4 | nb1) | na3 | na1); this.nullBit3 = a3 & (na1 | a1 & na2 | b3 & (na4 ^ b4)) | b3 & (nb1 | b1 & nb2); this.nullBit4 = na3 & (nb1 & nb3 & b4 | b1 & (nb2 & nb3 | a4 & b2 & nb4) | na1 & a4 & (nb3 | b1 & b2)) | a3 & a4 & (b3 & b4 | b1 & nb2 | na1 & a2) | na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2 | a1 & (na3 & (nb3 & b4 | b1 & b2 & b3 & nb4 | na2 & (nb3 | nb2)) | na2 & b3 & b4 | a2 & (nb1 & b4 | a3 & na4 & b1) & nb3) |nb1 & b2 & b3 & b4; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 30) { this.nullBit4 = ~0; } } } else { // other has no null info a1 = this.nullBit1; this.nullBit1 = 0; this.nullBit2 = (a2 = this.nullBit2) & (na3 = ~(a3 = this.nullBit3) | (na1 = ~a1)); this.nullBit3 = a3 & ((na2 = ~a2) & (a4 = this.nullBit4) | na1) | a1 & na2 & ~a4; this.nullBit4 = (na3 | na2) & na1 & a4 | a1 & na3 & na2; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 31) { this.nullBit4 = ~0; } } } } else if (otherHasNulls) { // only other had nulls this.nullBit1 = 0; this.nullBit2 = (b2 = otherInits.nullBit2) & (nb3 = ~(b3 = otherInits.nullBit3) | (nb1 = ~(b1 = otherInits.nullBit1))); this.nullBit3 = b3 & ((nb2 = ~b2) & (b4 = otherInits.nullBit4) | nb1) | b1 & nb2 & ~b4; this.nullBit4 = (nb3 | nb2) & nb1 & b4 | b1 & nb3 & nb2; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 32) { this.nullBit4 = ~0; } } thisHasNulls = // redundant with the three following ones this.nullBit2 != 0 || this.nullBit3 != 0 || this.nullBit4 != 0; } // treating extra storage if (this.extra != null || otherInits.extra != null) { int mergeLimit = 0, copyLimit = 0, resetLimit = 0; int i; if (this.extra != null) { if (otherInits.extra != null) { // both sides have extra storage int length, otherLength; if ((length = this.extra[0].length) < (otherLength = otherInits.extra[0].length)) { // current storage is shorter -> grow current for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, (this.extra[j] = new long[otherLength]), 0, length); } mergeLimit = length; copyLimit = otherLength; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 33) { throw new AssertionFailedException("COVERAGE 33"); //$NON-NLS-1$ } } } else { // current storage is longer mergeLimit = otherLength; resetLimit = length; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 34) { throw new AssertionFailedException("COVERAGE 34"); //$NON-NLS-1$ } } } } else { resetLimit = this.extra[0].length; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 35) { throw new AssertionFailedException("COVERAGE 35"); //$NON-NLS-1$ } } } } else if (otherInits.extra != null) { // no storage here, but other has extra storage. int otherLength = otherInits.extra[0].length; this.extra = new long[extraLength][]; for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[otherLength]; } System.arraycopy(otherInits.extra[1], 0, this.extra[1], 0, otherLength); copyLimit = otherLength; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 36) { throw new AssertionFailedException("COVERAGE 36"); //$NON-NLS-1$ } } } // MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][i]/g // manage definite assignment for (i = 0; i < mergeLimit; i++) { this.extra[0][i] &= otherInits.extra[0][i]; this.extra[1][i] |= otherInits.extra[1][i]; } for (; i < copyLimit; i++) { this.extra[1][i] = otherInits.extra[1][i]; } for (; i < resetLimit; i++) { this.extra[0][i] = 0; } // refine null bits requirements if (!otherHasNulls) { if (resetLimit < mergeLimit) { resetLimit = mergeLimit; } copyLimit = 0; // no need to carry inexisting nulls mergeLimit = 0; } if (!thisHadNulls) { resetLimit = 0; // no need to reset anything } // compose nulls for (i = 0; i < mergeLimit; i++) { this.extra[1 + 1][i] = (a1=this.extra[1+1][i]) & (b1=otherInits.extra[1+1][i]) & ( ((a2=this.extra[2+1][i]) & (((b2=otherInits.extra[2+1][i]) & ~(((a3=this.extra[3+1][i]) & (a4=this.extra[4+1][i])) ^ ((b3=otherInits.extra[3+1][i]) & (b4=otherInits.extra[4+1][i])))) |(a3 & a4 & (nb2=~b2)))) |((na2=~a2) & ((b2 & b3 & b4) |(nb2 & ((na3=~a3) ^ b3))))); this.extra[2 + 1][i] = b2 & ((nb3=~b3) | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & (nb4=~b4)) | a2 & (b2 | (na4=~a4) & b3 & (b4 | nb1) | na3 | na1); this.extra[3 + 1][i] = a3 & (na1 | a1 & na2 | b3 & (na4 ^ b4)) | b3 & (nb1 | b1 & nb2); this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4 | b1 & (nb2 & nb3 | a4 & b2 & nb4) | na1 & a4 & (nb3 | b1 & b2)) | a3 & a4 & (b3 & b4 | b1 & nb2 | na1 & a2) | na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2 | a1 & (na3 & (nb3 & b4 | b1 & b2 & b3 & nb4 | na2 & (nb3 | nb2)) | na2 & b3 & b4 | a2 & (nb1 & b4 | a3 & na4 & b1) & nb3) |nb1 & b2 & b3 & b4; thisHasNulls = thisHasNulls || this.extra[3][i] != 0 || this.extra[4][i] != 0 || this.extra[5][i] != 0 ; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 37) { this.extra[5][i] = ~0; } } } for (; i < copyLimit; i++) { this.extra[1 + 1][i] = 0; this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i]) & (nb3 = ~(b3 = otherInits.extra[3 + 1][i]) | (nb1 = ~(b1 = otherInits.extra[1 + 1][i]))); this.extra[3 + 1][i] = b3 & ((nb2 = ~b2) & (b4 = otherInits.extra[4 + 1][i]) | nb1) | b1 & nb2 & ~b4; this.extra[4 + 1][i] = (nb3 | nb2) & nb1 & b4 | b1 & nb3 & nb2; thisHasNulls = thisHasNulls || this.extra[3][i] != 0 || this.extra[4][i] != 0 || this.extra[5][i] != 0; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 38) { this.extra[5][i] = ~0; } } } for (; i < resetLimit; i++) { a1 = this.extra[1 + 1][i]; this.extra[1 + 1][i] = 0; this.extra[2 + 1][i] = (a2 = this.extra[2 + 1][i]) & (na3 = ~(a3 = this.extra[3 + 1][i]) | (na1 = ~a1)); this.extra[3 + 1][i] = a3 & ((na2 = ~a2) & (a4 = this.extra[4 + 1][i]) | na1) | a1 & na2 & ~a4; this.extra[4 + 1][i] = (na3 | na2) & na1 & a4 | a1 & na3 & na2; thisHasNulls = thisHasNulls || this.extra[3][i] != 0 || this.extra[4][i] != 0 || this.extra[5][i] != 0; if (COVERAGE_TEST_FLAG) { if(CoverageTestId == 39) { this.extra[5][i] = ~0; } } } } if (thisHasNulls) { this.tagBits |= NULL_FLAG_MASK; } else { this.tagBits &= ~NULL_FLAG_MASK; } return this; } /* * Answer the total number of fields in enclosing types of a given type */ static int numberOfEnclosingFields(ReferenceBinding type){ int count = 0; type = type.enclosingType(); while(type != null) { count += type.fieldCount(); type = type.enclosingType(); } return count; } public UnconditionalFlowInfo nullInfoLessUnconditionalCopy() { if (this == DEAD_END) { return this; } UnconditionalFlowInfo copy = new UnconditionalFlowInfo(); copy.definiteInits = this.definiteInits; copy.potentialInits = this.potentialInits; copy.tagBits = this.tagBits & ~NULL_FLAG_MASK; copy.maxFieldCount = this.maxFieldCount; if (this.extra != null) { int length; copy.extra = new long[extraLength][]; System.arraycopy(this.extra[0], 0, (copy.extra[0] = new long[length = this.extra[0].length]), 0, length); System.arraycopy(this.extra[1], 0, (copy.extra[1] = new long[length]), 0, length); for (int j = 2; j < extraLength; j++) { copy.extra[j] = new long[length]; } } return copy; } public FlowInfo safeInitsWhenTrue() { return copy(); } public FlowInfo setReachMode(int reachMode) { if (this == DEAD_END) {// cannot modify DEAD_END return this; } if (reachMode == REACHABLE ) { this.tagBits &= ~UNREACHABLE; } else if (reachMode == UNREACHABLE_BY_NULLANALYSIS ) { this.tagBits |= UNREACHABLE_BY_NULLANALYSIS; // do not interfere with definite assignment analysis } else { if ((this.tagBits & UNREACHABLE) == 0) { // reset optional inits when becoming unreachable // see InitializationTest#test090 (and others) this.potentialInits = 0; if (this.extra != null) { for (int i = 0, length = this.extra[0].length; i < length; i++) { this.extra[1][i] = 0; } } } this.tagBits |= reachMode; } return this; } public String toString(){ // PREMATURE consider printing bit fields as 0001 0001 1000 0001... if (this == DEAD_END){ return "FlowInfo.DEAD_END"; //$NON-NLS-1$ } if ((this.tagBits & NULL_FLAG_MASK) != 0) { if (this.extra == null) { return "FlowInfo"; //$NON-NLS-1$ } else { String def = "FlowInfo 3 ? 3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ pot += "," + this.extra[1][i]; //$NON-NLS-1$ nullS += "," + this.extra[2][i] //$NON-NLS-1$ + this.extra[3][i] + this.extra[4][i] + this.extra[5][i]; } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ pot += ",..."; //$NON-NLS-1$ nullS += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + nullS + "]>"; //$NON-NLS-1$ } } else { if (this.extra == null) { return "FlowInfo"; //$NON-NLS-1$ } else { String def = "FlowInfo 3 ? 3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ pot += "," + this.extra[1][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ pot += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + ", no null info>"; //$NON-NLS-1$ } } } public UnconditionalFlowInfo unconditionalCopy() { return (UnconditionalFlowInfo) copy(); } public UnconditionalFlowInfo unconditionalFieldLessCopy() { // TODO (maxime) may consider leveraging null contribution verification as it is done in copy UnconditionalFlowInfo copy = new UnconditionalFlowInfo(); copy.tagBits = this.tagBits; copy.maxFieldCount = this.maxFieldCount; int limit = this.maxFieldCount; if (limit < BitCacheSize) { long mask; copy.definiteInits = this.definiteInits & (mask = ~((1L << limit)-1)); copy.potentialInits = this.potentialInits & mask; copy.nullBit1 = this.nullBit1 & mask; copy.nullBit2 = this.nullBit2 & mask; copy.nullBit3 = this.nullBit3 & mask; copy.nullBit4 = this.nullBit4 & mask; } // use extra vector if (this.extra == null) { return copy; // if vector not yet allocated, then not initialized } int vectorIndex, length, copyStart; if ((vectorIndex = (limit / BitCacheSize) - 1) >= (length = this.extra[0].length)) { return copy; // not enough room yet } long mask; copy.extra = new long[extraLength][]; if ((copyStart = vectorIndex + 1) < length) { int copyLength = length - copyStart; for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], copyStart, (copy.extra[j] = new long[length]), copyStart, copyLength); } } else if (vectorIndex >= 0) { for (int j = 0; j < extraLength; j++) { copy.extra[j] = new long[length]; } } if (vectorIndex >= 0) { mask = ~((1L << (limit % BitCacheSize))-1); for (int j = 0; j < extraLength; j++) { copy.extra[j][vectorIndex] = this.extra[j][vectorIndex] & mask; } } return copy; } public UnconditionalFlowInfo unconditionalInits() { // also see conditional inits, where it requests them to merge return this; } public UnconditionalFlowInfo unconditionalInitsWithoutSideEffect() { return this; } public void resetAssignmentInfo(LocalVariableBinding local) { resetAssignmentInfo(local.id + this.maxFieldCount); } public void resetAssignmentInfo(int position) { if (this != DEAD_END) { // position is zero-based if (position < BitCacheSize) { // use bits long mask; this.definiteInits &= (mask = ~(1L << position)); this.potentialInits &= mask; } else { // use extra vector int vectorIndex = (position / BitCacheSize) - 1; if (this.extra == null || vectorIndex >= this.extra[0].length) return; // variable doesnt exist in flow info long mask; this.extra[0][vectorIndex] &= (mask = ~(1L << (position % BitCacheSize))); this.extra[1][vectorIndex] &= mask; } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/flow/FlowContext.java0000644000175000001440000012015512212041344030354 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis * bug 186342 - [compiler][null] Using annotations for null checking * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; import java.util.ArrayList; 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.Expression; import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; import org.eclipse.jdt.internal.compiler.ast.LabeledStatement; import org.eclipse.jdt.internal.compiler.ast.Reference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement; import org.eclipse.jdt.internal.compiler.ast.ThrowStatement; import org.eclipse.jdt.internal.compiler.ast.TryStatement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding; 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; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class FlowContext implements TypeConstants { // preempt marks looping contexts public final static FlowContext NotContinuableContext = new FlowContext(null, null); public ASTNode associatedNode; public FlowContext parent; public FlowInfo initsOnFinally; // only used within try blocks; remembers upstream flow info mergedWith // any null related operation happening within the try block /** * Used to record whether effects in a try block affect the finally-block * conditionally or unconditionally. * -1 means: no effect, * 0 means: unconditional effect, * > 0 means levels of nested conditional structures. */ public int conditionalLevel = -1; public int tagBits; // array to store the provided and expected types from the potential error location (for display in error messages): public TypeBinding[][] providedExpectedTypes = null; // record field references known to be non-null // this array will never shrink, only grow. reset happens by nulling the first cell // adding elements after reset ensures that the valid part of the array is always null-terminated private Reference[] nullCheckedFieldReferences = null; private int timeToLiveForNullCheckInfo = -1; public static final int DEFER_NULL_DIAGNOSTIC = 0x1; public static final int PREEMPT_NULL_DIAGNOSTIC = 0x2; // inside an assertFalse or a not-expression checks for equality / inequality have reversed meaning for syntactic analysis for fields: public static final int INSIDE_NEGATION = 0x4; /** * used to hide null comparison related warnings inside assert statements */ public static final int HIDE_NULL_COMPARISON_WARNING = 0x1000; public static final int HIDE_NULL_COMPARISON_WARNING_MASK = 0xF000; public static final int CAN_ONLY_NULL_NON_NULL = 0x0000; //check against null and non null, with definite values -- comparisons public static final int CAN_ONLY_NULL = 0x0001; //check against null, with definite values -- comparisons public static final int CAN_ONLY_NON_NULL = 0x0002; //check against non null, with definite values -- comparisons public static final int MAY_NULL = 0x0003; //check binding a value to a @NonNull variable public final static int ASSIGN_TO_NONNULL = 0x0080; //check against an unboxing conversion public static final int IN_UNBOXING = 0x0010; //check against unclosed resource at early exit: public static final int EXIT_RESOURCE = 0x0800; // check against null, with potential values -- NPE guard public static final int CHECK_MASK = 0x00FF; public static final int IN_COMPARISON_NULL = 0x0100; public static final int IN_COMPARISON_NON_NULL = 0x0200; // check happened in a comparison public static final int IN_ASSIGNMENT = 0x0300; // check happened in an assignment public static final int IN_INSTANCEOF = 0x0400; // check happened in an instanceof expression public static final int CONTEXT_MASK = ~CHECK_MASK & ~HIDE_NULL_COMPARISON_WARNING_MASK; public FlowContext(FlowContext parent, ASTNode associatedNode) { this.parent = parent; this.associatedNode = associatedNode; if (parent != null) { if ((parent.tagBits & (FlowContext.DEFER_NULL_DIAGNOSTIC | FlowContext.PREEMPT_NULL_DIAGNOSTIC)) != 0) { this.tagBits |= FlowContext.DEFER_NULL_DIAGNOSTIC; } this.initsOnFinally = parent.initsOnFinally; this.conditionalLevel = parent.conditionalLevel; this.nullCheckedFieldReferences = parent.nullCheckedFieldReferences; // re-use list if there is one } } /** * Record that a reference to a field has been seen in a non-null state. * * @param reference Can be a SingleNameReference, a FieldReference or a QualifiedNameReference resolving to a field * @param timeToLive control how many expire events are needed to expire this information */ public void recordNullCheckedFieldReference(Reference reference, int timeToLive) { this.timeToLiveForNullCheckInfo = timeToLive; if (this.nullCheckedFieldReferences == null) { // first entry: this.nullCheckedFieldReferences = new Reference[2]; this.nullCheckedFieldReferences[0] = reference; } else { int len = this.nullCheckedFieldReferences.length; // insert into first empty slot: for (int i=0; i 0) this.timeToLiveForNullCheckInfo += t; } /** * Forget any information about fields that were previously known to be non-null. * * Will only cause any effect if CompilerOptions.enableSyntacticNullAnalysisForFields * (implicitly by guards before calls to {@link #recordNullCheckedFieldReference(Reference, int)}). */ public void expireNullCheckedFieldInfo() { if (this.nullCheckedFieldReferences != null) { if (--this.timeToLiveForNullCheckInfo == 0) { this.nullCheckedFieldReferences[0] = null; // lazily wipe } } } /** * Is the given field reference equivalent to a reference that is freshly known to be non-null? * Can only return true if CompilerOptions.enableSyntacticNullAnalysisForFields * (implicitly by guards before calls to {@link #recordNullCheckedFieldReference(Reference, int)}). */ public boolean isNullcheckedFieldAccess(Reference reference) { if (this.nullCheckedFieldReferences == null) // always null unless CompilerOptions.enableSyntacticNullAnalysisForFields return false; int len = this.nullCheckedFieldReferences.length; for (int i=0; i= ClassFileConstants.JDK1_7 && location instanceof ThrowStatement) { Expression throwExpression = ((ThrowStatement)location).exception; LocalVariableBinding throwArgBinding = throwExpression.localVariableBinding(); if (throwExpression instanceof SingleNameReference // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350361 && throwArgBinding instanceof CatchParameterBinding && throwArgBinding.isEffectivelyFinal()) { CatchParameterBinding parameter = (CatchParameterBinding) throwArgBinding; checkExceptionHandlers(parameter.getPreciseTypes(), location, flowInfo, scope); return; } } while (traversedContext != null) { SubRoutineStatement sub; if (((sub = traversedContext.subroutine()) != null) && sub.isSubRoutineEscaping()) { // traversing a non-returning subroutine means that all unhandled // exceptions will actually never get sent... return; } // filter exceptions that are locally caught from the innermost enclosing // try statement to the outermost ones. if (traversedContext instanceof ExceptionHandlingFlowContext) { ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) traversedContext; ReferenceBinding[] caughtExceptions; if ((caughtExceptions = exceptionContext.handledExceptions) != Binding.NO_EXCEPTIONS) { boolean definitelyCaught = false; for (int caughtIndex = 0, caughtCount = caughtExceptions.length; caughtIndex < caughtCount; caughtIndex++) { ReferenceBinding caughtException = caughtExceptions[caughtIndex]; int state = caughtException == null ? Scope.EQUAL_OR_MORE_SPECIFIC /* any exception */ : Scope.compareTypes(raisedException, caughtException); if (abruptlyExitedLoops != null && caughtException != null && state != Scope.NOT_RELATED) { for (int i = 0, abruptlyExitedLoopsCount = abruptlyExitedLoops.size(); i < abruptlyExitedLoopsCount; i++) { LoopingFlowContext loop = (LoopingFlowContext) abruptlyExitedLoops.get(i); loop.recordCatchContextOfEscapingException(exceptionContext, caughtException); } } switch (state) { case Scope.EQUAL_OR_MORE_SPECIFIC : exceptionContext.recordHandlingException( caughtException, flowInfo.unconditionalInits(), raisedException, raisedException, // precise exception that will be caught location, definitelyCaught); // was it already definitely caught ? definitelyCaught = true; break; case Scope.MORE_GENERIC : exceptionContext.recordHandlingException( caughtException, flowInfo.unconditionalInits(), raisedException, caughtException, location, false); // was not caught already per construction } } if (definitelyCaught) return; } // method treatment for unchecked exceptions if (exceptionContext.isMethodContext) { if (raisedException.isUncheckedException(false)) return; // anonymous constructors are allowed to throw any exceptions (their thrown exceptions // clause will be fixed up later as per JLS 8.6). if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration){ AbstractMethodDeclaration method = (AbstractMethodDeclaration)exceptionContext.associatedNode; if (method.isConstructor() && method.binding.declaringClass.isAnonymousType()){ exceptionContext.mergeUnhandledException(raisedException); return; // no need to complain, will fix up constructor exceptions } } break; // not handled anywhere, thus jump to error handling } } else if (traversedContext instanceof LoopingFlowContext) { if (abruptlyExitedLoops == null) { abruptlyExitedLoops = new ArrayList(5); } abruptlyExitedLoops.add(traversedContext); } traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); if (!isExceptionOnAutoClose) { if (traversedContext instanceof InsideSubRoutineFlowContext) { ASTNode node = traversedContext.associatedNode; if (node instanceof TryStatement) { TryStatement tryStatement = (TryStatement) node; flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits } } } traversedContext = traversedContext.getLocalParent(); } // if reaches this point, then there are some remaining unhandled exception types. if (isExceptionOnAutoClose) { scope.problemReporter().unhandledExceptionFromAutoClose(raisedException, location); } else { scope.problemReporter().unhandledException(raisedException, location); } } public void checkExceptionHandlers(TypeBinding[] raisedExceptions, ASTNode location, FlowInfo flowInfo, BlockScope scope) { // check that all the argument exception types are handled // JDK Compatible implementation - when an exception type is thrown, // all related catch blocks are marked as reachable... instead of those only // until the point where it is safely handled (Smarter - see comment at the end) int remainingCount; // counting the number of remaining unhandled exceptions int raisedCount; // total number of exceptions raised if ((raisedExceptions == null) || ((raisedCount = raisedExceptions.length) == 0)) return; remainingCount = raisedCount; // duplicate the array of raised exceptions since it will be updated // (null replaces any handled exception) System.arraycopy( raisedExceptions, 0, (raisedExceptions = new TypeBinding[raisedCount]), 0, raisedCount); FlowContext traversedContext = this; ArrayList abruptlyExitedLoops = null; while (traversedContext != null) { SubRoutineStatement sub; if (((sub = traversedContext.subroutine()) != null) && sub.isSubRoutineEscaping()) { // traversing a non-returning subroutine means that all unhandled // exceptions will actually never get sent... return; } // filter exceptions that are locally caught from the innermost enclosing // try statement to the outermost ones. if (traversedContext instanceof ExceptionHandlingFlowContext) { ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) traversedContext; ReferenceBinding[] caughtExceptions; if ((caughtExceptions = exceptionContext.handledExceptions) != Binding.NO_EXCEPTIONS) { int caughtCount = caughtExceptions.length; boolean[] locallyCaught = new boolean[raisedCount]; // at most for (int caughtIndex = 0; caughtIndex < caughtCount; caughtIndex++) { ReferenceBinding caughtException = caughtExceptions[caughtIndex]; for (int raisedIndex = 0; raisedIndex < raisedCount; raisedIndex++) { TypeBinding raisedException; if ((raisedException = raisedExceptions[raisedIndex]) != null) { int state = caughtException == null ? Scope.EQUAL_OR_MORE_SPECIFIC /* any exception */ : Scope.compareTypes(raisedException, caughtException); if (abruptlyExitedLoops != null && caughtException != null && state != Scope.NOT_RELATED) { for (int i = 0, abruptlyExitedLoopsCount = abruptlyExitedLoops.size(); i < abruptlyExitedLoopsCount; i++) { LoopingFlowContext loop = (LoopingFlowContext) abruptlyExitedLoops.get(i); loop.recordCatchContextOfEscapingException(exceptionContext, caughtException); } } switch (state) { case Scope.EQUAL_OR_MORE_SPECIFIC : exceptionContext.recordHandlingException( caughtException, flowInfo.unconditionalInits(), raisedException, raisedException, // precise exception that will be caught location, locallyCaught[raisedIndex]); // was already definitely caught ? if (!locallyCaught[raisedIndex]) { locallyCaught[raisedIndex] = true; // remember that this exception has been definitely caught remainingCount--; } break; case Scope.MORE_GENERIC : exceptionContext.recordHandlingException( caughtException, flowInfo.unconditionalInits(), raisedException, caughtException, location, false); // was not caught already per construction } } } } // remove locally caught exceptions from the remaining ones for (int i = 0; i < raisedCount; i++) { if (locallyCaught[i]) { raisedExceptions[i] = null; // removed from the remaining ones. } } } // method treatment for unchecked exceptions if (exceptionContext.isMethodContext) { for (int i = 0; i < raisedCount; i++) { TypeBinding raisedException; if ((raisedException = raisedExceptions[i]) != null) { if (raisedException.isUncheckedException(false)) { remainingCount--; raisedExceptions[i] = null; } } } // anonymous constructors are allowed to throw any exceptions (their thrown exceptions // clause will be fixed up later as per JLS 8.6). if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration){ AbstractMethodDeclaration method = (AbstractMethodDeclaration)exceptionContext.associatedNode; if (method.isConstructor() && method.binding.declaringClass.isAnonymousType()){ for (int i = 0; i < raisedCount; i++) { TypeBinding raisedException; if ((raisedException = raisedExceptions[i]) != null) { exceptionContext.mergeUnhandledException(raisedException); } } return; // no need to complain, will fix up constructor exceptions } } break; // not handled anywhere, thus jump to error handling } } else if (traversedContext instanceof LoopingFlowContext) { if (abruptlyExitedLoops == null) { abruptlyExitedLoops = new ArrayList(5); } abruptlyExitedLoops.add(traversedContext); } if (remainingCount == 0) return; traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); if (traversedContext instanceof InsideSubRoutineFlowContext) { ASTNode node = traversedContext.associatedNode; if (node instanceof TryStatement) { TryStatement tryStatement = (TryStatement) node; flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits } } traversedContext = traversedContext.getLocalParent(); } // if reaches this point, then there are some remaining unhandled exception types. nextReport: for (int i = 0; i < raisedCount; i++) { TypeBinding exception; if ((exception = raisedExceptions[i]) != null) { // only one complaint if same exception declared to be thrown more than once for (int j = 0; j < i; j++) { if (raisedExceptions[j] == exception) continue nextReport; // already reported } scope.problemReporter().unhandledException(exception, location); } } } public BranchLabel continueLabel() { return null; } public FlowInfo getInitsForFinalBlankInitializationCheck(TypeBinding declaringType, FlowInfo flowInfo) { FlowContext current = this; FlowInfo inits = flowInfo; do { if (current instanceof InitializationFlowContext) { InitializationFlowContext initializationContext = (InitializationFlowContext) current; if (((TypeDeclaration)initializationContext.associatedNode).binding == declaringType) { return inits; } inits = initializationContext.initsBeforeContext; current = initializationContext.initializationParent; } else if (current instanceof ExceptionHandlingFlowContext) { ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) current; current = exceptionContext.initializationParent == null ? exceptionContext.getLocalParent() : exceptionContext.initializationParent; } else { current = current.getLocalParent(); } } while (current != null); // not found return null; } /* * lookup through break labels */ public FlowContext getTargetContextForBreakLabel(char[] labelName) { FlowContext current = this, lastNonReturningSubRoutine = null; while (current != null) { if (current.isNonReturningContext()) { lastNonReturningSubRoutine = current; } char[] currentLabelName; if (((currentLabelName = current.labelName()) != null) && CharOperation.equals(currentLabelName, labelName)) { ((LabeledStatement)current.associatedNode).bits |= ASTNode.LabelUsed; if (lastNonReturningSubRoutine == null) return current; return lastNonReturningSubRoutine; } current = current.getLocalParent(); } // not found return null; } /* * lookup through continue labels */ public FlowContext getTargetContextForContinueLabel(char[] labelName) { FlowContext current = this; FlowContext lastContinuable = null; FlowContext lastNonReturningSubRoutine = null; while (current != null) { if (current.isNonReturningContext()) { lastNonReturningSubRoutine = current; } else { if (current.isContinuable()) { lastContinuable = current; } } char[] currentLabelName; if ((currentLabelName = current.labelName()) != null && CharOperation.equals(currentLabelName, labelName)) { ((LabeledStatement)current.associatedNode).bits |= ASTNode.LabelUsed; // matching label found if ((lastContinuable != null) && (current.associatedNode.concreteStatement() == lastContinuable.associatedNode)) { if (lastNonReturningSubRoutine == null) return lastContinuable; return lastNonReturningSubRoutine; } // label is found, but not a continuable location return FlowContext.NotContinuableContext; } current = current.getLocalParent(); } // not found return null; } /* * lookup a default break through breakable locations */ public FlowContext getTargetContextForDefaultBreak() { FlowContext current = this, lastNonReturningSubRoutine = null; while (current != null) { if (current.isNonReturningContext()) { lastNonReturningSubRoutine = current; } if (current.isBreakable() && current.labelName() == null) { if (lastNonReturningSubRoutine == null) return current; return lastNonReturningSubRoutine; } current = current.getLocalParent(); } // not found return null; } /* * lookup a default continue amongst continuable locations */ public FlowContext getTargetContextForDefaultContinue() { FlowContext current = this, lastNonReturningSubRoutine = null; while (current != null) { if (current.isNonReturningContext()) { lastNonReturningSubRoutine = current; } if (current.isContinuable()) { if (lastNonReturningSubRoutine == null) return current; return lastNonReturningSubRoutine; } current = current.getLocalParent(); } // not found return null; } /** * Answer the parent flow context but be careful not to cross the boundary of a nested type, * or null if no such parent exists. */ public FlowContext getLocalParent() { if (this.associatedNode instanceof AbstractMethodDeclaration || this.associatedNode instanceof TypeDeclaration) return null; return this.parent; } public String individualToString() { return "Flow context"; //$NON-NLS-1$ } public FlowInfo initsOnBreak() { return FlowInfo.DEAD_END; } public UnconditionalFlowInfo initsOnReturn() { return FlowInfo.DEAD_END; } public boolean isBreakable() { return false; } public boolean isContinuable() { return false; } public boolean isNonReturningContext() { return false; } public boolean isSubRoutine() { return false; } public char[] labelName() { return null; } /** * Record a given null status of a given local variable as it will be seen in the finally block. * @param local the local variable being observed * @param nullStatus the null status of local at the current point in the flow */ public void markFinallyNullStatus(LocalVariableBinding local, int nullStatus) { if (this.initsOnFinally == null) return; if (this.conditionalLevel == -1) return; if (this.conditionalLevel == 0) { // node is unconditionally reached, take nullStatus as is: this.initsOnFinally.markNullStatus(local, nullStatus); return; } // node is reached only conditionally, weaken status to potentially_ and merge with previous UnconditionalFlowInfo newInfo = this.initsOnFinally.unconditionalCopy(); newInfo.markNullStatus(local, nullStatus); this.initsOnFinally = this.initsOnFinally.mergedWith(newInfo); } /** * Merge the effect of a statement presumably contained in a try-block, * i.e., record how the collected info will affect the corresponding finally-block. * Precondition: caller has checked that initsOnFinally != null. * @param flowInfo info after executing a statement of the try-block. */ public void mergeFinallyNullInfo(FlowInfo flowInfo) { if (this.initsOnFinally == null) return; if (this.conditionalLevel == -1) return; if (this.conditionalLevel == 0) { // node is unconditionally reached, take null info as is: this.initsOnFinally.addNullInfoFrom(flowInfo); return; } // node is reached only conditionally: merge flowInfo with existing since both paths are possible this.initsOnFinally = this.initsOnFinally.mergedWith(flowInfo.unconditionalCopy()); } /** * Record the fact that an abrupt exit has been observed, one of: * - potential exception (incl. unchecked exceptions) * - break * - continue * - return */ public void recordAbruptExit() { if (this.conditionalLevel > -1) { this.conditionalLevel++; // delegate up up-to the enclosing try-finally: if (!(this instanceof ExceptionHandlingFlowContext) && this.parent != null) { this.parent.recordAbruptExit(); } } } public void recordBreakFrom(FlowInfo flowInfo) { // default implementation: do nothing } public void recordBreakTo(FlowContext targetContext) { // default implementation: do nothing } public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) { // default implementation: do nothing } /** * Record that we found an early exit from a method while a resource is in scope. * @param scope enclosing scope * @param flowInfo flowInfo at the point of the early exit * @param trackingVar representation of the resource * @param reference the return or throw statement marking the early exit * @return true if the situation has been handled by this flow context. */ public boolean recordExitAgainstResource(BlockScope scope, FlowInfo flowInfo, FakedTrackingVariable trackingVar, ASTNode reference) { return false; // not handled } protected void recordProvidedExpectedTypes(TypeBinding providedType, TypeBinding expectedType, int nullCount) { if (nullCount == 0) { this.providedExpectedTypes = new TypeBinding[5][]; } else if (this.providedExpectedTypes == null) { int size = 5; while (size <= nullCount) size *= 2; this.providedExpectedTypes = new TypeBinding[size][]; } else if (nullCount >= this.providedExpectedTypes.length) { int oldLen = this.providedExpectedTypes.length; System.arraycopy(this.providedExpectedTypes, 0, this.providedExpectedTypes = new TypeBinding[nullCount * 2][], 0, oldLen); } this.providedExpectedTypes[nullCount] = new TypeBinding[]{providedType, expectedType}; } protected boolean recordFinalAssignment(VariableBinding variable, Reference finalReference) { return true; // keep going } /** * Record a null reference for use by deferred checks. Only looping or * finally contexts really record that information. Other contexts * immediately check for unboxing. * @param local the local variable involved in the check * @param location the location triggering the analysis, for normal null dereference * this is an expression resolving to 'local', for resource leaks it is an * early exit statement. * @param checkType the checkType against which the check must be performed; one of * {@link #CAN_ONLY_NULL CAN_ONLY_NULL}, {@link #CAN_ONLY_NULL_NON_NULL * CAN_ONLY_NULL_NON_NULL}, {@link #MAY_NULL MAY_NULL}, * {@link #CAN_ONLY_NON_NULL CAN_ONLY_NON_NULL}, potentially * combined with a context indicator (one of {@link #IN_COMPARISON_NULL}, * {@link #IN_COMPARISON_NON_NULL}, {@link #IN_ASSIGNMENT} or {@link #IN_INSTANCEOF}). *
* Alternatively, a {@link #IN_UNBOXING} check can e requested. */ protected void recordNullReference(LocalVariableBinding local, ASTNode location, int checkType) { // default implementation: do nothing } /** * Either AST analysis or checking of a child flow context has encountered an unboxing situation. * Record this fact for handling at an appropriate point in time. * @param nullStatus the status as we know it so far. */ public void recordUnboxing(Scope scope, Expression expression, int nullStatus, FlowInfo flowInfo) { // default: handle immediately: checkUnboxing(scope, expression, flowInfo); } /** During deferred checking re-visit a previously recording unboxing situation. */ protected void checkUnboxing(Scope scope, Expression expression, FlowInfo flowInfo) { int status = expression.nullStatus(flowInfo, this); if ((status & FlowInfo.NULL) != 0) { scope.problemReporter().nullUnboxing(expression, expression.resolvedType); return; } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0) { scope.problemReporter().potentialNullUnboxing(expression, expression.resolvedType); return; } else if ((status & FlowInfo.NON_NULL) != 0) { return; } // not handled, perhaps our parent will eventually have something to say? if (this.parent != null) { this.parent.recordUnboxing(scope, expression, FlowInfo.UNKNOWN, flowInfo); } } public void recordReturnFrom(UnconditionalFlowInfo flowInfo) { // default implementation: do nothing } public void recordSettingFinal(VariableBinding variable, Reference finalReference, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { // for initialization inside looping statement that effectively loops FlowContext context = this; while (context != null) { if (!context.recordFinalAssignment(variable, finalReference)) { break; // no need to keep going } context = context.getLocalParent(); } } } /** * Record a null reference for use by deferred checks. Only looping or * finally contexts really record that information. The context may * emit an error immediately depending on the status of local against * flowInfo and its nature (only looping of finally contexts defer part * of the checks; nonetheless, contexts that are nested into a looping or a * finally context get affected and delegate some checks to their enclosing * context). * @param scope the scope into which the check is performed * @param local the local variable involved in the check * @param location the location triggering the analysis, for normal null dereference * this is an expression resolving to 'local', for resource leaks it is an * early exit statement. * @param checkType the status against which the check must be performed; one * of {@link #CAN_ONLY_NULL CAN_ONLY_NULL}, {@link #CAN_ONLY_NULL_NON_NULL * CAN_ONLY_NULL_NON_NULL}, {@link #MAY_NULL MAY_NULL}, potentially * combined with a context indicator (one of {@link #IN_COMPARISON_NULL}, * {@link #IN_COMPARISON_NON_NULL}, {@link #IN_ASSIGNMENT} or {@link #IN_INSTANCEOF}) * and a bit to indicate whether the reference is being recorded inside an assert, * {@link #HIDE_NULL_COMPARISON_WARNING} * @param flowInfo the flow info at the check point; deferring contexts will * perform supplementary checks against flow info instances that cannot * be known at the time of calling this method (they are influenced by * code that follows the current point) */ public void recordUsingNullReference(Scope scope, LocalVariableBinding local, ASTNode location, int checkType, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 || flowInfo.isDefinitelyUnknown(local)) { return; } // if reference is being recorded inside an assert, we will not raise redundant null check warnings checkType |= (this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING); int checkTypeWithoutHideNullWarning = checkType & ~FlowContext.HIDE_NULL_COMPARISON_WARNING_MASK; switch (checkTypeWithoutHideNullWarning) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: if (flowInfo.isDefinitelyNonNull(local)) { if (checkTypeWithoutHideNullWarning == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNonNull(local, location); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } else { scope.problemReporter().localVariableNonNullComparedToNull(local, location); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } return; } else if (flowInfo.cannotBeDefinitelyNullOrNonNull(local)) { return; } //$FALL-THROUGH$ case CAN_ONLY_NULL | IN_COMPARISON_NULL: case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL: case CAN_ONLY_NULL | IN_ASSIGNMENT: case CAN_ONLY_NULL | IN_INSTANCEOF: Expression reference = (Expression)location; if (flowInfo.isDefinitelyNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) { scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); } flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariableNullReference(local, reference); return; } scope.problemReporter().localVariableNullComparedToNonNull(local, reference); flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); return; case FlowContext.IN_ASSIGNMENT: scope.problemReporter().localVariableRedundantNullAssignment(local, reference); return; case FlowContext.IN_INSTANCEOF: scope.problemReporter().localVariableNullInstanceof(local, reference); return; } } else if (flowInfo.isPotentiallyNull(local)) { switch(checkTypeWithoutHideNullWarning & CONTEXT_MASK) { case FlowContext.IN_COMPARISON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; case FlowContext.IN_COMPARISON_NON_NULL: if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning scope.problemReporter().localVariablePotentialNullReference(local, reference); return; } break; } } else if (flowInfo.cannotBeDefinitelyNullOrNonNull(local)) { return; } break; case MAY_NULL : if (flowInfo.isDefinitelyNull(local)) { scope.problemReporter().localVariableNullReference(local, location); return; } if (flowInfo.isPotentiallyNull(local)) { scope.problemReporter().localVariablePotentialNullReference(local, location); return; } break; default: // never happens } if (this.parent != null) { this.parent.recordUsingNullReference(scope, local, location, checkType, flowInfo); } } void removeFinalAssignmentIfAny(Reference reference) { // default implementation: do nothing } public SubRoutineStatement subroutine() { return null; } public String toString() { StringBuffer buffer = new StringBuffer(); FlowContext current = this; int parentsCount = 0; while ((current = current.parent) != null) { parentsCount++; } FlowContext[] parents = new FlowContext[parentsCount + 1]; current = this; int index = parentsCount; while (index >= 0) { parents[index--] = current; current = current.parent; } for (int i = 0; i < parentsCount; i++) { for (int j = 0; j < i; j++) buffer.append('\t'); buffer.append(parents[i].individualToString()).append('\n'); } buffer.append('*'); for (int j = 0; j < parentsCount + 1; j++) buffer.append('\t'); buffer.append(individualToString()).append('\n'); return buffer.toString(); } /** * Record that a nullity mismatch was detected against an annotated type reference. * @param currentScope scope for error reporting * @param expression the expression violating the specification * @param providedType the type of the provided value, i.e., either expression or an element thereof (in ForeachStatements) * @param expectedType the declared type of the spec'ed variable, for error reporting. * @param nullStatus the null status of expression at the current location */ public void recordNullityMismatch(BlockScope currentScope, Expression expression, TypeBinding providedType, TypeBinding expectedType, int nullStatus) { if (providedType == null) { return; // assume type error was already reported } if (expression.localVariableBinding() != null) { // flowContext cannot yet handle non-localvar expressions (e.g., fields) // find the inner-most flowContext that might need deferred handling: FlowContext currentContext = this; while (currentContext != null) { // some flow contexts implement deferred checking, should we participate in that? int isInsideAssert = 0x0; if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) { isInsideAssert = FlowContext.HIDE_NULL_COMPARISON_WARNING; } if (currentContext.internalRecordNullityMismatch(expression, providedType, nullStatus, expectedType, ASSIGN_TO_NONNULL | isInsideAssert)) return; currentContext = currentContext.parent; } } // no reason to defer, so report now: char[][] annotationName = currentScope.environment().getNonNullAnnotationName(); currentScope.problemReporter().nullityMismatch(expression, providedType, expectedType, nullStatus, annotationName); } protected boolean internalRecordNullityMismatch(Expression expression, TypeBinding providedType, int nullStatus, TypeBinding expectedType, int checkType) { // nop, to be overridden in subclasses return false; // not recorded } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/0000755000175000001440000000000012251602350025226 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java0000644000175000001440000034520012251602350031223 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Benjamin Muskalla - Contribution for bug 239066 * Stephan Herrmann - Contributions for * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used * bug 295551 - Add option to automatically promote all warnings to errors * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 366063 - Compiler should not add synthetic @NonNull annotations * bug 374605 - Unreasonable warning for enum-based switch statements * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated * bug 383368 - [compiler][null] syntactic null analysis for field references * Jesper Steen Moller - Contributions for * bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.Compiler; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.Util; public class CompilerOptions { /** * Option IDs */ public static final String OPTION_LocalVariableAttribute = "org.eclipse.jdt.core.compiler.debug.localVariable"; //$NON-NLS-1$ public static final String OPTION_LineNumberAttribute = "org.eclipse.jdt.core.compiler.debug.lineNumber"; //$NON-NLS-1$ public static final String OPTION_SourceFileAttribute = "org.eclipse.jdt.core.compiler.debug.sourceFile"; //$NON-NLS-1$ public static final String OPTION_PreserveUnusedLocal = "org.eclipse.jdt.core.compiler.codegen.unusedLocal"; //$NON-NLS-1$ public static final String OPTION_DocCommentSupport= "org.eclipse.jdt.core.compiler.doc.comment.support"; //$NON-NLS-1$ public static final String OPTION_ReportMethodWithConstructorName = "org.eclipse.jdt.core.compiler.problem.methodWithConstructorName"; //$NON-NLS-1$ public static final String OPTION_ReportOverridingPackageDefaultMethod = "org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod"; //$NON-NLS-1$ public static final String OPTION_ReportDeprecation = "org.eclipse.jdt.core.compiler.problem.deprecation"; //$NON-NLS-1$ public static final String OPTION_ReportDeprecationInDeprecatedCode = "org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode"; //$NON-NLS-1$ public static final String OPTION_ReportDeprecationWhenOverridingDeprecatedMethod = "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"; //$NON-NLS-1$ public static final String OPTION_ReportHiddenCatchBlock = "org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedLocal = "org.eclipse.jdt.core.compiler.problem.unusedLocal"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedParameter = "org.eclipse.jdt.core.compiler.problem.unusedParameter"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedParameterWhenImplementingAbstract = "org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedParameterWhenOverridingConcrete = "org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedParameterIncludeDocCommentReference = "org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedImport = "org.eclipse.jdt.core.compiler.problem.unusedImport"; //$NON-NLS-1$ public static final String OPTION_ReportSyntheticAccessEmulation = "org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation"; //$NON-NLS-1$ public static final String OPTION_ReportNoEffectAssignment = "org.eclipse.jdt.core.compiler.problem.noEffectAssignment"; //$NON-NLS-1$ public static final String OPTION_ReportLocalVariableHiding = "org.eclipse.jdt.core.compiler.problem.localVariableHiding"; //$NON-NLS-1$ public static final String OPTION_ReportSpecialParameterHidingField = "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"; //$NON-NLS-1$ public static final String OPTION_ReportFieldHiding = "org.eclipse.jdt.core.compiler.problem.fieldHiding"; //$NON-NLS-1$ public static final String OPTION_ReportTypeParameterHiding = "org.eclipse.jdt.core.compiler.problem.typeParameterHiding"; //$NON-NLS-1$ public static final String OPTION_ReportPossibleAccidentalBooleanAssignment = "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"; //$NON-NLS-1$ public static final String OPTION_ReportNonExternalizedStringLiteral = "org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral"; //$NON-NLS-1$ public static final String OPTION_ReportIncompatibleNonInheritedInterfaceMethod = "org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod"; //$NON-NLS-1$ 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$ public static final String OPTION_ReportUnnecessaryTypeCheck = "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"; //$NON-NLS-1$ public static final String OPTION_ReportUnnecessaryElse = "org.eclipse.jdt.core.compiler.problem.unnecessaryElse"; //$NON-NLS-1$ 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$ public static final String OPTION_ReportMissingJavadocTagsOverriding = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"; //$NON-NLS-1$ public static final String OPTION_ReportMissingJavadocTagsMethodTypeParameters = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters"; //$NON-NLS-1$ public static final String OPTION_ReportMissingJavadocComments = "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"; //$NON-NLS-1$ public static final String OPTION_ReportMissingJavadocTagDescription = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription"; //$NON-NLS-1$ public static final String OPTION_ReportMissingJavadocCommentsVisibility = "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"; //$NON-NLS-1$ public static final String OPTION_ReportMissingJavadocCommentsOverriding = "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"; //$NON-NLS-1$ public static final String OPTION_ReportFinallyBlockNotCompletingNormally = "org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally"; //$NON-NLS-1$ 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_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable"; //$NON-NLS-1$ public static final String OPTION_ReportUnqualifiedFieldAccess = "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"; //$NON-NLS-1$ public static final String OPTION_ReportUnavoidableGenericTypeProblems = "org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems"; //$NON-NLS-1$ public static final String OPTION_ReportUncheckedTypeOperation = "org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation"; //$NON-NLS-1$ public static final String OPTION_ReportRawTypeReference = "org.eclipse.jdt.core.compiler.problem.rawTypeReference"; //$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_ReportUnusedTypeArgumentsForMethodInvocation = "org.eclipse.jdt.core.compiler.problem.unusedTypeArgumentsForMethodInvocation"; //$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$ public static final String OPTION_Encoding = "org.eclipse.jdt.core.encoding"; //$NON-NLS-1$ public static final String OPTION_MaxProblemPerUnit = "org.eclipse.jdt.core.compiler.maxProblemPerUnit"; //$NON-NLS-1$ public static final String OPTION_TaskTags = "org.eclipse.jdt.core.compiler.taskTags"; //$NON-NLS-1$ 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_ShareCommonFinallyBlocks = "org.eclipse.jdt.core.compiler.codegen.shareCommonFinallyBlocks"; //$NON-NLS-1$ public static final String OPTION_ReportNullReference = "org.eclipse.jdt.core.compiler.problem.nullReference"; //$NON-NLS-1$ public static final String OPTION_ReportPotentialNullReference = "org.eclipse.jdt.core.compiler.problem.potentialNullReference"; //$NON-NLS-1$ public static final String OPTION_ReportRedundantNullCheck = "org.eclipse.jdt.core.compiler.problem.redundantNullCheck"; //$NON-NLS-1$ public static final String OPTION_ReportAutoboxing = "org.eclipse.jdt.core.compiler.problem.autoboxing"; //$NON-NLS-1$ public static final String OPTION_ReportAnnotationSuperInterface = "org.eclipse.jdt.core.compiler.problem.annotationSuperInterface"; //$NON-NLS-1$ public static final String OPTION_ReportMissingOverrideAnnotation = "org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation"; //$NON-NLS-1$ public static final String OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation = "org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation"; //$NON-NLS-1$ public static final String OPTION_ReportMissingDeprecatedAnnotation = "org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation"; //$NON-NLS-1$ public static final String OPTION_ReportIncompleteEnumSwitch = "org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch"; //$NON-NLS-1$ public static final String OPTION_ReportMissingEnumCaseDespiteDefault = "org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault"; //$NON-NLS-1$ public static final String OPTION_ReportMissingDefaultCase = "org.eclipse.jdt.core.compiler.problem.missingDefaultCase"; //$NON-NLS-1$ public static final String OPTION_ReportForbiddenReference = "org.eclipse.jdt.core.compiler.problem.forbiddenReference"; //$NON-NLS-1$ public static final String OPTION_ReportDiscouragedReference = "org.eclipse.jdt.core.compiler.problem.discouragedReference"; //$NON-NLS-1$ public static final String OPTION_SuppressWarnings = "org.eclipse.jdt.core.compiler.problem.suppressWarnings"; //$NON-NLS-1$ public static final String OPTION_SuppressOptionalErrors = "org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors"; //$NON-NLS-1$ public static final String OPTION_ReportUnhandledWarningToken = "org.eclipse.jdt.core.compiler.problem.unhandledWarningToken"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedTypeParameter = "org.eclipse.jdt.core.compiler.problem.unusedTypeParameter"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedWarningToken = "org.eclipse.jdt.core.compiler.problem.unusedWarningToken"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedLabel = "org.eclipse.jdt.core.compiler.problem.unusedLabel"; //$NON-NLS-1$ public static final String OPTION_FatalOptionalError = "org.eclipse.jdt.core.compiler.problem.fatalOptionalError"; //$NON-NLS-1$ public static final String OPTION_ReportParameterAssignment = "org.eclipse.jdt.core.compiler.problem.parameterAssignment"; //$NON-NLS-1$ public static final String OPTION_ReportFallthroughCase = "org.eclipse.jdt.core.compiler.problem.fallthroughCase"; //$NON-NLS-1$ public static final String OPTION_ReportOverridingMethodWithoutSuperInvocation = "org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation"; //$NON-NLS-1$ public static final String OPTION_GenerateClassFiles = "org.eclipse.jdt.core.compiler.generateClassFiles"; //$NON-NLS-1$ public static final String OPTION_Process_Annotations = "org.eclipse.jdt.core.compiler.processAnnotations"; //$NON-NLS-1$ public static final String OPTION_ReportRedundantSuperinterface = "org.eclipse.jdt.core.compiler.problem.redundantSuperinterface"; //$NON-NLS-1$ public static final String OPTION_ReportComparingIdentical = "org.eclipse.jdt.core.compiler.problem.comparingIdentical"; //$NON-NLS-1$ public static final String OPTION_ReportMissingSynchronizedOnInheritedMethod = "org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod"; //$NON-NLS-1$ public static final String OPTION_ReportMissingHashCodeMethod = "org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod"; //$NON-NLS-1$ public static final String OPTION_ReportDeadCode = "org.eclipse.jdt.core.compiler.problem.deadCode"; //$NON-NLS-1$ public static final String OPTION_ReportDeadCodeInTrivialIfStatement = "org.eclipse.jdt.core.compiler.problem.deadCodeInTrivialIfStatement"; //$NON-NLS-1$ public static final String OPTION_ReportTasks = "org.eclipse.jdt.core.compiler.problem.tasks"; //$NON-NLS-1$ public static final String OPTION_ReportUnusedObjectAllocation = "org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation"; //$NON-NLS-1$ public static final String OPTION_IncludeNullInfoFromAsserts = "org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts"; //$NON-NLS-1$ public static final String OPTION_ReportMethodCanBeStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic"; //$NON-NLS-1$ public static final String OPTION_ReportMethodCanBePotentiallyStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$ public static final String OPTION_ReportRedundantSpecificationOfTypeArguments = "org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments"; //$NON-NLS-1$ public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$ public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$ public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$ public static final String OPTION_ReportNullSpecViolation = "org.eclipse.jdt.core.compiler.problem.nullSpecViolation"; //$NON-NLS-1$ public static final String OPTION_ReportNullAnnotationInferenceConflict = "org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict"; //$NON-NLS-1$ public static final String OPTION_ReportNullUncheckedConversion = "org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion"; //$NON-NLS-1$ public static final String OPTION_ReportRedundantNullAnnotation = "org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation"; //$NON-NLS-1$ public static final String OPTION_AnnotationBasedNullAnalysis = "org.eclipse.jdt.core.compiler.annotation.nullanalysis"; //$NON-NLS-1$ public static final String OPTION_NullableAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nullable"; //$NON-NLS-1$ public static final String OPTION_NonNullAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnull"; //$NON-NLS-1$ public static final String OPTION_NonNullByDefaultAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnullbydefault"; //$NON-NLS-1$ // defaults for the above: static final char[][] DEFAULT_NULLABLE_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.Nullable".toCharArray()); //$NON-NLS-1$ static final char[][] DEFAULT_NONNULL_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNull".toCharArray()); //$NON-NLS-1$ static final char[][] DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNullByDefault".toCharArray()); //$NON-NLS-1$ public static final String OPTION_ReportMissingNonNullByDefaultAnnotation = "org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation"; //$NON-NLS-1$ public static final String OPTION_SyntacticNullAnalysisForFields = "org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields"; //$NON-NLS-1$ public static final String OPTION_InheritNullAnnotations = "org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations"; //$NON-NLS-1$ public static final String OPTION_ReportNonnullParameterAnnotationDropped = "org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped"; //$NON-NLS-1$ /** * Possible values for configurable options */ public static final String GENERATE = "generate";//$NON-NLS-1$ public static final String DO_NOT_GENERATE = "do not generate"; //$NON-NLS-1$ public static final String PRESERVE = "preserve"; //$NON-NLS-1$ public static final String OPTIMIZE_OUT = "optimize out"; //$NON-NLS-1$ public static final String VERSION_1_1 = "1.1"; //$NON-NLS-1$ public static final String VERSION_1_2 = "1.2"; //$NON-NLS-1$ public static final String VERSION_1_3 = "1.3"; //$NON-NLS-1$ public static final String VERSION_1_4 = "1.4"; //$NON-NLS-1$ public static final String VERSION_JSR14 = "jsr14"; //$NON-NLS-1$ public static final String VERSION_CLDC1_1 = "cldc1.1"; //$NON-NLS-1$ public static final String VERSION_1_5 = "1.5"; //$NON-NLS-1$ public static final String VERSION_1_6 = "1.6"; //$NON-NLS-1$ public static final String VERSION_1_7 = "1.7"; //$NON-NLS-1$ public static final String ERROR = "error"; //$NON-NLS-1$ public static final String WARNING = "warning"; //$NON-NLS-1$ public static final String IGNORE = "ignore"; //$NON-NLS-1$ public static final String ENABLED = "enabled"; //$NON-NLS-1$ public static final String DISABLED = "disabled"; //$NON-NLS-1$ public static final String PUBLIC = "public"; //$NON-NLS-1$ public static final String PROTECTED = "protected"; //$NON-NLS-1$ public static final String DEFAULT = "default"; //$NON-NLS-1$ public static final String PRIVATE = "private"; //$NON-NLS-1$ public static final String RETURN_TAG = "return_tag"; //$NON-NLS-1$ public static final String NO_TAG = "no_tag"; //$NON-NLS-1$ public static final String ALL_STANDARD_TAGS = "all_standard_tags"; //$NON-NLS-1$ /** * Bit mask for configurable problems (error/warning threshold) * Note: bitmask assumes 3 highest bits to denote irritant group (to allow storing 8 groups of 29 bits each */ // group 0 public static final int MethodWithConstructorName = IrritantSet.GROUP0 | ASTNode.Bit1; public static final int OverriddenPackageDefaultMethod = IrritantSet.GROUP0 | ASTNode.Bit2; public static final int UsingDeprecatedAPI = IrritantSet.GROUP0 | ASTNode.Bit3; public static final int MaskedCatchBlock = IrritantSet.GROUP0 | ASTNode.Bit4; public static final int UnusedLocalVariable = IrritantSet.GROUP0 | ASTNode.Bit5; public static final int UnusedArgument = IrritantSet.GROUP0 | ASTNode.Bit6; public static final int NoImplicitStringConversion = IrritantSet.GROUP0 | ASTNode.Bit7; public static final int AccessEmulation = IrritantSet.GROUP0 | ASTNode.Bit8; public static final int NonExternalizedString = IrritantSet.GROUP0 | ASTNode.Bit9; public static final int AssertUsedAsAnIdentifier = IrritantSet.GROUP0 | ASTNode.Bit10; public static final int UnusedImport = IrritantSet.GROUP0 | ASTNode.Bit11; public static final int NonStaticAccessToStatic = IrritantSet.GROUP0 | ASTNode.Bit12; public static final int Task = IrritantSet.GROUP0 | ASTNode.Bit13; public static final int NoEffectAssignment = IrritantSet.GROUP0 | ASTNode.Bit14; public static final int IncompatibleNonInheritedInterfaceMethod = IrritantSet.GROUP0 | ASTNode.Bit15; public static final int UnusedPrivateMember = IrritantSet.GROUP0 | ASTNode.Bit16; public static final int LocalVariableHiding = IrritantSet.GROUP0 | ASTNode.Bit17; public static final int FieldHiding = IrritantSet.GROUP0 | ASTNode.Bit18; public static final int AccidentalBooleanAssign = IrritantSet.GROUP0 | ASTNode.Bit19; public static final int EmptyStatement = IrritantSet.GROUP0 | ASTNode.Bit20; public static final int MissingJavadocComments = IrritantSet.GROUP0 | ASTNode.Bit21; public static final int MissingJavadocTags = IrritantSet.GROUP0 | ASTNode.Bit22; public static final int UnqualifiedFieldAccess = IrritantSet.GROUP0 | ASTNode.Bit23; public static final int UnusedDeclaredThrownException = IrritantSet.GROUP0 | ASTNode.Bit24; public static final int FinallyBlockNotCompleting = IrritantSet.GROUP0 | ASTNode.Bit25; public static final int InvalidJavadoc = IrritantSet.GROUP0 | ASTNode.Bit26; public static final int UnnecessaryTypeCheck = IrritantSet.GROUP0 | ASTNode.Bit27; public static final int UndocumentedEmptyBlock = IrritantSet.GROUP0 | ASTNode.Bit28; public static final int IndirectStaticAccess = IrritantSet.GROUP0 | ASTNode.Bit29; // group 1 public static final int UnnecessaryElse = IrritantSet.GROUP1 | ASTNode.Bit1; public static final int UncheckedTypeOperation = IrritantSet.GROUP1 | ASTNode.Bit2; public static final int FinalParameterBound = IrritantSet.GROUP1 | ASTNode.Bit3; public static final int MissingSerialVersion = IrritantSet.GROUP1 | ASTNode.Bit4; public static final int EnumUsedAsAnIdentifier = IrritantSet.GROUP1 | ASTNode.Bit5; public static final int ForbiddenReference = IrritantSet.GROUP1 | ASTNode.Bit6; public static final int VarargsArgumentNeedCast = IrritantSet.GROUP1 | ASTNode.Bit7; public static final int NullReference = IrritantSet.GROUP1 | ASTNode.Bit8; public static final int AutoBoxing = IrritantSet.GROUP1 | ASTNode.Bit9; public static final int AnnotationSuperInterface = IrritantSet.GROUP1 | ASTNode.Bit10; public static final int TypeHiding = IrritantSet.GROUP1 | ASTNode.Bit11; public static final int MissingOverrideAnnotation = IrritantSet.GROUP1 | ASTNode.Bit12; public static final int MissingEnumConstantCase = IrritantSet.GROUP1 | ASTNode.Bit13; public static final int MissingDeprecatedAnnotation = IrritantSet.GROUP1 | ASTNode.Bit14; public static final int DiscouragedReference = IrritantSet.GROUP1 | ASTNode.Bit15; public static final int UnhandledWarningToken = IrritantSet.GROUP1 | ASTNode.Bit16; public static final int RawTypeReference = IrritantSet.GROUP1 | ASTNode.Bit17; public static final int UnusedLabel = IrritantSet.GROUP1 | ASTNode.Bit18; public static final int ParameterAssignment = IrritantSet.GROUP1 | ASTNode.Bit19; public static final int FallthroughCase = IrritantSet.GROUP1 | ASTNode.Bit20; public static final int OverridingMethodWithoutSuperInvocation = IrritantSet.GROUP1 | ASTNode.Bit21; public static final int PotentialNullReference = IrritantSet.GROUP1 | ASTNode.Bit22; public static final int RedundantNullCheck = IrritantSet.GROUP1 | ASTNode.Bit23; public static final int MissingJavadocTagDescription = IrritantSet.GROUP1 | ASTNode.Bit24; public static final int UnusedTypeArguments = IrritantSet.GROUP1 | ASTNode.Bit25; public static final int UnusedWarningToken = IrritantSet.GROUP1 | ASTNode.Bit26; public static final int RedundantSuperinterface = IrritantSet.GROUP1 | ASTNode.Bit27; public static final int ComparingIdentical = IrritantSet.GROUP1 | ASTNode.Bit28; public static final int MissingSynchronizedModifierInInheritedMethod= IrritantSet.GROUP1 | ASTNode.Bit29; // group 2 public static final int ShouldImplementHashcode = IrritantSet.GROUP2 | ASTNode.Bit1; public static final int DeadCode = IrritantSet.GROUP2 | ASTNode.Bit2; public static final int Tasks = IrritantSet.GROUP2 | ASTNode.Bit3; public static final int UnusedObjectAllocation = IrritantSet.GROUP2 | ASTNode.Bit4; public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5; public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6; public static final int RedundantSpecificationOfTypeArguments = IrritantSet.GROUP2 | ASTNode.Bit7; public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit8; public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit9; public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit10; public static final int NullSpecViolation = IrritantSet.GROUP2 | ASTNode.Bit11; public static final int NullAnnotationInferenceConflict = IrritantSet.GROUP2 | ASTNode.Bit12; public static final int NullUncheckedConversion = IrritantSet.GROUP2 | ASTNode.Bit13; public static final int RedundantNullAnnotation = IrritantSet.GROUP2 | ASTNode.Bit14; public static final int MissingNonNullByDefaultAnnotation = IrritantSet.GROUP2 | ASTNode.Bit15; public static final int MissingDefaultCase = IrritantSet.GROUP2 | ASTNode.Bit16; public static final int UnusedTypeParameter = IrritantSet.GROUP2 | ASTNode.Bit17; public static final int NonnullParameterAnnotationDropped = IrritantSet.GROUP2 | ASTNode.Bit18; // Severity level for handlers /** * Defaults defined at {@link IrritantSet#COMPILER_DEFAULT_ERRORS} * @see #resetDefaults() */ protected IrritantSet errorThreshold; /** * Defaults defined at {@link IrritantSet#COMPILER_DEFAULT_WARNINGS} * @see #resetDefaults() */ protected IrritantSet warningThreshold; /** * Default settings are to be defined in {@lnk CompilerOptions#resetDefaults()} */ /** Classfile debug information, may contain source file name, line numbers, local variable tables, etc... */ public int produceDebugAttributes; /** Compliance level for the compiler, refers to a JDK version, e.g. {@link ClassFileConstants#JDK1_4} */ public long complianceLevel; /** Original compliance level for the compiler, refers to a JDK version, e.g. {@link ClassFileConstants#JDK1_4}, * Usually same as the field complianceLevel, though the latter could deviate to create temporary sandbox * modes during reconcile operations. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=323633 */ public long originalComplianceLevel; /** Java source level, refers to a JDK version, e.g. {@link ClassFileConstants#JDK1_4} */ public long sourceLevel; /** Original Java source level, refers to a JDK version, e.g. {@link ClassFileConstants#JDK1_4} * Usually same as the field sourceLevel, though the latter could deviate to create temporary sandbox * modes during reconcile operations. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=323633 * */ public long originalSourceLevel; /** VM target level, refers to a JDK version, e.g. {@link ClassFileConstants#JDK1_4} */ public long targetJDK; /** Source encoding format */ public String defaultEncoding; /** Compiler trace verbosity */ public boolean verbose; /** Indicates whether reference info is desired */ public boolean produceReferenceInfo; /** Indicates if unused/optimizable local variables need to be preserved (debugging purpose) */ public boolean preserveAllLocalVariables; /** Indicates whether literal expressions are inlined at parse-time or not */ public boolean parseLiteralExpressionsAsConstants; /** Max problems per compilation unit */ public int maxProblemsPerUnit; /** Tags used to recognize tasks in comments */ public char[][] taskTags; /** Respective priorities of recognized task tags */ public char[][] taskPriorities; /** Indicate whether tag detection is case sensitive or not */ public boolean isTaskCaseSensitive; /** Specify whether deprecation inside deprecated code is to be reported */ public boolean reportDeprecationInsideDeprecatedCode; /** Specify whether override of deprecated method is to be reported */ public boolean reportDeprecationWhenOverridingDeprecatedMethod; /** Specify if should report unused parameter when implementing abstract method */ public boolean reportUnusedParameterWhenImplementingAbstract; /** Specify if should report unused parameter when overriding concrete method */ public boolean reportUnusedParameterWhenOverridingConcrete; /** Specify if should report documented unused parameter (in javadoc) */ public boolean reportUnusedParameterIncludeDocCommentReference; /** Specify if should reported unused declared thrown exception when overriding method */ public boolean reportUnusedDeclaredThrownExceptionWhenOverriding; /** Specify if should reported unused declared thrown exception when documented in javadoc */ public boolean reportUnusedDeclaredThrownExceptionIncludeDocCommentReference; /** Specify if should reported unused declared thrown exception when Exception or Throwable */ public boolean reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable; /** Specify whether should report constructor/setter method parameter hiding */ public boolean reportSpecialParameterHidingField; /** Specify whether trivial deadcode pattern is to be reported (e.g. if (DEBUG) ...) */ public boolean reportDeadCodeInTrivialIfStatement; /** Master flag controlling whether doc comment should be processed */ public boolean docCommentSupport; /** Specify if invalid javadoc shall be reported */ public boolean reportInvalidJavadocTags; /** Only report invalid javadoc above a given level of visibility of associated construct */ public int reportInvalidJavadocTagsVisibility; /** Specify if deprecated javadoc ref is allowed */ public boolean reportInvalidJavadocTagsDeprecatedRef; /** Specify if non visible javadoc ref is allowed */ public boolean reportInvalidJavadocTagsNotVisibleRef; /** Specify when to report missing javadoc tag description */ public String reportMissingJavadocTagDescription; /** Only report missing javadoc tags above a given level of visibility of associated construct */ public int reportMissingJavadocTagsVisibility; /** Specify if need to flag missing javadoc tags for overriding method */ public boolean reportMissingJavadocTagsOverriding; /** Specify if need to flag missing javadoc tags for method type parameters (java 1.5 and above)*/ public boolean reportMissingJavadocTagsMethodTypeParameters; /** Only report missing javadoc comment above a given level of visibility of associated construct */ public int reportMissingJavadocCommentsVisibility; /** Specify if need to flag missing javadoc comment for overriding method */ public boolean reportMissingJavadocCommentsOverriding; /** Indicate whether the JSR bytecode should be inlined to avoid its presence in classfile */ public boolean inlineJsrBytecode; /** Indicate whether common escaping finally blocks should be shared */ public boolean shareCommonFinallyBlocks; /** Indicate if @SuppressWarning annotations are activated */ public boolean suppressWarnings; /** Indicate if @SuppressWarning annotations should also suppress optional errors */ public boolean suppressOptionalErrors; /** Specify if should treat optional error as fatal or just like warning */ public boolean treatOptionalErrorAsFatal; /** Specify if parser should perform structural recovery in methods */ public boolean performMethodsFullRecovery; /** Specify if parser perform statements recovery */ public boolean performStatementsRecovery; /** Control whether annotation processing is enabled */ public boolean processAnnotations; /** Store annotations */ public boolean storeAnnotations; /** Specify if need to report missing override annotation for a method implementing an interface method (java 1.6 and above)*/ public boolean reportMissingOverrideAnnotationForInterfaceMethodImplementation; /** Indicate if annotation processing generates classfiles */ public boolean generateClassFiles; /** Indicate if method bodies should be ignored */ public boolean ignoreMethodBodies; /** Raise null related warnings for variables tainted inside an assert statement (java 1.4 and above)*/ public boolean includeNullInfoFromAsserts; /** Controls whether forced generic type problems get reported */ public boolean reportUnavoidableGenericTypeProblems; /** Indicates that the 'ignore optional problems from source folder' option need to be ignored * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=372377 */ public boolean ignoreSourceFolderWarningOption; // === Support for Null Annotations: === /** Master switch for null analysis based on annotations: */ public boolean isAnnotationBasedNullAnalysisEnabled; /** Fully qualified name of annotation to use as marker for nullable types. */ public char[][] nullableAnnotationName; /** Fully qualified name of annotation to use as marker for nonnull types. */ public char[][] nonNullAnnotationName; /** Fully qualified name of annotation to use as marker for default nonnull. */ public char[][] nonNullByDefaultAnnotationName; /** TagBits-encoded default for non-annotated types. */ public long intendedDefaultNonNullness; // 0 or TagBits#AnnotationNonNull /** Should resources (objects of type Closeable) be analysed for matching calls to close()? */ public boolean analyseResourceLeaks; /** Should missing enum cases be reported even if a default case exists in the same switch? */ public boolean reportMissingEnumCaseDespiteDefault; /** Should the compiler tolerate illegal ambiguous varargs invocation in compliance < 1.7 * to be bug compatible with javac? (bug 383780) */ public static boolean tolerateIllegalAmbiguousVarargsInvocation; { String tolerateIllegalAmbiguousVarargs = System.getProperty("tolerateIllegalAmbiguousVarargsInvocation"); //$NON-NLS-1$ tolerateIllegalAmbiguousVarargsInvocation = tolerateIllegalAmbiguousVarargs != null && tolerateIllegalAmbiguousVarargs.equalsIgnoreCase("true"); //$NON-NLS-1$ } /** Should null annotations of overridden methods be inherited? */ public boolean inheritNullAnnotations; /** Should immediate null-check for fields be considered during null analysis (syntactical match)? */ public boolean enableSyntacticNullAnalysisForFields; // keep in sync with warningTokenToIrritant and warningTokenFromIrritant public final static String[] warningTokens = { "all", //$NON-NLS-1$ "boxing", //$NON-NLS-1$ "cast", //$NON-NLS-1$ "dep-ann", //$NON-NLS-1$ "deprecation", //$NON-NLS-1$ "fallthrough", //$NON-NLS-1$ "finally", //$NON-NLS-1$ "hiding", //$NON-NLS-1$ "incomplete-switch", //$NON-NLS-1$ "javadoc", //$NON-NLS-1$ "nls", //$NON-NLS-1$ "null", //$NON-NLS-1$ "rawtypes", //$NON-NLS-1$ "resource", //$NON-NLS-1$ "restriction", //$NON-NLS-1$ "serial", //$NON-NLS-1$ "static-access", //$NON-NLS-1$ "static-method", //$NON-NLS-1$ "super", //$NON-NLS-1$ "synthetic-access", //$NON-NLS-1$ "sync-override", //$NON-NLS-1$ "unchecked", //$NON-NLS-1$ "unqualified-field-access", //$NON-NLS-1$ "unused", //$NON-NLS-1$ }; /** * Initializing the compiler options with defaults */ public CompilerOptions(){ this(null); // use default options } /** * Initializing the compiler options with external settings * @param settings */ public CompilerOptions(Map settings){ resetDefaults(); if (settings != null) { set(settings); } } /** * @deprecated used to preserve 3.1 and 3.2M4 compatibility of some Compiler constructors */ public CompilerOptions(Map settings, boolean parseLiteralExpressionsAsConstants){ this(settings); this.parseLiteralExpressionsAsConstants = parseLiteralExpressionsAsConstants; } /** * Return the most specific option key controlling this irritant. Note that in some case, some irritant is controlled by * other master options (e.g. javadoc, deprecation, etc.). * This information is intended for grouping purpose (several problems governed by a rule) */ public static String optionKeyFromIrritant(int irritant) { // keep in sync with warningTokens and warningTokenToIrritant switch (irritant) { case MethodWithConstructorName : return OPTION_ReportMethodWithConstructorName; case OverriddenPackageDefaultMethod : return OPTION_ReportOverridingPackageDefaultMethod; case UsingDeprecatedAPI : case (InvalidJavadoc | UsingDeprecatedAPI) : return OPTION_ReportDeprecation; case MaskedCatchBlock : return OPTION_ReportHiddenCatchBlock; case UnusedLocalVariable : return OPTION_ReportUnusedLocal; case UnusedArgument : return OPTION_ReportUnusedParameter; case NoImplicitStringConversion : return OPTION_ReportNoImplicitStringConversion; case AccessEmulation : return OPTION_ReportSyntheticAccessEmulation; case NonExternalizedString : return OPTION_ReportNonExternalizedStringLiteral; case AssertUsedAsAnIdentifier : return OPTION_ReportAssertIdentifier; case UnusedImport : return OPTION_ReportUnusedImport; case NonStaticAccessToStatic : return OPTION_ReportNonStaticAccessToStatic; case Task : return OPTION_TaskTags; case NoEffectAssignment : return OPTION_ReportNoEffectAssignment; case IncompatibleNonInheritedInterfaceMethod : return OPTION_ReportIncompatibleNonInheritedInterfaceMethod; case UnusedPrivateMember : return OPTION_ReportUnusedPrivateMember; case LocalVariableHiding : return OPTION_ReportLocalVariableHiding; case FieldHiding : return OPTION_ReportFieldHiding; case AccidentalBooleanAssign : return OPTION_ReportPossibleAccidentalBooleanAssignment; case EmptyStatement : return OPTION_ReportEmptyStatement; case MissingJavadocComments : return OPTION_ReportMissingJavadocComments; case MissingJavadocTags : return OPTION_ReportMissingJavadocTags; case UnqualifiedFieldAccess : return OPTION_ReportUnqualifiedFieldAccess; case UnusedDeclaredThrownException : return OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding; case FinallyBlockNotCompleting : return OPTION_ReportFinallyBlockNotCompletingNormally; case InvalidJavadoc : return OPTION_ReportInvalidJavadoc; case UnnecessaryTypeCheck : return OPTION_ReportUnnecessaryTypeCheck; case UndocumentedEmptyBlock : return OPTION_ReportUndocumentedEmptyBlock; case IndirectStaticAccess : return OPTION_ReportIndirectStaticAccess; case UnnecessaryElse : return OPTION_ReportUnnecessaryElse; case UncheckedTypeOperation : return OPTION_ReportUncheckedTypeOperation; case FinalParameterBound : return OPTION_ReportFinalParameterBound; case MissingSerialVersion : return OPTION_ReportMissingSerialVersion ; case EnumUsedAsAnIdentifier : return OPTION_ReportEnumIdentifier; case ForbiddenReference : return OPTION_ReportForbiddenReference; case VarargsArgumentNeedCast : return OPTION_ReportVarargsArgumentNeedCast; case NullReference : return OPTION_ReportNullReference; case PotentialNullReference : return OPTION_ReportPotentialNullReference; case RedundantNullCheck : return OPTION_ReportRedundantNullCheck; case AutoBoxing : return OPTION_ReportAutoboxing; case AnnotationSuperInterface : return OPTION_ReportAnnotationSuperInterface; case TypeHiding : return OPTION_ReportTypeParameterHiding; case MissingOverrideAnnotation : return OPTION_ReportMissingOverrideAnnotation; case MissingEnumConstantCase : return OPTION_ReportIncompleteEnumSwitch; case MissingDefaultCase : return OPTION_ReportMissingDefaultCase; case MissingDeprecatedAnnotation : return OPTION_ReportMissingDeprecatedAnnotation; case DiscouragedReference : return OPTION_ReportDiscouragedReference; case UnhandledWarningToken : return OPTION_ReportUnhandledWarningToken; case RawTypeReference : return OPTION_ReportRawTypeReference; case UnusedLabel : return OPTION_ReportUnusedLabel; case ParameterAssignment : return OPTION_ReportParameterAssignment; case FallthroughCase : return OPTION_ReportFallthroughCase; case OverridingMethodWithoutSuperInvocation : return OPTION_ReportOverridingMethodWithoutSuperInvocation; case MissingJavadocTagDescription : return OPTION_ReportMissingJavadocTagDescription; case UnusedTypeArguments : return OPTION_ReportUnusedTypeArgumentsForMethodInvocation; case UnusedTypeParameter: return OPTION_ReportUnusedTypeParameter; case UnusedWarningToken : return OPTION_ReportUnusedWarningToken; case RedundantSuperinterface : return OPTION_ReportRedundantSuperinterface; case ComparingIdentical : return OPTION_ReportComparingIdentical; case MissingSynchronizedModifierInInheritedMethod : return OPTION_ReportMissingSynchronizedOnInheritedMethod; case ShouldImplementHashcode : return OPTION_ReportMissingHashCodeMethod; case DeadCode : return OPTION_ReportDeadCode; case UnusedObjectAllocation: return OPTION_ReportUnusedObjectAllocation; case MethodCanBeStatic : return OPTION_ReportMethodCanBeStatic; case MethodCanBePotentiallyStatic : return OPTION_ReportMethodCanBePotentiallyStatic; case MissingNonNullByDefaultAnnotation : return OPTION_ReportMissingNonNullByDefaultAnnotation; case RedundantSpecificationOfTypeArguments : return OPTION_ReportRedundantSpecificationOfTypeArguments; case UnclosedCloseable : return OPTION_ReportUnclosedCloseable; case PotentiallyUnclosedCloseable : return OPTION_ReportPotentiallyUnclosedCloseable; case ExplicitlyClosedAutoCloseable : return OPTION_ReportExplicitlyClosedAutoCloseable; case NullSpecViolation : return OPTION_ReportNullSpecViolation; case NullAnnotationInferenceConflict : return OPTION_ReportNullAnnotationInferenceConflict; case NullUncheckedConversion : return OPTION_ReportNullUncheckedConversion; case RedundantNullAnnotation : return OPTION_ReportRedundantNullAnnotation; case NonnullParameterAnnotationDropped: return OPTION_ReportNonnullParameterAnnotationDropped; } return null; } public static String versionFromJdkLevel(long jdkLevel) { switch ((int)(jdkLevel>>16)) { case ClassFileConstants.MAJOR_VERSION_1_1 : if (jdkLevel == ClassFileConstants.JDK1_1) return VERSION_1_1; break; case ClassFileConstants.MAJOR_VERSION_1_2 : if (jdkLevel == ClassFileConstants.JDK1_2) return VERSION_1_2; break; case ClassFileConstants.MAJOR_VERSION_1_3 : if (jdkLevel == ClassFileConstants.JDK1_3) return VERSION_1_3; break; case ClassFileConstants.MAJOR_VERSION_1_4 : if (jdkLevel == ClassFileConstants.JDK1_4) return VERSION_1_4; break; case ClassFileConstants.MAJOR_VERSION_1_5 : if (jdkLevel == ClassFileConstants.JDK1_5) return VERSION_1_5; break; case ClassFileConstants.MAJOR_VERSION_1_6 : if (jdkLevel == ClassFileConstants.JDK1_6) return VERSION_1_6; break; case ClassFileConstants.MAJOR_VERSION_1_7 : if (jdkLevel == ClassFileConstants.JDK1_7) return VERSION_1_7; break; } return Util.EMPTY_STRING; // unknown version } public static long versionToJdkLevel(Object versionID) { if (versionID instanceof String) { String version = (String) versionID; // verification is optimized for all versions with same length and same "1." prefix if (version.length() == 3 && version.charAt(0) == '1' && version.charAt(1) == '.') { switch (version.charAt(2)) { case '1': return ClassFileConstants.JDK1_1; case '2': return ClassFileConstants.JDK1_2; case '3': return ClassFileConstants.JDK1_3; case '4': return ClassFileConstants.JDK1_4; case '5': return ClassFileConstants.JDK1_5; case '6': return ClassFileConstants.JDK1_6; case '7': return ClassFileConstants.JDK1_7; default: return 0; // unknown } } if (VERSION_JSR14.equals(versionID)) { return ClassFileConstants.JDK1_4; } if (VERSION_CLDC1_1.equals(versionID)) { return ClassFileConstants.CLDC_1_1; } } return 0; // unknown } /** * Return all warning option names for use as keys in compiler options maps. * @return all warning option names */ public static String[] warningOptionNames() { String[] result = { OPTION_ReportAnnotationSuperInterface, OPTION_ReportAssertIdentifier, OPTION_ReportAutoboxing, OPTION_ReportComparingIdentical, OPTION_ReportDeadCode, OPTION_ReportDeadCodeInTrivialIfStatement, OPTION_ReportDeprecation, OPTION_ReportDeprecationInDeprecatedCode, OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, OPTION_ReportDiscouragedReference, OPTION_ReportEmptyStatement, OPTION_ReportEnumIdentifier, OPTION_ReportFallthroughCase, OPTION_ReportFieldHiding, OPTION_ReportFinallyBlockNotCompletingNormally, OPTION_ReportFinalParameterBound, OPTION_ReportForbiddenReference, OPTION_ReportHiddenCatchBlock, OPTION_ReportIncompatibleNonInheritedInterfaceMethod, OPTION_ReportMissingDefaultCase, OPTION_ReportIncompleteEnumSwitch, OPTION_ReportMissingEnumCaseDespiteDefault, OPTION_ReportIndirectStaticAccess, OPTION_ReportInvalidJavadoc, OPTION_ReportInvalidJavadocTags, OPTION_ReportInvalidJavadocTagsDeprecatedRef, OPTION_ReportInvalidJavadocTagsNotVisibleRef, OPTION_ReportInvalidJavadocTagsVisibility, OPTION_ReportLocalVariableHiding, OPTION_ReportMethodCanBePotentiallyStatic, OPTION_ReportMethodCanBeStatic, OPTION_ReportMethodWithConstructorName, OPTION_ReportMissingDeprecatedAnnotation, OPTION_ReportMissingHashCodeMethod, OPTION_ReportMissingJavadocComments, OPTION_ReportMissingJavadocCommentsOverriding, OPTION_ReportMissingJavadocCommentsVisibility, OPTION_ReportMissingJavadocTagDescription, OPTION_ReportMissingJavadocTags, OPTION_ReportMissingJavadocTagsMethodTypeParameters, OPTION_ReportMissingJavadocTagsOverriding, OPTION_ReportMissingJavadocTagsVisibility, OPTION_ReportMissingOverrideAnnotation, OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation, OPTION_ReportMissingSerialVersion, OPTION_ReportMissingSynchronizedOnInheritedMethod, OPTION_ReportNoEffectAssignment, OPTION_ReportNoImplicitStringConversion, OPTION_ReportNonExternalizedStringLiteral, OPTION_ReportNonStaticAccessToStatic, OPTION_ReportNullReference, OPTION_ReportOverridingMethodWithoutSuperInvocation, OPTION_ReportOverridingPackageDefaultMethod, OPTION_ReportParameterAssignment, OPTION_ReportPossibleAccidentalBooleanAssignment, OPTION_ReportPotentialNullReference, OPTION_ReportRawTypeReference, OPTION_ReportRedundantNullCheck, OPTION_ReportRedundantSuperinterface, OPTION_ReportRedundantSpecificationOfTypeArguments, OPTION_ReportSpecialParameterHidingField, OPTION_ReportSyntheticAccessEmulation, OPTION_ReportTasks, OPTION_ReportTypeParameterHiding, OPTION_ReportUnavoidableGenericTypeProblems, OPTION_ReportUncheckedTypeOperation, OPTION_ReportUndocumentedEmptyBlock, OPTION_ReportUnhandledWarningToken, OPTION_ReportUnnecessaryElse, OPTION_ReportUnnecessaryTypeCheck, OPTION_ReportUnqualifiedFieldAccess, OPTION_ReportUnusedDeclaredThrownException, OPTION_ReportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable, OPTION_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference, OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, OPTION_ReportUnusedImport, OPTION_ReportUnusedLabel, OPTION_ReportUnusedLocal, OPTION_ReportUnusedObjectAllocation, OPTION_ReportUnusedParameter, OPTION_ReportUnusedParameterIncludeDocCommentReference, OPTION_ReportUnusedParameterWhenImplementingAbstract, OPTION_ReportUnusedParameterWhenOverridingConcrete, OPTION_ReportUnusedPrivateMember, OPTION_ReportUnusedTypeArgumentsForMethodInvocation, OPTION_ReportUnusedWarningToken, OPTION_ReportVarargsArgumentNeedCast, OPTION_ReportUnclosedCloseable, OPTION_ReportPotentiallyUnclosedCloseable, OPTION_ReportExplicitlyClosedAutoCloseable, OPTION_AnnotationBasedNullAnalysis, OPTION_NonNullAnnotationName, OPTION_NullableAnnotationName, OPTION_NonNullByDefaultAnnotationName, OPTION_ReportMissingNonNullByDefaultAnnotation, OPTION_ReportNullSpecViolation, OPTION_ReportNullAnnotationInferenceConflict, OPTION_ReportNullUncheckedConversion, OPTION_ReportRedundantNullAnnotation, OPTION_SyntacticNullAnalysisForFields, OPTION_ReportUnusedTypeParameter, OPTION_InheritNullAnnotations, OPTION_ReportNonnullParameterAnnotationDropped }; return result; } /** * For suppressable warnings */ public static String warningTokenFromIrritant(int irritant) { // keep in sync with warningTokens and warningTokenToIrritant switch (irritant) { case (InvalidJavadoc | UsingDeprecatedAPI) : case UsingDeprecatedAPI : return "deprecation"; //$NON-NLS-1$ case FinallyBlockNotCompleting : return "finally"; //$NON-NLS-1$ case FieldHiding : case LocalVariableHiding : case MaskedCatchBlock : return "hiding"; //$NON-NLS-1$ case NonExternalizedString : return "nls"; //$NON-NLS-1$ case UnnecessaryTypeCheck : return "cast"; //$NON-NLS-1$ case IndirectStaticAccess : case NonStaticAccessToStatic : return "static-access"; //$NON-NLS-1$ case AccessEmulation : return "synthetic-access"; //$NON-NLS-1$ case UnqualifiedFieldAccess : return "unqualified-field-access"; //$NON-NLS-1$ case UncheckedTypeOperation : return "unchecked"; //$NON-NLS-1$ case MissingSerialVersion : return "serial"; //$NON-NLS-1$ case AutoBoxing : return "boxing"; //$NON-NLS-1$ case TypeHiding : return "hiding"; //$NON-NLS-1$ case MissingEnumConstantCase : case MissingDefaultCase : return "incomplete-switch"; //$NON-NLS-1$ case MissingDeprecatedAnnotation : return "dep-ann"; //$NON-NLS-1$ case RawTypeReference : return "rawtypes"; //$NON-NLS-1$ case UnusedLabel : case UnusedTypeArguments : case RedundantSuperinterface : case UnusedLocalVariable : case UnusedArgument : case UnusedImport : case UnusedPrivateMember : case UnusedDeclaredThrownException : case DeadCode : case UnusedObjectAllocation : case RedundantSpecificationOfTypeArguments : case UnusedTypeParameter: return "unused"; //$NON-NLS-1$ case DiscouragedReference : case ForbiddenReference : return "restriction"; //$NON-NLS-1$ case NullReference : case PotentialNullReference : case RedundantNullCheck : case NullSpecViolation : case NullAnnotationInferenceConflict : case NullUncheckedConversion : case RedundantNullAnnotation : case MissingNonNullByDefaultAnnotation: case NonnullParameterAnnotationDropped: return "null"; //$NON-NLS-1$ case FallthroughCase : return "fallthrough"; //$NON-NLS-1$ case OverridingMethodWithoutSuperInvocation : return "super"; //$NON-NLS-1$ case MethodCanBeStatic : case MethodCanBePotentiallyStatic : return "static-method"; //$NON-NLS-1$ case PotentiallyUnclosedCloseable: case UnclosedCloseable: case ExplicitlyClosedAutoCloseable: return "resource"; //$NON-NLS-1$ case InvalidJavadoc : case MissingJavadocComments : case MissingJavadocTags: return "javadoc"; //$NON-NLS-1$ case MissingSynchronizedModifierInInheritedMethod: return "sync-override"; //$NON-NLS-1$ } return null; } public static IrritantSet warningTokenToIrritants(String warningToken) { // keep in sync with warningTokens and warningTokenFromIrritant if (warningToken == null || warningToken.length() == 0) return null; switch (warningToken.charAt(0)) { case 'a' : if ("all".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.ALL; break; case 'b' : if ("boxing".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.BOXING; break; case 'c' : if ("cast".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.CAST; break; case 'd' : if ("deprecation".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.DEPRECATION; if ("dep-ann".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.DEP_ANN; break; case 'f' : if ("fallthrough".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.FALLTHROUGH; if ("finally".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.FINALLY; break; case 'h' : if ("hiding".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.HIDING; break; case 'i' : if ("incomplete-switch".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.INCOMPLETE_SWITCH; break; case 'j' : if ("javadoc".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.JAVADOC; break; case 'n' : if ("nls".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.NLS; if ("null".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.NULL; break; case 'r' : if ("rawtypes".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.RAW; if ("resource".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.RESOURCE; if ("restriction".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.RESTRICTION; break; case 's' : if ("serial".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.SERIAL; if ("static-access".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.STATIC_ACCESS; if ("static-method".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.STATIC_METHOD; if ("synthetic-access".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.SYNTHETIC_ACCESS; if ("super".equals(warningToken)) { //$NON-NLS-1$ return IrritantSet.SUPER; } if ("sync-override".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.SYNCHRONIZED; break; case 'u' : if ("unused".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.UNUSED; if ("unchecked".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.UNCHECKED; if ("unqualified-field-access".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.UNQUALIFIED_FIELD_ACCESS; break; } return null; } public Map getMap() { Map optionsMap = new HashMap(30); optionsMap.put(OPTION_LocalVariableAttribute, (this.produceDebugAttributes & ClassFileConstants.ATTR_VARS) != 0 ? GENERATE : DO_NOT_GENERATE); optionsMap.put(OPTION_LineNumberAttribute, (this.produceDebugAttributes & ClassFileConstants.ATTR_LINES) != 0 ? GENERATE : DO_NOT_GENERATE); optionsMap.put(OPTION_SourceFileAttribute, (this.produceDebugAttributes & ClassFileConstants.ATTR_SOURCE) != 0 ? GENERATE : DO_NOT_GENERATE); optionsMap.put(OPTION_PreserveUnusedLocal, this.preserveAllLocalVariables ? PRESERVE : OPTIMIZE_OUT); optionsMap.put(OPTION_DocCommentSupport, this.docCommentSupport ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportMethodWithConstructorName, getSeverityString(MethodWithConstructorName)); optionsMap.put(OPTION_ReportOverridingPackageDefaultMethod, getSeverityString(OverriddenPackageDefaultMethod)); optionsMap.put(OPTION_ReportDeprecation, getSeverityString(UsingDeprecatedAPI)); optionsMap.put(OPTION_ReportDeprecationInDeprecatedCode, this.reportDeprecationInsideDeprecatedCode ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, this.reportDeprecationWhenOverridingDeprecatedMethod ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportHiddenCatchBlock, getSeverityString(MaskedCatchBlock)); optionsMap.put(OPTION_ReportUnusedLocal, getSeverityString(UnusedLocalVariable)); optionsMap.put(OPTION_ReportUnusedParameter, getSeverityString(UnusedArgument)); optionsMap.put(OPTION_ReportUnusedImport, getSeverityString(UnusedImport)); optionsMap.put(OPTION_ReportSyntheticAccessEmulation, getSeverityString(AccessEmulation)); optionsMap.put(OPTION_ReportNoEffectAssignment, getSeverityString(NoEffectAssignment)); optionsMap.put(OPTION_ReportNonExternalizedStringLiteral, getSeverityString(NonExternalizedString)); optionsMap.put(OPTION_ReportNoImplicitStringConversion, getSeverityString(NoImplicitStringConversion)); optionsMap.put(OPTION_ReportNonStaticAccessToStatic, getSeverityString(NonStaticAccessToStatic)); optionsMap.put(OPTION_ReportIndirectStaticAccess, getSeverityString(IndirectStaticAccess)); optionsMap.put(OPTION_ReportIncompatibleNonInheritedInterfaceMethod, getSeverityString(IncompatibleNonInheritedInterfaceMethod)); optionsMap.put(OPTION_ReportUnusedPrivateMember, getSeverityString(UnusedPrivateMember)); optionsMap.put(OPTION_ReportLocalVariableHiding, getSeverityString(LocalVariableHiding)); optionsMap.put(OPTION_ReportFieldHiding, getSeverityString(FieldHiding)); optionsMap.put(OPTION_ReportTypeParameterHiding, getSeverityString(TypeHiding)); 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_ReportAutoboxing, getSeverityString(AutoBoxing)); optionsMap.put(OPTION_ReportAnnotationSuperInterface, getSeverityString(AnnotationSuperInterface)); optionsMap.put(OPTION_ReportIncompleteEnumSwitch, getSeverityString(MissingEnumConstantCase)); optionsMap.put(OPTION_ReportMissingEnumCaseDespiteDefault, this.reportMissingEnumCaseDespiteDefault ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportMissingDefaultCase, getSeverityString(MissingDefaultCase)); optionsMap.put(OPTION_ReportInvalidJavadoc, getSeverityString(InvalidJavadoc)); optionsMap.put(OPTION_ReportInvalidJavadocTagsVisibility, getVisibilityString(this.reportInvalidJavadocTagsVisibility)); 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); optionsMap.put(OPTION_ReportMissingJavadocTagsMethodTypeParameters, this.reportMissingJavadocTagsMethodTypeParameters ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportMissingJavadocComments, getSeverityString(MissingJavadocComments)); optionsMap.put(OPTION_ReportMissingJavadocTagDescription, this.reportMissingJavadocTagDescription); optionsMap.put(OPTION_ReportMissingJavadocCommentsVisibility, getVisibilityString(this.reportMissingJavadocCommentsVisibility)); optionsMap.put(OPTION_ReportMissingJavadocCommentsOverriding, this.reportMissingJavadocCommentsOverriding ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportFinallyBlockNotCompletingNormally, getSeverityString(FinallyBlockNotCompleting)); optionsMap.put(OPTION_ReportUnusedDeclaredThrownException, getSeverityString(UnusedDeclaredThrownException)); optionsMap.put(OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, this.reportUnusedDeclaredThrownExceptionWhenOverriding ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference, this.reportUnusedDeclaredThrownExceptionIncludeDocCommentReference ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable, this.reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnqualifiedFieldAccess, getSeverityString(UnqualifiedFieldAccess)); optionsMap.put(OPTION_ReportUnavoidableGenericTypeProblems, this.reportUnavoidableGenericTypeProblems ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUncheckedTypeOperation, getSeverityString(UncheckedTypeOperation)); optionsMap.put(OPTION_ReportRawTypeReference, getSeverityString(RawTypeReference)); optionsMap.put(OPTION_ReportFinalParameterBound, getSeverityString(FinalParameterBound)); optionsMap.put(OPTION_ReportMissingSerialVersion, getSeverityString(MissingSerialVersion)); optionsMap.put(OPTION_ReportForbiddenReference, getSeverityString(ForbiddenReference)); optionsMap.put(OPTION_ReportDiscouragedReference, getSeverityString(DiscouragedReference)); optionsMap.put(OPTION_ReportVarargsArgumentNeedCast, getSeverityString(VarargsArgumentNeedCast)); optionsMap.put(OPTION_ReportMissingOverrideAnnotation, getSeverityString(MissingOverrideAnnotation)); optionsMap.put(OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation, this.reportMissingOverrideAnnotationForInterfaceMethodImplementation ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportMissingDeprecatedAnnotation, getSeverityString(MissingDeprecatedAnnotation)); optionsMap.put(OPTION_ReportUnusedLabel, getSeverityString(UnusedLabel)); optionsMap.put(OPTION_ReportUnusedTypeArgumentsForMethodInvocation, getSeverityString(UnusedTypeArguments)); optionsMap.put(OPTION_Compliance, versionFromJdkLevel(this.complianceLevel)); optionsMap.put(OPTION_Source, versionFromJdkLevel(this.sourceLevel)); optionsMap.put(OPTION_TargetPlatform, versionFromJdkLevel(this.targetJDK)); optionsMap.put(OPTION_FatalOptionalError, this.treatOptionalErrorAsFatal ? ENABLED : DISABLED); if (this.defaultEncoding != null) { optionsMap.put(OPTION_Encoding, this.defaultEncoding); } optionsMap.put(OPTION_TaskTags, this.taskTags == null ? Util.EMPTY_STRING : new String(CharOperation.concatWith(this.taskTags,','))); optionsMap.put(OPTION_TaskPriorities, this.taskPriorities == null ? Util.EMPTY_STRING : new String(CharOperation.concatWith(this.taskPriorities,','))); optionsMap.put(OPTION_TaskCaseSensitive, this.isTaskCaseSensitive ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnusedParameterWhenImplementingAbstract, this.reportUnusedParameterWhenImplementingAbstract ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnusedParameterWhenOverridingConcrete, this.reportUnusedParameterWhenOverridingConcrete ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnusedParameterIncludeDocCommentReference, this.reportUnusedParameterIncludeDocCommentReference ? ENABLED : DISABLED); 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_ShareCommonFinallyBlocks, this.shareCommonFinallyBlocks ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportNullReference, getSeverityString(NullReference)); optionsMap.put(OPTION_ReportPotentialNullReference, getSeverityString(PotentialNullReference)); optionsMap.put(OPTION_ReportRedundantNullCheck, getSeverityString(RedundantNullCheck)); optionsMap.put(OPTION_SuppressWarnings, this.suppressWarnings ? ENABLED : DISABLED); optionsMap.put(OPTION_SuppressOptionalErrors, this.suppressOptionalErrors ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnhandledWarningToken, getSeverityString(UnhandledWarningToken)); optionsMap.put(OPTION_ReportUnusedWarningToken, getSeverityString(UnusedWarningToken)); optionsMap.put(OPTION_ReportParameterAssignment, getSeverityString(ParameterAssignment)); optionsMap.put(OPTION_ReportFallthroughCase, getSeverityString(FallthroughCase)); optionsMap.put(OPTION_ReportOverridingMethodWithoutSuperInvocation, getSeverityString(OverridingMethodWithoutSuperInvocation)); optionsMap.put(OPTION_GenerateClassFiles, this.generateClassFiles ? ENABLED : DISABLED); optionsMap.put(OPTION_Process_Annotations, this.processAnnotations ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportRedundantSuperinterface, getSeverityString(RedundantSuperinterface)); optionsMap.put(OPTION_ReportComparingIdentical, getSeverityString(ComparingIdentical)); optionsMap.put(OPTION_ReportMissingSynchronizedOnInheritedMethod, getSeverityString(MissingSynchronizedModifierInInheritedMethod)); optionsMap.put(OPTION_ReportMissingHashCodeMethod, getSeverityString(ShouldImplementHashcode)); optionsMap.put(OPTION_ReportDeadCode, getSeverityString(DeadCode)); optionsMap.put(OPTION_ReportDeadCodeInTrivialIfStatement, this.reportDeadCodeInTrivialIfStatement ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportTasks, getSeverityString(Tasks)); optionsMap.put(OPTION_ReportUnusedObjectAllocation, getSeverityString(UnusedObjectAllocation)); optionsMap.put(OPTION_IncludeNullInfoFromAsserts, this.includeNullInfoFromAsserts ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic)); optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic)); optionsMap.put(OPTION_ReportRedundantSpecificationOfTypeArguments, getSeverityString(RedundantSpecificationOfTypeArguments)); optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable)); optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable)); optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable)); optionsMap.put(OPTION_AnnotationBasedNullAnalysis, this.isAnnotationBasedNullAnalysisEnabled ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportNullSpecViolation, getSeverityString(NullSpecViolation)); optionsMap.put(OPTION_ReportNullAnnotationInferenceConflict, getSeverityString(NullAnnotationInferenceConflict)); optionsMap.put(OPTION_ReportNullUncheckedConversion, getSeverityString(NullUncheckedConversion)); optionsMap.put(OPTION_ReportRedundantNullAnnotation, getSeverityString(RedundantNullAnnotation)); optionsMap.put(OPTION_NullableAnnotationName, String.valueOf(CharOperation.concatWith(this.nullableAnnotationName, '.'))); optionsMap.put(OPTION_NonNullAnnotationName, String.valueOf(CharOperation.concatWith(this.nonNullAnnotationName, '.'))); optionsMap.put(OPTION_NonNullByDefaultAnnotationName, String.valueOf(CharOperation.concatWith(this.nonNullByDefaultAnnotationName, '.'))); optionsMap.put(OPTION_ReportMissingNonNullByDefaultAnnotation, getSeverityString(MissingNonNullByDefaultAnnotation)); optionsMap.put(OPTION_ReportUnusedTypeParameter, getSeverityString(UnusedTypeParameter)); optionsMap.put(OPTION_SyntacticNullAnalysisForFields, this.enableSyntacticNullAnalysisForFields ? ENABLED : DISABLED); optionsMap.put(OPTION_InheritNullAnnotations, this.inheritNullAnnotations ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportNonnullParameterAnnotationDropped, getSeverityString(NonnullParameterAnnotationDropped)); return optionsMap; } public int getSeverity(int irritant) { if (this.errorThreshold.isSet(irritant)) { if ((irritant & (IrritantSet.GROUP_MASK | UnusedWarningToken)) == UnusedWarningToken) { return ProblemSeverities.Error | ProblemSeverities.Optional; // cannot be treated as fatal - codegen already occurred } return this.treatOptionalErrorAsFatal ? ProblemSeverities.Error | ProblemSeverities.Optional | ProblemSeverities.Fatal : ProblemSeverities.Error | ProblemSeverities.Optional; } if (this.warningThreshold.isSet(irritant)) { return ProblemSeverities.Warning | ProblemSeverities.Optional; } return ProblemSeverities.Ignore; } public String getSeverityString(int irritant) { if(this.errorThreshold.isSet(irritant)) return ERROR; if(this.warningThreshold.isSet(irritant)) return WARNING; return IGNORE; } public String getVisibilityString(int level) { switch (level & ExtraCompilerModifiers.AccVisibilityMASK) { case ClassFileConstants.AccPublic: return PUBLIC; case ClassFileConstants.AccProtected: return PROTECTED; case ClassFileConstants.AccPrivate: return PRIVATE; default: return DEFAULT; } } public boolean isAnyEnabled(IrritantSet irritants) { return this.warningThreshold.isAnySet(irritants) || this.errorThreshold.isAnySet(irritants); } protected void resetDefaults() { // problem default severities defined on IrritantSet this.errorThreshold = new IrritantSet(IrritantSet.COMPILER_DEFAULT_ERRORS); this.warningThreshold = new IrritantSet(IrritantSet.COMPILER_DEFAULT_WARNINGS); // by default only lines and source attributes are generated. this.produceDebugAttributes = ClassFileConstants.ATTR_SOURCE | ClassFileConstants.ATTR_LINES; this.complianceLevel = this.originalComplianceLevel = ClassFileConstants.JDK1_4; // by default be compliant with 1.4 this.sourceLevel = this.originalSourceLevel = ClassFileConstants.JDK1_3; //1.3 source behavior by default this.targetJDK = ClassFileConstants.JDK1_2; // default generates for JVM1.2 this.defaultEncoding = null; // will use the platform default encoding // print what unit is being processed this.verbose = Compiler.DEBUG; this.produceReferenceInfo = false; // no reference info by default // indicates if unused/optimizable local variables need to be preserved (debugging purpose) this.preserveAllLocalVariables = false; // indicates whether literal expressions are inlined at parse-time or not this.parseLiteralExpressionsAsConstants = true; // max problems per compilation unit this.maxProblemsPerUnit = 100; // no more than 100 problems per default // tags used to recognize tasks in comments this.taskTags = null; this.taskPriorities = null; this.isTaskCaseSensitive = true; // deprecation report this.reportDeprecationInsideDeprecatedCode = false; this.reportDeprecationWhenOverridingDeprecatedMethod = false; // unused parameters report this.reportUnusedParameterWhenImplementingAbstract = false; this.reportUnusedParameterWhenOverridingConcrete = false; this.reportUnusedParameterIncludeDocCommentReference = true; // unused declaration of thrown exception this.reportUnusedDeclaredThrownExceptionWhenOverriding = false; this.reportUnusedDeclaredThrownExceptionIncludeDocCommentReference = true; this.reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable = true; // constructor/setter parameter hiding this.reportSpecialParameterHidingField = false; this.reportUnavoidableGenericTypeProblems = true; // check javadoc comments tags this.reportInvalidJavadocTagsVisibility = ClassFileConstants.AccPublic; this.reportInvalidJavadocTags = false; this.reportInvalidJavadocTagsDeprecatedRef = false; this.reportInvalidJavadocTagsNotVisibleRef = false; this.reportMissingJavadocTagDescription = RETURN_TAG; // check missing javadoc tags this.reportMissingJavadocTagsVisibility = ClassFileConstants.AccPublic; this.reportMissingJavadocTagsOverriding = false; this.reportMissingJavadocTagsMethodTypeParameters = false; // check missing javadoc comments this.reportMissingJavadocCommentsVisibility = ClassFileConstants.AccPublic; this.reportMissingJavadocCommentsOverriding = false; // JSR bytecode inlining and sharing this.inlineJsrBytecode = false; this.shareCommonFinallyBlocks = false; // javadoc comment support this.docCommentSupport = false; // suppress warning annotation this.suppressWarnings = true; // suppress also optional errors this.suppressOptionalErrors = false; // treat optional error as non fatal this.treatOptionalErrorAsFatal = false; // parser perform statements recovery this.performMethodsFullRecovery = true; // parser perform statements recovery this.performStatementsRecovery = true; // store annotations this.storeAnnotations = false; // annotation processing this.generateClassFiles = true; // enable annotation processing by default only in batch mode this.processAnnotations = false; // disable missing override annotation reporting for interface method implementation this.reportMissingOverrideAnnotationForInterfaceMethodImplementation = true; // dead code detection this.reportDeadCodeInTrivialIfStatement = false; // ignore method bodies this.ignoreMethodBodies = false; this.ignoreSourceFolderWarningOption = false; // allow null info from asserts to be considered downstream by default this.includeNullInfoFromAsserts = false; this.isAnnotationBasedNullAnalysisEnabled = false; this.nullableAnnotationName = DEFAULT_NULLABLE_ANNOTATION_NAME; this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME; this.nonNullByDefaultAnnotationName = DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME; this.intendedDefaultNonNullness = 0; this.enableSyntacticNullAnalysisForFields = false; this.inheritNullAnnotations = false; this.analyseResourceLeaks = true; this.reportMissingEnumCaseDespiteDefault = false; } public void set(Map optionsMap) { Object optionValue; if ((optionValue = optionsMap.get(OPTION_LocalVariableAttribute)) != null) { if (GENERATE.equals(optionValue)) { this.produceDebugAttributes |= ClassFileConstants.ATTR_VARS; } else if (DO_NOT_GENERATE.equals(optionValue)) { this.produceDebugAttributes &= ~ClassFileConstants.ATTR_VARS; } } if ((optionValue = optionsMap.get(OPTION_LineNumberAttribute)) != null) { if (GENERATE.equals(optionValue)) { this.produceDebugAttributes |= ClassFileConstants.ATTR_LINES; } else if (DO_NOT_GENERATE.equals(optionValue)) { this.produceDebugAttributes &= ~ClassFileConstants.ATTR_LINES; } } if ((optionValue = optionsMap.get(OPTION_SourceFileAttribute)) != null) { if (GENERATE.equals(optionValue)) { this.produceDebugAttributes |= ClassFileConstants.ATTR_SOURCE; } else if (DO_NOT_GENERATE.equals(optionValue)) { this.produceDebugAttributes &= ~ClassFileConstants.ATTR_SOURCE; } } if ((optionValue = optionsMap.get(OPTION_PreserveUnusedLocal)) != null) { if (PRESERVE.equals(optionValue)) { this.preserveAllLocalVariables = true; } else if (OPTIMIZE_OUT.equals(optionValue)) { this.preserveAllLocalVariables = false; } } if ((optionValue = optionsMap.get(OPTION_ReportDeprecationInDeprecatedCode)) != null) { if (ENABLED.equals(optionValue)) { this.reportDeprecationInsideDeprecatedCode = true; } else if (DISABLED.equals(optionValue)) { this.reportDeprecationInsideDeprecatedCode = false; } } if ((optionValue = optionsMap.get(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod)) != null) { if (ENABLED.equals(optionValue)) { this.reportDeprecationWhenOverridingDeprecatedMethod = true; } else if (DISABLED.equals(optionValue)) { this.reportDeprecationWhenOverridingDeprecatedMethod = false; } } if ((optionValue = optionsMap.get(OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding)) != null) { if (ENABLED.equals(optionValue)) { this.reportUnusedDeclaredThrownExceptionWhenOverriding = true; } else if (DISABLED.equals(optionValue)) { this.reportUnusedDeclaredThrownExceptionWhenOverriding = false; } } if ((optionValue = optionsMap.get(OPTION_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference)) != null) { if (ENABLED.equals(optionValue)) { this.reportUnusedDeclaredThrownExceptionIncludeDocCommentReference = true; } else if (DISABLED.equals(optionValue)) { this.reportUnusedDeclaredThrownExceptionIncludeDocCommentReference = false; } } if ((optionValue = optionsMap.get(OPTION_ReportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable)) != null) { if (ENABLED.equals(optionValue)) { this.reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable = true; } else if (DISABLED.equals(optionValue)) { this.reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable = false; } } if ((optionValue = optionsMap.get(OPTION_Compliance)) != null) { long level = versionToJdkLevel(optionValue); if (level != 0) this.complianceLevel = this.originalComplianceLevel = level; } if ((optionValue = optionsMap.get(OPTION_Source)) != null) { long level = versionToJdkLevel(optionValue); if (level != 0) this.sourceLevel = this.originalSourceLevel = level; } if ((optionValue = optionsMap.get(OPTION_TargetPlatform)) != null) { long level = versionToJdkLevel(optionValue); if (level != 0) { this.targetJDK = level; } if (this.targetJDK >= ClassFileConstants.JDK1_5) this.inlineJsrBytecode = true; // forced from 1.5 mode on } if ((optionValue = optionsMap.get(OPTION_Encoding)) != null) { if (optionValue instanceof String) { this.defaultEncoding = null; String stringValue = (String) optionValue; if (stringValue.length() > 0){ try { new InputStreamReader(new ByteArrayInputStream(new byte[0]), stringValue); this.defaultEncoding = stringValue; } catch(UnsupportedEncodingException e){ // ignore unsupported encoding } } } } if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameterWhenImplementingAbstract)) != null) { if (ENABLED.equals(optionValue)) { this.reportUnusedParameterWhenImplementingAbstract = true; } else if (DISABLED.equals(optionValue)) { this.reportUnusedParameterWhenImplementingAbstract = false; } } if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameterWhenOverridingConcrete)) != null) { if (ENABLED.equals(optionValue)) { this.reportUnusedParameterWhenOverridingConcrete = true; } else if (DISABLED.equals(optionValue)) { this.reportUnusedParameterWhenOverridingConcrete = false; } } if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameterIncludeDocCommentReference)) != null) { if (ENABLED.equals(optionValue)) { this.reportUnusedParameterIncludeDocCommentReference = true; } else if (DISABLED.equals(optionValue)) { this.reportUnusedParameterIncludeDocCommentReference = false; } } if ((optionValue = optionsMap.get(OPTION_ReportSpecialParameterHidingField)) != null) { if (ENABLED.equals(optionValue)) { this.reportSpecialParameterHidingField = true; } else if (DISABLED.equals(optionValue)) { this.reportSpecialParameterHidingField = false; } } if ((optionValue = optionsMap.get(OPTION_ReportUnavoidableGenericTypeProblems)) != null) { if (ENABLED.equals(optionValue)) { this.reportUnavoidableGenericTypeProblems = true; } else if (DISABLED.equals(optionValue)) { this.reportUnavoidableGenericTypeProblems = false; } } if ((optionValue = optionsMap.get(OPTION_ReportDeadCodeInTrivialIfStatement )) != null) { if (ENABLED.equals(optionValue)) { this.reportDeadCodeInTrivialIfStatement = true; } else if (DISABLED.equals(optionValue)) { this.reportDeadCodeInTrivialIfStatement = false; } } if ((optionValue = optionsMap.get(OPTION_MaxProblemPerUnit)) != null) { if (optionValue instanceof String) { String stringValue = (String) optionValue; try { int val = Integer.parseInt(stringValue); if (val >= 0) this.maxProblemsPerUnit = val; } catch(NumberFormatException e){ // ignore ill-formatted limit } } } if ((optionValue = optionsMap.get(OPTION_TaskTags)) != null) { if (optionValue instanceof String) { String stringValue = (String) optionValue; if (stringValue.length() == 0) { this.taskTags = null; } else { this.taskTags = CharOperation.splitAndTrimOn(',', stringValue.toCharArray()); } } } if ((optionValue = optionsMap.get(OPTION_TaskPriorities)) != null) { if (optionValue instanceof String) { String stringValue = (String) optionValue; if (stringValue.length() == 0) { this.taskPriorities = null; } else { this.taskPriorities = CharOperation.splitAndTrimOn(',', stringValue.toCharArray()); } } } if ((optionValue = optionsMap.get(OPTION_TaskCaseSensitive)) != null) { if (ENABLED.equals(optionValue)) { this.isTaskCaseSensitive = true; } else if (DISABLED.equals(optionValue)) { this.isTaskCaseSensitive = false; } } if ((optionValue = optionsMap.get(OPTION_InlineJsr)) != null) { if (this.targetJDK < ClassFileConstants.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_ShareCommonFinallyBlocks)) != null) { if (ENABLED.equals(optionValue)) { this.shareCommonFinallyBlocks = true; } else if (DISABLED.equals(optionValue)) { this.shareCommonFinallyBlocks = false; } } if ((optionValue = optionsMap.get(OPTION_SuppressWarnings)) != null) { if (ENABLED.equals(optionValue)) { this.suppressWarnings = true; } else if (DISABLED.equals(optionValue)) { this.suppressWarnings = false; } } if ((optionValue = optionsMap.get(OPTION_SuppressOptionalErrors)) != null) { if (ENABLED.equals(optionValue)) { this.suppressOptionalErrors = true; } else if (DISABLED.equals(optionValue)) { this.suppressOptionalErrors = false; } } if ((optionValue = optionsMap.get(OPTION_FatalOptionalError)) != null) { if (ENABLED.equals(optionValue)) { this.treatOptionalErrorAsFatal = true; } else if (DISABLED.equals(optionValue)) { this.treatOptionalErrorAsFatal = false; } } if ((optionValue = optionsMap.get(OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation)) != null) { if (ENABLED.equals(optionValue)) { this.reportMissingOverrideAnnotationForInterfaceMethodImplementation = true; } else if (DISABLED.equals(optionValue)) { this.reportMissingOverrideAnnotationForInterfaceMethodImplementation = false; } } if ((optionValue = optionsMap.get(OPTION_IncludeNullInfoFromAsserts)) != null) { if (ENABLED.equals(optionValue)) { this.includeNullInfoFromAsserts = true; } else if (DISABLED.equals(optionValue)) { this.includeNullInfoFromAsserts = false; } } if ((optionValue = optionsMap.get(OPTION_ReportMethodWithConstructorName)) != null) updateSeverity(MethodWithConstructorName, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportOverridingPackageDefaultMethod)) != null) updateSeverity(OverriddenPackageDefaultMethod, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportDeprecation)) != null) updateSeverity(UsingDeprecatedAPI, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportHiddenCatchBlock)) != null) updateSeverity(MaskedCatchBlock, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedLocal)) != null) updateSeverity(UnusedLocalVariable, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameter)) != null) updateSeverity(UnusedArgument, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedImport)) != null) updateSeverity(UnusedImport, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedPrivateMember)) != null) updateSeverity(UnusedPrivateMember, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedDeclaredThrownException)) != null) updateSeverity(UnusedDeclaredThrownException, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportNoImplicitStringConversion)) != null) updateSeverity(NoImplicitStringConversion, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportSyntheticAccessEmulation)) != null) updateSeverity(AccessEmulation, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportLocalVariableHiding)) != null) updateSeverity(LocalVariableHiding, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportFieldHiding)) != null) updateSeverity(FieldHiding, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportTypeParameterHiding)) != null) updateSeverity(TypeHiding, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportPossibleAccidentalBooleanAssignment)) != null) updateSeverity(AccidentalBooleanAssign, optionValue); 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_ReportUncheckedTypeOperation)) != null) updateSeverity(UncheckedTypeOperation, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportRawTypeReference)) != null) updateSeverity(RawTypeReference, 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_ReportDiscouragedReference)) != null) updateSeverity(DiscouragedReference, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportVarargsArgumentNeedCast)) != null) updateSeverity(VarargsArgumentNeedCast, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportNullReference)) != null) updateSeverity(NullReference, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportPotentialNullReference)) != null) updateSeverity(PotentialNullReference, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportRedundantNullCheck)) != null) updateSeverity(RedundantNullCheck, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportAutoboxing)) != null) updateSeverity(AutoBoxing, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportAnnotationSuperInterface)) != null) updateSeverity(AnnotationSuperInterface, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingOverrideAnnotation)) != null) updateSeverity(MissingOverrideAnnotation, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingDeprecatedAnnotation)) != null) updateSeverity(MissingDeprecatedAnnotation, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportIncompleteEnumSwitch)) != null) updateSeverity(MissingEnumConstantCase, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingEnumCaseDespiteDefault)) != null) { if (ENABLED.equals(optionValue)) { this.reportMissingEnumCaseDespiteDefault = true; } else if (DISABLED.equals(optionValue)) { this.reportMissingEnumCaseDespiteDefault = false; } } if ((optionValue = optionsMap.get(OPTION_ReportMissingDefaultCase)) != null) updateSeverity(MissingDefaultCase, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnhandledWarningToken)) != null) updateSeverity(UnhandledWarningToken, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedWarningToken)) != null) updateSeverity(UnusedWarningToken, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedLabel)) != null) updateSeverity(UnusedLabel, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportParameterAssignment)) != null) updateSeverity(ParameterAssignment, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportFallthroughCase)) != null) updateSeverity(FallthroughCase, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportOverridingMethodWithoutSuperInvocation)) != null) updateSeverity(OverridingMethodWithoutSuperInvocation, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedTypeArgumentsForMethodInvocation)) != null) updateSeverity(UnusedTypeArguments, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportRedundantSuperinterface)) != null) updateSeverity(RedundantSuperinterface, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportComparingIdentical)) != null) updateSeverity(ComparingIdentical, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingSynchronizedOnInheritedMethod)) != null) updateSeverity(MissingSynchronizedModifierInInheritedMethod, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingHashCodeMethod)) != null) updateSeverity(ShouldImplementHashcode, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportDeadCode)) != null) updateSeverity(DeadCode, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportTasks)) != null) updateSeverity(Tasks, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedObjectAllocation)) != null) updateSeverity(UnusedObjectAllocation, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBeStatic)) != null) updateSeverity(MethodCanBeStatic, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBePotentiallyStatic)) != null) updateSeverity(MethodCanBePotentiallyStatic, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportRedundantSpecificationOfTypeArguments)) != null) updateSeverity(RedundantSpecificationOfTypeArguments, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedTypeParameter)) != null) updateSeverity(UnusedTypeParameter, optionValue); if (getSeverity(UnclosedCloseable) == ProblemSeverities.Ignore && getSeverity(PotentiallyUnclosedCloseable) == ProblemSeverities.Ignore && getSeverity(ExplicitlyClosedAutoCloseable) == ProblemSeverities.Ignore) { this.analyseResourceLeaks = false; } else { this.analyseResourceLeaks = true; } if ((optionValue = optionsMap.get(OPTION_AnnotationBasedNullAnalysis)) != null) { this.isAnnotationBasedNullAnalysisEnabled = ENABLED.equals(optionValue); } if (this.isAnnotationBasedNullAnalysisEnabled) { if ((optionValue = optionsMap.get(OPTION_ReportNullSpecViolation)) != null) { if (ERROR.equals(optionValue)) { this.errorThreshold.set(NullSpecViolation); this.warningThreshold.clear(NullSpecViolation); } else if (WARNING.equals(optionValue)) { this.errorThreshold.clear(NullSpecViolation); this.warningThreshold.set(NullSpecViolation); } // "ignore" is not valid for this option } if ((optionValue = optionsMap.get(OPTION_ReportNullAnnotationInferenceConflict)) != null) updateSeverity(NullAnnotationInferenceConflict, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportNullUncheckedConversion)) != null) updateSeverity(NullUncheckedConversion, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportRedundantNullAnnotation)) != null) updateSeverity(RedundantNullAnnotation, optionValue); if ((optionValue = optionsMap.get(OPTION_NullableAnnotationName)) != null) { this.nullableAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray()); } if ((optionValue = optionsMap.get(OPTION_NonNullAnnotationName)) != null) { this.nonNullAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray()); } if ((optionValue = optionsMap.get(OPTION_NonNullByDefaultAnnotationName)) != null) { this.nonNullByDefaultAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray()); } if ((optionValue = optionsMap.get(OPTION_ReportMissingNonNullByDefaultAnnotation)) != null) updateSeverity(MissingNonNullByDefaultAnnotation, optionValue); if ((optionValue = optionsMap.get(OPTION_SyntacticNullAnalysisForFields)) != null) { this.enableSyntacticNullAnalysisForFields = ENABLED.equals(optionValue); } if ((optionValue = optionsMap.get(OPTION_InheritNullAnnotations)) != null) { this.inheritNullAnnotations = ENABLED.equals(optionValue); } if ((optionValue = optionsMap.get(OPTION_ReportNonnullParameterAnnotationDropped)) != null) updateSeverity(NonnullParameterAnnotationDropped, optionValue); } // Javadoc options if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) { if (ENABLED.equals(optionValue)) { this.docCommentSupport = true; } else if (DISABLED.equals(optionValue)) { this.docCommentSupport = false; } } if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadoc)) != null) { updateSeverity(InvalidJavadoc, optionValue); } if ( (optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTagsVisibility)) != null) { if (PUBLIC.equals(optionValue)) { this.reportInvalidJavadocTagsVisibility = ClassFileConstants.AccPublic; } else if (PROTECTED.equals(optionValue)) { this.reportInvalidJavadocTagsVisibility = ClassFileConstants.AccProtected; } else if (DEFAULT.equals(optionValue)) { this.reportInvalidJavadocTagsVisibility = ClassFileConstants.AccDefault; } else if (PRIVATE.equals(optionValue)) { this.reportInvalidJavadocTagsVisibility = ClassFileConstants.AccPrivate; } } if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTags)) != null) { if (ENABLED.equals(optionValue)) { 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); } if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagsVisibility)) != null) { if (PUBLIC.equals(optionValue)) { this.reportMissingJavadocTagsVisibility = ClassFileConstants.AccPublic; } else if (PROTECTED.equals(optionValue)) { this.reportMissingJavadocTagsVisibility = ClassFileConstants.AccProtected; } else if (DEFAULT.equals(optionValue)) { this.reportMissingJavadocTagsVisibility = ClassFileConstants.AccDefault; } else if (PRIVATE.equals(optionValue)) { this.reportMissingJavadocTagsVisibility = ClassFileConstants.AccPrivate; } } if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagsOverriding)) != null) { if (ENABLED.equals(optionValue)) { this.reportMissingJavadocTagsOverriding = true; } else if (DISABLED.equals(optionValue)) { this.reportMissingJavadocTagsOverriding = false; } } if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagsMethodTypeParameters)) != null) { if (ENABLED.equals(optionValue)) { this.reportMissingJavadocTagsMethodTypeParameters = true; } else if (DISABLED.equals(optionValue)) { this.reportMissingJavadocTagsMethodTypeParameters = false; } } if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocComments)) != null) { updateSeverity(MissingJavadocComments, optionValue); } if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagDescription)) != null) { this.reportMissingJavadocTagDescription = (String) optionValue; } if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocCommentsVisibility)) != null) { if (PUBLIC.equals(optionValue)) { this.reportMissingJavadocCommentsVisibility = ClassFileConstants.AccPublic; } else if (PROTECTED.equals(optionValue)) { this.reportMissingJavadocCommentsVisibility = ClassFileConstants.AccProtected; } else if (DEFAULT.equals(optionValue)) { this.reportMissingJavadocCommentsVisibility = ClassFileConstants.AccDefault; } else if (PRIVATE.equals(optionValue)) { this.reportMissingJavadocCommentsVisibility = ClassFileConstants.AccPrivate; } } if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocCommentsOverriding)) != null) { if (ENABLED.equals(optionValue)) { this.reportMissingJavadocCommentsOverriding = true; } else if (DISABLED.equals(optionValue)) { this.reportMissingJavadocCommentsOverriding = false; } } if ((optionValue = optionsMap.get(OPTION_GenerateClassFiles)) != null) { if (ENABLED.equals(optionValue)) { this.generateClassFiles = true; } else if (DISABLED.equals(optionValue)) { this.generateClassFiles = false; } } if ((optionValue = optionsMap.get(OPTION_Process_Annotations)) != null) { if (ENABLED.equals(optionValue)) { this.processAnnotations = true; this.storeAnnotations = true; // annotation processing requires annotation to be stored } else if (DISABLED.equals(optionValue)) { this.processAnnotations = false; this.storeAnnotations = false; } } } public String toString() { StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$ buf.append("\n\t- local variables debug attributes: ").append((this.produceDebugAttributes & ClassFileConstants.ATTR_VARS) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ buf.append("\n\t- line number debug attributes: ").append((this.produceDebugAttributes & ClassFileConstants.ATTR_LINES) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ buf.append("\n\t- source debug attributes: ").append((this.produceDebugAttributes & ClassFileConstants.ATTR_SOURCE) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ buf.append("\n\t- preserve all local variables: ").append(this.preserveAllLocalVariables ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ buf.append("\n\t- method with constructor name: ").append(getSeverityString(MethodWithConstructorName)); //$NON-NLS-1$ buf.append("\n\t- overridden package default method: ").append(getSeverityString(OverriddenPackageDefaultMethod)); //$NON-NLS-1$ buf.append("\n\t- deprecation: ").append(getSeverityString(UsingDeprecatedAPI)); //$NON-NLS-1$ buf.append("\n\t- masked catch block: ").append(getSeverityString(MaskedCatchBlock)); //$NON-NLS-1$ buf.append("\n\t- unused local variable: ").append(getSeverityString(UnusedLocalVariable)); //$NON-NLS-1$ buf.append("\n\t- unused parameter: ").append(getSeverityString(UnusedArgument)); //$NON-NLS-1$ buf.append("\n\t- unused import: ").append(getSeverityString(UnusedImport)); //$NON-NLS-1$ buf.append("\n\t- synthetic access emulation: ").append(getSeverityString(AccessEmulation)); //$NON-NLS-1$ buf.append("\n\t- assignment with no effect: ").append(getSeverityString(NoEffectAssignment)); //$NON-NLS-1$ buf.append("\n\t- non externalized string: ").append(getSeverityString(NonExternalizedString)); //$NON-NLS-1$ buf.append("\n\t- static access receiver: ").append(getSeverityString(NonStaticAccessToStatic)); //$NON-NLS-1$ buf.append("\n\t- indirect static access: ").append(getSeverityString(IndirectStaticAccess)); //$NON-NLS-1$ buf.append("\n\t- incompatible non inherited interface method: ").append(getSeverityString(IncompatibleNonInheritedInterfaceMethod)); //$NON-NLS-1$ buf.append("\n\t- unused private member: ").append(getSeverityString(UnusedPrivateMember)); //$NON-NLS-1$ buf.append("\n\t- local variable hiding another variable: ").append(getSeverityString(LocalVariableHiding)); //$NON-NLS-1$ buf.append("\n\t- field hiding another variable: ").append(getSeverityString(FieldHiding)); //$NON-NLS-1$ buf.append("\n\t- type hiding another type: ").append(getSeverityString(TypeHiding)); //$NON-NLS-1$ buf.append("\n\t- possible accidental boolean assignment: ").append(getSeverityString(AccidentalBooleanAssign)); //$NON-NLS-1$ buf.append("\n\t- superfluous semicolon: ").append(getSeverityString(EmptyStatement)); //$NON-NLS-1$ buf.append("\n\t- uncommented empty block: ").append(getSeverityString(UndocumentedEmptyBlock)); //$NON-NLS-1$ buf.append("\n\t- unnecessary type check: ").append(getSeverityString(UnnecessaryTypeCheck)); //$NON-NLS-1$ 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 visible 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$ buf.append("\n\t\t+ report missing javadoc tags for method type parameters: ").append(this.reportMissingJavadocTagsMethodTypeParameters ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t\t+ report missing javadoc tags in overriding methods: ").append(this.reportMissingJavadocTagsOverriding ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t\t+ missing javadoc comments: ").append(getSeverityString(MissingJavadocComments)); //$NON-NLS-1$ buf.append("\n\t\t+ report missing tag description option: ").append(this.reportMissingJavadocTagDescription); //$NON-NLS-1$ buf.append("\n\t\t+ visibility level to report missing javadoc comments: ").append(getVisibilityString(this.reportMissingJavadocCommentsVisibility)); //$NON-NLS-1$ buf.append("\n\t\t+ report missing javadoc comments in overriding methods: ").append(this.reportMissingJavadocCommentsOverriding ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- finally block not completing normally: ").append(getSeverityString(FinallyBlockNotCompleting)); //$NON-NLS-1$ buf.append("\n\t- report unused declared thrown exception: ").append(getSeverityString(UnusedDeclaredThrownException)); //$NON-NLS-1$ buf.append("\n\t- report unused declared thrown exception when overriding: ").append(this.reportUnusedDeclaredThrownExceptionWhenOverriding ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- report unused declared thrown exception include doc comment reference: ").append(this.reportUnusedDeclaredThrownExceptionIncludeDocCommentReference ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- report unused declared thrown exception exempt exception and throwable: ").append(this.reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- unnecessary else: ").append(getSeverityString(UnnecessaryElse)); //$NON-NLS-1$ buf.append("\n\t- JDK compliance level: "+ versionFromJdkLevel(this.complianceLevel)); //$NON-NLS-1$ buf.append("\n\t- JDK source level: "+ versionFromJdkLevel(this.sourceLevel)); //$NON-NLS-1$ buf.append("\n\t- JDK target level: "+ versionFromJdkLevel(this.targetJDK)); //$NON-NLS-1$ buf.append("\n\t- verbose : ").append(this.verbose ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ buf.append("\n\t- produce reference info : ").append(this.produceReferenceInfo ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ buf.append("\n\t- parse literal expressions as constants : ").append(this.parseLiteralExpressionsAsConstants ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ buf.append("\n\t- encoding : ").append(this.defaultEncoding == null ? "" : this.defaultEncoding); //$NON-NLS-1$ //$NON-NLS-2$ buf.append("\n\t- task tags: ").append(this.taskTags == null ? Util.EMPTY_STRING : new String(CharOperation.concatWith(this.taskTags,','))); //$NON-NLS-1$ buf.append("\n\t- task priorities : ").append(this.taskPriorities == null ? Util.EMPTY_STRING : new String(CharOperation.concatWith(this.taskPriorities,','))); //$NON-NLS-1$ buf.append("\n\t- report deprecation inside deprecated code : ").append(this.reportDeprecationInsideDeprecatedCode ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- report deprecation when overriding deprecated method : ").append(this.reportDeprecationWhenOverridingDeprecatedMethod ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- report unused parameter when implementing abstract method : ").append(this.reportUnusedParameterWhenImplementingAbstract ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- report unused parameter when overriding concrete method : ").append(this.reportUnusedParameterWhenOverridingConcrete ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- report unused parameter include doc comment reference : ").append(this.reportUnusedParameterIncludeDocCommentReference ? 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- share common finally blocks : ").append(this.shareCommonFinallyBlocks ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- report unavoidable generic type problems : ").append(this.reportUnavoidableGenericTypeProblems ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- unsafe type operation: ").append(getSeverityString(UncheckedTypeOperation)); //$NON-NLS-1$ buf.append("\n\t- unsafe raw type: ").append(getSeverityString(RawTypeReference)); //$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- discouraged reference to type with access restriction: ").append(getSeverityString(DiscouragedReference)); //$NON-NLS-1$ buf.append("\n\t- null reference: ").append(getSeverityString(NullReference)); //$NON-NLS-1$ buf.append("\n\t- potential null reference: ").append(getSeverityString(PotentialNullReference)); //$NON-NLS-1$ buf.append("\n\t- redundant null check: ").append(getSeverityString(RedundantNullCheck)); //$NON-NLS-1$ buf.append("\n\t- autoboxing: ").append(getSeverityString(AutoBoxing)); //$NON-NLS-1$ buf.append("\n\t- annotation super interface: ").append(getSeverityString(AnnotationSuperInterface)); //$NON-NLS-1$ buf.append("\n\t- missing @Override annotation: ").append(getSeverityString(MissingOverrideAnnotation)); //$NON-NLS-1$ buf.append("\n\t- missing @Override annotation for interface method implementation: ").append(this.reportMissingOverrideAnnotationForInterfaceMethodImplementation ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- missing @Deprecated annotation: ").append(getSeverityString(MissingDeprecatedAnnotation)); //$NON-NLS-1$ buf.append("\n\t- incomplete enum switch: ").append(getSeverityString(MissingEnumConstantCase)); //$NON-NLS-1$ buf.append("\n\t- raise null related warnings for variables tainted in assert statements: ").append(this.includeNullInfoFromAsserts ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- suppress warnings: ").append(this.suppressWarnings ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- suppress optional errors: ").append(this.suppressOptionalErrors ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- unhandled warning token: ").append(getSeverityString(UnhandledWarningToken)); //$NON-NLS-1$ buf.append("\n\t- unused warning token: ").append(getSeverityString(UnusedWarningToken)); //$NON-NLS-1$ buf.append("\n\t- unused label: ").append(getSeverityString(UnusedLabel)); //$NON-NLS-1$ buf.append("\n\t- treat optional error as fatal: ").append(this.treatOptionalErrorAsFatal ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- parameter assignment: ").append(getSeverityString(ParameterAssignment)); //$NON-NLS-1$ buf.append("\n\t- generate class files: ").append(this.generateClassFiles ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- process annotations: ").append(this.processAnnotations ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- unused type arguments for method/constructor invocation: ").append(getSeverityString(UnusedTypeArguments)); //$NON-NLS-1$ buf.append("\n\t- redundant superinterface: ").append(getSeverityString(RedundantSuperinterface)); //$NON-NLS-1$ buf.append("\n\t- comparing identical expr: ").append(getSeverityString(ComparingIdentical)); //$NON-NLS-1$ buf.append("\n\t- missing synchronized on inherited method: ").append(getSeverityString(MissingSynchronizedModifierInInheritedMethod)); //$NON-NLS-1$ buf.append("\n\t- should implement hashCode() method: ").append(getSeverityString(ShouldImplementHashcode)); //$NON-NLS-1$ buf.append("\n\t- dead code: ").append(getSeverityString(DeadCode)); //$NON-NLS-1$ buf.append("\n\t- dead code in trivial if statement: ").append(this.reportDeadCodeInTrivialIfStatement ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- tasks severity: ").append(getSeverityString(Tasks)); //$NON-NLS-1$ buf.append("\n\t- unused object allocation: ").append(getSeverityString(UnusedObjectAllocation)); //$NON-NLS-1$ buf.append("\n\t- method can be static: ").append(getSeverityString(MethodCanBeStatic)); //$NON-NLS-1$ buf.append("\n\t- method can be potentially static: ").append(getSeverityString(MethodCanBePotentiallyStatic)); //$NON-NLS-1$ buf.append("\n\t- redundant specification of type arguments: ").append(getSeverityString(RedundantSpecificationOfTypeArguments)); //$NON-NLS-1$ buf.append("\n\t- resource is not closed: ").append(getSeverityString(UnclosedCloseable)); //$NON-NLS-1$ buf.append("\n\t- resource may not be closed: ").append(getSeverityString(PotentiallyUnclosedCloseable)); //$NON-NLS-1$ buf.append("\n\t- resource should be handled by try-with-resources: ").append(getSeverityString(ExplicitlyClosedAutoCloseable)); //$NON-NLS-1$ buf.append("\n\t- Unused Type Parameter: ").append(getSeverityString(UnusedTypeParameter)); //$NON-NLS-1$ return buf.toString(); } protected void updateSeverity(int irritant, Object severityString) { if (ERROR.equals(severityString)) { this.errorThreshold.set(irritant); this.warningThreshold.clear(irritant); } else if (WARNING.equals(severityString)) { this.errorThreshold.clear(irritant); this.warningThreshold.set(irritant); } else if (IGNORE.equals(severityString)) { this.errorThreshold.clear(irritant); this.warningThreshold.clear(irritant); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java0000644000175000001440000000363112212041344031015 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class DoubleConstant extends Constant { private double value; public static Constant fromValue(double value) { return new DoubleConstant(value); } private DoubleConstant(double value) { this.value = value; } public byte byteValue() { return (byte) this.value; } public char charValue() { return (char) this.value; } public double doubleValue() { return this.value; } public float floatValue() { return (float) this.value; } public int intValue() { return (int) this.value; } public long longValue() { return (long) this.value; } public short shortValue() { return (short) this.value; } public String stringValue() { return String.valueOf(this.value); } public String toString() { if (this == NotAConstant) return "(Constant) NotAConstant"; //$NON-NLS-1$ return "(double)" + this.value; //$NON-NLS-1$ } public int typeID() { return T_double; } public int hashCode() { long temp = Double.doubleToLongBits(this.value); return (int) (temp ^ (temp >>> 32)); } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } DoubleConstant other = (DoubleConstant) obj; return Double.doubleToLongBits(this.value) == Double.doubleToLongBits(other.value); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java0000644000175000001440000000350012212041344030675 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class ShortConstant extends Constant { private short value; public static Constant fromValue(short value) { return new ShortConstant(value); } private ShortConstant(short value) { this.value = value; } public byte byteValue() { return (byte) this.value; } public char charValue() { return (char) this.value; } public double doubleValue() { return this.value; // implicit cast to return type } public float floatValue() { return this.value; // implicit cast to return type } public int intValue() { return this.value; // implicit cast to return type } public long longValue() { return this.value; // implicit cast to return type } public short shortValue() { return this.value; } public String stringValue() { // spec 15.17.11 return String.valueOf(this.value); } public String toString() { return "(short)" + this.value; //$NON-NLS-1$ } public int typeID() { return T_short; } public int hashCode() { return this.value; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ShortConstant other = (ShortConstant) obj; return this.value == other.value; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/CharConstant.java0000644000175000001440000000346512212041344030465 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class CharConstant extends Constant { private char value; public static Constant fromValue(char value) { return new CharConstant(value); } private CharConstant(char value) { this.value = value; } public byte byteValue() { return (byte) this.value; } public char charValue() { return this.value; } public double doubleValue() { return this.value; // implicit cast to return type } public float floatValue() { return this.value; // implicit cast to return type } public int intValue() { return this.value; // implicit cast to return type } public long longValue() { return this.value; // implicit cast to return type } public short shortValue() { return (short) this.value; } public String stringValue() { // spec 15.17.11 return String.valueOf(this.value); } public String toString() { return "(char)" + this.value; //$NON-NLS-1$ } public int typeID() { return T_char; } public int hashCode() { return this.value; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } CharConstant other = (CharConstant) obj; return this.value == other.value; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/Constant.java0000644000175000001440000025402712212041344027671 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement; import org.eclipse.jdt.internal.compiler.util.Messages; public abstract class Constant implements TypeIds, OperatorIds { public static final Constant NotAConstant = DoubleConstant.fromValue(Double.NaN); public boolean booleanValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotCastedInto, new String[] { typeName(), "boolean" })); //$NON-NLS-1$ } public byte byteValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotCastedInto, new String[] { typeName(), "byte" })); //$NON-NLS-1$ } public final Constant castTo(int conversionToTargetType){ //the cast is an int of the form // (castId<<4)+typeId (in order to follow the //user written style (cast)expression .... if (this == NotAConstant) return NotAConstant; switch(conversionToTargetType){ case T_undefined : return this; // TARGET TYPE <- FROM TYPE // case (T_undefined<<4)+T_undefined : return NotAConstant; // case (T_undefined<<4)+T_byte : return NotAConstant; // case (T_undefined<<4)+T_long : return NotAConstant; // case (T_undefined<<4)+T_short : return NotAConstant; // case (T_undefined<<4)+T_void : return NotAConstant; // case (T_undefined<<4)+T_String : return NotAConstant; // case (T_undefined<<4)+T_Object : return NotAConstant; // case (T_undefined<<4)+T_double : return NotAConstant; // case (T_undefined<<4)+T_float : return NotAConstant; // case (T_undefined<<4)+T_boolean : return NotAConstant; // case (T_undefined<<4)+T_char : return NotAConstant; // case (T_undefined<<4)+T_int : return NotAConstant; // case (T_byte<<4)+T_undefined : return NotAConstant; case (T_byte<<4)+T_byte : return this; case (T_byte<<4)+T_long : return ByteConstant.fromValue((byte)longValue()); case (T_byte<<4)+T_short : return ByteConstant.fromValue((byte)shortValue()); // case (T_byte<<4)+T_void : return NotAConstant; // case (T_byte<<4)+T_String : return NotAConstant; // case (T_byte<<4)+T_Object : return NotAConstant; case (T_byte<<4)+T_double : return ByteConstant.fromValue((byte)doubleValue()); case (T_byte<<4)+T_float : return ByteConstant.fromValue((byte)floatValue()); // case (T_byte<<4)+T_boolean : return NotAConstant; case (T_byte<<4)+T_char : return ByteConstant.fromValue((byte)charValue()); case (T_byte<<4)+T_int : return ByteConstant.fromValue((byte)intValue()); // case (T_long<<4)+T_undefined : return NotAConstant; case (T_long<<4)+T_byte : return LongConstant.fromValue(byteValue()); case (T_long<<4)+T_long : return this; case (T_long<<4)+T_short : return LongConstant.fromValue(shortValue()); // case (T_long<<4)+T_void : return NotAConstant; // case (T_long<<4)+T_String : return NotAConstant; // case (T_long<<4)+T_Object : return NotAConstant; case (T_long<<4)+T_double : return LongConstant.fromValue((long)doubleValue()); case (T_long<<4)+T_float : return LongConstant.fromValue((long)floatValue()); // case (T_long<<4)+T_boolean : return NotAConstant; case (T_long<<4)+T_char : return LongConstant.fromValue(charValue()); case (T_long<<4)+T_int : return LongConstant.fromValue(intValue()); // case (T_short<<4)+T_undefined : return NotAConstant; case (T_short<<4)+T_byte : return ShortConstant.fromValue(byteValue()); case (T_short<<4)+T_long : return ShortConstant.fromValue((short)longValue()); case (T_short<<4)+T_short : return this; // case (T_short<<4)+T_void : return NotAConstant; // case (T_short<<4)+T_String : return NotAConstant; // case (T_short<<4)+T_Object : return NotAConstant; case (T_short<<4)+T_double : return ShortConstant.fromValue((short)doubleValue()); case (T_short<<4)+T_float : return ShortConstant.fromValue((short)floatValue()); // case (T_short<<4)+T_boolean : return NotAConstant; case (T_short<<4)+T_char : return ShortConstant.fromValue((short)charValue()); case (T_short<<4)+T_int : return ShortConstant.fromValue((short)intValue()); // case (T_void<<4)+T_undefined : return NotAConstant; // case (T_void<<4)+T_byte : return NotAConstant; // case (T_void<<4)+T_long : return NotAConstant; // case (T_void<<4)+T_short : return NotAConstant; // case (T_void<<4)+T_void : return NotAConstant; // case (T_void<<4)+T_String : return NotAConstant; // case (T_void<<4)+T_Object : return NotAConstant; // case (T_void<<4)+T_double : return NotAConstant; // case (T_void<<4)+T_float : return NotAConstant; // case (T_void<<4)+T_boolean : return NotAConstant; // case (T_void<<4)+T_char : return NotAConstant; // case (T_void<<4)+T_int : return NotAConstant; // case (T_String<<4)+T_undefined : return NotAConstant; // case (T_String<<4)+T_byte : return NotAConstant; // 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_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; // case (T_String<<4)+T_boolean : return NotAConstant; // case (T_String<<4)+T_char : return NotAConstant; // case (T_String<<4)+T_int : return NotAConstant; // case (T_Object<<4)+T_undefined : return NotAConstant; // case (T_Object<<4)+T_byte : return NotAConstant; // case (T_Object<<4)+T_long : return NotAConstant; // case (T_Object<<4)+T_short : return NotAConstant; // case (T_Object<<4)+T_void : return NotAConstant; // case (T_Object<<4)+T_String : return NotAConstant; // case (T_Object<<4)+T_Object : return NotAConstant; // case (T_Object<<4)+T_double : return NotAConstant; // case (T_Object<<4)+T_float : return NotAConstant; // case (T_Object<<4)+T_boolean : return NotAConstant; // case (T_Object<<4)+T_char : return NotAConstant; // case (T_Object<<4)+T_int : return NotAConstant; // case (T_double<<4)+T_undefined : return NotAConstant; case (T_double<<4)+T_byte : return DoubleConstant.fromValue(byteValue()); case (T_double<<4)+T_long : return DoubleConstant.fromValue(longValue()); case (T_double<<4)+T_short : return DoubleConstant.fromValue(shortValue()); // case (T_double<<4)+T_void : return NotAConstant; // case (T_double<<4)+T_String : return NotAConstant; // case (T_double<<4)+T_Object : return NotAConstant; case (T_double<<4)+T_double : return this; case (T_double<<4)+T_float : return DoubleConstant.fromValue(floatValue()); // case (T_double<<4)+T_boolean : return NotAConstant; case (T_double<<4)+T_char : return DoubleConstant.fromValue(charValue()); case (T_double<<4)+T_int : return DoubleConstant.fromValue(intValue()); // case (T_float<<4)+T_undefined : return NotAConstant; case (T_float<<4)+T_byte : return FloatConstant.fromValue(byteValue()); case (T_float<<4)+T_long : return FloatConstant.fromValue(longValue()); case (T_float<<4)+T_short : return FloatConstant.fromValue(shortValue()); // case (T_float<<4)+T_void : return NotAConstant; // case (T_float<<4)+T_String : return NotAConstant; // case (T_float<<4)+T_Object : return NotAConstant; case (T_float<<4)+T_double : return FloatConstant.fromValue((float)doubleValue()); case (T_float<<4)+T_float : return this; // case (T_float<<4)+T_boolean : return NotAConstant; case (T_float<<4)+T_char : return FloatConstant.fromValue(charValue()); case (T_float<<4)+T_int : return FloatConstant.fromValue(intValue()); // case (T_boolean<<4)+T_undefined : return NotAConstant; // case (T_boolean<<4)+T_byte : return NotAConstant; // case (T_boolean<<4)+T_long : return NotAConstant; // case (T_boolean<<4)+T_short : return NotAConstant; // case (T_boolean<<4)+T_void : return NotAConstant; // case (T_boolean<<4)+T_String : return NotAConstant; // case (T_boolean<<4)+T_Object : return NotAConstant; // case (T_boolean<<4)+T_double : return NotAConstant; // case (T_boolean<<4)+T_float : return NotAConstant; case (T_boolean<<4)+T_boolean : return this; // case (T_boolean<<4)+T_char : return NotAConstant; // case (T_boolean<<4)+T_int : return NotAConstant; // case (T_char<<4)+T_undefined : return NotAConstant; case (T_char<<4)+T_byte : return CharConstant.fromValue((char)byteValue()); case (T_char<<4)+T_long : return CharConstant.fromValue((char)longValue()); case (T_char<<4)+T_short : return CharConstant.fromValue((char)shortValue()); // case (T_char<<4)+T_void : return NotAConstant; // case (T_char<<4)+T_String : return NotAConstant; // case (T_char<<4)+T_Object : return NotAConstant; case (T_char<<4)+T_double : return CharConstant.fromValue((char)doubleValue()); case (T_char<<4)+T_float : return CharConstant.fromValue((char)floatValue()); // case (T_char<<4)+T_boolean : return NotAConstant; case (T_char<<4)+T_char : return this; case (T_char<<4)+T_int : return CharConstant.fromValue((char)intValue()); // case (T_int<<4)+T_undefined : return NotAConstant; case (T_int<<4)+T_byte : return IntConstant.fromValue(byteValue()); case (T_int<<4)+T_long : return IntConstant.fromValue((int) longValue()); case (T_int<<4)+T_short : return IntConstant.fromValue(shortValue()); // case (T_int<<4)+T_void : return NotAConstant; // case (T_int<<4)+T_String : return NotAConstant; // case (T_int<<4)+T_Object : return NotAConstant; case (T_int<<4)+T_double : return IntConstant.fromValue((int) doubleValue()); case (T_int<<4)+T_float : return IntConstant.fromValue((int) floatValue()); // case (T_int<<4)+T_boolean : return NotAConstant; case (T_int<<4)+T_char : return IntConstant.fromValue(charValue()); case (T_int<<4)+T_int : return this; } return NotAConstant; } public char charValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotCastedInto, new String[] { typeName(), "char" })); //$NON-NLS-1$ } public static final Constant computeConstantOperation(Constant cst, int id, int operator) { switch (operator) { case NOT : return BooleanConstant.fromValue(!cst.booleanValue()); case PLUS : return computeConstantOperationPLUS(IntConstant.fromValue(0),T_int,cst,id); case MINUS : //the two special -9223372036854775808L and -2147483648 are inlined at parseTime switch (id){ case T_float : float f; if ( (f= cst.floatValue()) == 0.0f) { //positive and negative 0.... if (Float.floatToIntBits(f) == 0) return FloatConstant.fromValue(-0.0f); else return FloatConstant.fromValue(0.0f);} break; //default case case T_double : double d; if ( (d= cst.doubleValue()) == 0.0d) { //positive and negative 0.... if (Double.doubleToLongBits(d) == 0) return DoubleConstant.fromValue(-0.0d); else return DoubleConstant.fromValue(0.0d);} break; //default case } return computeConstantOperationMINUS(IntConstant.fromValue(0),T_int,cst,id); case TWIDDLE: switch (id){ case T_char : return IntConstant.fromValue(~ cst.charValue()); case T_byte: return IntConstant.fromValue(~ cst.byteValue()); case T_short: return IntConstant.fromValue(~ cst.shortValue()); case T_int: return IntConstant.fromValue(~ cst.intValue()); case T_long: return LongConstant.fromValue(~ cst.longValue()); default : return NotAConstant; } default : return NotAConstant; } } public static final Constant computeConstantOperation(Constant left, int leftId, int operator, Constant right, int rightId) { switch (operator) { 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, Constant right, int rightId) { switch (leftId){ case T_boolean : return BooleanConstant.fromValue(left.booleanValue() & right.booleanValue()); case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() & right.charValue()); case T_byte: return IntConstant.fromValue(left.charValue() & right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() & right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() & right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() & right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() & right.charValue()); case T_byte: return IntConstant.fromValue(left.byteValue() & right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() & right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() & right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() & right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() & right.charValue()); case T_byte: return IntConstant.fromValue(left.shortValue() & right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() & right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() & right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() & right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() & right.charValue()); case T_byte: return IntConstant.fromValue(left.intValue() & right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() & right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() & right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() & right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() & right.charValue()); case T_byte: return LongConstant.fromValue(left.longValue() & right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() & right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() & right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() & right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationAND_AND(Constant left, int leftId, Constant right, int rightId) { return BooleanConstant.fromValue(left.booleanValue() && right.booleanValue()); } 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){ case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() / right.charValue()); case T_float: return FloatConstant.fromValue(left.charValue() / right.floatValue()); case T_double: return DoubleConstant.fromValue(left.charValue() / right.doubleValue()); case T_byte: return IntConstant.fromValue(left.charValue() / right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() / right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() / right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() / right.longValue()); } break; case T_float : switch (rightId){ case T_char : return FloatConstant.fromValue(left.floatValue() / right.charValue()); case T_float: return FloatConstant.fromValue(left.floatValue() / right.floatValue()); case T_double: return DoubleConstant.fromValue(left.floatValue() / right.doubleValue()); case T_byte: return FloatConstant.fromValue(left.floatValue() / right.byteValue()); case T_short: return FloatConstant.fromValue(left.floatValue() / right.shortValue()); case T_int: return FloatConstant.fromValue(left.floatValue() / right.intValue()); case T_long: return FloatConstant.fromValue(left.floatValue() / right.longValue()); } break; case T_double : switch (rightId){ case T_char : return DoubleConstant.fromValue(left.doubleValue() / right.charValue()); case T_float: return DoubleConstant.fromValue(left.doubleValue() / right.floatValue()); case T_double: return DoubleConstant.fromValue(left.doubleValue() / right.doubleValue()); case T_byte: return DoubleConstant.fromValue(left.doubleValue() / right.byteValue()); case T_short: return DoubleConstant.fromValue(left.doubleValue() / right.shortValue()); case T_int: return DoubleConstant.fromValue(left.doubleValue() / right.intValue()); case T_long: return DoubleConstant.fromValue(left.doubleValue() / right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() / right.charValue()); case T_float: return FloatConstant.fromValue(left.byteValue() / right.floatValue()); case T_double: return DoubleConstant.fromValue(left.byteValue() / right.doubleValue()); case T_byte: return IntConstant.fromValue(left.byteValue() / right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() / right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() / right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() / right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() / right.charValue()); case T_float: return FloatConstant.fromValue(left.shortValue() / right.floatValue()); case T_double: return DoubleConstant.fromValue(left.shortValue() / right.doubleValue()); case T_byte: return IntConstant.fromValue(left.shortValue() / right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() / right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() / right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() / right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() / right.charValue()); case T_float: return FloatConstant.fromValue(left.intValue() / right.floatValue()); case T_double: return DoubleConstant.fromValue(left.intValue() / right.doubleValue()); case T_byte: return IntConstant.fromValue(left.intValue() / right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() / right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() / right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() / right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() / right.charValue()); case T_float: return FloatConstant.fromValue(left.longValue() / right.floatValue()); case T_double: return DoubleConstant.fromValue(left.longValue() / right.doubleValue()); case T_byte: return LongConstant.fromValue(left.longValue() / right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() / right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() / right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() / right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationEQUAL_EQUAL(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_boolean : if (rightId == T_boolean) { return BooleanConstant.fromValue(left.booleanValue() == right.booleanValue()); } break; case T_char : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.charValue() == right.charValue()); case T_float: return BooleanConstant.fromValue(left.charValue() == right.floatValue()); case T_double: return BooleanConstant.fromValue(left.charValue() == right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.charValue() == right.byteValue()); case T_short: return BooleanConstant.fromValue(left.charValue() == right.shortValue()); case T_int: return BooleanConstant.fromValue(left.charValue() == right.intValue()); case T_long: return BooleanConstant.fromValue(left.charValue() == right.longValue());} break; case T_float : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.floatValue() == right.charValue()); case T_float: return BooleanConstant.fromValue(left.floatValue() == right.floatValue()); case T_double: return BooleanConstant.fromValue(left.floatValue() == right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.floatValue() == right.byteValue()); case T_short: return BooleanConstant.fromValue(left.floatValue() == right.shortValue()); case T_int: return BooleanConstant.fromValue(left.floatValue() == right.intValue()); case T_long: return BooleanConstant.fromValue(left.floatValue() == right.longValue()); } break; case T_double : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.doubleValue() == right.charValue()); case T_float: return BooleanConstant.fromValue(left.doubleValue() == right.floatValue()); case T_double: return BooleanConstant.fromValue(left.doubleValue() == right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.doubleValue() == right.byteValue()); case T_short: return BooleanConstant.fromValue(left.doubleValue() == right.shortValue()); case T_int: return BooleanConstant.fromValue(left.doubleValue() == right.intValue()); case T_long: return BooleanConstant.fromValue(left.doubleValue() == right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.byteValue() == right.charValue()); case T_float: return BooleanConstant.fromValue(left.byteValue() == right.floatValue()); case T_double: return BooleanConstant.fromValue(left.byteValue() == right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.byteValue() == right.byteValue()); case T_short: return BooleanConstant.fromValue(left.byteValue() == right.shortValue()); case T_int: return BooleanConstant.fromValue(left.byteValue() == right.intValue()); case T_long: return BooleanConstant.fromValue(left.byteValue() == right.longValue()); } break; case T_short : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.shortValue() == right.charValue()); case T_float: return BooleanConstant.fromValue(left.shortValue() == right.floatValue()); case T_double: return BooleanConstant.fromValue(left.shortValue() == right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.shortValue() == right.byteValue()); case T_short: return BooleanConstant.fromValue(left.shortValue() == right.shortValue()); case T_int: return BooleanConstant.fromValue(left.shortValue() == right.intValue()); case T_long: return BooleanConstant.fromValue(left.shortValue() == right.longValue()); } break; case T_int : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.intValue() == right.charValue()); case T_float: return BooleanConstant.fromValue(left.intValue() == right.floatValue()); case T_double: return BooleanConstant.fromValue(left.intValue() == right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.intValue() == right.byteValue()); case T_short: return BooleanConstant.fromValue(left.intValue() == right.shortValue()); case T_int: return BooleanConstant.fromValue(left.intValue() == right.intValue()); case T_long: return BooleanConstant.fromValue(left.intValue() == right.longValue()); } break; case T_long : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.longValue() == right.charValue()); case T_float: return BooleanConstant.fromValue(left.longValue() == right.floatValue()); case T_double: return BooleanConstant.fromValue(left.longValue() == right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.longValue() == right.byteValue()); case T_short: return BooleanConstant.fromValue(left.longValue() == right.shortValue()); case T_int: return BooleanConstant.fromValue(left.longValue() == right.intValue()); case T_long: return BooleanConstant.fromValue(left.longValue() == right.longValue()); } break; 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 BooleanConstant.fromValue(((StringConstant)left).hasSameValue(right)); } break; case T_null : if (rightId == T_JavaLangString) { return BooleanConstant.fromValue(false); } else { if (rightId == T_null) { return BooleanConstant.fromValue(true); } } } return BooleanConstant.fromValue(false); } public static final Constant computeConstantOperationGREATER(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.charValue() > right.charValue()); case T_float: return BooleanConstant.fromValue(left.charValue() > right.floatValue()); case T_double: return BooleanConstant.fromValue(left.charValue() > right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.charValue() > right.byteValue()); case T_short: return BooleanConstant.fromValue(left.charValue() > right.shortValue()); case T_int: return BooleanConstant.fromValue(left.charValue() > right.intValue()); case T_long: return BooleanConstant.fromValue(left.charValue() > right.longValue()); } break; case T_float : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.floatValue() > right.charValue()); case T_float: return BooleanConstant.fromValue(left.floatValue() > right.floatValue()); case T_double: return BooleanConstant.fromValue(left.floatValue() > right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.floatValue() > right.byteValue()); case T_short: return BooleanConstant.fromValue(left.floatValue() > right.shortValue()); case T_int: return BooleanConstant.fromValue(left.floatValue() > right.intValue()); case T_long: return BooleanConstant.fromValue(left.floatValue() > right.longValue()); } break; case T_double : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.doubleValue() > right.charValue()); case T_float: return BooleanConstant.fromValue(left.doubleValue() > right.floatValue()); case T_double: return BooleanConstant.fromValue(left.doubleValue() > right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.doubleValue() > right.byteValue()); case T_short: return BooleanConstant.fromValue(left.doubleValue() > right.shortValue()); case T_int: return BooleanConstant.fromValue(left.doubleValue() > right.intValue()); case T_long: return BooleanConstant.fromValue(left.doubleValue() > right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.byteValue() > right.charValue()); case T_float: return BooleanConstant.fromValue(left.byteValue() > right.floatValue()); case T_double: return BooleanConstant.fromValue(left.byteValue() > right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.byteValue() > right.byteValue()); case T_short: return BooleanConstant.fromValue(left.byteValue() > right.shortValue()); case T_int: return BooleanConstant.fromValue(left.byteValue() > right.intValue()); case T_long: return BooleanConstant.fromValue(left.byteValue() > right.longValue()); } break; case T_short : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.shortValue() > right.charValue()); case T_float: return BooleanConstant.fromValue(left.shortValue() > right.floatValue()); case T_double: return BooleanConstant.fromValue(left.shortValue() > right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.shortValue() > right.byteValue()); case T_short: return BooleanConstant.fromValue(left.shortValue() > right.shortValue()); case T_int: return BooleanConstant.fromValue(left.shortValue() > right.intValue()); case T_long: return BooleanConstant.fromValue(left.shortValue() > right.longValue()); } break; case T_int : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.intValue() > right.charValue()); case T_float: return BooleanConstant.fromValue(left.intValue() > right.floatValue()); case T_double: return BooleanConstant.fromValue(left.intValue() > right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.intValue() > right.byteValue()); case T_short: return BooleanConstant.fromValue(left.intValue() > right.shortValue()); case T_int: return BooleanConstant.fromValue(left.intValue() > right.intValue()); case T_long: return BooleanConstant.fromValue(left.intValue() > right.longValue()); } break; case T_long : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.longValue() > right.charValue()); case T_float: return BooleanConstant.fromValue(left.longValue() > right.floatValue()); case T_double: return BooleanConstant.fromValue(left.longValue() > right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.longValue() > right.byteValue()); case T_short: return BooleanConstant.fromValue(left.longValue() > right.shortValue()); case T_int: return BooleanConstant.fromValue(left.longValue() > right.intValue()); case T_long: return BooleanConstant.fromValue(left.longValue() > right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationGREATER_EQUAL(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.charValue() >= right.charValue()); case T_float: return BooleanConstant.fromValue(left.charValue() >= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.charValue() >= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.charValue() >= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.charValue() >= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.charValue() >= right.intValue()); case T_long: return BooleanConstant.fromValue(left.charValue() >= right.longValue()); } break; case T_float : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.floatValue() >= right.charValue()); case T_float: return BooleanConstant.fromValue(left.floatValue() >= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.floatValue() >= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.floatValue() >= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.floatValue() >= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.floatValue() >= right.intValue()); case T_long: return BooleanConstant.fromValue(left.floatValue() >= right.longValue()); } break; case T_double : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.doubleValue() >= right.charValue()); case T_float: return BooleanConstant.fromValue(left.doubleValue() >= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.doubleValue() >= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.doubleValue() >= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.doubleValue() >= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.doubleValue() >= right.intValue()); case T_long: return BooleanConstant.fromValue(left.doubleValue() >= right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.byteValue() >= right.charValue()); case T_float: return BooleanConstant.fromValue(left.byteValue() >= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.byteValue() >= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.byteValue() >= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.byteValue() >= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.byteValue() >= right.intValue()); case T_long: return BooleanConstant.fromValue(left.byteValue() >= right.longValue()); } break; case T_short : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.shortValue() >= right.charValue()); case T_float: return BooleanConstant.fromValue(left.shortValue() >= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.shortValue() >= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.shortValue() >= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.shortValue() >= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.shortValue() >= right.intValue()); case T_long: return BooleanConstant.fromValue(left.shortValue() >= right.longValue()); } break; case T_int : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.intValue() >= right.charValue()); case T_float: return BooleanConstant.fromValue(left.intValue() >= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.intValue() >= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.intValue() >= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.intValue() >= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.intValue() >= right.intValue()); case T_long: return BooleanConstant.fromValue(left.intValue() >= right.longValue()); } break; case T_long : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.longValue() >= right.charValue()); case T_float: return BooleanConstant.fromValue(left.longValue() >= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.longValue() >= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.longValue() >= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.longValue() >= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.longValue() >= right.intValue()); case T_long: return BooleanConstant.fromValue(left.longValue() >= right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationLEFT_SHIFT(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() << right.charValue()); case T_byte: return IntConstant.fromValue(left.charValue() << right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() << right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() << right.intValue()); case T_long: return IntConstant.fromValue(left.charValue() << right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() << right.charValue()); case T_byte: return IntConstant.fromValue(left.byteValue() << right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() << right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() << right.intValue()); case T_long: return IntConstant.fromValue(left.byteValue() << right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() << right.charValue()); case T_byte: return IntConstant.fromValue(left.shortValue() << right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() << right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() << right.intValue()); case T_long: return IntConstant.fromValue(left.shortValue() << right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() << right.charValue()); case T_byte: return IntConstant.fromValue(left.intValue() << right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() << right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() << right.intValue()); case T_long: return IntConstant.fromValue(left.intValue() << right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() << right.charValue()); case T_byte: return LongConstant.fromValue(left.longValue() << right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() << right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() << right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() << right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationLESS(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.charValue() < right.charValue()); case T_float: return BooleanConstant.fromValue(left.charValue() < right.floatValue()); case T_double: return BooleanConstant.fromValue(left.charValue() < right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.charValue() < right.byteValue()); case T_short: return BooleanConstant.fromValue(left.charValue() < right.shortValue()); case T_int: return BooleanConstant.fromValue(left.charValue() < right.intValue()); case T_long: return BooleanConstant.fromValue(left.charValue() < right.longValue()); } break; case T_float : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.floatValue() < right.charValue()); case T_float: return BooleanConstant.fromValue(left.floatValue() < right.floatValue()); case T_double: return BooleanConstant.fromValue(left.floatValue() < right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.floatValue() < right.byteValue()); case T_short: return BooleanConstant.fromValue(left.floatValue() < right.shortValue()); case T_int: return BooleanConstant.fromValue(left.floatValue() < right.intValue()); case T_long: return BooleanConstant.fromValue(left.floatValue() < right.longValue()); } break; case T_double : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.doubleValue() < right.charValue()); case T_float: return BooleanConstant.fromValue(left.doubleValue() < right.floatValue()); case T_double: return BooleanConstant.fromValue(left.doubleValue() < right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.doubleValue() < right.byteValue()); case T_short: return BooleanConstant.fromValue(left.doubleValue() < right.shortValue()); case T_int: return BooleanConstant.fromValue(left.doubleValue() < right.intValue()); case T_long: return BooleanConstant.fromValue(left.doubleValue() < right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.byteValue() < right.charValue()); case T_float: return BooleanConstant.fromValue(left.byteValue() < right.floatValue()); case T_double: return BooleanConstant.fromValue(left.byteValue() < right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.byteValue() < right.byteValue()); case T_short: return BooleanConstant.fromValue(left.byteValue() < right.shortValue()); case T_int: return BooleanConstant.fromValue(left.byteValue() < right.intValue()); case T_long: return BooleanConstant.fromValue(left.byteValue() < right.longValue()); } break; case T_short : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.shortValue() < right.charValue()); case T_float: return BooleanConstant.fromValue(left.shortValue() < right.floatValue()); case T_double: return BooleanConstant.fromValue(left.shortValue() < right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.shortValue() < right.byteValue()); case T_short: return BooleanConstant.fromValue(left.shortValue() < right.shortValue()); case T_int: return BooleanConstant.fromValue(left.shortValue() < right.intValue()); case T_long: return BooleanConstant.fromValue(left.shortValue() < right.longValue()); } break; case T_int : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.intValue() < right.charValue()); case T_float: return BooleanConstant.fromValue(left.intValue() < right.floatValue()); case T_double: return BooleanConstant.fromValue(left.intValue() < right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.intValue() < right.byteValue()); case T_short: return BooleanConstant.fromValue(left.intValue() < right.shortValue()); case T_int: return BooleanConstant.fromValue(left.intValue() < right.intValue()); case T_long: return BooleanConstant.fromValue(left.intValue() < right.longValue()); } break; case T_long : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.longValue() < right.charValue()); case T_float: return BooleanConstant.fromValue(left.longValue() < right.floatValue()); case T_double: return BooleanConstant.fromValue(left.longValue() < right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.longValue() < right.byteValue()); case T_short: return BooleanConstant.fromValue(left.longValue() < right.shortValue()); case T_int: return BooleanConstant.fromValue(left.longValue() < right.intValue()); case T_long: return BooleanConstant.fromValue(left.longValue() < right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationLESS_EQUAL(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.charValue() <= right.charValue()); case T_float: return BooleanConstant.fromValue(left.charValue() <= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.charValue() <= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.charValue() <= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.charValue() <= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.charValue() <= right.intValue()); case T_long: return BooleanConstant.fromValue(left.charValue() <= right.longValue()); } break; case T_float : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.floatValue() <= right.charValue()); case T_float: return BooleanConstant.fromValue(left.floatValue() <= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.floatValue() <= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.floatValue() <= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.floatValue() <= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.floatValue() <= right.intValue()); case T_long: return BooleanConstant.fromValue(left.floatValue() <= right.longValue()); } break; case T_double : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.doubleValue() <= right.charValue()); case T_float: return BooleanConstant.fromValue(left.doubleValue() <= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.doubleValue() <= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.doubleValue() <= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.doubleValue() <= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.doubleValue() <= right.intValue()); case T_long: return BooleanConstant.fromValue(left.doubleValue() <= right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.byteValue() <= right.charValue()); case T_float: return BooleanConstant.fromValue(left.byteValue() <= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.byteValue() <= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.byteValue() <= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.byteValue() <= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.byteValue() <= right.intValue()); case T_long: return BooleanConstant.fromValue(left.byteValue() <= right.longValue()); } break; case T_short : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.shortValue() <= right.charValue()); case T_float: return BooleanConstant.fromValue(left.shortValue() <= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.shortValue() <= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.shortValue() <= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.shortValue() <= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.shortValue() <= right.intValue()); case T_long: return BooleanConstant.fromValue(left.shortValue() <= right.longValue()); } break; case T_int : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.intValue() <= right.charValue()); case T_float: return BooleanConstant.fromValue(left.intValue() <= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.intValue() <= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.intValue() <= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.intValue() <= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.intValue() <= right.intValue()); case T_long: return BooleanConstant.fromValue(left.intValue() <= right.longValue()); } break; case T_long : switch (rightId){ case T_char : return BooleanConstant.fromValue(left.longValue() <= right.charValue()); case T_float: return BooleanConstant.fromValue(left.longValue() <= right.floatValue()); case T_double: return BooleanConstant.fromValue(left.longValue() <= right.doubleValue()); case T_byte: return BooleanConstant.fromValue(left.longValue() <= right.byteValue()); case T_short: return BooleanConstant.fromValue(left.longValue() <= right.shortValue()); case T_int: return BooleanConstant.fromValue(left.longValue() <= right.intValue()); case T_long: return BooleanConstant.fromValue(left.longValue() <= right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationMINUS(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() - right.charValue()); case T_float: return FloatConstant.fromValue(left.charValue() - right.floatValue()); case T_double: return DoubleConstant.fromValue(left.charValue() - right.doubleValue()); case T_byte: return IntConstant.fromValue(left.charValue() - right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() - right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() - right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() - right.longValue()); } break; case T_float : switch (rightId){ case T_char : return FloatConstant.fromValue(left.floatValue() - right.charValue()); case T_float: return FloatConstant.fromValue(left.floatValue() - right.floatValue()); case T_double: return DoubleConstant.fromValue(left.floatValue() - right.doubleValue()); case T_byte: return FloatConstant.fromValue(left.floatValue() - right.byteValue()); case T_short: return FloatConstant.fromValue(left.floatValue() - right.shortValue()); case T_int: return FloatConstant.fromValue(left.floatValue() - right.intValue()); case T_long: return FloatConstant.fromValue(left.floatValue() - right.longValue()); } break; case T_double : switch (rightId){ case T_char : return DoubleConstant.fromValue(left.doubleValue() - right.charValue()); case T_float: return DoubleConstant.fromValue(left.doubleValue() - right.floatValue()); case T_double: return DoubleConstant.fromValue(left.doubleValue() - right.doubleValue()); case T_byte: return DoubleConstant.fromValue(left.doubleValue() - right.byteValue()); case T_short: return DoubleConstant.fromValue(left.doubleValue() - right.shortValue()); case T_int: return DoubleConstant.fromValue(left.doubleValue() - right.intValue()); case T_long: return DoubleConstant.fromValue(left.doubleValue() - right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() - right.charValue()); case T_float: return FloatConstant.fromValue(left.byteValue() - right.floatValue()); case T_double: return DoubleConstant.fromValue(left.byteValue() - right.doubleValue()); case T_byte: return IntConstant.fromValue(left.byteValue() - right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() - right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() - right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() - right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() - right.charValue()); case T_float: return FloatConstant.fromValue(left.shortValue() - right.floatValue()); case T_double: return DoubleConstant.fromValue(left.shortValue() - right.doubleValue()); case T_byte: return IntConstant.fromValue(left.shortValue() - right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() - right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() - right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() - right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() - right.charValue()); case T_float: return FloatConstant.fromValue(left.intValue() - right.floatValue()); case T_double: return DoubleConstant.fromValue(left.intValue() - right.doubleValue()); case T_byte: return IntConstant.fromValue(left.intValue() - right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() - right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() - right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() - right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() - right.charValue()); case T_float: return FloatConstant.fromValue(left.longValue() - right.floatValue()); case T_double: return DoubleConstant.fromValue(left.longValue() - right.doubleValue()); case T_byte: return LongConstant.fromValue(left.longValue() - right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() - right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() - right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() - right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationMULTIPLY(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() * right.charValue()); case T_float: return FloatConstant.fromValue(left.charValue() * right.floatValue()); case T_double: return DoubleConstant.fromValue(left.charValue() * right.doubleValue()); case T_byte: return IntConstant.fromValue(left.charValue() * right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() * right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() * right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() * right.longValue()); } break; case T_float : switch (rightId){ case T_char : return FloatConstant.fromValue(left.floatValue() * right.charValue()); case T_float: return FloatConstant.fromValue(left.floatValue() * right.floatValue()); case T_double: return DoubleConstant.fromValue(left.floatValue() * right.doubleValue()); case T_byte: return FloatConstant.fromValue(left.floatValue() * right.byteValue()); case T_short: return FloatConstant.fromValue(left.floatValue() * right.shortValue()); case T_int: return FloatConstant.fromValue(left.floatValue() * right.intValue()); case T_long: return FloatConstant.fromValue(left.floatValue() * right.longValue()); } break; case T_double : switch (rightId){ case T_char : return DoubleConstant.fromValue(left.doubleValue() * right.charValue()); case T_float: return DoubleConstant.fromValue(left.doubleValue() * right.floatValue()); case T_double: return DoubleConstant.fromValue(left.doubleValue() * right.doubleValue()); case T_byte: return DoubleConstant.fromValue(left.doubleValue() * right.byteValue()); case T_short: return DoubleConstant.fromValue(left.doubleValue() * right.shortValue()); case T_int: return DoubleConstant.fromValue(left.doubleValue() * right.intValue()); case T_long: return DoubleConstant.fromValue(left.doubleValue() * right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() * right.charValue()); case T_float: return FloatConstant.fromValue(left.byteValue() * right.floatValue()); case T_double: return DoubleConstant.fromValue(left.byteValue() * right.doubleValue()); case T_byte: return IntConstant.fromValue(left.byteValue() * right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() * right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() * right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() * right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() * right.charValue()); case T_float: return FloatConstant.fromValue(left.shortValue() * right.floatValue()); case T_double: return DoubleConstant.fromValue(left.shortValue() * right.doubleValue()); case T_byte: return IntConstant.fromValue(left.shortValue() * right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() * right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() * right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() * right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() * right.charValue()); case T_float: return FloatConstant.fromValue(left.intValue() * right.floatValue()); case T_double: return DoubleConstant.fromValue(left.intValue() * right.doubleValue()); case T_byte: return IntConstant.fromValue(left.intValue() * right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() * right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() * right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() * right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() * right.charValue()); case T_float: return FloatConstant.fromValue(left.longValue() * right.floatValue()); case T_double: return DoubleConstant.fromValue(left.longValue() * right.doubleValue()); case T_byte: return LongConstant.fromValue(left.longValue() * right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() * right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() * right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() * right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationOR(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_boolean : return BooleanConstant.fromValue(left.booleanValue() | right.booleanValue()); case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() | right.charValue()); case T_byte: return IntConstant.fromValue(left.charValue() | right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() | right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() | right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() | right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() | right.charValue()); case T_byte: return IntConstant.fromValue(left.byteValue() | right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() | right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() | right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() | right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() | right.charValue()); case T_byte: return IntConstant.fromValue(left.shortValue() | right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() | right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() | right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() | right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() | right.charValue()); case T_byte: return IntConstant.fromValue(left.intValue() | right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() | right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() | right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() | right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() | right.charValue()); case T_byte: return LongConstant.fromValue(left.longValue() | right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() | right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() | right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() | right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationOR_OR(Constant left, int leftId, Constant right, int rightId) { return BooleanConstant.fromValue(left.booleanValue() || right.booleanValue()); } public static final Constant computeConstantOperationPLUS(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_JavaLangObject : if (rightId == T_JavaLangString) { return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_boolean : if (rightId == T_JavaLangString) { return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() + right.charValue()); case T_float: return FloatConstant.fromValue(left.charValue() + right.floatValue()); case T_double: return DoubleConstant.fromValue(left.charValue() + right.doubleValue()); case T_byte: return IntConstant.fromValue(left.charValue() + right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() + right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() + right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() + right.longValue()); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_float : switch (rightId){ case T_char : return FloatConstant.fromValue(left.floatValue() + right.charValue()); case T_float: return FloatConstant.fromValue(left.floatValue() + right.floatValue()); case T_double: return DoubleConstant.fromValue(left.floatValue() + right.doubleValue()); case T_byte: return FloatConstant.fromValue(left.floatValue() + right.byteValue()); case T_short: return FloatConstant.fromValue(left.floatValue() + right.shortValue()); case T_int: return FloatConstant.fromValue(left.floatValue() + right.intValue()); case T_long: return FloatConstant.fromValue(left.floatValue() + right.longValue()); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_double : switch (rightId){ case T_char : return DoubleConstant.fromValue(left.doubleValue() + right.charValue()); case T_float: return DoubleConstant.fromValue(left.doubleValue() + right.floatValue()); case T_double: return DoubleConstant.fromValue(left.doubleValue() + right.doubleValue()); case T_byte: return DoubleConstant.fromValue(left.doubleValue() + right.byteValue()); case T_short: return DoubleConstant.fromValue(left.doubleValue() + right.shortValue()); case T_int: return DoubleConstant.fromValue(left.doubleValue() + right.intValue()); case T_long: return DoubleConstant.fromValue(left.doubleValue() + right.longValue()); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() + right.charValue()); case T_float: return FloatConstant.fromValue(left.byteValue() + right.floatValue()); case T_double: return DoubleConstant.fromValue(left.byteValue() + right.doubleValue()); case T_byte: return IntConstant.fromValue(left.byteValue() + right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() + right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() + right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() + right.longValue()); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() + right.charValue()); case T_float: return FloatConstant.fromValue(left.shortValue() + right.floatValue()); case T_double: return DoubleConstant.fromValue(left.shortValue() + right.doubleValue()); case T_byte: return IntConstant.fromValue(left.shortValue() + right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() + right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() + right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() + right.longValue()); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() + right.charValue()); case T_float: return FloatConstant.fromValue(left.intValue() + right.floatValue()); case T_double: return DoubleConstant.fromValue(left.intValue() + right.doubleValue()); case T_byte: return IntConstant.fromValue(left.intValue() + right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() + right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() + right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() + right.longValue()); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() + right.charValue()); case T_float: return FloatConstant.fromValue(left.longValue() + right.floatValue()); case T_double: return DoubleConstant.fromValue(left.longValue() + right.doubleValue()); case T_byte: return LongConstant.fromValue(left.longValue() + right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() + right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() + right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() + right.longValue()); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); } break; case T_JavaLangString : switch (rightId){ case T_char : return StringConstant.fromValue(left.stringValue() + String.valueOf(right.charValue())); case T_float: return StringConstant.fromValue(left.stringValue() + String.valueOf(right.floatValue())); case T_double: return StringConstant.fromValue(left.stringValue() + String.valueOf(right.doubleValue())); case T_byte: return StringConstant.fromValue(left.stringValue() + String.valueOf(right.byteValue())); case T_short: return StringConstant.fromValue(left.stringValue() + String.valueOf(right.shortValue())); case T_int: return StringConstant.fromValue(left.stringValue() + String.valueOf(right.intValue())); case T_long: return StringConstant.fromValue(left.stringValue() + String.valueOf(right.longValue())); case T_JavaLangString: return StringConstant.fromValue(left.stringValue() + right.stringValue()); case T_boolean: return StringConstant.fromValue(left.stringValue() + right.booleanValue()); } break; // case T_null : // switch (rightId){ // case T_char : return Constant.fromValue(left.stringValue() + String.valueOf(right.charValue())); // case T_float: return Constant.fromValue(left.stringValue() + String.valueOf(right.floatValue())); // case T_double: return Constant.fromValue(left.stringValue() + String.valueOf(right.doubleValue())); // case T_byte: return Constant.fromValue(left.stringValue() + String.valueOf(right.byteValue())); // case T_short: return Constant.fromValue(left.stringValue() + String.valueOf(right.shortValue())); // case T_int: return Constant.fromValue(left.stringValue() + String.valueOf(right.intValue())); // case T_long: return Constant.fromValue(left.stringValue() + String.valueOf(right.longValue())); // case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue()); // case T_boolean: return Constant.fromValue(left.stringValue() + right.booleanValue()); // } } return NotAConstant; } public static final Constant computeConstantOperationREMAINDER(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() % right.charValue()); case T_float: return FloatConstant.fromValue(left.charValue() % right.floatValue()); case T_double: return DoubleConstant.fromValue(left.charValue() % right.doubleValue()); case T_byte: return IntConstant.fromValue(left.charValue() % right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() % right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() % right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() % right.longValue()); } break; case T_float : switch (rightId){ case T_char : return FloatConstant.fromValue(left.floatValue() % right.charValue()); case T_float: return FloatConstant.fromValue(left.floatValue() % right.floatValue()); case T_double: return DoubleConstant.fromValue(left.floatValue() % right.doubleValue()); case T_byte: return FloatConstant.fromValue(left.floatValue() % right.byteValue()); case T_short: return FloatConstant.fromValue(left.floatValue() % right.shortValue()); case T_int: return FloatConstant.fromValue(left.floatValue() % right.intValue()); case T_long: return FloatConstant.fromValue(left.floatValue() % right.longValue()); } break; case T_double : switch (rightId){ case T_char : return DoubleConstant.fromValue(left.doubleValue() % right.charValue()); case T_float: return DoubleConstant.fromValue(left.doubleValue() % right.floatValue()); case T_double: return DoubleConstant.fromValue(left.doubleValue() % right.doubleValue()); case T_byte: return DoubleConstant.fromValue(left.doubleValue() % right.byteValue()); case T_short: return DoubleConstant.fromValue(left.doubleValue() % right.shortValue()); case T_int: return DoubleConstant.fromValue(left.doubleValue() % right.intValue()); case T_long: return DoubleConstant.fromValue(left.doubleValue() % right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() % right.charValue()); case T_float: return FloatConstant.fromValue(left.byteValue() % right.floatValue()); case T_double: return DoubleConstant.fromValue(left.byteValue() % right.doubleValue()); case T_byte: return IntConstant.fromValue(left.byteValue() % right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() % right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() % right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() % right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() % right.charValue()); case T_float: return FloatConstant.fromValue(left.shortValue() % right.floatValue()); case T_double: return DoubleConstant.fromValue(left.shortValue() % right.doubleValue()); case T_byte: return IntConstant.fromValue(left.shortValue() % right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() % right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() % right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() % right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() % right.charValue()); case T_float: return FloatConstant.fromValue(left.intValue() % right.floatValue()); case T_double: return DoubleConstant.fromValue(left.intValue() % right.doubleValue()); case T_byte: return IntConstant.fromValue(left.intValue() % right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() % right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() % right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() % right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() % right.charValue()); case T_float: return FloatConstant.fromValue(left.longValue() % right.floatValue()); case T_double: return DoubleConstant.fromValue(left.longValue() % right.doubleValue()); case T_byte: return LongConstant.fromValue(left.longValue() % right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() % right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() % right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() % right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationRIGHT_SHIFT(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() >> right.charValue()); case T_byte: return IntConstant.fromValue(left.charValue() >> right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() >> right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() >> right.intValue()); case T_long: return IntConstant.fromValue(left.charValue() >> right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() >> right.charValue()); case T_byte: return IntConstant.fromValue(left.byteValue() >> right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() >> right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() >> right.intValue()); case T_long: return IntConstant.fromValue(left.byteValue() >> right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() >> right.charValue()); case T_byte: return IntConstant.fromValue(left.shortValue() >> right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() >> right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() >> right.intValue()); case T_long: return IntConstant.fromValue(left.shortValue() >> right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() >> right.charValue()); case T_byte: return IntConstant.fromValue(left.intValue() >> right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() >> right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() >> right.intValue()); case T_long: return IntConstant.fromValue(left.intValue() >> right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() >> right.charValue()); case T_byte: return LongConstant.fromValue(left.longValue() >> right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() >> right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() >> right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() >> right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationUNSIGNED_RIGHT_SHIFT(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() >>> right.charValue()); case T_byte: return IntConstant.fromValue(left.charValue() >>> right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() >>> right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() >>> right.intValue()); case T_long: return IntConstant.fromValue(left.charValue() >>> right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() >>> right.charValue()); case T_byte: return IntConstant.fromValue(left.byteValue() >>> right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() >>> right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() >>> right.intValue()); case T_long: return IntConstant.fromValue(left.byteValue() >>> right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() >>> right.charValue()); case T_byte: return IntConstant.fromValue(left.shortValue() >>> right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() >>> right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() >>> right.intValue()); case T_long: return IntConstant.fromValue(left.shortValue() >>> right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() >>> right.charValue()); case T_byte: return IntConstant.fromValue(left.intValue() >>> right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() >>> right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() >>> right.intValue()); case T_long: return IntConstant.fromValue(left.intValue() >>> right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() >>> right.charValue()); case T_byte: return LongConstant.fromValue(left.longValue() >>> right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() >>> right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() >>> right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() >>> right.longValue()); } } return NotAConstant; } public static final Constant computeConstantOperationXOR(Constant left, int leftId, Constant right, int rightId) { switch (leftId){ case T_boolean : return BooleanConstant.fromValue(left.booleanValue() ^ right.booleanValue()); case T_char : switch (rightId){ case T_char : return IntConstant.fromValue(left.charValue() ^ right.charValue()); case T_byte: return IntConstant.fromValue(left.charValue() ^ right.byteValue()); case T_short: return IntConstant.fromValue(left.charValue() ^ right.shortValue()); case T_int: return IntConstant.fromValue(left.charValue() ^ right.intValue()); case T_long: return LongConstant.fromValue(left.charValue() ^ right.longValue()); } break; case T_byte : switch (rightId){ case T_char : return IntConstant.fromValue(left.byteValue() ^ right.charValue()); case T_byte: return IntConstant.fromValue(left.byteValue() ^ right.byteValue()); case T_short: return IntConstant.fromValue(left.byteValue() ^ right.shortValue()); case T_int: return IntConstant.fromValue(left.byteValue() ^ right.intValue()); case T_long: return LongConstant.fromValue(left.byteValue() ^ right.longValue()); } break; case T_short : switch (rightId){ case T_char : return IntConstant.fromValue(left.shortValue() ^ right.charValue()); case T_byte: return IntConstant.fromValue(left.shortValue() ^ right.byteValue()); case T_short: return IntConstant.fromValue(left.shortValue() ^ right.shortValue()); case T_int: return IntConstant.fromValue(left.shortValue() ^ right.intValue()); case T_long: return LongConstant.fromValue(left.shortValue() ^ right.longValue()); } break; case T_int : switch (rightId){ case T_char : return IntConstant.fromValue(left.intValue() ^ right.charValue()); case T_byte: return IntConstant.fromValue(left.intValue() ^ right.byteValue()); case T_short: return IntConstant.fromValue(left.intValue() ^ right.shortValue()); case T_int: return IntConstant.fromValue(left.intValue() ^ right.intValue()); case T_long: return LongConstant.fromValue(left.intValue() ^ right.longValue()); } break; case T_long : switch (rightId){ case T_char : return LongConstant.fromValue(left.longValue() ^ right.charValue()); case T_byte: return LongConstant.fromValue(left.longValue() ^ right.byteValue()); case T_short: return LongConstant.fromValue(left.longValue() ^ right.shortValue()); case T_int: return LongConstant.fromValue(left.longValue() ^ right.intValue()); case T_long: return LongConstant.fromValue(left.longValue() ^ right.longValue()); } } return NotAConstant; } public double doubleValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotCastedInto, new String[] { typeName(), "double" })); //$NON-NLS-1$ } public float floatValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotCastedInto, new String[] { typeName(), "float" })); //$NON-NLS-1$ } /** * Returns true if both constants have the same type and the same actual value * @param otherConstant */ public boolean hasSameValue(Constant otherConstant) { if (this == otherConstant) return true; int typeID; if ((typeID = typeID()) != otherConstant.typeID()) return false; switch (typeID) { case TypeIds.T_boolean: return booleanValue() == otherConstant.booleanValue(); case TypeIds.T_byte: return byteValue() == otherConstant.byteValue(); case TypeIds.T_char: return charValue() == otherConstant.charValue(); case TypeIds.T_double: return doubleValue() == otherConstant.doubleValue(); case TypeIds.T_float: return floatValue() == otherConstant.floatValue(); case TypeIds.T_int: return intValue() == otherConstant.intValue(); case TypeIds.T_short: return shortValue() == otherConstant.shortValue(); case TypeIds.T_long: return longValue() == otherConstant.longValue(); case TypeIds.T_JavaLangString: String value = stringValue(); return value == null ? otherConstant.stringValue() == null : value.equals(otherConstant.stringValue()); } return false; } public int intValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotCastedInto, new String[] { typeName(), "int" })); //$NON-NLS-1$ } public long longValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotCastedInto, new String[] { typeName(), "long" })); //$NON-NLS-1$ } public short shortValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotConvertedTo, new String[] { typeName(), "short" })); //$NON-NLS-1$ } public String stringValue() { throw new ShouldNotImplement(Messages.bind(Messages.constant_cannotConvertedTo, new String[] { typeName(), "String" })); //$NON-NLS-1$ } public String toString(){ if (this == NotAConstant) return "(Constant) NotAConstant"; //$NON-NLS-1$ return super.toString(); } public abstract int typeID(); public String typeName() { switch (typeID()) { case T_int : return "int"; //$NON-NLS-1$ case T_byte : return "byte"; //$NON-NLS-1$ case T_short : return "short"; //$NON-NLS-1$ case T_char : return "char"; //$NON-NLS-1$ case T_float : return "float"; //$NON-NLS-1$ 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_JavaLangString : return "java.lang.String"; //$NON-NLS-1$ default: return "unknown"; //$NON-NLS-1$ } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java0000644000175000001440000000311112212041344031153 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class BooleanConstant extends Constant { private boolean value; private static final BooleanConstant TRUE = new BooleanConstant(true); private static final BooleanConstant FALSE = new BooleanConstant(false); public static Constant fromValue(boolean value) { return value ? BooleanConstant.TRUE : BooleanConstant.FALSE; } private BooleanConstant(boolean value) { this.value = value; } public boolean booleanValue() { return this.value; } public String stringValue() { // spec 15.17.11 return String.valueOf(this.value); } public String toString() { return "(boolean)" + this.value; //$NON-NLS-1$ } public int typeID() { return T_boolean; } public int hashCode() { return this.value ? 1231 : 1237; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } // cannot be true anymore as the first test would have returned true return false; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java0000644000175000001440000000351512212041344030507 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class ByteConstant extends Constant { private byte value; public static Constant fromValue(byte value) { return new ByteConstant(value); } private ByteConstant(byte value) { this.value = value; } public byte byteValue() { return this.value; } public char charValue() { return (char) this.value; } public double doubleValue() { return this.value; // implicit cast to return type } public float floatValue() { return this.value; // implicit cast to return type } public int intValue() { return this.value; // implicit cast to return type } public long longValue() { return this.value; // implicit cast to return type } public short shortValue() { return this.value; // implicit cast to return type } public String stringValue() { // spec 15.17.11 return String.valueOf(this.value); } public String toString() { return "(byte)" + this.value; //$NON-NLS-1$ } public int typeID() { return T_byte; } public int hashCode() { return this.value; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ByteConstant other = (ByteConstant) obj; return this.value == other.value; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java0000644000175000001440000000343212212041344030647 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class FloatConstant extends Constant { float value; public static Constant fromValue(float value) { return new FloatConstant(value); } private FloatConstant(float value) { this.value = value; } public byte byteValue() { return (byte) this.value; } public char charValue() { return (char) this.value; } public double doubleValue() { return this.value; // implicit cast to return type } public float floatValue() { return this.value; } public int intValue() { return (int) this.value; } public long longValue() { return (long) this.value; } public short shortValue() { return (short) this.value; } public String stringValue() { return String.valueOf(this.value); } public String toString() { return "(float)" + this.value; //$NON-NLS-1$ } public int typeID() { return T_float; } public int hashCode() { return Float.floatToIntBits(this.value); } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } FloatConstant other = (FloatConstant) obj; return Float.floatToIntBits(this.value) == Float.floatToIntBits(other.value); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java0000644000175000001440000002642612212041344030350 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 265744 - Enum switch should warn about missing default * bug 374605 - Unreasonable warning for enum-based switch statements * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; import org.eclipse.jdt.internal.compiler.ast.ASTNode; /** * Represent a set of irritant flags. Irritants are organized in up to 8 group * of 29, allowing for a maximum of 232 distinct irritants. */ public class IrritantSet { // Reserve two high bits for selecting the right bit pattern public final static int GROUP_MASK = ASTNode.Bit32 | ASTNode.Bit31 | ASTNode.Bit30; public final static int GROUP_SHIFT = 29; public final static int GROUP_MAX = 3; // can be increased up to 8 // Group prefix for irritants public final static int GROUP0 = 0 << GROUP_SHIFT; public final static int GROUP1 = 1 << GROUP_SHIFT; public final static int GROUP2 = 2 << GROUP_SHIFT; // reveal subsequent groups as needed // public final static int GROUP3 = 3 << GROUP_SHIFT; // public final static int GROUP4 = 4 << GROUP_SHIFT; // public final static int GROUP5 = 5 << GROUP_SHIFT; // public final static int GROUP6 = 6 << GROUP_SHIFT; // public final static int GROUP7 = 7 << GROUP_SHIFT; // Predefine sets of irritants matching warning tokens public static final IrritantSet ALL = new IrritantSet(0xFFFFFFFF & ~GROUP_MASK); public static final IrritantSet BOXING = new IrritantSet(CompilerOptions.AutoBoxing); public static final IrritantSet CAST = new IrritantSet(CompilerOptions.UnnecessaryTypeCheck); public static final IrritantSet DEPRECATION = new IrritantSet(CompilerOptions.UsingDeprecatedAPI); public static final IrritantSet DEP_ANN = new IrritantSet(CompilerOptions.MissingDeprecatedAnnotation); public static final IrritantSet FALLTHROUGH = new IrritantSet(CompilerOptions.FallthroughCase); public static final IrritantSet FINALLY = new IrritantSet(CompilerOptions.FinallyBlockNotCompleting); public static final IrritantSet HIDING = new IrritantSet(CompilerOptions.MaskedCatchBlock); public static final IrritantSet INCOMPLETE_SWITCH = new IrritantSet(CompilerOptions.MissingEnumConstantCase); public static final IrritantSet NLS = new IrritantSet(CompilerOptions.NonExternalizedString); public static final IrritantSet NULL = new IrritantSet(CompilerOptions.NullReference); public static final IrritantSet RAW = new IrritantSet(CompilerOptions.RawTypeReference); public static final IrritantSet RESTRICTION = new IrritantSet(CompilerOptions.ForbiddenReference); public static final IrritantSet SERIAL = new IrritantSet(CompilerOptions.MissingSerialVersion); public static final IrritantSet STATIC_ACCESS = new IrritantSet(CompilerOptions.IndirectStaticAccess); public static final IrritantSet STATIC_METHOD = new IrritantSet(CompilerOptions.MethodCanBeStatic); public static final IrritantSet SYNTHETIC_ACCESS = new IrritantSet(CompilerOptions.AccessEmulation); public static final IrritantSet SYNCHRONIZED = new IrritantSet(CompilerOptions.MissingSynchronizedModifierInInheritedMethod); public static final IrritantSet SUPER = new IrritantSet(CompilerOptions.OverridingMethodWithoutSuperInvocation); public static final IrritantSet UNUSED = new IrritantSet(CompilerOptions.UnusedLocalVariable); public static final IrritantSet UNCHECKED = new IrritantSet(CompilerOptions.UncheckedTypeOperation); public static final IrritantSet UNQUALIFIED_FIELD_ACCESS = new IrritantSet(CompilerOptions.UnqualifiedFieldAccess); public static final IrritantSet RESOURCE = new IrritantSet(CompilerOptions.UnclosedCloseable); public static final IrritantSet JAVADOC = new IrritantSet(CompilerOptions.InvalidJavadoc); public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // no optional error by default public static final IrritantSet COMPILER_DEFAULT_WARNINGS = new IrritantSet(0); // see static initializer below static { COMPILER_DEFAULT_WARNINGS // group-0 warnings enabled by default .set( CompilerOptions.MethodWithConstructorName | CompilerOptions.OverriddenPackageDefaultMethod | CompilerOptions.UsingDeprecatedAPI | CompilerOptions.MaskedCatchBlock | CompilerOptions.UnusedLocalVariable | CompilerOptions.NoImplicitStringConversion | CompilerOptions.AssertUsedAsAnIdentifier | CompilerOptions.UnusedImport | CompilerOptions.NonStaticAccessToStatic | CompilerOptions.NoEffectAssignment | CompilerOptions.IncompatibleNonInheritedInterfaceMethod | CompilerOptions.UnusedPrivateMember | CompilerOptions.FinallyBlockNotCompleting) // group-1 warnings enabled by default .set( CompilerOptions.UncheckedTypeOperation | CompilerOptions.FinalParameterBound | CompilerOptions.MissingSerialVersion | CompilerOptions.EnumUsedAsAnIdentifier | CompilerOptions.ForbiddenReference | CompilerOptions.VarargsArgumentNeedCast | CompilerOptions.NullReference | CompilerOptions.AnnotationSuperInterface | CompilerOptions.TypeHiding | CompilerOptions.DiscouragedReference | CompilerOptions.UnhandledWarningToken | CompilerOptions.RawTypeReference | CompilerOptions.UnusedLabel | CompilerOptions.UnusedTypeArguments | CompilerOptions.UnusedWarningToken | CompilerOptions.ComparingIdentical | CompilerOptions.MissingEnumConstantCase) // group-2 warnings enabled by default .set( CompilerOptions.DeadCode |CompilerOptions.Tasks |CompilerOptions.UnclosedCloseable |CompilerOptions.NullUncheckedConversion |CompilerOptions.RedundantNullAnnotation |CompilerOptions.NonnullParameterAnnotationDropped); // default errors IF AnnotationBasedNullAnalysis is enabled: COMPILER_DEFAULT_ERRORS.set( CompilerOptions.NullSpecViolation |CompilerOptions.NullAnnotationInferenceConflict); ALL.setAll(); HIDING .set(CompilerOptions.FieldHiding) .set(CompilerOptions.LocalVariableHiding) .set(CompilerOptions.TypeHiding); NULL .set(CompilerOptions.PotentialNullReference) .set(CompilerOptions.RedundantNullCheck) .set(CompilerOptions.NullSpecViolation) .set(CompilerOptions.NullAnnotationInferenceConflict) .set(CompilerOptions.NullUncheckedConversion) .set(CompilerOptions.RedundantNullAnnotation) .set(CompilerOptions.NonnullParameterAnnotationDropped); RESTRICTION.set(CompilerOptions.DiscouragedReference); STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic); UNUSED .set(CompilerOptions.UnusedArgument) .set(CompilerOptions.UnusedPrivateMember) .set(CompilerOptions.UnusedDeclaredThrownException) .set(CompilerOptions.UnusedLabel) .set(CompilerOptions.UnusedImport) .set(CompilerOptions.UnusedTypeArguments) .set(CompilerOptions.RedundantSuperinterface) .set(CompilerOptions.DeadCode) .set(CompilerOptions.UnusedObjectAllocation) .set(CompilerOptions.UnusedTypeParameter) .set(CompilerOptions.RedundantSpecificationOfTypeArguments); STATIC_METHOD .set(CompilerOptions.MethodCanBePotentiallyStatic); RESOURCE .set(CompilerOptions.PotentiallyUnclosedCloseable) .set(CompilerOptions.ExplicitlyClosedAutoCloseable); INCOMPLETE_SWITCH.set(CompilerOptions.MissingDefaultCase); String suppressRawWhenUnchecked = System.getProperty("suppressRawWhenUnchecked"); //$NON-NLS-1$ if (suppressRawWhenUnchecked != null && "true".equalsIgnoreCase(suppressRawWhenUnchecked)) { //$NON-NLS-1$ UNCHECKED.set(CompilerOptions.RawTypeReference); } JAVADOC .set(CompilerOptions.MissingJavadocComments) .set(CompilerOptions.MissingJavadocTags); } // Internal state private int[] bits = new int[GROUP_MAX]; /** * Constructor with initial irritant set */ public IrritantSet(int singleGroupIrritants) { initialize(singleGroupIrritants); } /** * Constructor with initial irritant set */ public IrritantSet(IrritantSet other) { initialize(other); } public boolean areAllSet() { for (int i = 0; i < GROUP_MAX; i++) { if (this.bits[i] != (0xFFFFFFFF & ~GROUP_MASK)) return false; } return true; } public IrritantSet clear(int singleGroupIrritants) { int group = (singleGroupIrritants & GROUP_MASK) >> GROUP_SHIFT; this.bits[group] &= ~singleGroupIrritants; return this; } public IrritantSet clearAll() { for (int i = 0; i < GROUP_MAX; i++) { this.bits[i] = 0; } return this; } /** * Initialize a set of irritants in one group * * @param singleGroupIrritants */ public void initialize(int singleGroupIrritants) { if (singleGroupIrritants == 0) return; int group = (singleGroupIrritants & GROUP_MASK) >> GROUP_SHIFT; this.bits[group] = singleGroupIrritants & ~GROUP_MASK; // erase group information } public void initialize(IrritantSet other) { if (other == null) return; System.arraycopy(other.bits, 0, this.bits = new int[GROUP_MAX], 0, GROUP_MAX); } /** * Returns true if any of the irritants in given other set is positionned in receiver * @param other */ public boolean isAnySet(IrritantSet other) { if (other == null) return false; for (int i = 0; i < GROUP_MAX; i++) { if ((this.bits[i] & other.bits[i]) != 0) return true; } return false; } /** * Returns true if all of the irritants in the given irritant set are set in receiver * @param irritantSet the given irritant set */ public boolean hasSameIrritants(IrritantSet irritantSet) { if (irritantSet == null) return false; for (int i = 0; i < GROUP_MAX; i++) { if (this.bits[i] != irritantSet.bits[i]) return false; } return true; } public boolean isSet(int singleGroupIrritants) { int group = (singleGroupIrritants & GROUP_MASK) >> GROUP_SHIFT; return (this.bits[group] & singleGroupIrritants) != 0; } public IrritantSet set(int singleGroupIrritants) { int group = (singleGroupIrritants & GROUP_MASK) >> GROUP_SHIFT; this.bits[group] |= (singleGroupIrritants & ~GROUP_MASK); // erase the group bits return this; } /** * Return updated irritantSet or null if it was a no-op * * @param other */ public IrritantSet set(IrritantSet other) { if (other == null) return this; boolean wasNoOp = true; for (int i = 0; i < GROUP_MAX; i++) { int otherIrritant = other.bits[i] & ~GROUP_MASK; // erase the // group // bits if ((this.bits[i] & otherIrritant) != otherIrritant) { wasNoOp = false; this.bits[i] |= otherIrritant; } } return wasNoOp ? null : this; } public IrritantSet setAll() { for (int i = 0; i < GROUP_MAX; i++) { this.bits[i] |= 0xFFFFFFFF & ~GROUP_MASK; // erase the group // bits; } return this; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/CompilerStats.java0000644000175000001440000000243112212041344030657 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class CompilerStats implements Comparable { // overall public long startTime; public long endTime; public long lineCount; // compile phases public long parseTime; public long resolveTime; public long analyzeTime; public long generateTime; /** * Returns the total elapsed time (between start and end) * @return the time spent between start and end */ public long elapsedTime() { return this.endTime - this.startTime; } /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(Object o) { CompilerStats otherStats = (CompilerStats) o; long time1 = elapsedTime(); long time2 = otherStats.elapsedTime(); return time1 < time2 ? -1 : (time1 == time2 ? 0 : 1); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/IntConstant.java0000644000175000001440000000664012212041344030340 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class IntConstant extends Constant { int value; private static final IntConstant MIN_VALUE = new IntConstant(Integer.MIN_VALUE); private static final IntConstant MINUS_FOUR = new IntConstant(-4); private static final IntConstant MINUS_THREE = new IntConstant(-3); private static final IntConstant MINUS_TWO = new IntConstant(-2); private static final IntConstant MINUS_ONE = new IntConstant(-1); private static final IntConstant ZERO = new IntConstant(0); private static final IntConstant ONE = new IntConstant(1); private static final IntConstant TWO = new IntConstant(2); private static final IntConstant THREE = new IntConstant(3); private static final IntConstant FOUR = new IntConstant(4); private static final IntConstant FIVE = new IntConstant(5); private static final IntConstant SIX = new IntConstant(6); private static final IntConstant SEVEN = new IntConstant(7); private static final IntConstant EIGHT= new IntConstant(8); private static final IntConstant NINE = new IntConstant(9); private static final IntConstant TEN = new IntConstant(10); public static Constant fromValue(int value) { switch (value) { case Integer.MIN_VALUE : return IntConstant.MIN_VALUE; case -4 : return IntConstant.MINUS_FOUR; case -3 : return IntConstant.MINUS_THREE; case -2 : return IntConstant.MINUS_TWO; case -1 : return IntConstant.MINUS_ONE; case 0 : return IntConstant.ZERO; case 1 : return IntConstant.ONE; case 2 : return IntConstant.TWO; case 3 : return IntConstant.THREE; case 4 : return IntConstant.FOUR; case 5 : return IntConstant.FIVE; case 6 : return IntConstant.SIX; case 7 : return IntConstant.SEVEN; case 8 : return IntConstant.EIGHT; case 9 : return IntConstant.NINE; case 10 : return IntConstant.TEN; } return new IntConstant(value); } private IntConstant(int value) { this.value = value; } public byte byteValue() { return (byte) this.value; } public char charValue() { return (char) this.value; } public double doubleValue() { return this.value; // implicit cast to return type } public float floatValue() { return this.value; // implicit cast to return type } public int intValue() { return this.value; } public long longValue() { return this.value; // implicit cast to return type } public short shortValue() { return (short) this.value; } public String stringValue() { //spec 15.17.11 return String.valueOf(this.value); } public String toString() { return "(int)" + this.value; //$NON-NLS-1$ } public int typeID() { return T_int; } public int hashCode() { return this.value; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } IntConstant other = (IntConstant) obj; return this.value == other.value; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java0000644000175000001440000000223712212041344031335 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; /* * Implementors are valid compilation contexts from which we can * escape in case of error: * For example: method, type or compilation unit. */ import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; public interface ReferenceContext { void abort(int abortLevel, CategorizedProblem problem); CompilationResult compilationResult(); CompilationUnitDeclaration getCompilationUnitDeclaration(); boolean hasErrors(); void tagAsHavingErrors(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/StringConstant.java0000644000175000001440000000326412212041344031053 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class StringConstant extends Constant { private String value; public static Constant fromValue(String value) { return new StringConstant(value); } private StringConstant(String value) { this.value = value; } public String stringValue() { // spec 15.17.11 // the next line do not go into the toString() send....! return this.value; /* * String s = value.toString() ; if (s == null) return "null"; else return s; */ } public String toString() { return "(String)\"" + this.value + "\""; //$NON-NLS-2$ //$NON-NLS-1$ } public int typeID() { return T_JavaLangString; } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((this.value == null) ? 0 : this.value.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } StringConstant other = (StringConstant) obj; if (this.value == null) { return other.value == null; } else { return this.value.equals(other.value); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java0000644000175000001440000000314612212041344031036 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ 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; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; public interface ITypeRequestor { /** * Accept the resolved binary form for the requested type. */ void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction); /** * Accept the requested type's compilation unit. */ void accept(ICompilationUnit unit, AccessRestriction accessRestriction); /** * Accept the unresolved source forms for the requested type. * Note that the multiple source forms can be answered, in case the target compilation unit * contains multiple types. The first one is then guaranteed to be the one corresponding to the * requested type. */ void accept(ISourceType[] sourceType, PackageBinding packageBinding, AccessRestriction accessRestriction); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/impl/LongConstant.java0000644000175000001440000000374312212041344030506 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.impl; public class LongConstant extends Constant { private static final LongConstant ZERO = new LongConstant(0L); private static final LongConstant MIN_VALUE = new LongConstant(Long.MIN_VALUE); private long value; public static Constant fromValue(long value) { if (value == 0L) { return ZERO; } else if (value == Long.MIN_VALUE) { return MIN_VALUE; } return new LongConstant(value); } private LongConstant(long value) { this.value = value; } public byte byteValue() { return (byte) this.value; } public char charValue() { return (char) this.value; } public double doubleValue() { return this.value; // implicit cast to return type } public float floatValue() { return this.value; // implicit cast to return type } public int intValue() { return (int) this.value; } public long longValue() { return this.value; } public short shortValue() { return (short) this.value; } public String stringValue() { //spec 15.17.11 return String.valueOf(this.value); } public String toString(){ return "(long)" + this.value ; //$NON-NLS-1$ } public int typeID() { return T_long; } public int hashCode() { return (int) (this.value ^ (this.value >>> 32)); } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } LongConstant other = (LongConstant) obj; return this.value == other.value; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/IProblemFactory.java0000644000175000001440000000662012212041344030172 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; import java.util.Locale; import org.eclipse.jdt.core.compiler.CategorizedProblem; /* * Factory used from inside the compiler to build the actual problems * which are handed back in the compilation result. * * This allows sharing the internal problem representation with the environment. * * Note: The factory is responsible for computing and storing a localized error message. */ public interface IProblemFactory { CategorizedProblem createProblem( char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, // shorter versions of the problemArguments int severity, int startPosition, int endPosition, int lineNumber, int columnNumber); /** * Answer a new IProblem created according to the parameters values. * @param originatingFileName the name of the file from which the problem is originated * @param problemId the problem id * @param problemArguments the fully qualified arguments recorded inside the problem * @param elaborationId the message elaboration id (0 for problems that have no message elaboration) * @param messageArguments the arguments needed to set the error message (shorter names than problemArguments ones) * @param severity the severity of the problem * @param startPosition the start position of the problem * @param endPosition the end position of the problem * @param lineNumber the line on which the problem occurred * @return a new IProblem created according to the parameters values. */ CategorizedProblem createProblem( char[] originatingFileName, int problemId, String[] problemArguments, int elaborationId, String[] messageArguments, // shorter versions of the problemArguments int severity, int startPosition, int endPosition, int lineNumber, int columnNumber); Locale getLocale(); String getLocalizedMessage(int problemId, String[] messageArguments); /** * Inject the supplied message arguments into a localized template * elaborated from the supplied problem id and an optional elaboration id * and return the resulting message. The arguments number should match the * highest placeholder index in the template. When an elaboration id is * used, the template matching that elaboration id replaces '{0}' into the * template matching the problem id before the message arguments are * injected. * @param problemId the problem id taken from * {@link org.eclipse.jdt.core.compiler.IProblem} constants * @param elaborationId 0 if the considered problem has no elaboration, a * valid elaboration id else * @param messageArguments the arguments to inject into the template * @return a localized message elaborated from the supplied problem id, * elaboration id and message parameters */ String getLocalizedMessage(int problemId, int elaborationId, String[] messageArguments); } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.ja0000644000175000001440000000347012212041344032335 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; public class DefaultErrorHandlingPolicies { /* * Accumulate all problems, then exit without proceeding. * * Typically, the #proceedWithProblems(Problem[]) should * show the problems. * */ public static IErrorHandlingPolicy exitAfterAllProblems() { return new IErrorHandlingPolicy() { public boolean stopOnFirstError() { return false; } public boolean proceedOnErrors(){ return false; } }; } /* * Exit without proceeding on the first problem wich appears * to be an error. * */ public static IErrorHandlingPolicy exitOnFirstError() { return new IErrorHandlingPolicy() { public boolean stopOnFirstError() { return true; } public boolean proceedOnErrors(){ return false; } }; } /* * Proceed on the first error met. * */ public static IErrorHandlingPolicy proceedOnFirstError() { return new IErrorHandlingPolicy() { public boolean stopOnFirstError() { return true; } public boolean proceedOnErrors(){ return true; } }; } /* * Accumulate all problems, then proceed with them. * */ public static IErrorHandlingPolicy proceedWithAllProblems() { return new IErrorHandlingPolicy() { public boolean stopOnFirstError() { return false; } public boolean proceedOnErrors(){ return true; } }; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/0000755000175000001440000000000012212041344025237 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/GenericXMLWriter.java0000644000175000001440000000776412212041344031252 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Writer; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Map; public class GenericXMLWriter extends PrintWriter { /* constants */ private static final String XML_VERSION= ""; //$NON-NLS-1$ private static void appendEscapedChar(StringBuffer buffer, char c) { String replacement= getReplacement(c); if (replacement != null) { buffer.append('&'); buffer.append(replacement); buffer.append(';'); } else { buffer.append(c); } } private static String getEscaped(String s) { StringBuffer result= new StringBuffer(s.length() + 10); for (int i= 0; i < s.length(); ++i) appendEscapedChar(result, s.charAt(i)); return result.toString(); } private static String getReplacement(char c) { // Encode special XML characters into the equivalent character references. // These five are defined by default for all XML documents. switch (c) { case '<' : return "lt"; //$NON-NLS-1$ case '>' : return "gt"; //$NON-NLS-1$ case '"' : return "quot"; //$NON-NLS-1$ case '\'' : return "apos"; //$NON-NLS-1$ case '&' : return "amp"; //$NON-NLS-1$ } return null; } private String lineSeparator; private int tab; public GenericXMLWriter(OutputStream stream, String lineSeparator, boolean printXmlVersion) { this(new PrintWriter(stream), lineSeparator, printXmlVersion); } public GenericXMLWriter(Writer writer, String lineSeparator, boolean printXmlVersion) { super(writer); this.tab= 0; this.lineSeparator = lineSeparator; if (printXmlVersion) { print(XML_VERSION); print(this.lineSeparator); } } public void endTag(String name, boolean insertTab, boolean insertNewLine) { this.tab --; printTag('/' + name, null/*no parameters*/, insertTab, insertNewLine, false/*don't close tag*/); } /* * External API */ public void printString(String string, boolean insertTab, boolean insertNewLine) { if (insertTab) { printTabulation(); } print(string); if (insertNewLine) { print(this.lineSeparator); } } private void printTabulation() { for (int i= 0; i < this.tab; i++) this.print('\t'); } public void printTag(String name, HashMap parameters, boolean insertTab, boolean insertNewLine, boolean closeTag) { if (insertTab) { printTabulation(); } this.print('<'); this.print(name); if (parameters != null) { int length = parameters.size(); Map.Entry[] entries = new Map.Entry[length]; parameters.entrySet().toArray(entries); Arrays.sort(entries, new Comparator() { public int compare(Object o1, Object o2) { Map.Entry entry1 = (Map.Entry) o1; Map.Entry entry2 = (Map.Entry) o2; return ((String) entry1.getKey()).compareTo((String) entry2.getKey()); } }); for (int i = 0; i < length; i++) { this.print(' '); this.print(entries[i].getKey()); this.print("=\""); //$NON-NLS-1$ this.print(getEscaped(String.valueOf(entries[i].getValue()))); this.print('\"'); } } if (closeTag) { this.print("/>"); //$NON-NLS-1$ } else { this.print(">"); //$NON-NLS-1$ } if (insertNewLine) { print(this.lineSeparator); } if (parameters != null && !closeTag) this.tab++; } public void startTag(String name, boolean insertTab) { printTag(name, null/*no parameters*/, insertTab, true/*insert new line*/, false/*don't close tag*/); this.tab++; } } ././@LongLink0000644000000000000000000000015312251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToIntArray.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToIntArra0000644000175000001440000001125012212041344032254 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * Hashtable of {Object --> int[] } */ public final class HashtableOfObjectToIntArray implements Cloneable { // to avoid using Enumerations, walk the individual tables skipping nulls public Object[] keyTable; public int[][] valueTable; public int elementSize; // number of elements in the table int threshold; public HashtableOfObjectToIntArray() { this(13); } public HashtableOfObjectToIntArray(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new Object[extraRoom]; this.valueTable = new int[extraRoom][]; } public Object clone() throws CloneNotSupportedException { HashtableOfObjectToIntArray result = (HashtableOfObjectToIntArray) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.keyTable.length; result.keyTable = new Object[length]; System.arraycopy(this.keyTable, 0, result.keyTable, 0, length); length = this.valueTable.length; result.valueTable = new int[length][]; System.arraycopy(this.valueTable, 0, result.valueTable, 0, length); return result; } public boolean containsKey(Object key) { int length = this.keyTable.length, index = (key.hashCode()& 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return true; if (++index == length) { index = 0; } } return false; } public int[] get(Object key) { int length = this.keyTable.length, index = (key.hashCode()& 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return this.valueTable[index]; if (++index == length) { index = 0; } } return null; } public void keysToArray(Object[] array) { int index = 0; for (int i=0, length=this.keyTable.length; i this.threshold) rehash(); return value; } public int[] removeKey(Object key) { int length = this.keyTable.length, index = (key.hashCode()& 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) { int[] value = this.valueTable[index]; this.elementSize--; this.keyTable[index] = null; rehash(); return value; } if (++index == length) { index = 0; } } return null; } private void rehash() { HashtableOfObjectToIntArray newHashtable = new HashtableOfObjectToIntArray(this.elementSize * 2); // double the number of expected elements Object currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != null) newHashtable.put(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { StringBuffer buffer = new StringBuffer(); Object key; for (int i = 0, length = this.keyTable.length; i < length; i++) { if ((key = this.keyTable[i]) != null) { buffer.append(key).append(" -> "); //$NON-NLS-1$ int[] ints = this.valueTable[i]; buffer.append('['); if (ints != null) { for (int j = 0, max = ints.length; j < max; j++) { if (j > 0) { buffer.append(','); } buffer.append(ints[j]); } } buffer.append("]\n"); //$NON-NLS-1$ } } return String.valueOf(buffer); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/ManifestAnalyzer.java0000644000175000001440000001324112212041344031357 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class ManifestAnalyzer { private static final int START = 0, IN_CLASSPATH_HEADER = 1, // multistate PAST_CLASSPATH_HEADER = 2, SKIPPING_WHITESPACE = 3, READING_JAR = 4, CONTINUING = 5, SKIP_LINE = 6; private static final char[] CLASSPATH_HEADER_TOKEN = "Class-Path:".toCharArray(); //$NON-NLS-1$ private int classpathSectionsCount; private ArrayList calledFilesNames; /** * Analyze the manifest contents. The given input stream is read using a UTF-8 encoded reader. * If the contents of the input stream is not encoded using a UTF-8 encoding, the analysis will fail. * * @param inputStream the given input stream. * * @return true if the analysis is successful, false otherwise. * @throws IOException if an exception occurs while analyzing the file */ public boolean analyzeManifestContents(InputStream inputStream) throws IOException { char[] chars = Util.getInputStreamAsCharArray(inputStream, -1, Util.UTF_8); int state = START, substate = 0; StringBuffer currentJarToken = new StringBuffer(); int currentChar; this.classpathSectionsCount = 0; this.calledFilesNames = null; for (int i = 0, max = chars.length; i < max;) { currentChar = chars[i++]; if (currentChar == '\r') { // skip \r, will consider \n later (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=251079 ) if (i < max) { currentChar = chars[i++]; } } switch (state) { case START: if (currentChar == CLASSPATH_HEADER_TOKEN[0]) { state = IN_CLASSPATH_HEADER; substate = 1; } else { state = SKIP_LINE; } break; case IN_CLASSPATH_HEADER: if (currentChar == '\n') { state = START; } else if (currentChar != CLASSPATH_HEADER_TOKEN[substate++]) { state = SKIP_LINE; } else if (substate == CLASSPATH_HEADER_TOKEN.length) { state = PAST_CLASSPATH_HEADER; } break; case PAST_CLASSPATH_HEADER: if (currentChar == ' ') { state = SKIPPING_WHITESPACE; this.classpathSectionsCount++; } else { return false; } break; case SKIPPING_WHITESPACE: if (currentChar == '\n') { state = CONTINUING; } else if (currentChar != ' ') { currentJarToken.append((char) currentChar); state = READING_JAR; } else { // >>>>>>>>>>>>>>>>>> Add the latest jar read addCurrentTokenJarWhenNecessary(currentJarToken); } break; case CONTINUING: if (currentChar == '\n') { addCurrentTokenJarWhenNecessary(currentJarToken); state = START; } else if (currentChar == ' ') { state = SKIPPING_WHITESPACE; } else if (currentChar == CLASSPATH_HEADER_TOKEN[0]) { addCurrentTokenJarWhenNecessary(currentJarToken); state = IN_CLASSPATH_HEADER; substate = 1; } else if (this.calledFilesNames == null) { // >>>>>>>>>>>>>>>>>> Add the latest jar read addCurrentTokenJarWhenNecessary(currentJarToken); state = START; } else { // >>>>>>>>>>>>>>>>>> Add the latest jar read addCurrentTokenJarWhenNecessary(currentJarToken); state = SKIP_LINE; } break; case SKIP_LINE: if (currentChar == '\n') { state = START; } break; case READING_JAR: if (currentChar == '\n') { // appends token below state = CONTINUING; // >>>>>>>>>>> Add a break to not add the jar yet as it can continue on the next line break; } else if (currentChar == ' ') { // appends token below state = SKIPPING_WHITESPACE; } else { currentJarToken.append((char) currentChar); break; } addCurrentTokenJarWhenNecessary(currentJarToken); break; } } switch (state) { case START: return true; case IN_CLASSPATH_HEADER: return true; case PAST_CLASSPATH_HEADER: return false; case SKIPPING_WHITESPACE: // >>>>>>>>>>>>>>>>>> Add the latest jar read addCurrentTokenJarWhenNecessary(currentJarToken); return true; case CONTINUING: // >>>>>>>>>>>>>>>>>> Add the latest jar read addCurrentTokenJarWhenNecessary(currentJarToken); return true; case SKIP_LINE: if (this.classpathSectionsCount != 0) { if (this.calledFilesNames == null) { return false; } } return true; case READING_JAR: // >>>>>>>>>>>>>>>>>> Add the latest jar read return false; } return true; } // >>>>>>>>>>>>>>>> Method Extracted from analyzeManifestContents in the READING_JAR Block private boolean addCurrentTokenJarWhenNecessary(StringBuffer currentJarToken) { if (currentJarToken != null && currentJarToken.length() > 0) { if (this.calledFilesNames == null) { this.calledFilesNames = new ArrayList(); } this.calledFilesNames.add(currentJarToken.toString()); currentJarToken.setLength(0); return true; } return false; } // <<<<<<<<<<<<<<<<<<<<<< public int getClasspathSectionsCount() { return this.classpathSectionsCount; } public List getCalledFileNames() { return this.calledFilesNames; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/CompoundNameVector.java0000644000175000001440000000471412212041344031660 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import org.eclipse.jdt.core.compiler.CharOperation; public final class CompoundNameVector { static int INITIAL_SIZE = 10; public int size; int maxSize; char[][][] elements; public CompoundNameVector() { this.maxSize = INITIAL_SIZE; this.size = 0; this.elements = new char[this.maxSize][][]; } public void add(char[][] newElement) { if (this.size == this.maxSize) // knows that size starts <= maxSize System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize *= 2][][]), 0, this.size); this.elements[this.size++] = newElement; } public void addAll(char[][][] newElements) { if (this.size + newElements.length >= this.maxSize) { this.maxSize = this.size + newElements.length; // assume no more elements will be added System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize][][]), 0, this.size); } System.arraycopy(newElements, 0, this.elements, this.size, newElements.length); this.size += newElements.length; } public boolean contains(char[][] element) { for (int i = this.size; --i >= 0;) if (CharOperation.equals(element, this.elements[i])) return true; return false; } public char[][] elementAt(int index) { return this.elements[index]; } public char[][] remove(char[][] element) { // assumes only one occurrence of the element exists for (int i = this.size; --i >= 0;) if (element == this.elements[i]) { // shift the remaining elements down one spot System.arraycopy(this.elements, i + 1, this.elements, i, --this.size - i); this.elements[this.size] = null; return element; } return null; } public void removeAll() { for (int i = this.size; --i >= 0;) this.elements[i] = null; this.size = 0; } public String toString() { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < this.size; i++) { buffer.append(CharOperation.toString(this.elements[i])).append("\n"); //$NON-NLS-1$ } return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/FloatUtil.java0000644000175000001440000003066112212041344030013 0ustar dokousers/******************************************************************************* * Copyright (c) 2004, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * Internal utility for declaring with hexadecimal double and float literals. * * @since 3.1 */ public class FloatUtil { private static final int DOUBLE_FRACTION_WIDTH = 52; private static final int DOUBLE_PRECISION = 53; private static final int MAX_DOUBLE_EXPONENT = +1023; private static final int MIN_NORMALIZED_DOUBLE_EXPONENT = -1022; private static final int MIN_UNNORMALIZED_DOUBLE_EXPONENT = MIN_NORMALIZED_DOUBLE_EXPONENT - DOUBLE_PRECISION; private static final int DOUBLE_EXPONENT_BIAS = +1023; private static final int DOUBLE_EXPONENT_SHIFT = 52; private static final int SINGLE_FRACTION_WIDTH = 23; private static final int SINGLE_PRECISION = 24; private static final int MAX_SINGLE_EXPONENT = +127; private static final int MIN_NORMALIZED_SINGLE_EXPONENT = -126; private static final int MIN_UNNORMALIZED_SINGLE_EXPONENT = MIN_NORMALIZED_SINGLE_EXPONENT - SINGLE_PRECISION; private static final int SINGLE_EXPONENT_BIAS = +127; private static final int SINGLE_EXPONENT_SHIFT = 23; /** * Returns the float value corresponding to the given * hexadecimal floating-point single precision literal. * The literal must be syntactically correct, and must be * a float literal (end in a 'f' or 'F'). It must not * include either leading or trailing whitespace or * a sign. *

* This method returns the same answer as * Float.parseFloat(new String(source)) does in JDK 1.5, * except that this method returns Floal.NaN if it * would underflow to 0 (parseFloat just returns 0). * The method handles all the tricky cases, including * fraction rounding to 24 bits and gradual underflow. *

* * @param source source string containing single precision * hexadecimal floating-point literal * @return the float value, including Float.POSITIVE_INFINITY * if the non-zero value is too large to be represented, and * Float.NaN if the non-zero value is too small to be represented */ public static float valueOfHexFloatLiteral(char[] source) { long bits = convertHexFloatingPointLiteralToBits(source); return Float.intBitsToFloat((int) bits); } /** * Returns the double value corresponding to the given * hexadecimal floating-point double precision literal. * The literal must be syntactially correct, and must be * a double literal (end in an optional 'd' or 'D'). * It must not include either leading or trailing whitespace or * a sign. *

* This method returns the same answer as * Double.parseDouble(new String(source)) does in JDK 1.5, * except that this method throw NumberFormatException in * the case of overflow to infinity or underflow to 0. * The method handles all the tricky cases, including * fraction rounding to 53 bits and gradual underflow. *

* * @param source source string containing double precision * hexadecimal floating-point literal * @return the double value, including Double.POSITIVE_INFINITY * if the non-zero value is too large to be represented, and * Double.NaN if the non-zero value is too small to be represented */ public static double valueOfHexDoubleLiteral(char[] source) { long bits = convertHexFloatingPointLiteralToBits(source); return Double.longBitsToDouble(bits); } /** * Returns the given hexadecimal floating-point literal as * the bits for a single-precision (float) or a * double-precision (double) IEEE floating point number. * The literal must be syntactically correct. It must not * include either leading or trailing whitespace or a sign. * * @param source source string containing hexadecimal floating-point literal * @return for double precision literals, bits suitable * for passing to Double.longBitsToDouble; for single precision literals, * bits suitable for passing to Single.intBitsToDouble in the bottom * 32 bits of the result * @throws NumberFormatException if the number cannot be parsed */ private static long convertHexFloatingPointLiteralToBits(char[] source) { int length = source.length; long mantissa = 0; // Step 1: process the '0x' lead-in int next = 0; char nextChar = source[next]; nextChar = source[next]; if (nextChar == '0') { next++; } else { throw new NumberFormatException(); } nextChar = source[next]; if (nextChar == 'X' || nextChar == 'x') { next++; } else { throw new NumberFormatException(); } // Step 2: process leading '0's either before or after the '.' int binaryPointPosition = -1; loop: while (true) { nextChar = source[next]; switch (nextChar) { case '0': next++; continue loop; case '.': binaryPointPosition = next; next++; continue loop; default: break loop; } } // Step 3: process the mantissa // leading zeros have been trimmed int mantissaBits = 0; int leadingDigitPosition = -1; loop: while (true) { nextChar = source[next]; int hexdigit; switch (nextChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': hexdigit = nextChar - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': hexdigit = (nextChar - 'a') + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': hexdigit = (nextChar - 'A') + 10; break; case '.': binaryPointPosition = next; next++; continue loop; default: if (binaryPointPosition < 0) { // record virtual '.' as being to right of all digits binaryPointPosition = next; } break loop; } if (mantissaBits == 0) { // this is the first non-zero hex digit // ignore leading binary 0's in hex digit leadingDigitPosition = next; mantissa = hexdigit; mantissaBits = 4; } else if (mantissaBits < 60) { // middle hex digits mantissa <<= 4; mantissa |= hexdigit; mantissaBits += 4; } else { // more mantissa bits than we can handle // drop this hex digit on the ground } next++; continue loop; } // Step 4: process the 'P' nextChar = source[next]; if (nextChar == 'P' || nextChar == 'p') { next++; } else { throw new NumberFormatException(); } // Step 5: process the exponent int exponent = 0; int exponentSign = +1; loop: while (next < length) { nextChar = source[next]; switch (nextChar) { case '+': exponentSign = +1; next++; continue loop; case '-': exponentSign = -1; next++; continue loop; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': int digit = nextChar - '0'; exponent = (exponent * 10) + digit; next++; continue loop; default: break loop; } } // Step 6: process the optional 'f' or 'd' boolean doublePrecision = true; if (next < length) { nextChar = source[next]; switch (nextChar) { case 'f': case 'F': doublePrecision = false; next++; break; case 'd': case 'D': doublePrecision = true; next++; break; default: throw new NumberFormatException(); } } // at this point, all the parsing is done // Step 7: handle mantissa of zero if (mantissa == 0) { return 0L; } // Step 8: normalize non-zero mantissa // mantissa is in right-hand mantissaBits // ensure that top bit (as opposed to hex digit) is 1 int scaleFactorCompensation = 0; long top = (mantissa >>> (mantissaBits - 4)); if ((top & 0x8) == 0) { mantissaBits--; scaleFactorCompensation++; if ((top & 0x4) == 0) { mantissaBits--; scaleFactorCompensation++; if ((top & 0x2) == 0) { mantissaBits--; scaleFactorCompensation++; } } } // Step 9: convert double literals to IEEE double long result = 0L; if (doublePrecision) { long fraction; if (mantissaBits > DOUBLE_PRECISION) { // more bits than we can keep int extraBits = mantissaBits - DOUBLE_PRECISION; // round to DOUBLE_PRECISION bits fraction = mantissa >>> (extraBits - 1); long lowBit = fraction & 0x1; fraction += lowBit; fraction = fraction >>> 1; if ((fraction & (1L << DOUBLE_PRECISION)) != 0) { fraction = fraction >>> 1; scaleFactorCompensation -= 1; } } else { // less bits than the faction can hold - pad on right with 0s fraction = mantissa << (DOUBLE_PRECISION - mantissaBits); } int scaleFactor = 0; // how many bits to move '.' to before leading hex digit if (mantissaBits > 0) { if (leadingDigitPosition < binaryPointPosition) { // e.g., 0x80.0p0 has scaleFactor == +8 scaleFactor = 4 * (binaryPointPosition - leadingDigitPosition); // e.g., 0x10.0p0 has scaleFactorCompensation == +3 scaleFactor -= scaleFactorCompensation; } else { // e.g., 0x0.08p0 has scaleFactor == -4 scaleFactor = -4 * (leadingDigitPosition - binaryPointPosition - 1); // e.g., 0x0.01p0 has scaleFactorCompensation == +3 scaleFactor -= scaleFactorCompensation; } } int e = (exponentSign * exponent) + scaleFactor; if (e - 1 > MAX_DOUBLE_EXPONENT) { // overflow to +infinity result = Double.doubleToLongBits(Double.POSITIVE_INFINITY); } else if (e - 1 >= MIN_NORMALIZED_DOUBLE_EXPONENT) { // can be represented as a normalized double // the left most bit must be discarded (it's always a 1) long biasedExponent = e - 1 + DOUBLE_EXPONENT_BIAS; result = fraction & ~(1L << DOUBLE_FRACTION_WIDTH); result |= (biasedExponent << DOUBLE_EXPONENT_SHIFT); } else if (e - 1 > MIN_UNNORMALIZED_DOUBLE_EXPONENT) { // can be represented as an unnormalized double long biasedExponent = 0; result = fraction >>> (MIN_NORMALIZED_DOUBLE_EXPONENT - e + 1); result |= (biasedExponent << DOUBLE_EXPONENT_SHIFT); } else { // underflow - return Double.NaN result = Double.doubleToLongBits(Double.NaN); } return result; } // Step 10: convert float literals to IEEE single long fraction; if (mantissaBits > SINGLE_PRECISION) { // more bits than we can keep int extraBits = mantissaBits - SINGLE_PRECISION; // round to DOUBLE_PRECISION bits fraction = mantissa >>> (extraBits - 1); long lowBit = fraction & 0x1; fraction += lowBit; fraction = fraction >>> 1; if ((fraction & (1L << SINGLE_PRECISION)) != 0) { fraction = fraction >>> 1; scaleFactorCompensation -= 1; } } else { // less bits than the faction can hold - pad on right with 0s fraction = mantissa << (SINGLE_PRECISION - mantissaBits); } int scaleFactor = 0; // how many bits to move '.' to before leading hex digit if (mantissaBits > 0) { if (leadingDigitPosition < binaryPointPosition) { // e.g., 0x80.0p0 has scaleFactor == +8 scaleFactor = 4 * (binaryPointPosition - leadingDigitPosition); // e.g., 0x10.0p0 has scaleFactorCompensation == +3 scaleFactor -= scaleFactorCompensation; } else { // e.g., 0x0.08p0 has scaleFactor == -4 scaleFactor = -4 * (leadingDigitPosition - binaryPointPosition - 1); // e.g., 0x0.01p0 has scaleFactorCompensation == +3 scaleFactor -= scaleFactorCompensation; } } int e = (exponentSign * exponent) + scaleFactor; if (e - 1 > MAX_SINGLE_EXPONENT) { // overflow to +infinity result = Float.floatToIntBits(Float.POSITIVE_INFINITY); } else if (e - 1 >= MIN_NORMALIZED_SINGLE_EXPONENT) { // can be represented as a normalized single // the left most bit must be discarded (it's always a 1) long biasedExponent = e - 1 + SINGLE_EXPONENT_BIAS; result = fraction & ~(1L << SINGLE_FRACTION_WIDTH); result |= (biasedExponent << SINGLE_EXPONENT_SHIFT); } else if (e - 1 > MIN_UNNORMALIZED_SINGLE_EXPONENT) { // can be represented as an unnormalized single long biasedExponent = 0; result = fraction >>> (MIN_NORMALIZED_SINGLE_EXPONENT - e + 1); result |= (biasedExponent << SINGLE_EXPONENT_SHIFT); } else { // underflow - return Float.NaN result = Float.floatToIntBits(Float.NaN); } return result; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java0000644000175000001440000000665212212041344031547 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; public final class HashtableOfPackage { // to avoid using Enumerations, walk the individual tables skipping nulls public char[] keyTable[]; public PackageBinding valueTable[]; public int elementSize; // number of elements in the table int threshold; public HashtableOfPackage() { this(3); // usually not very large } public HashtableOfPackage(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new char[extraRoom][]; this.valueTable = new PackageBinding[extraRoom]; } public boolean containsKey(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return true; if (++index == length) { index = 0; } } return false; } public PackageBinding get(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index]; if (++index == length) { index = 0; } } return null; } public PackageBinding put(char[] key, PackageBinding value) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return value; } private void rehash() { HashtableOfPackage newHashtable = new HashtableOfPackage(this.elementSize * 2); // double the number of expected elements char[] currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != null) newHashtable.put(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { String s = ""; //$NON-NLS-1$ PackageBinding pkg; for (int i = 0, length = this.valueTable.length; i < length; i++) if ((pkg = this.valueTable[i]) != null) s += pkg.toString() + "\n"; //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/Util.java0000644000175000001440000014226312212041344027027 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * daolaf@gmail.com - Contribution for bug 3292227 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.HashSet; import java.util.List; import java.util.StringTokenizer; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.eclipse.jdt.internal.compiler.batch.Main; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; public class Util implements SuffixConstants { /** * Character constant indicating the primitive type boolean in a signature. * Value is 'Z'. */ public static final char C_BOOLEAN = 'Z'; /** * Character constant indicating the primitive type byte in a signature. * Value is 'B'. */ public static final char C_BYTE = 'B'; /** * Character constant indicating the primitive type char in a signature. * Value is 'C'. */ public static final char C_CHAR = 'C'; /** * Character constant indicating the primitive type double in a signature. * Value is 'D'. */ public static final char C_DOUBLE = 'D'; /** * Character constant indicating the primitive type float in a signature. * Value is 'F'. */ public static final char C_FLOAT = 'F'; /** * Character constant indicating the primitive type int in a signature. * Value is 'I'. */ public static final char C_INT = 'I'; /** * Character constant indicating the semicolon in a signature. * Value is ';'. */ public static final char C_SEMICOLON = ';'; /** * Character constant indicating the colon in a signature. * Value is ':'. * @since 3.0 */ public static final char C_COLON = ':'; /** * Character constant indicating the primitive type long in a signature. * Value is 'J'. */ public static final char C_LONG = 'J'; /** * Character constant indicating the primitive type short in a signature. * Value is 'S'. */ public static final char C_SHORT = 'S'; /** * Character constant indicating result type void in a signature. * Value is 'V'. */ public static final char C_VOID = 'V'; /** * Character constant indicating the start of a resolved type variable in a * signature. Value is 'T'. * @since 3.0 */ public static final char C_TYPE_VARIABLE = 'T'; /** * Character constant indicating an unbound wildcard type argument * in a signature. * Value is '*'. * @since 3.0 */ public static final char C_STAR = '*'; /** * Character constant indicating an exception in a signature. * Value is '^'. * @since 3.1 */ public static final char C_EXCEPTION_START = '^'; /** * Character constant indicating a bound wildcard type argument * in a signature with extends clause. * Value is '+'. * @since 3.1 */ public static final char C_EXTENDS = '+'; /** * Character constant indicating a bound wildcard type argument * in a signature with super clause. * Value is '-'. * @since 3.1 */ public static final char C_SUPER = '-'; /** * Character constant indicating the dot in a signature. * Value is '.'. */ public static final char C_DOT = '.'; /** * Character constant indicating the dollar in a signature. * Value is '$'. */ public static final char C_DOLLAR = '$'; /** * Character constant indicating an array type in a signature. * Value is '['. */ public static final char C_ARRAY = '['; /** * Character constant indicating the start of a resolved, named type in a * signature. Value is 'L'. */ public static final char C_RESOLVED = 'L'; /** * Character constant indicating the start of an unresolved, named type in a * signature. Value is 'Q'. */ public static final char C_UNRESOLVED = 'Q'; /** * Character constant indicating the end of a named type in a signature. * Value is ';'. */ public static final char C_NAME_END = ';'; /** * Character constant indicating the start of a parameter type list in a * signature. Value is '('. */ public static final char C_PARAM_START = '('; /** * Character constant indicating the end of a parameter type list in a * signature. Value is ')'. */ public static final char C_PARAM_END = ')'; /** * Character constant indicating the start of a formal type parameter * (or type argument) list in a signature. Value is '<'. * @since 3.0 */ public static final char C_GENERIC_START = '<'; /** * Character constant indicating the end of a generic type list in a * signature. Value is '>'. * @since 3.0 */ public static final char C_GENERIC_END = '>'; /** * Character constant indicating a capture of a wildcard type in a * signature. Value is '!'. * @since 3.1 */ public static final char C_CAPTURE = '!'; public interface Displayable { String displayString(Object o); } private static final int DEFAULT_READING_SIZE = 8192; private static final int DEFAULT_WRITING_SIZE = 1024; public final static String UTF_8 = "UTF-8"; //$NON-NLS-1$ public static final String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$ public static final String EMPTY_STRING = new String(CharOperation.NO_CHAR); public static final int[] EMPTY_INT_ARRAY= new int[0]; /** * 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; outputPath = outputPath.replace('/', fileSeparatorChar); // these could be optimized out if we normalized paths once and for // all relativeFileName = relativeFileName.replace('/', fileSeparatorChar); String outputDirPath, fileName; int separatorIndex = relativeFileName.lastIndexOf(fileSeparatorChar); if (separatorIndex == -1) { if (outputPath.endsWith(fileSeparator)) { outputDirPath = outputPath.substring(0, outputPath.length() - 1); fileName = outputPath + relativeFileName; } else { outputDirPath = outputPath; fileName = outputPath + fileSeparator + relativeFileName; } } else { if (outputPath.endsWith(fileSeparator)) { outputDirPath = outputPath + relativeFileName.substring(0, separatorIndex); fileName = outputPath + relativeFileName; } else { outputDirPath = outputPath + fileSeparator + relativeFileName.substring(0, separatorIndex); fileName = outputPath + fileSeparator + relativeFileName; } } f = new File(outputDirPath); f.mkdirs(); if (f.isDirectory()) { return fileName; } else { // the directory creation failed for some reason - retry using // a slower algorithm so as to refine the diagnostic if (outputPath.endsWith(fileSeparator)) { outputPath = outputPath.substring(0, outputPath.length() - 1); } f = new File(outputPath); boolean checkFileType = false; if (f.exists()) { checkFileType = true; // pre-existed } else { // we have to create that directory if (!f.mkdirs()) { if (f.exists()) { // someone else created f -- need to check its type checkFileType = true; } else { // no one could create f -- complain throw new IOException(Messages.bind( Messages.output_notValidAll, f.getAbsolutePath())); } } } if (checkFileType) { if (!f.isDirectory()) { throw new IOException(Messages.bind( Messages.output_isFile, f.getAbsolutePath())); } } 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()); checkFileType = false; // reset if (f.exists()) { checkFileType = true; // this is suboptimal, but it catches corner cases // in which a regular file pre-exists } else { // we have to create that directory if (!f.mkdir()) { if (f.exists()) { // someone else created f -- need to check its type checkFileType = true; } else { // no one could create f -- complain throw new IOException(Messages.bind( Messages.output_notValid, outDir.substring(outputPath.length() + 1, outDir.length() - 1), outputPath)); } } } if (checkFileType) { if (!f.isDirectory()) { throw new IOException(Messages.bind( Messages.output_isFile, f.getAbsolutePath())); } } token = tokenizer.nextToken(); } // token contains the last one return outDir.append(token).toString(); } } /** * Returns the given bytes as a char array using a given encoding (null means platform default). */ public static char[] bytesToChar(byte[] bytes, String encoding) throws IOException { return getInputStreamAsCharArray(new ByteArrayInputStream(bytes), bytes.length, encoding); } /** * Returns the outer most enclosing type's visibility for the given TypeDeclaration * and visibility based on compiler options. */ public static int computeOuterMostVisibility(TypeDeclaration typeDeclaration, int visibility) { while (typeDeclaration != null) { switch (typeDeclaration.modifiers & ExtraCompilerModifiers.AccVisibilityMASK) { case ClassFileConstants.AccPrivate: visibility = ClassFileConstants.AccPrivate; break; case ClassFileConstants.AccDefault: if (visibility != ClassFileConstants.AccPrivate) { visibility = ClassFileConstants.AccDefault; } break; case ClassFileConstants.AccProtected: if (visibility == ClassFileConstants.AccPublic) { visibility = ClassFileConstants.AccProtected; } break; } typeDeclaration = typeDeclaration.enclosingType; } return visibility; } /** * Returns the contents of the given file as a byte array. * @throws IOException if a problem occured reading the file. */ public static byte[] getFileByteContent(File file) throws IOException { InputStream stream = null; try { stream = new BufferedInputStream(new FileInputStream(file)); return getInputStreamAsByteArray(stream, (int) file.length()); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // ignore } } } } /** * Returns the contents of the given file as a char array. * When encoding is null, then the platform default one is used * @throws IOException if a problem occured reading the file. */ public static char[] getFileCharContent(File file, String encoding) throws IOException { InputStream stream = null; try { stream = new FileInputStream(file); return getInputStreamAsCharArray(stream, (int) file.length(), encoding); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // ignore } } } } private static FileOutputStream getFileOutputStream(boolean generatePackagesStructure, String outputPath, String relativeFileName) throws IOException { if (generatePackagesStructure) { return 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); } } return new FileOutputStream(new File(fileName)); } } /* * NIO support to get input stream as byte array. * Not used as with JDK 1.4.2 this support is slower than standard IO one... * Keep it as comment for future in case of next JDK versions improve performance * in this area... * public static byte[] getInputStreamAsByteArray(FileInputStream stream, int length) throws IOException { FileChannel channel = stream.getChannel(); int size = (int)channel.size(); if (length >= 0 && length < size) size = length; byte[] contents = new byte[size]; ByteBuffer buffer = ByteBuffer.wrap(contents); channel.read(buffer); return contents; } */ /** * Returns the given input stream's contents as a byte array. * If a length is specified (i.e. if length != -1), only length bytes * are returned. Otherwise all bytes in the stream are returned. * Note this doesn't close the stream. * @throws IOException if a problem occured reading the stream. */ public static byte[] getInputStreamAsByteArray(InputStream stream, int length) throws IOException { byte[] contents; if (length == -1) { contents = new byte[0]; int contentsLength = 0; int amountRead = -1; do { int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K // resize contents if needed if (contentsLength + amountRequested > contents.length) { System.arraycopy( contents, 0, contents = new byte[contentsLength + amountRequested], 0, contentsLength); } // read as many bytes as possible amountRead = stream.read(contents, contentsLength, amountRequested); if (amountRead > 0) { // remember length of contents contentsLength += amountRead; } } while (amountRead != -1); // resize contents if necessary if (contentsLength < contents.length) { System.arraycopy( contents, 0, contents = new byte[contentsLength], 0, contentsLength); } } else { contents = new byte[length]; int len = 0; int readSize = 0; while ((readSize != -1) && (len != length)) { // See PR 1FMS89U // We record first the read size. In this case len is the actual read size. len += readSize; readSize = stream.read(contents, len, length - len); } } return contents; } /* * NIO support to get input stream as char array. * Not used as with JDK 1.4.2 this support is slower than standard IO one... * Keep it as comment for future in case of next JDK versions improve performance * in this area... public static char[] getInputStreamAsCharArray(FileInputStream stream, int length, String encoding) throws IOException { FileChannel channel = stream.getChannel(); int size = (int)channel.size(); if (length >= 0 && length < size) size = length; Charset charset = encoding==null?systemCharset:Charset.forName(encoding); if (charset != null) { MappedByteBuffer bbuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size); CharsetDecoder decoder = charset.newDecoder(); CharBuffer buffer = decoder.decode(bbuffer); char[] contents = new char[buffer.limit()]; buffer.get(contents); return contents; } throw new UnsupportedCharsetException(SYSTEM_FILE_ENCODING); } */ /** * Returns the given input stream's contents as a character array. * If a length is specified (i.e. if length != -1), this represents the number of bytes in the stream. * Note this doesn't close the stream. * @throws IOException if a problem occured reading the stream. */ public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) throws IOException { BufferedReader reader = null; try { reader = encoding == null ? new BufferedReader(new InputStreamReader(stream)) : new BufferedReader(new InputStreamReader(stream, encoding)); } catch (UnsupportedEncodingException e) { // encoding is not supported reader = new BufferedReader(new InputStreamReader(stream)); } char[] contents; int totalRead = 0; if (length == -1) { contents = CharOperation.NO_CHAR; } else { // length is a good guess when the encoding produces less or the same amount of characters than the file length contents = new char[length]; // best guess } while (true) { int amountRequested; if (totalRead < length) { // until known length is met, reuse same array sized eagerly amountRequested = length - totalRead; } else { // reading beyond known length int current = reader.read(); if (current < 0) break; amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K // resize contents if needed if (totalRead + 1 + amountRequested > contents.length) System.arraycopy(contents, 0, contents = new char[totalRead + 1 + amountRequested], 0, totalRead); // add current character contents[totalRead++] = (char) current; // coming from totalRead==length } // read as many chars as possible int amountRead = reader.read(contents, totalRead, amountRequested); if (amountRead < 0) break; totalRead += amountRead; } // Do not keep first character for UTF-8 BOM encoding int start = 0; if (totalRead > 0 && UTF_8.equals(encoding)) { if (contents[0] == 0xFEFF) { // if BOM char then skip totalRead--; start = 1; } } // resize contents if necessary if (totalRead < contents.length) System.arraycopy(contents, start, contents = new char[totalRead], 0, totalRead); return contents; } /** * Returns a one line summary for an exception (extracted from its stacktrace: name + first frame) * @param exception * @return one line summary for an exception */ public static String getExceptionSummary(Throwable exception) { StringWriter stringWriter = new StringWriter(); exception.printStackTrace(new PrintWriter(stringWriter)); StringBuffer buffer = stringWriter.getBuffer(); StringBuffer exceptionBuffer = new StringBuffer(50); exceptionBuffer.append(exception.toString()); // only keep leading frame portion of the trace (i.e. line no. 2 from the stacktrace) lookupLine2: for (int i = 0, lineSep = 0, max = buffer.length(), line2Start = 0; i < max; i++) { switch (buffer.charAt(i)) { case '\n': case '\r' : if (line2Start > 0) { exceptionBuffer.append(' ').append(buffer.substring(line2Start, i)); break lookupLine2; } lineSep++; break; case ' ' : case '\t' : break; default : if (lineSep > 0) { line2Start = i; lineSep = 0; } break; } } return exceptionBuffer.toString(); } public static int getLineNumber(int position, int[] lineEnds, int g, int d) { if (lineEnds == null) return 1; if (d == -1) return 1; int m = g, start; while (g <= d) { m = g + (d - g) /2; if (position < (start = lineEnds[m])) { d = m-1; } else if (position > start) { g = m+1; } else { return m + 1; } } if (position < lineEnds[m]) { return m+1; } return m+2; } /** * Returns the contents of the given zip entry as a byte array. * @throws IOException if a problem occured reading the zip entry. */ public static byte[] getZipEntryByteContent(ZipEntry ze, ZipFile zip) throws IOException { InputStream stream = null; try { InputStream inputStream = zip.getInputStream(ze); if (inputStream == null) throw new IOException("Invalid zip entry name : " + ze.getName()); //$NON-NLS-1$ stream = new BufferedInputStream(inputStream); return getInputStreamAsByteArray(stream, (int) ze.getSize()); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // ignore } } } } public static int hashCode(Object[] array) { int prime = 31; if (array == null) { return 0; } int result = 1; for (int index = 0; index < array.length; index++) { result = prime * result + (array[index] == null ? 0 : array[index].hashCode()); } return result; } /** * Returns whether the given name is potentially a zip archive file name * (it has a file extension and it is not ".java" nor ".class") */ public final static boolean isPotentialZipArchive(String name) { int lastDot = name.lastIndexOf('.'); if (lastDot == -1) return false; // no file extension, it cannot be a zip archive name if (name.lastIndexOf(File.separatorChar) > lastDot) return false; // dot was before the last file separator, it cannot be a zip archive name int length = name.length(); int extensionLength = length - lastDot - 1; if (extensionLength == EXTENSION_java.length()) { for (int i = extensionLength-1; i >=0; i--) { if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_java.charAt(i)) { break; // not a ".java" file, check ".class" file case below } if (i == 0) { return false; // it is a ".java" file, it cannot be a zip archive name } } } if (extensionLength == EXTENSION_class.length()) { for (int i = extensionLength-1; i >=0; i--) { if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_class.charAt(i)) { return true; // not a ".class" file, so this is a potential archive name } } return false; // it is a ".class" file, it cannot be a zip archive name } return true; // it is neither a ".java" file nor a ".class" file, so this is a potential archive name } /** * Returns true iff str.toLowerCase().endsWith(".class") * implementation is not creating extra strings. */ public final static boolean isClassFileName(char[] name) { int nameLength = name == null ? 0 : name.length; int suffixLength = SUFFIX_CLASS.length; if (nameLength < suffixLength) return false; for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { char c = name[offset + i]; if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false; } return true; } /** * Returns true iff str.toLowerCase().endsWith(".class") * implementation is not creating extra strings. */ public final static boolean isClassFileName(String name) { int nameLength = name == null ? 0 : name.length(); int suffixLength = SUFFIX_CLASS.length; if (nameLength < suffixLength) return false; for (int i = 0; i < suffixLength; i++) { char c = name.charAt(nameLength - i - 1); int suffixIndex = suffixLength - i - 1; if (c != SUFFIX_class[suffixIndex] && c != SUFFIX_CLASS[suffixIndex]) return false; } return true; } /* TODO (philippe) should consider promoting it to CharOperation * Returns whether the given resource path matches one of the inclusion/exclusion * patterns. * NOTE: should not be asked directly using pkg root pathes * @see IClasspathEntry#getInclusionPatterns * @see IClasspathEntry#getExclusionPatterns */ public final static boolean isExcluded(char[] path, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean isFolderPath) { if (inclusionPatterns == null && exclusionPatterns == null) return false; inclusionCheck: if (inclusionPatterns != null) { for (int i = 0, length = inclusionPatterns.length; i < length; i++) { char[] pattern = inclusionPatterns[i]; char[] folderPattern = pattern; if (isFolderPath) { int lastSlash = CharOperation.lastIndexOf('/', pattern); if (lastSlash != -1 && lastSlash != pattern.length-1){ // trailing slash -> adds '**' for free (see http://ant.apache.org/manual/dirtasks.html) int star = CharOperation.indexOf('*', pattern, lastSlash); if ((star == -1 || star >= pattern.length-1 || pattern[star+1] != '*')) { folderPattern = CharOperation.subarray(pattern, 0, lastSlash); } } } if (CharOperation.pathMatch(folderPattern, path, true, '/')) { break inclusionCheck; } } return true; // never included } if (isFolderPath) { path = CharOperation.concat(path, new char[] {'*'}, '/'); } if (exclusionPatterns != null) { for (int i = 0, length = exclusionPatterns.length; i < length; i++) { if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) { return true; } } } return false; } /** * Returns true iff str.toLowerCase().endsWith(".java") * implementation is not creating extra strings. */ public final static boolean isJavaFileName(char[] name) { int nameLength = name == null ? 0 : name.length; int suffixLength = SUFFIX_JAVA.length; if (nameLength < suffixLength) return false; for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { char c = name[offset + i]; if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false; } return true; } /** * Returns true iff str.toLowerCase().endsWith(".java") * implementation is not creating extra strings. */ public final static boolean isJavaFileName(String name) { int nameLength = name == null ? 0 : name.length(); int suffixLength = SUFFIX_JAVA.length; if (nameLength < suffixLength) return false; for (int i = 0; i < suffixLength; i++) { char c = name.charAt(nameLength - i - 1); int suffixIndex = suffixLength - i - 1; if (c != SUFFIX_java[suffixIndex] && c != SUFFIX_JAVA[suffixIndex]) return false; } return true; } public static void reverseQuickSort(char[][] list, int left, int right) { int original_left= left; int original_right= right; char[] mid= list[left + ((right-left)/2)]; do { while (CharOperation.compareTo(list[left], mid) > 0) { left++; } while (CharOperation.compareTo(mid, list[right]) > 0) { right--; } if (left <= right) { char[] tmp= list[left]; list[left]= list[right]; list[right]= tmp; left++; right--; } } while (left <= right); if (original_left < right) { reverseQuickSort(list, original_left, right); } if (left < original_right) { reverseQuickSort(list, left, original_right); } } public static void reverseQuickSort(char[][] list, int left, int right, int[] result) { int original_left= left; int original_right= right; char[] mid= list[left + ((right-left)/2)]; do { while (CharOperation.compareTo(list[left], mid) > 0) { left++; } while (CharOperation.compareTo(mid, list[right]) > 0) { right--; } if (left <= right) { char[] tmp= list[left]; list[left]= list[right]; list[right]= tmp; int temp = result[left]; result[left] = result[right]; result[right] = temp; left++; right--; } } while (left <= right); if (original_left < right) { reverseQuickSort(list, original_left, right, result); } if (left < original_right) { reverseQuickSort(list, left, original_right, result); } } /** * INTERNAL USE-ONLY * Search the column number corresponding to a specific position */ public static final int searchColumnNumber(int[] startLineIndexes, int lineNumber, int position) { switch(lineNumber) { case 1 : return position + 1; case 2: return position - startLineIndexes[0]; default: int line = lineNumber - 2; int length = startLineIndexes.length; if (line >= length) { return position - startLineIndexes[length - 1]; } return position - startLineIndexes[line]; } } /** * Converts a boolean value into Boolean. * @param bool The boolean to convert * @return The corresponding Boolean object (TRUE or FALSE). */ public static Boolean toBoolean(boolean bool) { if (bool) { return Boolean.TRUE; } else { return Boolean.FALSE; } } /** * Converts an array of Objects into String. */ public static String toString(Object[] objects) { return toString(objects, new Displayable(){ public String displayString(Object o) { if (o == null) return "null"; //$NON-NLS-1$ return o.toString(); } }); } /** * Converts an array of Objects into String. */ public static String toString(Object[] objects, Displayable renderer) { if (objects == null) return ""; //$NON-NLS-1$ StringBuffer buffer = new StringBuffer(10); for (int i = 0; i < objects.length; i++){ if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append(renderer.displayString(objects[i])); } return buffer.toString(); } /** * 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 given output directory * @param relativeFileName the given relative file name * @param classFile the given classFile to write * */ public static void writeToDisk(boolean generatePackagesStructure, String outputPath, String relativeFileName, ClassFile classFile) throws IOException { FileOutputStream file = getFileOutputStream(generatePackagesStructure, outputPath, relativeFileName); /* use java.nio to write if (true) { FileChannel ch = file.getChannel(); try { ByteBuffer buffer = ByteBuffer.allocate(classFile.headerOffset + classFile.contentsOffset); buffer.put(classFile.header, 0, classFile.headerOffset); buffer.put(classFile.contents, 0, classFile.contentsOffset); buffer.flip(); while (true) { if (ch.write(buffer) == 0) break; } } finally { ch.close(); } return; } */ BufferedOutputStream output = new BufferedOutputStream(file, DEFAULT_WRITING_SIZE); // BufferedOutputStream output = new BufferedOutputStream(file); try { // if no IOException occured, output cannot be null output.write(classFile.header, 0, classFile.headerOffset); output.write(classFile.contents, 0, classFile.contentsOffset); output.flush(); } catch(IOException e) { throw e; } finally { output.close(); } } public static void recordNestedType(ClassFile classFile, TypeBinding typeBinding) { if (classFile.visitedTypes == null) { classFile.visitedTypes = new HashSet(3); } else if (classFile.visitedTypes.contains(typeBinding)) { // type is already visited return; } classFile.visitedTypes.add(typeBinding); if (typeBinding.isParameterizedType() && ((typeBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0)) { ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) typeBinding; ReferenceBinding genericType = parameterizedTypeBinding.genericType(); if ((genericType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { recordNestedType(classFile, genericType); } TypeBinding[] arguments = parameterizedTypeBinding.arguments; if (arguments != null) { for (int j = 0, max2 = arguments.length; j < max2; j++) { TypeBinding argument = arguments[j]; if (argument.isWildcard()) { WildcardBinding wildcardBinding = (WildcardBinding) argument; TypeBinding bound = wildcardBinding.bound; if (bound != null && ((bound.tagBits & TagBits.ContainsNestedTypeReferences) != 0)) { recordNestedType(classFile, bound); } ReferenceBinding superclass = wildcardBinding.superclass(); if (superclass != null && ((superclass.tagBits & TagBits.ContainsNestedTypeReferences) != 0)) { recordNestedType(classFile, superclass); } ReferenceBinding[] superInterfaces = wildcardBinding.superInterfaces(); if (superInterfaces != null) { for (int k = 0, max3 = superInterfaces.length; k < max3; k++) { ReferenceBinding superInterface = superInterfaces[k]; if ((superInterface.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { recordNestedType(classFile, superInterface); } } } } else if ((argument.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { recordNestedType(classFile, argument); } } } } else if (typeBinding.isTypeVariable() && ((typeBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0)) { TypeVariableBinding typeVariableBinding = (TypeVariableBinding) typeBinding; TypeBinding upperBound = typeVariableBinding.upperBound(); if (upperBound != null && ((upperBound.tagBits & TagBits.ContainsNestedTypeReferences) != 0)) { recordNestedType(classFile, upperBound); } TypeBinding[] upperBounds = typeVariableBinding.otherUpperBounds(); if (upperBounds != null) { for (int k = 0, max3 = upperBounds.length; k < max3; k++) { TypeBinding otherUpperBound = upperBounds[k]; if ((otherUpperBound.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { recordNestedType(classFile, otherUpperBound); } } } } else if (typeBinding.isNestedType()) { classFile.recordInnerClasses(typeBinding); } } /* * External API */ public static File getJavaHome() { String javaHome = System.getProperty("java.home");//$NON-NLS-1$ if (javaHome != null) { File javaHomeFile = new File(javaHome); if (javaHomeFile.exists()) { return javaHomeFile; } } return null; } public static void collectRunningVMBootclasspath(List bootclasspaths) { /* no bootclasspath specified * we can try to retrieve the default librairies of the VM used to run * the batch compiler */ String javaversion = System.getProperty("java.version");//$NON-NLS-1$ if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$ throw new IllegalStateException(); } /* * Handle >= JDK 1.2.2 settings: retrieve the bootclasspath */ // check bootclasspath properties for Sun, JRockit and Harmony VMs String bootclasspathProperty = System.getProperty("sun.boot.class.path"); //$NON-NLS-1$ if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) { // IBM J9 VMs bootclasspathProperty = System.getProperty("vm.boot.class.path"); //$NON-NLS-1$ if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) { // Harmony using IBM VME bootclasspathProperty = System.getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$ } } if ((bootclasspathProperty != null) && (bootclasspathProperty.length() != 0)) { StringTokenizer tokenizer = new StringTokenizer(bootclasspathProperty, File.pathSeparator); String token; while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); FileSystem.Classpath currentClasspath = FileSystem.getClasspath(token, null, null); if (currentClasspath != null) { bootclasspaths.add(currentClasspath); } } } else { // try to get all jars inside the lib folder of the java home final File javaHome = getJavaHome(); if (javaHome != null) { File[] directoriesToCheck = null; if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$ directoriesToCheck = new File[] { new File(javaHome, "../Classes"), //$NON-NLS-1$ }; } else { // fall back to try to retrieve them out of the lib directory directoriesToCheck = new File[] { new File(javaHome, "lib") //$NON-NLS-1$ }; } File[][] systemLibrariesJars = Main.getLibrariesFiles(directoriesToCheck); if (systemLibrariesJars != null) { for (int i = 0, max = systemLibrariesJars.length; i < max; i++) { File[] current = systemLibrariesJars[i]; if (current != null) { for (int j = 0, max2 = current.length; j < max2; j++) { FileSystem.Classpath classpath = FileSystem.getClasspath(current[j].getAbsolutePath(), null, false, null, null); if (classpath != null) { bootclasspaths.add(classpath); } } } } } } } } public static int getParameterCount(char[] methodSignature) { try { int count = 0; int i = CharOperation.indexOf(C_PARAM_START, methodSignature); if (i < 0) { throw new IllegalArgumentException(); } else { i++; } for (;;) { if (methodSignature[i] == C_PARAM_END) { return count; } int e= Util.scanTypeSignature(methodSignature, i); if (e < 0) { throw new IllegalArgumentException(); } else { i = e + 1; } count++; } } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException(); } } /** * Scans the given string for a type signature starting at the given index * and returns the index of the last character. *
	 * TypeSignature:
	 *  |  BaseTypeSignature
	 *  |  ArrayTypeSignature
	 *  |  ClassTypeSignature
	 *  |  TypeVariableSignature
	 * 
* * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a type signature */ public static int scanTypeSignature(char[] string, int start) { // need a minimum 1 char if (start >= string.length) { throw new IllegalArgumentException(); } char c = string[start]; switch (c) { case C_ARRAY : return scanArrayTypeSignature(string, start); case C_RESOLVED : case C_UNRESOLVED : return scanClassTypeSignature(string, start); case C_TYPE_VARIABLE : return scanTypeVariableSignature(string, start); 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 : return scanBaseTypeSignature(string, start); case C_CAPTURE : return scanCaptureTypeSignature(string, start); case C_EXTENDS: case C_SUPER: case C_STAR: return scanTypeBoundSignature(string, start); default : throw new IllegalArgumentException(); } } /** * Scans the given string for a base type signature starting at the given index * and returns the index of the last character. *
	 * BaseTypeSignature:
	 *     B | C | D | F | I
	 *   | J | S | V | Z
	 * 
* Note that although the base type "V" is only allowed in method return types, * there is no syntactic ambiguity. This method will accept them anywhere * without complaint. * * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a base type signature */ public static int scanBaseTypeSignature(char[] string, int start) { // need a minimum 1 char if (start >= string.length) { throw new IllegalArgumentException(); } char c = string[start]; if ("BCDFIJSVZ".indexOf(c) >= 0) { //$NON-NLS-1$ return start; } else { throw new IllegalArgumentException(); } } /** * Scans the given string for an array type signature starting at the given * index and returns the index of the last character. *
	 * ArrayTypeSignature:
	 *     [ TypeSignature
	 * 
* * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not an array type signature */ public static int scanArrayTypeSignature(char[] string, int start) { int length = string.length; // need a minimum 2 char if (start >= length - 1) { throw new IllegalArgumentException(); } char c = string[start]; if (c != C_ARRAY) { throw new IllegalArgumentException(); } c = string[++start]; while(c == C_ARRAY) { // need a minimum 2 char if (start >= length - 1) { throw new IllegalArgumentException(); } c = string[++start]; } return scanTypeSignature(string, start); } /** * Scans the given string for a capture of a wildcard type signature starting at the given * index and returns the index of the last character. *
	 * CaptureTypeSignature:
	 *     ! TypeBoundSignature
	 * 
* * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a capture type signature */ public static int scanCaptureTypeSignature(char[] string, int start) { // need a minimum 2 char if (start >= string.length - 1) { throw new IllegalArgumentException(); } char c = string[start]; if (c != C_CAPTURE) { throw new IllegalArgumentException(); } return scanTypeBoundSignature(string, start + 1); } /** * Scans the given string for a type variable signature starting at the given * index and returns the index of the last character. *
	 * TypeVariableSignature:
	 *     T Identifier ;
	 * 
* * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a type variable signature */ public static int scanTypeVariableSignature(char[] string, int start) { // need a minimum 3 chars "Tx;" if (start >= string.length - 2) { throw new IllegalArgumentException(); } // must start in "T" char c = string[start]; if (c != C_TYPE_VARIABLE) { throw new IllegalArgumentException(); } int id = scanIdentifier(string, start + 1); c = string[id + 1]; if (c == C_SEMICOLON) { return id + 1; } else { throw new IllegalArgumentException(); } } /** * Scans the given string for an identifier starting at the given * index and returns the index of the last character. * Stop characters are: ";", ":", "<", ">", "/", ".". * * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not an identifier */ public static int scanIdentifier(char[] string, int start) { // need a minimum 1 char if (start >= string.length) { throw new IllegalArgumentException(); } int p = start; while (true) { char c = string[p]; if (c == '<' || c == '>' || c == ':' || c == ';' || c == '.' || c == '/') { return p - 1; } p++; if (p == string.length) { return p - 1; } } } /** * Scans the given string for a class type signature starting at the given * index and returns the index of the last character. *
	 * ClassTypeSignature:
	 *     { L | Q } Identifier
	 *           { { / | . Identifier [ < TypeArgumentSignature* > ] }
	 *           ;
	 * 
* Note that although all "/"-identifiers most come before "."-identifiers, * there is no syntactic ambiguity. This method will accept them without * complaint. * * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a class type signature */ public static int scanClassTypeSignature(char[] string, int start) { // 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) { return -1; } int p = start + 1; while (true) { if (p >= string.length) { throw new IllegalArgumentException(); } c = string[p]; if (c == C_SEMICOLON) { // all done return p; } else if (c == C_GENERIC_START) { int e = scanTypeArgumentSignatures(string, p); p = e; } else if (c == C_DOT || c == '/') { int id = scanIdentifier(string, p + 1); p = id; } p++; } } /** * Scans the given string for a type bound signature starting at the given * index and returns the index of the last character. *
	 * TypeBoundSignature:
	 *     [-+] TypeSignature ;
	 *     *
	 * 
* * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a type variable signature */ public static int scanTypeBoundSignature(char[] string, int start) { // need a minimum 1 char for wildcard if (start >= string.length) { throw new IllegalArgumentException(); } char c = string[start]; switch (c) { case C_STAR : return start; case C_SUPER : case C_EXTENDS : // need a minimum 3 chars "+[I" if (start >= string.length - 2) { throw new IllegalArgumentException(); } break; default : // must start in "+/-" throw new IllegalArgumentException(); } c = string[++start]; switch (c) { case C_CAPTURE : return scanCaptureTypeSignature(string, start); case C_SUPER : case C_EXTENDS : return scanTypeBoundSignature(string, start); case C_RESOLVED : case C_UNRESOLVED : return scanClassTypeSignature(string, start); case C_TYPE_VARIABLE : return scanTypeVariableSignature(string, start); case C_ARRAY : return scanArrayTypeSignature(string, start); case C_STAR: return start; default: throw new IllegalArgumentException(); } } /** * Scans the given string for a list of type argument signatures starting at * the given index and returns the index of the last character. *
	 * TypeArgumentSignatures:
	 *     < TypeArgumentSignature* >
	 * 
* Note that although there is supposed to be at least one type argument, there * is no syntactic ambiguity if there are none. This method will accept zero * type argument signatures without complaint. * * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a list of type arguments * signatures */ public static int scanTypeArgumentSignatures(char[] string, int start) { // 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(); } int p = start + 1; while (true) { if (p >= string.length) { throw new IllegalArgumentException(); } c = string[p]; if (c == C_GENERIC_END) { return p; } int e = scanTypeArgumentSignature(string, p); p = e + 1; } } /** * Scans the given string for a type argument signature starting at the given * index and returns the index of the last character. *
	 * TypeArgumentSignature:
	 *     *
	 *  |  + TypeSignature
	 *  |  - TypeSignature
	 *  |  TypeSignature
	 * 
* Note that although base types are not allowed in type arguments, there is * no syntactic ambiguity. This method will accept them without complaint. * * @param string the signature string * @param start the 0-based character index of the first character * @return the 0-based character index of the last character * @exception IllegalArgumentException if this is not a type argument signature */ public static int scanTypeArgumentSignature(char[] string, int start) { // need a minimum 1 char if (start >= string.length) { throw new IllegalArgumentException(); } char c = string[start]; switch (c) { case C_STAR : return start; case C_EXTENDS : case C_SUPER : return scanTypeBoundSignature(string, start); default : return scanTypeSignature(string, start); } } }ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashSetOfInt.java0000644000175000001440000000644712212041344030414 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * HashSet of Object[] */ public final class HashSetOfInt implements Cloneable { // to avoid using Enumerations, walk the individual tables skipping nulls public int[] set; public int elementSize; // number of elements in the table int threshold; public HashSetOfInt() { this(13); } public HashSetOfInt(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.set = new int[extraRoom]; } public Object clone() throws CloneNotSupportedException { HashSetOfInt result = (HashSetOfInt) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.set.length; result.set = new int[length]; System.arraycopy(this.set, 0, result.set, 0, length); return result; } public boolean contains(int element) { int length = this.set.length; int index = element % length; int currentElement; while ((currentElement = this.set[index]) != 0) { if (currentElement == element) return true; if (++index == length) { index = 0; } } return false; } public int add(int element) { int length = this.set.length; int index = element % length; int currentElement; while ((currentElement = this.set[index]) != 0) { if (currentElement == element) return this.set[index] = element; if (++index == length) { index = 0; } } this.set[index] = element; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return element; } public int remove(int element) { int length = this.set.length; int index = element % length; int currentElement; while ((currentElement = this.set[index]) != 0) { if (currentElement == element) { int existing = this.set[index]; this.elementSize--; this.set[index] = 0; rehash(); return existing; } if (++index == length) { index = 0; } } return 0; } private void rehash() { HashSetOfInt newHashSet = new HashSetOfInt(this.elementSize * 2); // double the number of expected elements int currentElement; for (int i = this.set.length; --i >= 0;) if ((currentElement = this.set[i]) != 0) newHashSet.add(currentElement); this.set = newHashSet.set; this.threshold = newHashSet.threshold; } public int size() { return this.elementSize; } public String toString() { StringBuffer buffer = new StringBuffer(); int element; for (int i = 0, length = this.set.length; i < length; i++) if ((element = this.set[i]) != 0) { buffer.append(element); if (i != length-1) buffer.append('\n'); } return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfInt.java0000644000175000001440000000571112212041344030741 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * Hashtable for non-zero int keys. */ public final class HashtableOfInt { // to avoid using Enumerations, walk the individual tables skipping nulls public int[] keyTable; public Object[] valueTable; public int elementSize; // number of elements in the table int threshold; public HashtableOfInt() { this(13); } public HashtableOfInt(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new int[extraRoom]; this.valueTable = new Object[extraRoom]; } public boolean containsKey(int key) { int length = this.keyTable.length, index = key % length; int currentKey; while ((currentKey = this.keyTable[index]) != 0) { if (currentKey == key) return true; if (++index == length) { index = 0; } } return false; } public Object get(int key) { int length = this.keyTable.length, index = key % length; int currentKey; while ((currentKey = this.keyTable[index]) != 0) { if (currentKey == key) return this.valueTable[index]; if (++index == length) { index = 0; } } return null; } public Object put(int key, Object value) { int length = this.keyTable.length, index = key % length; int currentKey; while ((currentKey = this.keyTable[index]) != 0) { if (currentKey == key) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return value; } private void rehash() { HashtableOfInt newHashtable = new HashtableOfInt(this.elementSize * 2); // double the number of expected elements int currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != 0) newHashtable.put(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { String s = ""; //$NON-NLS-1$ Object object; for (int i = 0, length = this.valueTable.length; i < length; i++) if ((object = this.valueTable[i]) != null) s += this.keyTable[i] + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfLong.java0000644000175000001440000000601612212041344031105 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * Hashtable for non-zero long keys. */ public final class HashtableOfLong { // to avoid using Enumerations, walk the individual tables skipping nulls public long[] keyTable; public Object[] valueTable; public int elementSize; // number of elements in the table int threshold; public HashtableOfLong() { this(13); } public HashtableOfLong(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new long[extraRoom]; this.valueTable = new Object[extraRoom]; } public boolean containsKey(long key) { int length = this.keyTable.length, index = ((int)(key >>> 32)) % length; long currentKey; while ((currentKey = this.keyTable[index]) != 0) { if (currentKey == key) return true; if (++index == length) { index = 0; } } return false; } public Object get(long key) { int length = this.keyTable.length, index = ((int)(key >>> 32)) % length; long currentKey; while ((currentKey = this.keyTable[index]) != 0) { if (currentKey == key) return this.valueTable[index]; if (++index == length) { index = 0; } } return null; } public Object put(long key, Object value) { int length = this.keyTable.length, index = ((int)(key >>> 32)) % length; long currentKey; while ((currentKey = this.keyTable[index]) != 0) { if (currentKey == key) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return value; } private void rehash() { HashtableOfLong newHashtable = new HashtableOfLong(this.elementSize * 2); // double the number of expected elements long currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != 0) newHashtable.put(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { String s = ""; //$NON-NLS-1$ Object object; for (int i = 0, length = this.valueTable.length; i < length; i++) if ((object = this.valueTable[i]) != null) s += this.keyTable[i] + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/Sorting.java0000644000175000001440000000472712212041344027541 0ustar dokousers/********************************************************************** * Copyright 2008, 2013 Technical University Berlin, Germany and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stephan Herrmann - Initial API and implementation **********************************************************************/ package org.eclipse.jdt.internal.compiler.util; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; /** * Sorting utilities. * Originally developed for the Object Teams project. */ public class Sorting { /** * Topological sort for types * Guarantee: supertypes come before subtypes. */ public static ReferenceBinding[] sortTypes(ReferenceBinding[] types) { int len = types.length; ReferenceBinding[] unsorted = new ReferenceBinding[len]; ReferenceBinding[] sorted = new ReferenceBinding[len]; System.arraycopy(types, 0, unsorted, 0, len); int o = 0; for(int i=0; i int} */ public final class HashtableOfIntValues implements Cloneable { public static final int NO_VALUE = Integer.MIN_VALUE; // to avoid using Enumerations, walk the individual tables skipping nulls public char[] keyTable[]; public int valueTable[]; public int elementSize; // number of elements in the table int threshold; public HashtableOfIntValues() { this(13); } public HashtableOfIntValues(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new char[extraRoom][]; this.valueTable = new int[extraRoom]; } public Object clone() throws CloneNotSupportedException { HashtableOfIntValues result = (HashtableOfIntValues) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.keyTable.length; result.keyTable = new char[length][]; System.arraycopy(this.keyTable, 0, result.keyTable, 0, length); length = this.valueTable.length; result.valueTable = new int[length]; System.arraycopy(this.valueTable, 0, result.valueTable, 0, length); return result; } public boolean containsKey(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return true; if (++index == length) { index = 0; } } return false; } public int get(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index]; if (++index == length) { index = 0; } } return NO_VALUE; } public int put(char[] key, int value) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return value; } public int removeKey(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) { int value = this.valueTable[index]; this.elementSize--; this.keyTable[index] = null; this.valueTable[index] = NO_VALUE; rehash(); return value; } if (++index == length) { index = 0; } } return NO_VALUE; } private void rehash() { HashtableOfIntValues newHashtable = new HashtableOfIntValues(this.elementSize * 2); // double the number of expected elements char[] currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != null) newHashtable.put(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { String s = ""; //$NON-NLS-1$ char[] key; for (int i = 0, length = this.valueTable.length; i < length; i++) if ((key = this.keyTable[i]) != null) s += new String(key) + " -> " + this.valueTable[i] + "\n"; //$NON-NLS-2$ //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/Messages.java0000644000175000001440000002074612212041344027662 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; public final class Messages { private static class MessagesProperties extends Properties { private static final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC; private static final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL; private static final long serialVersionUID = 1L; private final Map fields; public MessagesProperties(Field[] fieldArray, String bundleName) { super(); final int len = fieldArray.length; this.fields = new HashMap(len * 2); for (int i = 0; i < len; i++) { this.fields.put(fieldArray[i].getName(), fieldArray[i]); } } /* (non-Javadoc) * @see java.util.Hashtable#put(java.lang.Object, java.lang.Object) */ public synchronized Object put(Object key, Object value) { try { Field field = (Field) this.fields.get(key); if (field == null) { return null; } //can only set value of public static non-final fields if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED) return null; // Set the value into the field. We should never get an exception here because // we know we have a public static non-final field. If we do get an exception, silently // log it and continue. This means that the field will (most likely) be un-initialized and // will fail later in the code and if so then we will see both the NPE and this error. try { field.set(null, value); } catch (Exception e) { // ignore } } catch (SecurityException e) { // ignore } return null; } } private static String[] nlSuffixes; private static final String EXTENSION = ".properties"; //$NON-NLS-1$ private static final String BUNDLE_NAME = "org.eclipse.jdt.internal.compiler.messages";//$NON-NLS-1$ private Messages() { // Do not instantiate } public static String compilation_unresolvedProblem; public static String compilation_unresolvedProblems; public static String compilation_request; public static String compilation_loadBinary; public static String compilation_process; public static String compilation_write; public static String compilation_done; public static String compilation_units; public static String compilation_unit; public static String compilation_internalError; public static String compilation_beginningToCompile; public static String compilation_processing; public static String output_isFile; public static String output_notValidAll; public static String output_notValid; public static String problem_noSourceInformation; public static String problem_atLine; public static String abort_invalidAttribute; public static String abort_invalidExceptionAttribute; public static String abort_invalidOpcode; public static String abort_missingCode; public static String abort_againstSourceModel; public static String accept_cannot; public static String parser_incorrectPath; public static String parser_moveFiles; public static String parser_syntaxRecovery; public static String parser_regularParse; public static String parser_missingFile; public static String parser_corruptedFile; public static String parser_endOfFile; public static String parser_endOfConstructor; public static String parser_endOfMethod; public static String parser_endOfInitializer; public static String ast_missingCode; public static String constant_cannotCastedInto; public static String constant_cannotConvertedTo; static { initializeMessages(BUNDLE_NAME, Messages.class); } /** * Bind the given message's substitution locations with the given string values. * * @param message the message to be manipulated * @return the manipulated String */ public static String bind(String message) { return bind(message, null); } /** * Bind the given message's substitution locations with the given string values. * * @param message the message to be manipulated * @param binding the object to be inserted into the message * @return the manipulated String */ public static String bind(String message, Object binding) { return bind(message, new Object[] {binding}); } /** * Bind the given message's substitution locations with the given string values. * * @param message the message to be manipulated * @param binding1 An object to be inserted into the message * @param binding2 A second object to be inserted into the message * @return the manipulated String */ public static String bind(String message, Object binding1, Object binding2) { return bind(message, new Object[] {binding1, binding2}); } /** * Bind the given message's substitution locations with the given string values. * * @param message the message to be manipulated * @param bindings An array of objects to be inserted into the message * @return the manipulated String */ public static String bind(String message, Object[] bindings) { return MessageFormat.format(message, bindings); } /* * Build an array of directories to search */ private static String[] buildVariants(String root) { if (nlSuffixes == null) { //build list of suffixes for loading resource bundles String nl = Locale.getDefault().toString(); ArrayList result = new ArrayList(4); int lastSeparator; while (true) { result.add('_' + nl + EXTENSION); lastSeparator = nl.lastIndexOf('_'); if (lastSeparator == -1) break; nl = nl.substring(0, lastSeparator); } //add the empty suffix last (most general) result.add(EXTENSION); nlSuffixes = (String[]) result.toArray(new String[result.size()]); } root = root.replace('.', '/'); String[] variants = new String[nlSuffixes.length]; for (int i = 0; i < variants.length; i++) variants[i] = root + nlSuffixes[i]; return variants; } public static void initializeMessages(String bundleName, Class clazz) { // load the resource bundle and set the fields final Field[] fields = clazz.getDeclaredFields(); load(bundleName, clazz.getClassLoader(), fields); // iterate over the fields in the class to make sure that there aren't any empty ones final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC; final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL; final int numFields = fields.length; for (int i = 0; i < numFields; i++) { Field field = fields[i]; if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED) continue; try { // Set the value into the field if its empty. We should never get an exception here because // we know we have a public static non-final field. If we do get an exception, silently // log it and continue. This means that the field will (most likely) be un-initialized and // will fail later in the code and if so then we will see both the NPE and this error. if (field.get(clazz) == null) { String value = "Missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$ field.set(null, value); } } catch (IllegalArgumentException e) { // ignore } catch (IllegalAccessException e) { // ignore } } } /** * Load the given resource bundle using the specified class loader. */ public static void load(final String bundleName, final ClassLoader loader, final Field[] fields) { final String[] variants = buildVariants(bundleName); // search the dirs in reverse order so the cascading defaults is set correctly for (int i = variants.length; --i >= 0;) { InputStream input = (loader == null) ? ClassLoader.getSystemResourceAsStream(variants[i]) : loader.getResourceAsStream(variants[i]); if (input == null) continue; try { final MessagesProperties properties = new MessagesProperties(fields, bundleName); properties.load(input); } catch (IOException e) { // ignore } finally { try { input.close(); } catch (IOException e) { // ignore } } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java0000644000175000001440000000302112212041344031237 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; public interface SuffixConstants { public final static String EXTENSION_class = "class"; //$NON-NLS-1$ public final static String EXTENSION_CLASS = "CLASS"; //$NON-NLS-1$ public final static String EXTENSION_java = "java"; //$NON-NLS-1$ public final static String EXTENSION_JAVA = "JAVA"; //$NON-NLS-1$ public final static String SUFFIX_STRING_class = "." + EXTENSION_class; //$NON-NLS-1$ public final static String SUFFIX_STRING_CLASS = "." + EXTENSION_CLASS; //$NON-NLS-1$ public final static String SUFFIX_STRING_java = "." + EXTENSION_java; //$NON-NLS-1$ public final static String SUFFIX_STRING_JAVA = "." + EXTENSION_JAVA; //$NON-NLS-1$ public final static char[] SUFFIX_class = SUFFIX_STRING_class.toCharArray(); public final static char[] SUFFIX_CLASS = SUFFIX_STRING_CLASS.toCharArray(); public final static char[] SUFFIX_java = SUFFIX_STRING_java.toCharArray(); public final static char[] SUFFIX_JAVA = SUFFIX_STRING_JAVA.toCharArray(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/SimpleSet.java0000644000175000001440000001036612212041344030015 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * A simple lookup table is a non-synchronized Hashtable, whose keys * and values are Objects. It also uses linear probing to resolve collisions * rather than a linked list of hash table entries. */ public final class SimpleSet implements Cloneable { // to avoid using Enumerations, walk the individual values skipping nulls public Object[] values; public int elementSize; // number of elements in the table public int threshold; public SimpleSet() { this(13); } public SimpleSet(int size) { if (size < 3) size = 3; this.elementSize = 0; this.threshold = size + 1; // size is the expected number of elements this.values = new Object[2 * size + 1]; } public Object add(Object object) { int length = this.values.length; int index = (object.hashCode() & 0x7FFFFFFF) % length; Object current; while ((current = this.values[index]) != null) { if (current.equals(object)) return this.values[index] = object; if (++index == length) index = 0; } this.values[index] = object; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return object; } public Object addIfNotIncluded(Object object) { int length = this.values.length; int index = (object.hashCode() & 0x7FFFFFFF) % length; Object current; while ((current = this.values[index]) != null) { if (current.equals(object)) return null; // already existed if (++index == length) index = 0; } this.values[index] = object; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return object; } public void asArray(Object[] copy) { if (this.elementSize != copy.length) throw new IllegalArgumentException(); int index = this.elementSize; for (int i = 0, l = this.values.length; i < l && index > 0; i++) if (this.values[i] != null) copy[--index] = this.values[i]; } public void clear() { for (int i = this.values.length; --i >= 0;) this.values[i] = null; this.elementSize = 0; } public Object clone() throws CloneNotSupportedException { SimpleSet result = (SimpleSet) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.values.length; result.values = new Object[length]; System.arraycopy(this.values, 0, result.values, 0, length); return result; } public boolean includes(Object object) { int length = this.values.length; int index = (object.hashCode() & 0x7FFFFFFF) % length; Object current; while ((current = this.values[index]) != null) { if (current.equals(object)) return true; if (++index == length) index = 0; } return false; } public Object remove(Object object) { int length = this.values.length; int index = (object.hashCode() & 0x7FFFFFFF) % length; Object current; while ((current = this.values[index]) != null) { if (current.equals(object)) { this.elementSize--; Object oldValue = this.values[index]; this.values[index] = null; if (this.values[index + 1 == length ? 0 : index + 1] != null) rehash(); // only needed if a possible collision existed return oldValue; } if (++index == length) index = 0; } return null; } private void rehash() { SimpleSet newSet = new SimpleSet(this.elementSize * 2); // double the number of expected elements Object current; for (int i = this.values.length; --i >= 0;) if ((current = this.values[i]) != null) newSet.add(current); this.values = newSet.values; this.elementSize = newSet.elementSize; this.threshold = newSet.threshold; } public String toString() { String s = ""; //$NON-NLS-1$ Object object; for (int i = 0, l = this.values.length; i < l; i++) if ((object = this.values[i]) != null) s += object.toString() + "\n"; //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/SimpleNameVector.java0000644000175000001440000000516712212041344031330 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import org.eclipse.jdt.core.compiler.CharOperation; public final class SimpleNameVector { static int INITIAL_SIZE = 10; public int size; int maxSize; char[][] elements; public SimpleNameVector() { this.maxSize = INITIAL_SIZE; this.size = 0; this.elements = new char[this.maxSize][]; } public void add(char[] newElement) { if (this.size == this.maxSize) // knows that size starts <= maxSize System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize *= 2][]), 0, this.size); this.elements[this.size++] = newElement; } public void addAll(char[][] newElements) { if (this.size + newElements.length >= this.maxSize) { this.maxSize = this.size + newElements.length; // assume no more elements will be added System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize][]), 0, this.size); } System.arraycopy(newElements, 0, this.elements, this.size, newElements.length); this.size += newElements.length; } public void copyInto(Object[] targetArray){ System.arraycopy(this.elements, 0, targetArray, 0, this.size); } public boolean contains(char[] element) { for (int i = this.size; --i >= 0;) if (CharOperation.equals(element, this.elements[i])) return true; return false; } public char[] elementAt(int index) { return this.elements[index]; } public char[] remove(char[] element) { // assumes only one occurrence of the element exists for (int i = this.size; --i >= 0;) if (element == this.elements[i]) { // shift the remaining elements down one spot System.arraycopy(this.elements, i + 1, this.elements, i, --this.size - i); this.elements[this.size] = null; return element; } return null; } public void removeAll() { for (int i = this.size; --i >= 0;) this.elements[i] = null; this.size = 0; } public int size(){ return this.size; } public String toString() { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < this.size; i++) { buffer.append(this.elements[i]).append("\n"); //$NON-NLS-1$ } return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java0000644000175000001440000000666112212041344031135 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; public final class HashtableOfType { // to avoid using Enumerations, walk the individual tables skipping nulls public char[] keyTable[]; public ReferenceBinding valueTable[]; public int elementSize; // number of elements in the table int threshold; public HashtableOfType() { this(3); } public HashtableOfType(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new char[extraRoom][]; this.valueTable = new ReferenceBinding[extraRoom]; } public boolean containsKey(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return true; if (++index == length) { index = 0; } } return false; } public ReferenceBinding get(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index]; if (++index == length) { index = 0; } } return null; } public ReferenceBinding put(char[] key, ReferenceBinding value) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return value; } private void rehash() { HashtableOfType newHashtable = new HashtableOfType(this.elementSize < 100 ? 100 : this.elementSize * 2); // double the number of expected elements char[] currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != null) newHashtable.put(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { String s = ""; //$NON-NLS-1$ ReferenceBinding type; for (int i = 0, length = this.valueTable.length; i < length; i++) if ((type = this.valueTable[i]) != null) s += type.toString() + "\n"; //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java0000644000175000001440000001250712212041344031502 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * A simple lookup table is a non-synchronized Hashtable, whose keys * and values are Objects. It also uses linear probing to resolve collisions * rather than a linked list of hash table entries. */ public final class SimpleLookupTable implements Cloneable { // to avoid using Enumerations, walk the individual tables skipping nulls public Object[] keyTable; public Object[] valueTable; public int elementSize; // number of elements in the table public int threshold; public SimpleLookupTable() { this(13); } public SimpleLookupTable(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.5f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new Object[extraRoom]; this.valueTable = new Object[extraRoom]; } public Object clone() throws CloneNotSupportedException { SimpleLookupTable result = (SimpleLookupTable) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.keyTable.length; result.keyTable = new Object[length]; System.arraycopy(this.keyTable, 0, result.keyTable, 0, length); length = this.valueTable.length; result.valueTable = new Object[length]; System.arraycopy(this.valueTable, 0, result.valueTable, 0, length); return result; } public boolean containsKey(Object key) { int length = this.keyTable.length; int index = (key.hashCode() & 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return true; if (++index == length) index = 0; } return false; } public Object get(Object key) { int length = this.keyTable.length; int index = (key.hashCode() & 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return this.valueTable[index]; if (++index == length) index = 0; } return null; } public Object getKey(Object key) { int length = this.keyTable.length; int index = (key.hashCode() & 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return currentKey; if (++index == length) index = 0; } return key; } public Object keyForValue(Object valueToMatch) { if (valueToMatch != null) for (int i = 0, l = this.keyTable.length; i < l; i++) if (this.keyTable[i] != null && valueToMatch.equals(this.valueTable[i])) return this.keyTable[i]; return null; } public Object put(Object key, Object value) { int length = this.keyTable.length; int index = (key.hashCode() & 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return this.valueTable[index] = value; if (++index == length) index = 0; } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return value; } public Object removeKey(Object key) { int length = this.keyTable.length; int index = (key.hashCode() & 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) { this.elementSize--; Object oldValue = this.valueTable[index]; this.keyTable[index] = null; this.valueTable[index] = null; if (this.keyTable[index + 1 == length ? 0 : index + 1] != null) rehash(); // only needed if a possible collision existed return oldValue; } if (++index == length) index = 0; } return null; } public void removeValue(Object valueToRemove) { boolean rehash = false; for (int i = 0, l = this.valueTable.length; i < l; i++) { Object value = this.valueTable[i]; if (value != null && value.equals(valueToRemove)) { this.elementSize--; this.keyTable[i] = null; this.valueTable[i] = null; if (!rehash && this.keyTable[i + 1 == l ? 0 : i + 1] != null) rehash = true; // only needed if a possible collision existed } } if (rehash) rehash(); } private void rehash() { SimpleLookupTable newLookupTable = new SimpleLookupTable(this.elementSize * 2); // double the number of expected elements Object currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != null) newLookupTable.put(currentKey, this.valueTable[i]); this.keyTable = newLookupTable.keyTable; this.valueTable = newLookupTable.valueTable; this.elementSize = newLookupTable.elementSize; this.threshold = newLookupTable.threshold; } public String toString() { String s = ""; //$NON-NLS-1$ Object object; for (int i = 0, l = this.valueTable.length; i < l; i++) if ((object = this.valueTable[i]) != null) s += this.keyTable[i].toString() + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/SimpleSetOfCharArray.java0000644000175000001440000001071312212041344032073 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import org.eclipse.jdt.core.compiler.CharOperation; /** * A simple lookup table is a non-synchronized Hashtable, whose keys * and values are char[]. It also uses linear probing to resolve collisions * rather than a linked list of hash table entries. */ public final class SimpleSetOfCharArray implements Cloneable { // to avoid using Enumerations, walk the individual values skipping nulls public char[][] values; public int elementSize; // number of elements in the table public int threshold; public SimpleSetOfCharArray() { this(13); } public SimpleSetOfCharArray(int size) { if (size < 3) size = 3; this.elementSize = 0; this.threshold = size + 1; // size is the expected number of elements this.values = new char[2 * size + 1][]; } public Object add(char[] object) { int length = this.values.length; int index = (CharOperation.hashCode(object) & 0x7FFFFFFF) % length; char[] current; while ((current = this.values[index]) != null) { if (CharOperation.equals(current, object)) return this.values[index] = object; if (++index == length) index = 0; } this.values[index] = object; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return object; } public void asArray(Object[] copy) { if (this.elementSize != copy.length) throw new IllegalArgumentException(); int index = this.elementSize; for (int i = 0, l = this.values.length; i < l && index > 0; i++) if (this.values[i] != null) copy[--index] = this.values[i]; } public void clear() { for (int i = this.values.length; --i >= 0;) this.values[i] = null; this.elementSize = 0; } public Object clone() throws CloneNotSupportedException { SimpleSetOfCharArray result = (SimpleSetOfCharArray) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.values.length; result.values = new char[length][]; System.arraycopy(this.values, 0, result.values, 0, length); return result; } public char[] get(char[] object) { int length = this.values.length; int index = (CharOperation.hashCode(object) & 0x7FFFFFFF) % length; char[] current; while ((current = this.values[index]) != null) { if (CharOperation.equals(current, object)) return current; if (++index == length) index = 0; } this.values[index] = object; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return object; } public boolean includes(char[] object) { int length = this.values.length; int index = (CharOperation.hashCode(object) & 0x7FFFFFFF) % length; char[] current; while ((current = this.values[index]) != null) { if (CharOperation.equals(current, object)) return true; if (++index == length) index = 0; } return false; } public char[] remove(char[] object) { int length = this.values.length; int index = (CharOperation.hashCode(object) & 0x7FFFFFFF) % length; char[] current; while ((current = this.values[index]) != null) { if (CharOperation.equals(current, object)) { this.elementSize--; char[] oldValue = this.values[index]; this.values[index] = null; if (this.values[index + 1 == length ? 0 : index + 1] != null) rehash(); // only needed if a possible collision existed return oldValue; } if (++index == length) index = 0; } return null; } private void rehash() { SimpleSetOfCharArray newSet = new SimpleSetOfCharArray(this.elementSize * 2); // double the number of expected elements char[] current; for (int i = this.values.length; --i >= 0;) if ((current = this.values[i]) != null) newSet.add(current); this.values = newSet.values; this.elementSize = newSet.elementSize; this.threshold = newSet.threshold; } public String toString() { String s = ""; //$NON-NLS-1$ char[] object; for (int i = 0, l = this.values.length; i < l; i++) if ((object = this.values[i]) != null) s += new String(object) + "\n"; //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/ObjectVector.java0000644000175000001440000000674612212041344030510 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; public final class ObjectVector { static int INITIAL_SIZE = 10; public int size; int maxSize; Object[] elements; public ObjectVector() { this(INITIAL_SIZE); } public ObjectVector(int initialSize) { this.maxSize = initialSize > 0 ? initialSize : INITIAL_SIZE; this.size = 0; this.elements = new Object[this.maxSize]; } public void add(Object newElement) { if (this.size == this.maxSize) // knows that size starts <= maxSize System.arraycopy(this.elements, 0, (this.elements = new Object[this.maxSize *= 2]), 0, this.size); this.elements[this.size++] = newElement; } public void addAll(Object[] newElements) { if (this.size + newElements.length >= this.maxSize) { this.maxSize = this.size + newElements.length; // assume no more elements will be added System.arraycopy(this.elements, 0, (this.elements = new Object[this.maxSize]), 0, this.size); } System.arraycopy(newElements, 0, this.elements, this.size, newElements.length); this.size += newElements.length; } public void addAll(ObjectVector newVector) { if (this.size + newVector.size >= this.maxSize) { this.maxSize = this.size + newVector.size; // assume no more elements will be added System.arraycopy(this.elements, 0, (this.elements = new Object[this.maxSize]), 0, this.size); } System.arraycopy(newVector.elements, 0, this.elements, this.size, newVector.size); this.size += newVector.size; } /** * Identity check */ public boolean containsIdentical(Object element) { for (int i = this.size; --i >= 0;) if (element == this.elements[i]) return true; return false; } /** * Equality check */ public boolean contains(Object element) { for (int i = this.size; --i >= 0;) if (element.equals(this.elements[i])) return true; return false; } public void copyInto(Object[] targetArray){ this.copyInto(targetArray, 0); } public void copyInto(Object[] targetArray, int index){ System.arraycopy(this.elements, 0, targetArray, index, this.size); } public Object elementAt(int index) { return this.elements[index]; } public Object find(Object element) { for (int i = this.size; --i >= 0;) if (element.equals(this.elements[i])) return this.elements[i]; return null; } public Object remove(Object element) { // assumes only one occurrence of the element exists for (int i = this.size; --i >= 0;) if (element.equals(this.elements[i])) { // shift the remaining elements down one spot System.arraycopy(this.elements, i + 1, this.elements, i, --this.size - i); this.elements[this.size] = null; return element; } return null; } public void removeAll() { for (int i = this.size; --i >= 0;) this.elements[i] = null; this.size = 0; } public int size(){ return this.size; } public String toString() { String s = ""; //$NON-NLS-1$ for (int i = 0; i < this.size; i++) s += this.elements[i].toString() + "\n"; //$NON-NLS-1$ return s; } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToInt.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToInt.jav0000644000175000001440000001050512212041344032227 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; /** * Hashtable of {Object --> int } */ public final class HashtableOfObjectToInt implements Cloneable { // to avoid using Enumerations, walk the individual tables skipping nulls public Object[] keyTable; public int[] valueTable; public int elementSize; // number of elements in the table int threshold; public HashtableOfObjectToInt() { this(13); } public HashtableOfObjectToInt(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new Object[extraRoom]; this.valueTable = new int[extraRoom]; } public Object clone() throws CloneNotSupportedException { HashtableOfObjectToInt result = (HashtableOfObjectToInt) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.keyTable.length; result.keyTable = new Object[length]; System.arraycopy(this.keyTable, 0, result.keyTable, 0, length); length = this.valueTable.length; result.valueTable = new int[length]; System.arraycopy(this.valueTable, 0, result.valueTable, 0, length); return result; } public boolean containsKey(Object key) { int length = this.keyTable.length, index = (key.hashCode()& 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return true; if (++index == length) { index = 0; } } return false; } public int get(Object key) { int length = this.keyTable.length, index = (key.hashCode()& 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) return this.valueTable[index]; if (++index == length) { index = 0; } } return -1; } public void keysToArray(Object[] array) { int index = 0; for (int i=0, length=this.keyTable.length; i this.threshold) rehash(); return value; } public int removeKey(Object key) { int length = this.keyTable.length, index = (key.hashCode()& 0x7FFFFFFF) % length; Object currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.equals(key)) { int value = this.valueTable[index]; this.elementSize--; this.keyTable[index] = null; rehash(); return value; } if (++index == length) { index = 0; } } return -1; } private void rehash() { HashtableOfObjectToInt newHashtable = new HashtableOfObjectToInt(this.elementSize * 2); // double the number of expected elements Object currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != null) newHashtable.put(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { String s = ""; //$NON-NLS-1$ Object key; for (int i = 0, length = this.keyTable.length; i < length; i++) if ((key = this.keyTable[i]) != null) s += key + " -> " + this.valueTable[i] + "\n"; //$NON-NLS-2$ //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/util/HashtableOfObject.java0000644000175000001440000001271212212041344031414 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; import org.eclipse.jdt.core.compiler.CharOperation; /** * Hashtable of {char[] --> Object } */ public final class HashtableOfObject implements Cloneable { // to avoid using Enumerations, walk the individual tables skipping nulls public char[] keyTable[]; public Object valueTable[]; public int elementSize; // number of elements in the table int threshold; public HashtableOfObject() { this(13); } public HashtableOfObject(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.keyTable = new char[extraRoom][]; this.valueTable = new Object[extraRoom]; } public void clear() { for (int i = this.keyTable.length; --i >= 0;) { this.keyTable[i] = null; this.valueTable[i] = null; } this.elementSize = 0; } public Object clone() throws CloneNotSupportedException { HashtableOfObject result = (HashtableOfObject) super.clone(); result.elementSize = this.elementSize; result.threshold = this.threshold; int length = this.keyTable.length; result.keyTable = new char[length][]; System.arraycopy(this.keyTable, 0, result.keyTable, 0, length); length = this.valueTable.length; result.valueTable = new Object[length]; System.arraycopy(this.valueTable, 0, result.valueTable, 0, length); return result; } public boolean containsKey(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return true; if (++index == length) { index = 0; } } return false; } public Object get(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index]; if (++index == length) { index = 0; } } return null; } public Object put(char[] key, Object value) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) return this.valueTable[index] = value; if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); return value; } /** * Put a value at the index of the given using the local hash code computation. *

* Note that this is an unsafe put as there's no prior verification whether * the given key already exists in the table or not. *

* @param key The key of the table entry * @param value The value of the table entry */ public void putUnsafely(char[] key, Object value) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (++index == length) { index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) { rehash(); } } public Object removeKey(char[] key) { int length = this.keyTable.length, index = CharOperation.hashCode(key) % length; int keyLength = key.length; char[] currentKey; while ((currentKey = this.keyTable[index]) != null) { if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) { Object value = this.valueTable[index]; this.elementSize--; this.keyTable[index] = null; this.valueTable[index] = null; rehash(); return value; } if (++index == length) { index = 0; } } return null; } private void rehash() { HashtableOfObject newHashtable = new HashtableOfObject(this.elementSize * 2); // double the number of expected elements char[] currentKey; for (int i = this.keyTable.length; --i >= 0;) if ((currentKey = this.keyTable[i]) != null) newHashtable.putUnsafely(currentKey, this.valueTable[i]); this.keyTable = newHashtable.keyTable; this.valueTable = newHashtable.valueTable; this.threshold = newHashtable.threshold; } public int size() { return this.elementSize; } public String toString() { String s = ""; //$NON-NLS-1$ Object object; for (int i = 0, length = this.valueTable.length; i < length; i++) if ((object = this.valueTable[i]) != null) s += new String(this.keyTable[i]) + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$ return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ProcessTaskManager.java0000644000175000001440000001213312212041344030661 0ustar dokousers/******************************************************************************* * Copyright (c) 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.util.Messages; public class ProcessTaskManager implements Runnable { Compiler compiler; private int unitIndex; private Thread processingThread; CompilationUnitDeclaration unitToProcess; private Throwable caughtException; // queue volatile int currentIndex, availableIndex, size, sleepCount; CompilationUnitDeclaration[] units; public static final int PROCESSED_QUEUE_SIZE = 12; public ProcessTaskManager(Compiler compiler) { this.compiler = compiler; this.unitIndex = 0; this.currentIndex = 0; this.availableIndex = 0; this.size = PROCESSED_QUEUE_SIZE; this.sleepCount = 0; // 0 is no one, +1 is the processing thread & -1 is the writing/main thread this.units = new CompilationUnitDeclaration[this.size]; synchronized (this) { this.processingThread = new Thread(this, "Compiler Processing Task"); //$NON-NLS-1$ this.processingThread.setDaemon(true); this.processingThread.start(); } } // add unit to the queue - wait if no space is available private synchronized void addNextUnit(CompilationUnitDeclaration newElement) { while (this.units[this.availableIndex] != null) { //System.out.print('a'); //if (this.sleepCount < 0) throw new IllegalStateException(new Integer(this.sleepCount).toString()); this.sleepCount = 1; try { wait(250); } catch (InterruptedException ignore) { // ignore } this.sleepCount = 0; } this.units[this.availableIndex++] = newElement; if (this.availableIndex >= this.size) this.availableIndex = 0; if (this.sleepCount <= -1) notify(); // wake up writing thread to accept next unit - could be the last one - must avoid deadlock } public CompilationUnitDeclaration removeNextUnit() throws Error { CompilationUnitDeclaration next = null; boolean yield = false; synchronized (this) { next = this.units[this.currentIndex]; if (next == null || this.caughtException != null) { do { if (this.processingThread == null) { if (this.caughtException != null) { // rethrow the caught exception from the processingThread in the main compiler thread if (this.caughtException instanceof Error) throw (Error) this.caughtException; throw (RuntimeException) this.caughtException; } return null; } //System.out.print('r'); //if (this.sleepCount > 0) throw new IllegalStateException(new Integer(this.sleepCount).toString()); this.sleepCount = -1; try { wait(100); } catch (InterruptedException ignore) { // ignore } this.sleepCount = 0; next = this.units[this.currentIndex]; } while (next == null); } this.units[this.currentIndex++] = null; if (this.currentIndex >= this.size) this.currentIndex = 0; if (this.sleepCount >= 1 && ++this.sleepCount > 4) { notify(); // wake up processing thread to add next unit but only after removing some elements first yield = this.sleepCount > 8; } } if (yield) Thread.yield(); return next; } public void run() { while (this.processingThread != null) { this.unitToProcess = null; int index = -1; try { synchronized (this) { if (this.processingThread == null) return; this.unitToProcess = this.compiler.getUnitToProcess(this.unitIndex); if (this.unitToProcess == null) { this.processingThread = null; return; } index = this.unitIndex++; } try { this.compiler.reportProgress(Messages.bind(Messages.compilation_processing, new String(this.unitToProcess.getFileName()))); if (this.compiler.options.verbose) this.compiler.out.println( Messages.bind(Messages.compilation_process, new String[] { String.valueOf(index + 1), String.valueOf(this.compiler.totalUnits), new String(this.unitToProcess.getFileName()) })); this.compiler.process(this.unitToProcess, index); } finally { if (this.unitToProcess != null) this.unitToProcess.cleanUp(); } addNextUnit(this.unitToProcess); } catch (Error e) { synchronized (this) { this.processingThread = null; this.caughtException = e; } return; } catch (RuntimeException e) { synchronized (this) { this.processingThread = null; this.caughtException = e; } return; } } } public void shutdown() { try { Thread t = null; synchronized (this) { if (this.processingThread != null) { t = this.processingThread; this.processingThread = null; notifyAll(); } } if (t != null) t.join(250); // do not wait forever } catch (InterruptedException ignored) { // ignore } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/0000755000175000001440000000000012212041344025556 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser22.rsc0000644000175000001440000000121212212041344027723 0ustar dokousers!# ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java0000644000175000001440000003050312212041344031304 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; /** * Internal field structure for parsing recovery */ import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; public class RecoveredField extends RecoveredElement { public FieldDeclaration fieldDeclaration; boolean alreadyCompletedFieldInitialization; public RecoveredAnnotation[] annotations; public int annotationCount; public int modifiers; public int modifiersStart; public RecoveredType[] anonymousTypes; public int anonymousTypeCount; public RecoveredField(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance){ this(fieldDeclaration, parent, bracketBalance, null); } public RecoveredField(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){ super(parent, bracketBalance, parser); this.fieldDeclaration = fieldDeclaration; this.alreadyCompletedFieldInitialization = fieldDeclaration.initialization != null; } /* * Record a field declaration */ public RecoveredElement add(FieldDeclaration addedfieldDeclaration, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore if (this.fieldDeclaration.declarationSourceStart == addedfieldDeclaration.declarationSourceStart) { if (this.fieldDeclaration.initialization != null) { this.updateSourceEndIfNecessary(this.fieldDeclaration.initialization.sourceEnd); } else { this.updateSourceEndIfNecessary(this.fieldDeclaration.sourceEnd); } } else { this.updateSourceEndIfNecessary(previousAvailableLineEnd(addedfieldDeclaration.declarationSourceStart - 1)); } return this.parent.add(addedfieldDeclaration, bracketBalanceValue); } /* * Record an expression statement if field is expecting an initialization expression, * used for completion inside field initializers. */ public RecoveredElement add(Statement statement, int bracketBalanceValue) { if (this.alreadyCompletedFieldInitialization || !(statement instanceof Expression)) { return super.add(statement, bracketBalanceValue); } else { if (statement.sourceEnd > 0) this.alreadyCompletedFieldInitialization = true; // else we may still be inside the initialization, having parsed only a part of it yet this.fieldDeclaration.initialization = (Expression)statement; this.fieldDeclaration.declarationSourceEnd = statement.sourceEnd; this.fieldDeclaration.declarationEnd = statement.sourceEnd; return this; } } /* * Record a type declaration if this field is expecting an initialization expression * and the type is an anonymous type. * Used for completion inside field initializers. */ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { if (this.alreadyCompletedFieldInitialization || ((typeDeclaration.bits & ASTNode.IsAnonymousType) == 0) || (this.fieldDeclaration.declarationSourceEnd != 0 && typeDeclaration.sourceStart > this.fieldDeclaration.declarationSourceEnd)) { return super.add(typeDeclaration, bracketBalanceValue); } else { // Prepare anonymous type list if (this.anonymousTypes == null) { this.anonymousTypes = new RecoveredType[5]; this.anonymousTypeCount = 0; } else { if (this.anonymousTypeCount == this.anonymousTypes.length) { System.arraycopy( this.anonymousTypes, 0, (this.anonymousTypes = new RecoveredType[2 * this.anonymousTypeCount]), 0, this.anonymousTypeCount); } } // Store type declaration as an anonymous type RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); this.anonymousTypes[this.anonymousTypeCount++] = element; return element; } } public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) { if (annotCount > 0) { Annotation[] existingAnnotations = this.fieldDeclaration.annotations; if (existingAnnotations != null) { this.annotations = new RecoveredAnnotation[annotCount]; this.annotationCount = 0; next : for (int i = 0; i < annotCount; i++) { for (int j = 0; j < existingAnnotations.length; j++) { if (annots[i].annotation == existingAnnotations[j]) continue next; } this.annotations[this.annotationCount++] = annots[i]; } } else { this.annotations = annots; this.annotationCount = annotCount; } } if (mods != 0) { this.modifiers = mods; this.modifiersStart = modsSourceStart; } } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.fieldDeclaration; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.fieldDeclaration.declarationSourceEnd; } public String toString(int tab){ StringBuffer buffer = new StringBuffer(tabString(tab)); buffer.append("Recovered field:\n"); //$NON-NLS-1$ this.fieldDeclaration.print(tab + 1, buffer); if (this.annotations != null) { for (int i = 0; i < this.annotationCount; i++) { buffer.append("\n"); //$NON-NLS-1$ buffer.append(this.annotations[i].toString(tab + 1)); } } if (this.anonymousTypes != null) { for (int i = 0; i < this.anonymousTypeCount; i++){ buffer.append("\n"); //$NON-NLS-1$ buffer.append(this.anonymousTypes[i].toString(tab + 1)); } } return buffer.toString(); } public FieldDeclaration updatedFieldDeclaration(int depth, Set knownTypes){ /* update annotations */ if (this.modifiers != 0) { this.fieldDeclaration.modifiers |= this.modifiers; if (this.modifiersStart < this.fieldDeclaration.declarationSourceStart) { this.fieldDeclaration.declarationSourceStart = this.modifiersStart; } } /* update annotations */ if (this.annotationCount > 0){ int existingCount = this.fieldDeclaration.annotations == null ? 0 : this.fieldDeclaration.annotations.length; Annotation[] annotationReferences = new Annotation[existingCount + this.annotationCount]; if (existingCount > 0){ System.arraycopy(this.fieldDeclaration.annotations, 0, annotationReferences, this.annotationCount, existingCount); } for (int i = 0; i < this.annotationCount; i++){ annotationReferences[i] = this.annotations[i].updatedAnnotationReference(); } this.fieldDeclaration.annotations = annotationReferences; int start = this.annotations[0].annotation.sourceStart; if (start < this.fieldDeclaration.declarationSourceStart) { this.fieldDeclaration.declarationSourceStart = start; } } if (this.anonymousTypes != null) { if(this.fieldDeclaration.initialization == null) { ArrayInitializer recoveredInitializers = null; int recoveredInitializersCount = 0; if (this.anonymousTypeCount > 1) { recoveredInitializers = new ArrayInitializer(); recoveredInitializers.expressions = new Expression[this.anonymousTypeCount]; } for (int i = 0; i < this.anonymousTypeCount; i++){ RecoveredType recoveredType = this.anonymousTypes[i]; TypeDeclaration typeDeclaration = recoveredType.typeDeclaration; if(typeDeclaration.declarationSourceEnd == 0) { typeDeclaration.declarationSourceEnd = this.fieldDeclaration.declarationSourceEnd; typeDeclaration.bodyEnd = this.fieldDeclaration.declarationSourceEnd; } if (recoveredType.preserveContent){ TypeDeclaration anonymousType = recoveredType.updatedTypeDeclaration(depth + 1, knownTypes); if (anonymousType != null) { if (this.anonymousTypeCount > 1) { if (recoveredInitializersCount == 0) { this.fieldDeclaration.initialization = recoveredInitializers; } recoveredInitializers.expressions[recoveredInitializersCount++] = anonymousType.allocation; } else { this.fieldDeclaration.initialization = anonymousType.allocation; } int end = anonymousType.declarationSourceEnd; if (end > this.fieldDeclaration.declarationSourceEnd) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=307337 this.fieldDeclaration.declarationSourceEnd = end; this.fieldDeclaration.declarationEnd = end; } } } } if (this.anonymousTypeCount > 0) this.fieldDeclaration.bits |= ASTNode.HasLocalType; } else if(this.fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { // fieldDeclaration is an enum constant for (int i = 0; i < this.anonymousTypeCount; i++){ RecoveredType recoveredType = this.anonymousTypes[i]; TypeDeclaration typeDeclaration = recoveredType.typeDeclaration; if(typeDeclaration.declarationSourceEnd == 0) { typeDeclaration.declarationSourceEnd = this.fieldDeclaration.declarationSourceEnd; typeDeclaration.bodyEnd = this.fieldDeclaration.declarationSourceEnd; } // if the enum is recovered then enum constants must be recovered too. // depth is considered as the same as the depth of the enum recoveredType.updatedTypeDeclaration(depth, knownTypes); } } } return this.fieldDeclaration; } /* * A closing brace got consumed, might have closed the current element, * in which case both the currentElement is exited. * * Fields have no associated braces, thus if matches, then update parent. */ public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if (this.bracketBalance > 0){ // was an array initializer this.bracketBalance--; if (this.bracketBalance == 0) { if(this.fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { updateSourceEndIfNecessary(braceEnd - 1); return this.parent; } else { if (this.fieldDeclaration.declarationSourceEnd > 0) this.alreadyCompletedFieldInitialization = true; } } return this; } else if (this.bracketBalance == 0) { this.alreadyCompletedFieldInitialization = true; updateSourceEndIfNecessary(braceEnd - 1); } if (this.parent != null){ return this.parent.updateOnClosingBrace(braceStart, braceEnd); } return this; } /* * An opening brace got consumed, might be the expected opening one of the current element, * in which case the bodyStart is updated. */ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ if (this.fieldDeclaration.declarationSourceEnd == 0) { if (this.fieldDeclaration.type instanceof ArrayTypeReference || this.fieldDeclaration.type instanceof ArrayQualifiedTypeReference) { if (!this.alreadyCompletedFieldInitialization) { this.bracketBalance++; return null; // no update is necessary (array initializer) } } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=308980 // in case an initializer bracket is opened in a non-array field // e.g. int field = {.. this.bracketBalance++; return null; // no update is necessary (array initializer) } } if (this.fieldDeclaration.declarationSourceEnd == 0 && this.fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT){ this.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); } public void updateParseTree(){ updatedFieldDeclaration(0, new HashSet()); } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ if (this.fieldDeclaration.declarationSourceEnd == 0) { this.fieldDeclaration.declarationSourceEnd = bodyEnd; this.fieldDeclaration.declarationEnd = bodyEnd; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser17.rsc0000644000175000001440000000132412212041344027733 0ustar dokousers     ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/Scanner.java0000644000175000001440000040604012212041344030016 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.util.Util; /** * IMPORTANT NOTE: Internal Scanner implementation. It is mirrored in * org.eclipse.jdt.core.compiler public package where it is API. * The mirror implementation is using the backward compatible ITerminalSymbols constant * definitions (stable with 2.0), whereas the internal implementation uses TerminalTokens * which constant values reflect the latest parser generation state. */ public class Scanner implements TerminalTokens { //public int newIdentCount = 0; /* APIs ares - getNextToken() which return the current type of the token (this value is not memorized by the scanner) - getCurrentTokenSource() which provides with the token "REAL" source (aka all unicode have been transformed into a correct char) - sourceStart gives the position into the stream - currentPosition-1 gives the sourceEnd position into the stream */ public long sourceLevel; public long complianceLevel; // 1.4 feature 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; public int currentPosition; public int initialPosition, eofPosition; // after this position eof are generated instead of real token from the source public boolean skipComments = false; public boolean tokenizeComments = false; public boolean tokenizeWhiteSpace = false; //source should be viewed as a window (aka a part) //of a entire very large stream public char source[]; //unicode support public char[] withoutUnicodeBuffer; public int withoutUnicodePtr; //when == 0 ==> no unicode in the current token public boolean unicodeAsBackSlash = false; public boolean scanningFloatLiteral = false; //support for /** comments public final static int COMMENT_ARRAYS_SIZE = 30; public int[] commentStops = new int[COMMENT_ARRAYS_SIZE]; public int[] commentStarts = new int[COMMENT_ARRAYS_SIZE]; public int[] commentTagStarts = new int[COMMENT_ARRAYS_SIZE]; public int commentPtr = -1; // no comment test with commentPtr value -1 protected int lastCommentLinePosition = -1; // task tag support public char[][] foundTaskTags = null; public char[][] foundTaskMessages; public char[][] foundTaskPriorities = null; public int[][] foundTaskPositions; public int foundTaskCount = 0; public char[][] taskTags = null; public char[][] taskPriorities = null; public boolean isTaskCaseSensitive = true; //diet parsing support - jump over some method body when requested public boolean diet = false; //support for the poor-line-debuggers .... //remember the position of the cr/lf public int[] lineEnds = new int[250]; public int linePtr = -1; public boolean wasAcr = false; public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$ public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$ public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$ public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant"; //$NON-NLS-1$ public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$ public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$ public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$ public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$ public static final String INVALID_LOW_SURROGATE = "Invalid_Low_Surrogate"; //$NON-NLS-1$ public static final String INVALID_HIGH_SURROGATE = "Invalid_High_Surrogate"; //$NON-NLS-1$ public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$ 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$ private static final int[] EMPTY_LINE_ENDS = Util.EMPTY_INT_ARRAY; public static final String INVALID_BINARY = "Invalid_Binary_Literal"; //$NON-NLS-1$ public static final String BINARY_LITERAL_NOT_BELOW_17 = "Binary_Literal_Not_Below_17"; //$NON-NLS-1$ public static final String ILLEGAL_HEXA_LITERAL = "Illegal_Hexa_Literal"; //$NON-NLS-1$ public static final String INVALID_UNDERSCORE = "Invalid_Underscore"; //$NON-NLS-1$ public static final String UNDERSCORES_IN_LITERALS_NOT_BELOW_17 = "Underscores_In_Literals_Not_Below_17"; //$NON-NLS-1$` //----------------optimized identifier managment------------------ static final char[] charArray_a = new char[] {'a'}, charArray_b = new char[] {'b'}, charArray_c = new char[] {'c'}, charArray_d = new char[] {'d'}, charArray_e = new char[] {'e'}, charArray_f = new char[] {'f'}, charArray_g = new char[] {'g'}, charArray_h = new char[] {'h'}, charArray_i = new char[] {'i'}, charArray_j = new char[] {'j'}, charArray_k = new char[] {'k'}, charArray_l = new char[] {'l'}, charArray_m = new char[] {'m'}, charArray_n = new char[] {'n'}, charArray_o = new char[] {'o'}, charArray_p = new char[] {'p'}, charArray_q = new char[] {'q'}, charArray_r = new char[] {'r'}, charArray_s = new char[] {'s'}, charArray_t = new char[] {'t'}, charArray_u = new char[] {'u'}, charArray_v = new char[] {'v'}, charArray_w = new char[] {'w'}, charArray_x = new char[] {'x'}, charArray_y = new char[] {'y'}, charArray_z = new char[] {'z'}; static final char[] initCharArray = new char[] {'\u0000', '\u0000', '\u0000', '\u0000', '\u0000', '\u0000'}; static final int TableSize = 30, InternalTableSize = 6; //30*6 =210 entries public static final int OptimizedLength = 7; public /*static*/ final char[][][][] charArray_length = new char[OptimizedLength][TableSize][InternalTableSize][]; // support for detecting non-externalized string literals public static final char[] TAG_PREFIX= "//$NON-NLS-".toCharArray(); //$NON-NLS-1$ public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length; public static final char TAG_POSTFIX= '$'; public static final int TAG_POSTFIX_LENGTH= 1; private NLSTag[] nlsTags = null; protected int nlsTagsPtr; public boolean checkNonExternalizedStringLiterals; protected int lastPosition; // generic support public boolean returnOnlyGreater = false; /*static*/ { for (int i = 0; i < 6; i++) { for (int j = 0; j < TableSize; j++) { for (int k = 0; k < InternalTableSize; k++) { this.charArray_length[i][j][k] = initCharArray; } } } } /*static*/ int newEntry2 = 0, newEntry3 = 0, newEntry4 = 0, newEntry5 = 0, newEntry6 = 0; public boolean insideRecovery = false; public static final int RoundBracket = 0; public static final int SquareBracket = 1; public static final int CurlyBracket = 2; public static final int BracketKinds = 3; // extended unicode support public static final int LOW_SURROGATE_MIN_VALUE = 0xDC00; public static final int HIGH_SURROGATE_MIN_VALUE = 0xD800; public static final int HIGH_SURROGATE_MAX_VALUE = 0xDBFF; public static final int LOW_SURROGATE_MAX_VALUE = 0xDFFF; public Scanner() { this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/); } public Scanner( boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean checkNonExternalizedStringLiterals, long sourceLevel, long complianceLevel, char[][] taskTags, char[][] taskPriorities, boolean isTaskCaseSensitive) { this.eofPosition = Integer.MAX_VALUE; this.tokenizeComments = tokenizeComments; this.tokenizeWhiteSpace = tokenizeWhiteSpace; this.sourceLevel = sourceLevel; this.complianceLevel = complianceLevel; this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals; if (taskTags != null) { int taskTagsLength = taskTags.length; int length = taskTagsLength; if (taskPriorities != null) { int taskPrioritiesLength = taskPriorities.length; if (taskPrioritiesLength != taskTagsLength) { if (taskPrioritiesLength > taskTagsLength) { System.arraycopy(taskPriorities, 0, (taskPriorities = new char[taskTagsLength][]), 0, taskTagsLength); } else { System.arraycopy(taskTags, 0, (taskTags = new char[taskPrioritiesLength][]), 0, taskPrioritiesLength); length = taskPrioritiesLength; } } int[] initialIndexes = new int[length]; for (int i = 0; i < length; i++) { initialIndexes[i] = i; } Util.reverseQuickSort(taskTags, 0, length - 1, initialIndexes); char[][] temp = new char[length][]; for (int i = 0; i < length; i++) { temp[i] = taskPriorities[initialIndexes[i]]; } this.taskPriorities = temp; } else { Util.reverseQuickSort(taskTags, 0, length - 1); } this.taskTags = taskTags; this.isTaskCaseSensitive = isTaskCaseSensitive; } } public Scanner( boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean checkNonExternalizedStringLiterals, long sourceLevel, char[][] taskTags, char[][] taskPriorities, boolean isTaskCaseSensitive) { this( tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, sourceLevel, sourceLevel, taskTags, taskPriorities, isTaskCaseSensitive); } public final boolean atEnd() { // This code is not relevant if source is // Only a part of the real stream input return this.eofPosition <= this.currentPosition; } // chech presence of task: tags // TODO (frederic) see if we need to take unicode characters into account... public void checkTaskTag(int commentStart, int commentEnd) throws InvalidInputException { char[] src = this.source; // only look for newer task: tags if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) { return; } int foundTaskIndex = this.foundTaskCount; char previous = src[commentStart+1]; // should be '*' or '/' for ( int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) { char[] tag = null; char[] priority = null; // check for tag occurrence only if not ambiguous with javadoc tag if (previous != '@') { nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) { tag = this.taskTags[itag]; int tagLength = tag.length; if (tagLength == 0) continue nextTag; // ensure tag is not leaded with letter if tag starts with a letter if (ScannerHelper.isJavaIdentifierStart(this.complianceLevel, tag[0])) { if (ScannerHelper.isJavaIdentifierPart(this.complianceLevel, previous)) { continue nextTag; } } for (int t = 0; t < tagLength; t++) { char sc, tc; int x = i+t; if (x >= this.eofPosition || x >= commentEnd) continue nextTag; // case sensitive check if ((sc = src[i + t]) != (tc = tag[t])) { // case insensitive check if (this.isTaskCaseSensitive || (ScannerHelper.toLowerCase(sc) != ScannerHelper.toLowerCase(tc))) { continue nextTag; } } } // ensure tag is not followed with letter if tag finishes with a letter if (i+tagLength < commentEnd && ScannerHelper.isJavaIdentifierPart(this.complianceLevel, src[i+tagLength-1])) { if (ScannerHelper.isJavaIdentifierPart(this.complianceLevel, src[i + tagLength])) continue nextTag; } if (this.foundTaskTags == null) { this.foundTaskTags = new char[5][]; this.foundTaskMessages = new char[5][]; this.foundTaskPriorities = new char[5][]; this.foundTaskPositions = new int[5][]; } else if (this.foundTaskCount == this.foundTaskTags.length) { System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount); } priority = this.taskPriorities != null && itag < this.taskPriorities.length ? this.taskPriorities[itag] : null; this.foundTaskTags[this.foundTaskCount] = tag; this.foundTaskPriorities[this.foundTaskCount] = priority; this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 }; this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR; this.foundTaskCount++; i += tagLength - 1; // will be incremented when looping break nextTag; } } previous = src[i]; } boolean containsEmptyTask = false; for (int i = foundTaskIndex; i < this.foundTaskCount; i++) { // retrieve message start and end positions int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length; int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd - 1; // at most beginning of next task if (max_value < msgStart) { max_value = msgStart; // would only occur if tag is before EOF. } int end = -1; char c; for (int j = msgStart; j < max_value; j++) { if ((c = src[j]) == '\n' || c == '\r') { end = j - 1; break; } } if (end == -1) { for (int j = max_value; j > msgStart; j--) { if ((c = src[j]) == '*') { end = j - 1; break; } } if (end == -1) end = max_value; } if (msgStart == end) { // if the description is empty, we might want to see if two tags are not sharing the same message // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=110797 containsEmptyTask = true; continue; } // trim the message // we don't trim the beginning of the message to be able to show it after the task tag while (CharOperation.isWhitespace(src[end]) && msgStart <= end) end--; // update the end position of the task this.foundTaskPositions[i][1] = end; // get the message source final int messageLength = end - msgStart + 1; char[] message = new char[messageLength]; System.arraycopy(src, msgStart, message, 0, messageLength); this.foundTaskMessages[i] = message; } if (containsEmptyTask) { for (int i = foundTaskIndex, max = this.foundTaskCount; i < max; i++) { if (this.foundTaskMessages[i].length == 0) { loop: for (int j = i + 1; j < max; j++) { if (this.foundTaskMessages[j].length != 0) { this.foundTaskMessages[i] = this.foundTaskMessages[j]; this.foundTaskPositions[i][1] = this.foundTaskPositions[j][1]; break loop; } } } } } } public char[] getCurrentIdentifierSource() { //return the token REAL source (aka unicodes are precomputed) if (this.withoutUnicodePtr != 0) { //0 is used as a fast test flag so the real first char is in position 1 char[] result = new char[this.withoutUnicodePtr]; System.arraycopy( this.withoutUnicodeBuffer, 1, result, 0, this.withoutUnicodePtr); return result; } int length = this.currentPosition - this.startPosition; if (length == this.eofPosition) return this.source; switch (length) { // see OptimizedLength case 1 : return optimizedCurrentTokenSource1(); case 2 : return optimizedCurrentTokenSource2(); case 3 : return optimizedCurrentTokenSource3(); case 4 : return optimizedCurrentTokenSource4(); case 5 : return optimizedCurrentTokenSource5(); case 6 : return optimizedCurrentTokenSource6(); } char[] result = new char[length]; System.arraycopy(this.source, this.startPosition, result, 0, length); return result; } public int getCurrentTokenEndPosition(){ return this.currentPosition - 1; } public char[] getCurrentTokenSource() { // Return the token REAL source (aka unicodes are precomputed) char[] result; if (this.withoutUnicodePtr != 0) // 0 is used as a fast test flag so the real first char is in position 1 System.arraycopy( this.withoutUnicodeBuffer, 1, result = new char[this.withoutUnicodePtr], 0, this.withoutUnicodePtr); else { int length; System.arraycopy( this.source, this.startPosition, result = new char[length = this.currentPosition - this.startPosition], 0, length); } return result; } public final String getCurrentTokenString() { // Return current token as a string if (this.withoutUnicodePtr != 0) { // 0 is used as a fast test flag so the real first char is in position 1 return new String( this.withoutUnicodeBuffer, 1, this.withoutUnicodePtr); } return new String( this.source, this.startPosition, this.currentPosition - this.startPosition); } public char[] getCurrentTokenSourceString() { //return the token REAL source (aka unicodes are precomputed). //REMOVE the two " that are at the beginning and the end. char[] result; if (this.withoutUnicodePtr != 0) //0 is used as a fast test flag so the real first char is in position 1 System.arraycopy(this.withoutUnicodeBuffer, 2, //2 is 1 (real start) + 1 (to jump over the ") result = new char[this.withoutUnicodePtr - 2], 0, this.withoutUnicodePtr - 2); else { int length; System.arraycopy( this.source, this.startPosition + 1, result = new char[length = this.currentPosition - this.startPosition - 2], 0, length); } return result; } public final String getCurrentStringLiteral() { //return the token REAL source (aka unicodes are precomputed). //REMOVE the two " that are at the beginning and the end. if (this.withoutUnicodePtr != 0) //0 is used as a fast test flag so the real first char is in position 1 //2 is 1 (real start) + 1 (to jump over the ") return new String(this.withoutUnicodeBuffer, 2, this.withoutUnicodePtr - 2); else { return new String(this.source, this.startPosition + 1, this.currentPosition - this.startPosition - 2); } } public final char[] getRawTokenSource() { int length = this.currentPosition - this.startPosition; char[] tokenSource = new char[length]; System.arraycopy(this.source, this.startPosition, tokenSource, 0, length); return tokenSource; } public final char[] getRawTokenSourceEnd() { int length = this.eofPosition - this.currentPosition - 1; char[] sourceEnd = new char[length]; System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length); return sourceEnd; } public int getCurrentTokenStartPosition(){ return this.startPosition; } /* * Search the source position corresponding to the end of a given line number * * Line numbers are 1-based, and relative to the scanner initialPosition. * Character positions are 0-based. * * In case the given line number is inconsistent, answers -1. */ public final int getLineEnd(int lineNumber) { if (this.lineEnds == null || this.linePtr == -1) return -1; if (lineNumber > this.lineEnds.length+1) return -1; if (lineNumber <= 0) return -1; if (lineNumber == this.lineEnds.length + 1) return this.eofPosition; return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line } public final int[] getLineEnds() { //return a bounded copy of this.lineEnds if (this.linePtr == -1) { return EMPTY_LINE_ENDS; } int[] copy; System.arraycopy(this.lineEnds, 0, copy = new int[this.linePtr + 1], 0, this.linePtr + 1); return copy; } /** * Search the source position corresponding to the beginning of a given line number * * Line numbers are 1-based, and relative to the scanner initialPosition. * Character positions are 0-based. * * e.g. getLineStart(1) --> 0 indicates that the first line starts at character 0. * * In case the given line number is inconsistent, answers -1. * * @param lineNumber int * @return int */ public final int getLineStart(int lineNumber) { if (this.lineEnds == null || this.linePtr == -1) return -1; if (lineNumber > this.lineEnds.length + 1) return -1; if (lineNumber <= 0) return -1; if (lineNumber == 1) return this.initialPosition; return this.lineEnds[lineNumber-2]+1; // next line start one character behind the lineEnd of the previous line } public final int getNextChar() { try { if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { this.unicodeAsBackSlash = false; if (this.withoutUnicodePtr != 0) { unicodeStore(); } } return this.currentCharacter; } catch (IndexOutOfBoundsException e) { return -1; } catch(InvalidInputException e) { return -1; } } public final int getNextCharWithBoundChecks() { if (this.currentPosition >= this.eofPosition) { return -1; } this.currentCharacter = this.source[this.currentPosition++]; if (this.currentPosition >= this.eofPosition) { this.unicodeAsBackSlash = false; if (this.withoutUnicodePtr != 0) { unicodeStore(); } return this.currentCharacter; } if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') { try { getNextUnicodeChar(); } catch (InvalidInputException e) { return -1; } } else { this.unicodeAsBackSlash = false; if (this.withoutUnicodePtr != 0) { unicodeStore(); } } return this.currentCharacter; } public final boolean getNextChar(char testedChar) { //BOOLEAN //handle the case of unicode. //when a unicode appears then we must use a buffer that holds char internal values //At the end of this method currentCharacter holds the new visited char //and currentPosition points right next after it //Both previous lines are true if the currentCharacter is == to the testedChar //On false, no side effect has occured. //ALL getNextChar.... ARE OPTIMIZED COPIES if (this.currentPosition >= this.eofPosition) { // handle the obvious case upfront this.unicodeAsBackSlash = false; return false; } int temp = this.currentPosition; try { if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); if (this.currentCharacter != testedChar) { this.currentPosition = temp; this.withoutUnicodePtr--; return false; } return true; } //-------------end unicode traitement-------------- else { if (this.currentCharacter != testedChar) { this.currentPosition = temp; return false; } this.unicodeAsBackSlash = false; if (this.withoutUnicodePtr != 0) unicodeStore(); return true; } } catch (IndexOutOfBoundsException e) { this.unicodeAsBackSlash = false; this.currentPosition = temp; return false; } catch(InvalidInputException e) { this.unicodeAsBackSlash = false; this.currentPosition = temp; return false; } } public final int getNextChar(char testedChar1, char testedChar2) { //INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others //test can be done with (x==0) for the first and (x>0) for the second //handle the case of unicode. //when a unicode appears then we must use a buffer that holds char internal values //At the end of this method currentCharacter holds the new visited char //and currentPosition points right next after it //Both previous lines are true if the currentCharacter is == to the testedChar1/2 //On false, no side effect has occured. //ALL getNextChar.... ARE OPTIMIZED COPIES if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront return -1; int temp = this.currentPosition; try { int result; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); if (this.currentCharacter == testedChar1) { result = 0; } else if (this.currentCharacter == testedChar2) { result = 1; } else { this.currentPosition = temp; this.withoutUnicodePtr--; result = -1; } return result; } else { if (this.currentCharacter == testedChar1) { result = 0; } else if (this.currentCharacter == testedChar2) { result = 1; } else { this.currentPosition = temp; return -1; } if (this.withoutUnicodePtr != 0) unicodeStore(); return result; } } catch (IndexOutOfBoundsException e) { this.currentPosition = temp; return -1; } catch(InvalidInputException e) { this.currentPosition = temp; return -1; } } /* * This method consumes digits as well as underscores if underscores are located between digits * @throws InvalidInputException if underscores are not located between digits or if underscores are used in source < 1.7 */ private final void consumeDigits(int radix) throws InvalidInputException { consumeDigits(radix, false); } /* * This method consumes digits as well as underscores if underscores are located between digits * @throws InvalidInputException if underscores are not located between digits or if underscores are used in source < 1.7 */ private final void consumeDigits(int radix, boolean expectingDigitFirst) throws InvalidInputException { final int USING_UNDERSCORE = 1; final int INVALID_POSITION = 2; switch(consumeDigits0(radix, USING_UNDERSCORE, INVALID_POSITION, expectingDigitFirst)) { case USING_UNDERSCORE : if (this.sourceLevel < ClassFileConstants.JDK1_7) { throw new InvalidInputException(UNDERSCORES_IN_LITERALS_NOT_BELOW_17); } break; case INVALID_POSITION : if (this.sourceLevel < ClassFileConstants.JDK1_7) { throw new InvalidInputException(UNDERSCORES_IN_LITERALS_NOT_BELOW_17); } throw new InvalidInputException(INVALID_UNDERSCORE); } } private final int consumeDigits0(int radix, int usingUnderscore, int invalidPosition, boolean expectingDigitFirst) throws InvalidInputException { int kind = 0; if (getNextChar('_')) { if (expectingDigitFirst) { return invalidPosition; } kind = usingUnderscore; while (getNextChar('_')) {/*empty */} } if (getNextCharAsDigit(radix)) { // continue to read digits or underscore while (getNextCharAsDigit(radix)) {/*empty */} int kind2 = consumeDigits0(radix, usingUnderscore, invalidPosition, false); if (kind2 == 0) { return kind; } return kind2; } if (kind == usingUnderscore) return invalidPosition; return kind; } public final boolean getNextCharAsDigit() throws InvalidInputException { //BOOLEAN //handle the case of unicode. //when a unicode appears then we must use a buffer that holds char internal values //At the end of this method currentCharacter holds the new visited char //and currentPosition points right next after it //Both previous lines are true if the currentCharacter is a digit //On false, no side effect has occured. //ALL getNextChar.... ARE OPTIMIZED COPIES if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront return false; int temp = this.currentPosition; try { if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); if (!ScannerHelper.isDigit(this.currentCharacter)) { this.currentPosition = temp; this.withoutUnicodePtr--; return false; } return true; } else { if (!ScannerHelper.isDigit(this.currentCharacter)) { this.currentPosition = temp; return false; } if (this.withoutUnicodePtr != 0) unicodeStore(); return true; } } catch (IndexOutOfBoundsException e) { this.currentPosition = temp; return false; } catch(InvalidInputException e) { this.currentPosition = temp; return false; } } public final boolean getNextCharAsDigit(int radix) { //BOOLEAN //handle the case of unicode. //when a unicode appears then we must use a buffer that holds char internal values //At the end of this method currentCharacter holds the new visited char //and currentPosition points right next after it //Both previous lines are true if the currentCharacter is a digit base on radix //On false, no side effect has occured. //ALL getNextChar.... ARE OPTIMIZED COPIES if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront return false; int temp = this.currentPosition; try { if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); if (ScannerHelper.digit(this.currentCharacter, radix) == -1) { this.currentPosition = temp; this.withoutUnicodePtr--; return false; } return true; } else { if (ScannerHelper.digit(this.currentCharacter, radix) == -1) { this.currentPosition = temp; return false; } if (this.withoutUnicodePtr != 0) unicodeStore(); return true; } } catch (IndexOutOfBoundsException e) { this.currentPosition = temp; return false; } catch(InvalidInputException e) { this.currentPosition = temp; return false; } } public boolean getNextCharAsJavaIdentifierPartWithBoundCheck() { //BOOLEAN //handle the case of unicode. //when a unicode appears then we must use a buffer that holds char internal values //At the end of this method currentCharacter holds the new visited char //and currentPosition points right next after it //Both previous lines are true if the currentCharacter is a JavaIdentifierPart //On false, no side effect has occured. //ALL getNextChar.... ARE OPTIMIZED COPIES int pos = this.currentPosition; if (pos >= this.eofPosition) // handle the obvious case upfront return false; int temp2 = this.withoutUnicodePtr; try { boolean unicode = false; this.currentCharacter = this.source[this.currentPosition++]; if (this.currentPosition < this.eofPosition) { if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') { getNextUnicodeChar(); unicode = true; } } char c = this.currentCharacter; boolean isJavaIdentifierPart = false; if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { if (this.complianceLevel < ClassFileConstants.JDK1_5) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } // Unicode 4 detection char low = (char) getNextCharWithBoundChecks(); if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { // illegal low surrogate this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c, low); } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } else { isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c); } if (unicode) { if (!isJavaIdentifierPart) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } return true; } else { if (!isJavaIdentifierPart) { this.currentPosition = pos; return false; } if (this.withoutUnicodePtr != 0) unicodeStore(); return true; } } catch(InvalidInputException e) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } } public boolean getNextCharAsJavaIdentifierPart() { //BOOLEAN //handle the case of unicode. //when a unicode appears then we must use a buffer that holds char internal values //At the end of this method currentCharacter holds the new visited char //and currentPosition points right next after it //Both previous lines are true if the currentCharacter is a JavaIdentifierPart //On false, no side effect has occured. //ALL getNextChar.... ARE OPTIMIZED COPIES int pos; if ((pos = this.currentPosition) >= this.eofPosition) // handle the obvious case upfront return false; int temp2 = this.withoutUnicodePtr; try { boolean unicode = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); unicode = true; } char c = this.currentCharacter; boolean isJavaIdentifierPart = false; if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { if (this.complianceLevel < ClassFileConstants.JDK1_5) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } // Unicode 4 detection char low = (char) getNextChar(); if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { // illegal low surrogate this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c, low); } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } else { isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c); } if (unicode) { if (!isJavaIdentifierPart) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } return true; } else { if (!isJavaIdentifierPart) { this.currentPosition = pos; return false; } if (this.withoutUnicodePtr != 0) unicodeStore(); return true; } } catch (IndexOutOfBoundsException e) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } catch(InvalidInputException e) { this.currentPosition = pos; this.withoutUnicodePtr = temp2; return false; } } /* * External API in JavaConventions. * This is used to optimize the case where the scanner is used to scan a single identifier. * In this case, the AIOOBE is slower to handle than a bound check */ public int scanIdentifier() throws InvalidInputException { int whiteStart = 0; while (true) { //loop for jumping over comments this.withoutUnicodePtr = 0; //start with a new token (even comment written with unicode ) // ---------Consume white space and handles startPosition--------- whiteStart = this.currentPosition; boolean isWhiteSpace, hasWhiteSpaces = false; int offset; int unicodePtr; boolean checkIfUnicode = false; do { unicodePtr = this.withoutUnicodePtr; offset = this.currentPosition; this.startPosition = this.currentPosition; if (this.currentPosition < this.eofPosition) { this.currentCharacter = this.source[this.currentPosition++]; checkIfUnicode = this.currentPosition < this.eofPosition && this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u'; } else if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) { // reposition scanner in case we are interested by spaces as tokens this.currentPosition--; this.startPosition = whiteStart; return TokenNameWHITESPACE; } else { return TokenNameEOF; } if (checkIfUnicode) { isWhiteSpace = jumpOverUnicodeWhiteSpace(); offset = this.currentPosition - offset; } else { offset = this.currentPosition - offset; // inline version of: //isWhiteSpace = // (this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter); switch (this.currentCharacter) { case 10 : /* \ u000a: LINE FEED */ case 12 : /* \ u000c: FORM FEED */ case 13 : /* \ u000d: CARRIAGE RETURN */ case 32 : /* \ u0020: SPACE */ case 9 : /* \ u0009: HORIZONTAL TABULATION */ isWhiteSpace = true; break; default : isWhiteSpace = false; } } if (isWhiteSpace) { hasWhiteSpaces = true; } } while (isWhiteSpace); if (hasWhiteSpaces) { if (this.tokenizeWhiteSpace) { // reposition scanner in case we are interested by spaces as tokens this.currentPosition-=offset; this.startPosition = whiteStart; if (checkIfUnicode) { this.withoutUnicodePtr = unicodePtr; } return TokenNameWHITESPACE; } else if (checkIfUnicode) { this.withoutUnicodePtr = 0; unicodeStore(); } else { this.withoutUnicodePtr = 0; } } char c = this.currentCharacter; if (c < ScannerHelper.MAX_OBVIOUS) { if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) { return scanIdentifierOrKeywordWithBoundCheck(); } return TokenNameERROR; } boolean isJavaIdStart; if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { if (this.complianceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } // Unicode 4 detection char low = (char) getNextCharWithBoundChecks(); if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { // illegal low surrogate throw new InvalidInputException(INVALID_LOW_SURROGATE); } isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low); } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { if (this.complianceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } throw new InvalidInputException(INVALID_HIGH_SURROGATE); } else { // optimized case already checked isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c); } if (isJavaIdStart) return scanIdentifierOrKeywordWithBoundCheck(); return TokenNameERROR; } } public int getNextToken() throws InvalidInputException { this.wasAcr = false; if (this.diet) { jumpOverMethodBody(); this.diet = false; return this.currentPosition > this.eofPosition ? TokenNameEOF : TokenNameRBRACE; } int whiteStart = 0; try { while (true) { //loop for jumping over comments this.withoutUnicodePtr = 0; //start with a new token (even comment written with unicode ) // ---------Consume white space and handles startPosition--------- whiteStart = this.currentPosition; boolean isWhiteSpace, hasWhiteSpaces = false; int offset; int unicodePtr; boolean checkIfUnicode = false; do { unicodePtr = this.withoutUnicodePtr; offset = this.currentPosition; this.startPosition = this.currentPosition; try { checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u'); } catch(IndexOutOfBoundsException e) { if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) { // reposition scanner in case we are interested by spaces as tokens this.currentPosition--; this.startPosition = whiteStart; return TokenNameWHITESPACE; } if (this.currentPosition > this.eofPosition) return TokenNameEOF; } if (this.currentPosition > this.eofPosition) { if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) { this.currentPosition--; // reposition scanner in case we are interested by spaces as tokens this.startPosition = whiteStart; return TokenNameWHITESPACE; } return TokenNameEOF; } if (checkIfUnicode) { isWhiteSpace = jumpOverUnicodeWhiteSpace(); offset = this.currentPosition - offset; } else { offset = this.currentPosition - offset; if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { if (this.recordLineSeparator) { pushLineSeparator(); } } // inline version of: //isWhiteSpace = // (this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter); switch (this.currentCharacter) { case 10 : /* \ u000a: LINE FEED */ case 12 : /* \ u000c: FORM FEED */ case 13 : /* \ u000d: CARRIAGE RETURN */ case 32 : /* \ u0020: SPACE */ case 9 : /* \ u0009: HORIZONTAL TABULATION */ isWhiteSpace = true; break; default : isWhiteSpace = false; } } if (isWhiteSpace) { hasWhiteSpaces = true; } } while (isWhiteSpace); if (hasWhiteSpaces) { if (this.tokenizeWhiteSpace) { // reposition scanner in case we are interested by spaces as tokens this.currentPosition-=offset; this.startPosition = whiteStart; if (checkIfUnicode) { this.withoutUnicodePtr = unicodePtr; } return TokenNameWHITESPACE; } else if (checkIfUnicode) { this.withoutUnicodePtr = 0; unicodeStore(); } else { this.withoutUnicodePtr = 0; } } // ---------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 ')' : return TokenNameRPAREN; case '{' : return TokenNameLBRACE; case '}' : return TokenNameRBRACE; case '[' : return TokenNameLBRACKET; case ']' : return TokenNameRBRACKET; case ';' : return TokenNameSEMICOLON; case ',' : return TokenNameCOMMA; case '.' : if (getNextCharAsDigit()) { return scanNumber(true); } 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; if ((test = getNextChar('+', '=')) == 0) return TokenNamePLUS_PLUS; if (test > 0) return TokenNamePLUS_EQUAL; return TokenNamePLUS; } case '-' : { int test; if ((test = getNextChar('-', '=')) == 0) return TokenNameMINUS_MINUS; if (test > 0) return TokenNameMINUS_EQUAL; return TokenNameMINUS; } case '~' : return TokenNameTWIDDLE; case '!' : if (getNextChar('=')) return TokenNameNOT_EQUAL; return TokenNameNOT; case '*' : if (getNextChar('=')) return TokenNameMULTIPLY_EQUAL; return TokenNameMULTIPLY; case '%' : if (getNextChar('=')) return TokenNameREMAINDER_EQUAL; return TokenNameREMAINDER; case '<' : { int test; if ((test = getNextChar('=', '<')) == 0) return TokenNameLESS_EQUAL; if (test > 0) { if (getNextChar('=')) return TokenNameLEFT_SHIFT_EQUAL; return TokenNameLEFT_SHIFT; } return TokenNameLESS; } case '>' : { int test; if (this.returnOnlyGreater) { return TokenNameGREATER; } if ((test = getNextChar('=', '>')) == 0) return TokenNameGREATER_EQUAL; if (test > 0) { if ((test = getNextChar('=', '>')) == 0) return TokenNameRIGHT_SHIFT_EQUAL; if (test > 0) { if (getNextChar('=')) return TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL; return TokenNameUNSIGNED_RIGHT_SHIFT; } return TokenNameRIGHT_SHIFT; } return TokenNameGREATER; } case '=' : if (getNextChar('=')) return TokenNameEQUAL_EQUAL; return TokenNameEQUAL; case '&' : { int test; if ((test = getNextChar('&', '=')) == 0) return TokenNameAND_AND; if (test > 0) return TokenNameAND_EQUAL; return TokenNameAND; } case '|' : { int test; if ((test = getNextChar('|', '=')) == 0) return TokenNameOR_OR; if (test > 0) return TokenNameOR_EQUAL; return TokenNameOR; } case '^' : if (getNextChar('=')) return TokenNameXOR_EQUAL; return TokenNameXOR; case '?' : return TokenNameQUESTION; case ':' : return TokenNameCOLON; case '\'' : { int test; if ((test = getNextChar('\n', '\r')) == 0) { throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); } if (test > 0) { // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed for (int lookAhead = 0; lookAhead < 3; lookAhead++) { if (this.currentPosition + lookAhead == this.eofPosition) break; if (this.source[this.currentPosition + lookAhead] == '\n') break; if (this.source[this.currentPosition + lookAhead] == '\'') { this.currentPosition += lookAhead + 1; break; } } throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); } } if (getNextChar('\'')) { // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed for (int lookAhead = 0; lookAhead < 3; lookAhead++) { if (this.currentPosition + lookAhead == this.eofPosition) break; if (this.source[this.currentPosition + lookAhead] == '\n') break; if (this.source[this.currentPosition + lookAhead] == '\'') { this.currentPosition += lookAhead + 1; break; } } throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); } if (getNextChar('\\')) { if (this.unicodeAsBackSlash) { // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } else { this.currentCharacter = this.source[this.currentPosition++]; } scanEscapeCharacter(); } else { // consume next character this.unicodeAsBackSlash = false; checkIfUnicode = false; try { checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u'); } catch(IndexOutOfBoundsException e) { this.currentPosition--; throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); } if (checkIfUnicode) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } if (getNextChar('\'')) return TokenNameCharacterLiteral; // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed for (int lookAhead = 0; lookAhead < 20; lookAhead++) { if (this.currentPosition + lookAhead == this.eofPosition) break; if (this.source[this.currentPosition + lookAhead] == '\n') break; if (this.source[this.currentPosition + lookAhead] == '\'') { this.currentPosition += lookAhead + 1; break; } } throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); case '"' : try { // consume next character this.unicodeAsBackSlash = false; boolean isUnicode = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } while (this.currentCharacter != '"') { if (this.currentPosition >= this.eofPosition) { throw new InvalidInputException(UNTERMINATED_STRING); } /**** \r and \n are not valid in string literals ****/ if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) { // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed if (isUnicode) { int start = this.currentPosition; for (int lookAhead = 0; lookAhead < 50; lookAhead++) { if (this.currentPosition >= this.eofPosition) { this.currentPosition = start; break; } if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { isUnicode = true; getNextUnicodeChar(); } else { isUnicode = false; } if (!isUnicode && this.currentCharacter == '\n') { this.currentPosition--; // set current position on new line character break; } if (this.currentCharacter == '\"') { throw new InvalidInputException(INVALID_CHAR_IN_STRING); } } } else { this.currentPosition--; // set current position on new line character } throw new InvalidInputException(INVALID_CHAR_IN_STRING); } if (this.currentCharacter == '\\') { if (this.unicodeAsBackSlash) { this.withoutUnicodePtr--; // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; this.withoutUnicodePtr--; } else { isUnicode = false; } } else { if (this.withoutUnicodePtr == 0) { unicodeInitializeBuffer(this.currentPosition - this.startPosition); } this.withoutUnicodePtr --; this.currentCharacter = this.source[this.currentPosition++]; } // we need to compute the escape character in a separate buffer scanEscapeCharacter(); if (this.withoutUnicodePtr != 0) { unicodeStore(); } } // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; } else { isUnicode = false; if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } } catch (IndexOutOfBoundsException e) { this.currentPosition--; throw new InvalidInputException(UNTERMINATED_STRING); } catch (InvalidInputException e) { if (e.getMessage().equals(INVALID_ESCAPE)) { // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed for (int lookAhead = 0; lookAhead < 50; lookAhead++) { if (this.currentPosition + lookAhead == this.eofPosition) break; if (this.source[this.currentPosition + lookAhead] == '\n') break; if (this.source[this.currentPosition + lookAhead] == '\"') { this.currentPosition += lookAhead + 1; break; } } } throw e; // rethrow } return TokenNameStringLiteral; case '/' : if (!this.skipComments) { int test = getNextChar('/', '*'); if (test == 0) { //line comment this.lastCommentLinePosition = this.currentPosition; try { //get the next char if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; } //jump over the \\ boolean isUnicode = false; while (this.currentCharacter != '\r' && this.currentCharacter != '\n') { if (this.currentPosition >= this.eofPosition) { this.lastCommentLinePosition = this.currentPosition; this.currentPosition ++; // this avoids duplicating the code in the catch(IndexOutOfBoundsException e) throw new IndexOutOfBoundsException(); } this.lastCommentLinePosition = this.currentPosition; //get the next char isUnicode = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; } //jump over the \\ } /* * We need to completely consume the line break */ if (this.currentCharacter == '\r' && this.eofPosition > this.currentPosition) { if (this.source[this.currentPosition] == '\n') { this.currentPosition++; this.currentCharacter = '\n'; } else if ((this.source[this.currentPosition] == '\\') && (this.source[this.currentPosition + 1] == 'u')) { getNextUnicodeChar(); isUnicode = true; } } recordComment(TokenNameCOMMENT_LINE); if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { if (this.checkNonExternalizedStringLiterals && this.lastPosition < this.currentPosition) { parseTags(); } if (this.recordLineSeparator) { if (isUnicode) { pushUnicodeLineSeparator(); } else { pushLineSeparator(); } } } if (this.tokenizeComments) { return TokenNameCOMMENT_LINE; } } catch (IndexOutOfBoundsException e) { this.currentPosition--; recordComment(TokenNameCOMMENT_LINE); if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); if (this.checkNonExternalizedStringLiterals && this.lastPosition < this.currentPosition) { parseTags(); } if (this.tokenizeComments) { return TokenNameCOMMENT_LINE; } else { this.currentPosition++; } } break; } if (test > 0) { //traditional and javadoc comment try { //get the next char boolean isJavadoc = false, star = false; boolean isUnicode = false; int previous; // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; } else { isUnicode = false; if (this.withoutUnicodePtr != 0) { unicodeStore(); } } if (this.currentCharacter == '*') { isJavadoc = true; star = true; } if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { if (this.recordLineSeparator) { if (isUnicode) { pushUnicodeLineSeparator(); } else { pushLineSeparator(); } } } isUnicode = false; previous = this.currentPosition; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { //-------------unicode traitement ------------ getNextUnicodeChar(); isUnicode = true; } else { isUnicode = false; } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; //jump over the \\ } // empty comment is not a javadoc /**/ if (this.currentCharacter == '/') { isJavadoc = false; } //loop until end of comment */ int firstTag = 0; while ((this.currentCharacter != '/') || (!star)) { if (this.currentPosition >= this.eofPosition) { throw new InvalidInputException(UNTERMINATED_COMMENT); } if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { if (this.recordLineSeparator) { if (isUnicode) { pushUnicodeLineSeparator(); } else { pushLineSeparator(); } } } switch (this.currentCharacter) { case '*': star = true; break; case '@': if (firstTag == 0 && this.isFirstTag()) { firstTag = previous; } //$FALL-THROUGH$ default case to set star to false default: star = false; } //get next char previous = this.currentPosition; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { //-------------unicode traitement ------------ getNextUnicodeChar(); isUnicode = true; } else { isUnicode = false; } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; } //jump over the \\ } int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK; recordComment(token); this.commentTagStarts[this.commentPtr] = firstTag; if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); if (this.tokenizeComments) { /* if (isJavadoc) return TokenNameCOMMENT_JAVADOC; return TokenNameCOMMENT_BLOCK; */ return token; } } catch (IndexOutOfBoundsException e) { this.currentPosition--; throw new InvalidInputException(UNTERMINATED_COMMENT); } break; } } if (getNextChar('=')) return TokenNameDIVIDE_EQUAL; return TokenNameDIVIDE; case '\u001a' : if (atEnd()) return TokenNameEOF; //the atEnd may not be if source is only some part of a real (external) stream throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$ default : char c = this.currentCharacter; if (c < ScannerHelper.MAX_OBVIOUS) { if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) { return scanIdentifierOrKeyword(); } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) { return scanNumber(false); } else { return TokenNameERROR; } } boolean isJavaIdStart; if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { if (this.complianceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } // Unicode 4 detection char low = (char) getNextChar(); if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { // illegal low surrogate throw new InvalidInputException(INVALID_LOW_SURROGATE); } isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low); } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { if (this.complianceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } throw new InvalidInputException(INVALID_HIGH_SURROGATE); } else { // optimized case already checked isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c); } if (isJavaIdStart) return scanIdentifierOrKeyword(); if (ScannerHelper.isDigit(this.currentCharacter)) { return scanNumber(false); } return TokenNameERROR; } } } //-----------------end switch while try-------------------- catch (IndexOutOfBoundsException e) { if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) { // reposition scanner in case we are interested by spaces as tokens this.currentPosition--; this.startPosition = whiteStart; return TokenNameWHITESPACE; } } return TokenNameEOF; } public void getNextUnicodeChar() throws InvalidInputException { //VOID //handle the case of unicode. //when a unicode appears then we must use a buffer that holds char internal values //At the end of this method currentCharacter holds the new visited char //and currentPosition points right next after it //ALL getNextChar.... ARE OPTIMIZED COPIES int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6; this.currentPosition++; if (this.currentPosition < this.eofPosition) { while (this.source[this.currentPosition] == 'u') { this.currentPosition++; if (this.currentPosition >= this.eofPosition) { this.currentPosition--; throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } unicodeSize++; } } else { this.currentPosition--; throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } if ((this.currentPosition + 4) > this.eofPosition) { this.currentPosition += (this.eofPosition - this.currentPosition); throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } if ((c1 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15 || c1 < 0 || (c2 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15 || c2 < 0 || (c3 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15 || c3 < 0 || (c4 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15 || c4 < 0){ throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); //need the unicode buffer if (this.withoutUnicodePtr == 0) { //buffer all the entries that have been left aside.... unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition); } //fill the buffer with the char unicodeStore(); this.unicodeAsBackSlash = this.currentCharacter == '\\'; } public NLSTag[] getNLSTags() { final int length = this.nlsTagsPtr; if (length != 0) { NLSTag[] result = new NLSTag[length]; System.arraycopy(this.nlsTags, 0, result, 0, length); this.nlsTagsPtr = 0; return result; } return null; } public char[] getSource(){ return this.source; } protected boolean isFirstTag() { return true; } public final void jumpOverMethodBody() { this.wasAcr = false; int found = 1; try { while (true) { //loop for jumping over comments this.withoutUnicodePtr = 0; // ---------Consume white space and handles startPosition--------- boolean isWhiteSpace; do { this.startPosition = this.currentPosition; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { isWhiteSpace = jumpOverUnicodeWhiteSpace(); } else { if (this.recordLineSeparator && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) { pushLineSeparator(); } isWhiteSpace = CharOperation.isWhitespace(this.currentCharacter); } } while (isWhiteSpace); // -------consume token until } is found--------- NextToken: switch (this.currentCharacter) { case '{' : found++; break NextToken; case '}' : found--; if (found == 0) return; break NextToken; case '\'' : { boolean test; test = getNextChar('\\'); if (test) { try { if (this.unicodeAsBackSlash) { // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } else { this.currentCharacter = this.source[this.currentPosition++]; } scanEscapeCharacter(); } catch (InvalidInputException ex) { // ignore } } else { try { // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } catch (InvalidInputException ex) { // ignore } } getNextChar('\''); break NextToken; } case '"' : try { try { // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } catch (InvalidInputException ex) { // ignore } while (this.currentCharacter != '"') { if (this.currentPosition >= this.eofPosition) { return; } if (this.currentCharacter == '\r'){ if (this.source[this.currentPosition] == '\n') this.currentPosition++; break NextToken; // the string cannot go further that the line } if (this.currentCharacter == '\n'){ break; // the string cannot go further that the line } if (this.currentCharacter == '\\') { try { if (this.unicodeAsBackSlash) { // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } else { this.currentCharacter = this.source[this.currentPosition++]; } scanEscapeCharacter(); } catch (InvalidInputException ex) { // ignore } } try { // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } } catch (InvalidInputException ex) { // ignore } } } catch (IndexOutOfBoundsException e) { return; } break NextToken; case '/' : { int test; if ((test = getNextChar('/', '*')) == 0) { //line comment try { this.lastCommentLinePosition = this.currentPosition; //get the next char if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; } //jump over the \\ boolean isUnicode = false; while (this.currentCharacter != '\r' && this.currentCharacter != '\n') { if (this.currentPosition >= this.eofPosition) { this.lastCommentLinePosition = this.currentPosition; this.currentPosition ++; // this avoids duplicating the code inside the catch(IndexOutOfBoundsException e) below throw new IndexOutOfBoundsException(); } this.lastCommentLinePosition = this.currentPosition; //get the next char isUnicode = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { isUnicode = true; getNextUnicodeChar(); } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; } //jump over the \\ } /* * We need to completely consume the line break */ if (this.currentCharacter == '\r' && this.eofPosition > this.currentPosition) { if (this.source[this.currentPosition] == '\n') { this.currentPosition++; this.currentCharacter = '\n'; } else if ((this.source[this.currentPosition] == '\\') && (this.source[this.currentPosition + 1] == 'u')) { isUnicode = true; getNextUnicodeChar(); } } recordComment(TokenNameCOMMENT_LINE); if (this.recordLineSeparator && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) { if (this.checkNonExternalizedStringLiterals && this.lastPosition < this.currentPosition) { parseTags(); } if (this.recordLineSeparator) { if (isUnicode) { pushUnicodeLineSeparator(); } else { pushLineSeparator(); } } } } catch (IndexOutOfBoundsException e) { //an eof will then be generated this.currentPosition--; recordComment(TokenNameCOMMENT_LINE); if (this.checkNonExternalizedStringLiterals && this.lastPosition < this.currentPosition) { parseTags(); } if (!this.tokenizeComments) { this.currentPosition++; } } break NextToken; } if (test > 0) { //traditional and javadoc comment boolean isJavadoc = false; try { //get the next char boolean star = false; int previous; boolean isUnicode = false; // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; } else { isUnicode = false; if (this.withoutUnicodePtr != 0) { unicodeStore(); } } if (this.currentCharacter == '*') { isJavadoc = true; star = true; } if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { if (this.recordLineSeparator) { if (isUnicode) { pushUnicodeLineSeparator(); } else { pushLineSeparator(); } } } isUnicode = false; previous = this.currentPosition; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; } else { isUnicode = false; } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; //jump over the \\ } // empty comment is not a javadoc /**/ if (this.currentCharacter == '/') { isJavadoc = false; } //loop until end of comment */ int firstTag = 0; while ((this.currentCharacter != '/') || (!star)) { if (this.currentPosition >= this.eofPosition) { return; } if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { if (this.recordLineSeparator) { if (isUnicode) { pushUnicodeLineSeparator(); } else { pushLineSeparator(); } } } switch (this.currentCharacter) { case '*': star = true; break; case '@': if (firstTag == 0 && this.isFirstTag()) { firstTag = previous; } //$FALL-THROUGH$ default case to set star to false default: star = false; } //get next char previous = this.currentPosition; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); isUnicode = true; } else { isUnicode = false; } //handle the \\u case manually into comment if (this.currentCharacter == '\\') { if (this.source[this.currentPosition] == '\\') this.currentPosition++; } //jump over the \\ } recordComment(isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK); this.commentTagStarts[this.commentPtr] = firstTag; } catch (IndexOutOfBoundsException e) { return; } break NextToken; } break NextToken; } default : try { char c = this.currentCharacter; if (c < ScannerHelper.MAX_OBVIOUS) { if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) { scanIdentifierOrKeyword(); break NextToken; } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) { scanNumber(false); break NextToken; } else { break NextToken; } } boolean isJavaIdStart; if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { if (this.complianceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(INVALID_UNICODE_ESCAPE); } // Unicode 4 detection char low = (char) getNextChar(); if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { // illegal low surrogate break NextToken; } isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low); } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { break NextToken; } else { // optimized case already checked isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c); } if (isJavaIdStart) { scanIdentifierOrKeyword(); break NextToken; } // if (ScannerHelper.isDigit(this.currentCharacter)) { // scanNumber(false); // break NextToken; // } } catch (InvalidInputException ex) { // ignore } } } //-----------------end switch while try-------------------- } catch (IndexOutOfBoundsException e) { // ignore } catch (InvalidInputException e) { // ignore } return; } public final boolean jumpOverUnicodeWhiteSpace() throws InvalidInputException { //BOOLEAN //handle the case of unicode. Jump over the next whiteSpace //making startPosition pointing on the next available char //On false, the currentCharacter is filled up with a potential //correct char this.wasAcr = false; getNextUnicodeChar(); return CharOperation.isWhitespace(this.currentCharacter); } final char[] optimizedCurrentTokenSource1() { //return always the same char[] build only once //optimization at no speed cost of 99.5 % of the singleCharIdentifier char charOne = this.source[this.startPosition]; switch (charOne) { case 'a' : return charArray_a; case 'b' : return charArray_b; case 'c' : return charArray_c; case 'd' : return charArray_d; case 'e' : return charArray_e; case 'f' : return charArray_f; case 'g' : return charArray_g; case 'h' : return charArray_h; case 'i' : return charArray_i; case 'j' : return charArray_j; case 'k' : return charArray_k; case 'l' : return charArray_l; case 'm' : return charArray_m; case 'n' : return charArray_n; case 'o' : return charArray_o; case 'p' : return charArray_p; case 'q' : return charArray_q; case 'r' : return charArray_r; case 's' : return charArray_s; case 't' : return charArray_t; case 'u' : return charArray_u; case 'v' : return charArray_v; case 'w' : return charArray_w; case 'x' : return charArray_x; case 'y' : return charArray_y; case 'z' : return charArray_z; default : return new char[] {charOne}; } } final char[] optimizedCurrentTokenSource2() { //try to return the same char[] build only once char[] src = this.source; int start = this.startPosition; char c0 , c1; int hash = (((c0=src[start]) << 6) + (c1=src[start+1])) % TableSize; char[][] table = this.charArray_length[0][hash]; int i = this.newEntry2; while (++i < InternalTableSize) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1])) return charArray; } //---------other side--------- i = -1; int max = this.newEntry2; while (++i <= max) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1])) return charArray; } //--------add the entry------- if (++max >= InternalTableSize) max = 0; char[] r; System.arraycopy(src, start, r= new char[2], 0, 2); //newIdentCount++; return table[this.newEntry2 = max] = r; //(r = new char[] {c0, c1}); } final char[] optimizedCurrentTokenSource3() { //try to return the same char[] build only once char[] src = this.source; int start = this.startPosition; char c0, c1=src[start+1], c2; int hash = (((c0=src[start])<< 6) + (c2=src[start+2])) % TableSize; // int hash = ((c0 << 12) + (c1<< 6) + c2) % TableSize; char[][] table = this.charArray_length[1][hash]; int i = this.newEntry3; while (++i < InternalTableSize) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])) return charArray; } //---------other side--------- i = -1; int max = this.newEntry3; while (++i <= max) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])) return charArray; } //--------add the entry------- if (++max >= InternalTableSize) max = 0; char[] r; System.arraycopy(src, start, r= new char[3], 0, 3); //newIdentCount++; return table[this.newEntry3 = max] = r; //(r = new char[] {c0, c1, c2}); } final char[] optimizedCurrentTokenSource4() { //try to return the same char[] build only once char[] src = this.source; int start = this.startPosition; char c0, c1 = src[start+1], c2, c3 = src[start+3]; int hash = (((c0=src[start]) << 6) + (c2=src[start+2])) % TableSize; // int hash = (int) (((((long) c0) << 18) + (c1 << 12) + (c2 << 6) + c3) % TableSize); char[][] table = this.charArray_length[2][hash]; int i = this.newEntry4; while (++i < InternalTableSize) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3])) return charArray; } //---------other side--------- i = -1; int max = this.newEntry4; while (++i <= max) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3])) return charArray; } //--------add the entry------- if (++max >= InternalTableSize) max = 0; char[] r; System.arraycopy(src, start, r= new char[4], 0, 4); //newIdentCount++; return table[this.newEntry4 = max] = r; //(r = new char[] {c0, c1, c2, c3}); } final char[] optimizedCurrentTokenSource5() { //try to return the same char[] build only once char[] src = this.source; int start = this.startPosition; char c0, c1 = src[start+1], c2, c3 = src[start+3], c4; int hash = (((c0=src[start]) << 12) +((c2=src[start+2]) << 6) + (c4=src[start+4])) % TableSize; // int hash = (int) (((((long) c0) << 24) + (((long) c1) << 18) + (c2 << 12) + (c3 << 6) + c4) % TableSize); char[][] table = this.charArray_length[3][hash]; int i = this.newEntry5; while (++i < InternalTableSize) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4])) return charArray; } //---------other side--------- i = -1; int max = this.newEntry5; while (++i <= max) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4])) return charArray; } //--------add the entry------- if (++max >= InternalTableSize) max = 0; char[] r; System.arraycopy(src, start, r= new char[5], 0, 5); //newIdentCount++; return table[this.newEntry5 = max] = r; //(r = new char[] {c0, c1, c2, c3, c4}); } final char[] optimizedCurrentTokenSource6() { //try to return the same char[] build only once char[] src = this.source; int start = this.startPosition; char c0, c1 = src[start+1], c2, c3 = src[start+3], c4, c5 = src[start+5]; int hash = (((c0=src[start]) << 12) +((c2=src[start+2]) << 6) + (c4=src[start+4])) % TableSize; // int hash = (int)(((((long) c0) << 32) + (((long) c1) << 24) + (((long) c2) << 18) + (c3 << 12) + (c4 << 6) + c5) % TableSize); char[][] table = this.charArray_length[4][hash]; int i = this.newEntry6; while (++i < InternalTableSize) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4]) && (c5 == charArray[5])) return charArray; } //---------other side--------- i = -1; int max = this.newEntry6; while (++i <= max) { char[] charArray = table[i]; if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4]) && (c5 == charArray[5])) return charArray; } //--------add the entry------- if (++max >= InternalTableSize) max = 0; char[] r; System.arraycopy(src, start, r= new char[6], 0, 6); //newIdentCount++; return table[this.newEntry6 = max] = r; //(r = new char[] {c0, c1, c2, c3, c4, c5}); } private void parseTags() { int position = 0; final int currentStartPosition = this.startPosition; final int currentLinePtr = this.linePtr; if (currentLinePtr >= 0) { position = this.lineEnds[currentLinePtr] + 1; } while (ScannerHelper.isWhitespace(this.source[position])) { position++; } if (currentStartPosition == position) { // the whole line is commented out return; } char[] s = null; int sourceEnd = this.currentPosition; int sourceStart = currentStartPosition; int sourceDelta = 0; if (this.withoutUnicodePtr != 0) { // 0 is used as a fast test flag so the real first char is in position 1 System.arraycopy( this.withoutUnicodeBuffer, 1, s = new char[this.withoutUnicodePtr], 0, this.withoutUnicodePtr); sourceEnd = this.withoutUnicodePtr; sourceStart = 1; sourceDelta = currentStartPosition; } else { s = this.source; } int pos = CharOperation.indexOf(TAG_PREFIX, s, true, sourceStart, sourceEnd); if (pos != -1) { if (this.nlsTags == null) { this.nlsTags = new NLSTag[10]; this.nlsTagsPtr = 0; } while (pos != -1) { int start = pos + TAG_PREFIX_LENGTH; int end = CharOperation.indexOf(TAG_POSTFIX, s, start, sourceEnd); if (end != -1) { NLSTag currentTag = null; final int currentLine = currentLinePtr + 1; try { currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, extractInt(s, start, end)); } catch (NumberFormatException e) { currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, -1); } if (this.nlsTagsPtr == this.nlsTags.length) { // resize System.arraycopy(this.nlsTags, 0, (this.nlsTags = new NLSTag[this.nlsTagsPtr + 10]), 0, this.nlsTagsPtr); } this.nlsTags[this.nlsTagsPtr++] = currentTag; } else { end = start; } pos = CharOperation.indexOf(TAG_PREFIX, s, true, end, sourceEnd); } } } private int extractInt(char[] array, int start, int end) { int value = 0; for (int i = start; i < end; i++) { final char currentChar = array[i]; int digit = 0; switch(currentChar) { case '0' : digit = 0; break; case '1' : digit = 1; break; case '2' : digit = 2; break; case '3' : digit = 3; break; case '4' : digit = 4; break; case '5' : digit = 5; break; case '6' : digit = 6; break; case '7' : digit = 7; break; case '8' : digit = 8; break; case '9' : digit = 9; break; default : throw new NumberFormatException(); } value *= 10; if (digit < 0) throw new NumberFormatException(); value += digit; } return value; } public final void pushLineSeparator() { //see comment on isLineDelimiter(char) for the use of '\n' and '\r' final int INCREMENT = 250; //currentCharacter is at position currentPosition-1 // cr 000D if (this.currentCharacter == '\r') { int separatorPos = this.currentPosition - 1; if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return; int length = this.lineEnds.length; if (++this.linePtr >= length) System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length); this.lineEnds[this.linePtr] = separatorPos; // look-ahead for merged cr+lf try { if (this.source[this.currentPosition] == '\n') { //System.out.println("look-ahead LF-" + this.currentPosition); this.lineEnds[this.linePtr] = this.currentPosition; this.currentPosition++; this.wasAcr = false; } else { this.wasAcr = true; } } catch(IndexOutOfBoundsException e) { this.wasAcr = true; } } else { // lf 000A if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf if (this.wasAcr && (this.lineEnds[this.linePtr] == (this.currentPosition - 2))) { //System.out.println("merge LF-" + (this.currentPosition - 1)); this.lineEnds[this.linePtr] = this.currentPosition - 1; } else { int separatorPos = this.currentPosition - 1; if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return; int length = this.lineEnds.length; if (++this.linePtr >= length) System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length); this.lineEnds[this.linePtr] = separatorPos; } this.wasAcr = false; } } } public final void pushUnicodeLineSeparator() { // cr 000D if (this.currentCharacter == '\r') { if (this.source[this.currentPosition] == '\n') { this.wasAcr = false; } else { this.wasAcr = true; } } else { // lf 000A if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf this.wasAcr = false; } } } public void recordComment(int token) { // compute position int commentStart = this.startPosition; int stopPosition = this.currentPosition; switch (token) { case TokenNameCOMMENT_LINE: // both positions are negative commentStart = -this.startPosition; stopPosition = -this.lastCommentLinePosition; break; case TokenNameCOMMENT_BLOCK: // only end position is negative stopPosition = -this.currentPosition; break; } // a new comment is recorded int length = this.commentStops.length; if (++this.commentPtr >= length) { int newLength = length + COMMENT_ARRAYS_SIZE*10; System.arraycopy(this.commentStops, 0, this.commentStops = new int[newLength], 0, length); System.arraycopy(this.commentStarts, 0, this.commentStarts = new int[newLength], 0, length); System.arraycopy(this.commentTagStarts, 0, this.commentTagStarts = new int[newLength], 0, length); } this.commentStops[this.commentPtr] = stopPosition; this.commentStarts[this.commentPtr] = commentStart; } /** * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position. * Beyond this position, the scanner will answer EOF tokens (ITerminalSymbols.TokenNameEOF). * * @param begin the given start position * @param end the given end position */ public void resetTo(int begin, int end) { //reset the scanner to a given position where it may rescan again this.diet = false; this.initialPosition = this.startPosition = this.currentPosition = begin; if (this.source != null && this.source.length < end) { this.eofPosition = this.source.length; } else { this.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end; } this.commentPtr = -1; // reset comment stack this.foundTaskCount = 0; } protected final void scanEscapeCharacter() throws InvalidInputException { // the string with "\\u" is a legal string of two chars \ and u //thus we use a direct access to the source (for regular cases). switch (this.currentCharacter) { case 'b' : this.currentCharacter = '\b'; break; case 't' : this.currentCharacter = '\t'; break; case 'n' : this.currentCharacter = '\n'; break; case 'f' : this.currentCharacter = '\f'; break; case 'r' : this.currentCharacter = '\r'; break; case '\"' : this.currentCharacter = '\"'; break; case '\'' : this.currentCharacter = '\''; break; case '\\' : this.currentCharacter = '\\'; break; default : // -----------octal escape-------------- // OctalDigit // OctalDigit OctalDigit // ZeroToThree OctalDigit OctalDigit int number = ScannerHelper.getHexadecimalValue(this.currentCharacter); if (number >= 0 && number <= 7) { boolean zeroToThreeNot = number > 3; if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) { int digit = ScannerHelper.getHexadecimalValue(this.currentCharacter); if (digit >= 0 && digit <= 7) { number = (number * 8) + digit; if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) { if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character this.currentPosition--; } else { digit = ScannerHelper.getHexadecimalValue(this.currentCharacter); if (digit >= 0 && digit <= 7){ // has read \ZeroToThree OctalDigit OctalDigit number = (number * 8) + digit; } else {// has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character this.currentPosition--; } } } else { // has read \OctalDigit NonDigit--> ignore last character this.currentPosition--; } } else { // has read \OctalDigit NonOctalDigit--> ignore last character this.currentPosition--; } } else { // has read \OctalDigit --> ignore last character this.currentPosition--; } if (number > 255) throw new InvalidInputException(INVALID_ESCAPE); this.currentCharacter = (char) number; } else throw new InvalidInputException(INVALID_ESCAPE); } } public int scanIdentifierOrKeywordWithBoundCheck() { //test keywords //first dispatch on the first char. //then the length. If there are several //keywors with the same length AND the same first char, then do another //dispatch on the second char this.useAssertAsAnIndentifier = false; this.useEnumAsAnIndentifier = false; char[] src = this.source; identLoop: { int pos; int srcLength = this.eofPosition; while (true) { if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront break identLoop; char c = src[pos]; if (c < ScannerHelper.MAX_OBVIOUS) { if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) { if (this.withoutUnicodePtr != 0) { this.currentCharacter = c; unicodeStore(); } this.currentPosition++; } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) { this.currentCharacter = c; break identLoop; } else { //System.out.println("slow<=128: "+ c); while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/} break identLoop; } } else { //System.out.println("slow>>128: "+ c); while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/} break identLoop; } } } int index, length; char[] data; if (this.withoutUnicodePtr == 0) { //quick test on length == 1 but not on length > 12 while most identifier //have a length which is <= 12...but there are lots of identifier with //only one char.... if ((length = this.currentPosition - this.startPosition) == 1) { return TokenNameIdentifier; } data = this.source; index = this.startPosition; } else { if ((length = this.withoutUnicodePtr) == 1) return TokenNameIdentifier; data = this.withoutUnicodeBuffer; index = 1; } return internalScanIdentifierOrKeyword(index, length, data); } public int scanIdentifierOrKeyword() { //test keywords //first dispatch on the first char. //then the length. If there are several //keywords with the same length AND the same first char, then do another //dispatch on the second char this.useAssertAsAnIndentifier = false; this.useEnumAsAnIndentifier = false; char[] src = this.source; identLoop: { int pos; int srcLength = this.eofPosition; while (true) { if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront break identLoop; char c = src[pos]; if (c < ScannerHelper.MAX_OBVIOUS) { if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) { if (this.withoutUnicodePtr != 0) { this.currentCharacter = c; unicodeStore(); } this.currentPosition++; } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) { this.currentCharacter = c; break identLoop; } else { //System.out.println("slow<=128: "+ c); while (getNextCharAsJavaIdentifierPart()){/*empty*/} break identLoop; } } else { //System.out.println("slow>>128: "+ c); while (getNextCharAsJavaIdentifierPart()){/*empty*/} break identLoop; } } } int index, length; char[] data; if (this.withoutUnicodePtr == 0) { //quick test on length == 1 but not on length > 12 while most identifier //have a length which is <= 12...but there are lots of identifier with //only one char.... if ((length = this.currentPosition - this.startPosition) == 1) { return TokenNameIdentifier; } data = this.source; index = this.startPosition; } else { if ((length = this.withoutUnicodePtr) == 1) return TokenNameIdentifier; data = this.withoutUnicodeBuffer; index = 1; } return internalScanIdentifierOrKeyword(index, length, data); } private int internalScanIdentifierOrKeyword(int index, int length, char[] data) { switch (data[index]) { case 'a' : switch(length) { case 8: //abstract if ((data[++index] == 'b') && (data[++index] == 's') && (data[++index] == 't') && (data[++index] == 'r') && (data[++index] == 'a') && (data[++index] == 'c') && (data[++index] == 't')) { return TokenNameabstract; } else { return TokenNameIdentifier; } case 6: // assert if ((data[++index] == 's') && (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 'r') && (data[++index] == 't')) { if (this.sourceLevel >= ClassFileConstants.JDK1_4) { this.containsAssertKeyword = true; return TokenNameassert; } else { this.useAssertAsAnIndentifier = true; return TokenNameIdentifier; } } else { return TokenNameIdentifier; } default: return TokenNameIdentifier; } case 'b' : //boolean break byte switch (length) { case 4 : if ((data[++index] == 'y') && (data[++index] == 't') && (data[++index] == 'e')) return TokenNamebyte; else return TokenNameIdentifier; case 5 : if ((data[++index] == 'r') && (data[++index] == 'e') && (data[++index] == 'a') && (data[++index] == 'k')) return TokenNamebreak; else return TokenNameIdentifier; case 7 : if ((data[++index] == 'o') && (data[++index] == 'o') && (data[++index] == 'l') && (data[++index] == 'e') && (data[++index] == 'a') && (data[++index] == 'n')) return TokenNameboolean; else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'c' : //case char catch const class continue switch (length) { case 4 : if (data[++index] == 'a') if ((data[++index] == 's') && (data[++index] == 'e')) return TokenNamecase; else return TokenNameIdentifier; else if ((data[index] == 'h') && (data[++index] == 'a') && (data[++index] == 'r')) return TokenNamechar; else return TokenNameIdentifier; case 5 : if (data[++index] == 'a') if ((data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h')) return TokenNamecatch; else return TokenNameIdentifier; else if (data[index] == 'l') if ((data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 's')) return TokenNameclass; else return TokenNameIdentifier; else if ((data[index] == 'o') && (data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 't')) return TokenNameconst; //const is not used in java ??????? else return TokenNameIdentifier; case 8 : if ((data[++index] == 'o') && (data[++index] == 'n') && (data[++index] == 't') && (data[++index] == 'i') && (data[++index] == 'n') && (data[++index] == 'u') && (data[++index] == 'e')) return TokenNamecontinue; else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'd' : //default do double switch (length) { case 2 : if ((data[++index] == 'o')) return TokenNamedo; else return TokenNameIdentifier; case 6 : if ((data[++index] == 'o') && (data[++index] == 'u') && (data[++index] == 'b') && (data[++index] == 'l') && (data[++index] == 'e')) return TokenNamedouble; else return TokenNameIdentifier; case 7 : if ((data[++index] == 'e') && (data[++index] == 'f') && (data[++index] == 'a') && (data[++index] == 'u') && (data[++index] == 'l') && (data[++index] == 't')) return TokenNamedefault; else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'e' : //else extends switch (length) { case 4 : if (data[++index] == 'l') { if ((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; } } return TokenNameIdentifier; case 7 : if ((data[++index] == 'x') && (data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 's')) return TokenNameextends; else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'f' : //final finally float for false switch (length) { case 3 : if ((data[++index] == 'o') && (data[++index] == 'r')) return TokenNamefor; else return TokenNameIdentifier; case 5 : if (data[++index] == 'i') if ((data[++index] == 'n') && (data[++index] == 'a') && (data[++index] == 'l')) { return TokenNamefinal; } else return TokenNameIdentifier; else if (data[index] == 'l') if ((data[++index] == 'o') && (data[++index] == 'a') && (data[++index] == 't')) return TokenNamefloat; else return TokenNameIdentifier; else if ((data[index] == 'a') && (data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e')) return TokenNamefalse; else return TokenNameIdentifier; case 7 : if ((data[++index] == 'i') && (data[++index] == 'n') && (data[++index] == 'a') && (data[++index] == 'l') && (data[++index] == 'l') && (data[++index] == 'y')) return TokenNamefinally; else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'g' : //goto if (length == 4) { if ((data[++index] == 'o') && (data[++index] == 't') && (data[++index] == 'o')) { return TokenNamegoto; } } //no goto in java are allowed, so why java removes this keyword ??? return TokenNameIdentifier; case 'i' : //if implements import instanceof int interface switch (length) { case 2 : if (data[++index] == 'f') return TokenNameif; else return TokenNameIdentifier; case 3 : if ((data[++index] == 'n') && (data[++index] == 't')) return TokenNameint; else return TokenNameIdentifier; case 6 : if ((data[++index] == 'm') && (data[++index] == 'p') && (data[++index] == 'o') && (data[++index] == 'r') && (data[++index] == 't')) return TokenNameimport; else return TokenNameIdentifier; case 9 : if ((data[++index] == 'n') && (data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'r') && (data[++index] == 'f') && (data[++index] == 'a') && (data[++index] == 'c') && (data[++index] == 'e')) return TokenNameinterface; else return TokenNameIdentifier; case 10 : if (data[++index] == 'm') if ((data[++index] == 'p') && (data[++index] == 'l') && (data[++index] == 'e') && (data[++index] == 'm') && (data[++index] == 'e') && (data[++index] == 'n') && (data[++index] == 't') && (data[++index] == 's')) return TokenNameimplements; else return TokenNameIdentifier; else if ((data[index] == 'n') && (data[++index] == 's') && (data[++index] == 't') && (data[++index] == 'a') && (data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 'e') && (data[++index] == 'o') && (data[++index] == 'f')) return TokenNameinstanceof; else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'l' : //long if (length == 4) { if ((data[++index] == 'o') && (data[++index] == 'n') && (data[++index] == 'g')) { return TokenNamelong; } } return TokenNameIdentifier; case 'n' : //native new null switch (length) { case 3 : if ((data[++index] == 'e') && (data[++index] == 'w')) return TokenNamenew; else return TokenNameIdentifier; case 4 : if ((data[++index] == 'u') && (data[++index] == 'l') && (data[++index] == 'l')) return TokenNamenull; else return TokenNameIdentifier; case 6 : if ((data[++index] == 'a') && (data[++index] == 't') && (data[++index] == 'i') && (data[++index] == 'v') && (data[++index] == 'e')) { return TokenNamenative; } else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'p' : //package private protected public switch (length) { case 6 : if ((data[++index] == 'u') && (data[++index] == 'b') && (data[++index] == 'l') && (data[++index] == 'i') && (data[++index] == 'c')) { return TokenNamepublic; } else return TokenNameIdentifier; case 7 : if (data[++index] == 'a') if ((data[++index] == 'c') && (data[++index] == 'k') && (data[++index] == 'a') && (data[++index] == 'g') && (data[++index] == 'e')) return TokenNamepackage; else return TokenNameIdentifier; else if ((data[index] == 'r') && (data[++index] == 'i') && (data[++index] == 'v') && (data[++index] == 'a') && (data[++index] == 't') && (data[++index] == 'e')) { return TokenNameprivate; } else return TokenNameIdentifier; case 9 : if ((data[++index] == 'r') && (data[++index] == 'o') && (data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'c') && (data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'd')) { return TokenNameprotected; } else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'r' : //return if (length == 6) { if ((data[++index] == 'e') && (data[++index] == 't') && (data[++index] == 'u') && (data[++index] == 'r') && (data[++index] == 'n')) { return TokenNamereturn; } } return TokenNameIdentifier; case 's' : //short static super switch synchronized strictfp switch (length) { case 5 : if (data[++index] == 'h') if ((data[++index] == 'o') && (data[++index] == 'r') && (data[++index] == 't')) return TokenNameshort; else return TokenNameIdentifier; else if ((data[index] == 'u') && (data[++index] == 'p') && (data[++index] == 'e') && (data[++index] == 'r')) return TokenNamesuper; else return TokenNameIdentifier; case 6 : if (data[++index] == 't') if ((data[++index] == 'a') && (data[++index] == 't') && (data[++index] == 'i') && (data[++index] == 'c')) { return TokenNamestatic; } else return TokenNameIdentifier; else if ((data[index] == 'w') && (data[++index] == 'i') && (data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h')) return TokenNameswitch; else return TokenNameIdentifier; case 8 : if ((data[++index] == 't') && (data[++index] == 'r') && (data[++index] == 'i') && (data[++index] == 'c') && (data[++index] == 't') && (data[++index] == 'f') && (data[++index] == 'p')) return TokenNamestrictfp; else return TokenNameIdentifier; case 12 : if ((data[++index] == 'y') && (data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 'h') && (data[++index] == 'r') && (data[++index] == 'o') && (data[++index] == 'n') && (data[++index] == 'i') && (data[++index] == 'z') && (data[++index] == 'e') && (data[++index] == 'd')) { return TokenNamesynchronized; } else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 't' : //try throw throws transient this true switch (length) { case 3 : if ((data[++index] == 'r') && (data[++index] == 'y')) return TokenNametry; else return TokenNameIdentifier; case 4 : if (data[++index] == 'h') if ((data[++index] == 'i') && (data[++index] == 's')) return TokenNamethis; else return TokenNameIdentifier; else if ((data[index] == 'r') && (data[++index] == 'u') && (data[++index] == 'e')) return TokenNametrue; else return TokenNameIdentifier; case 5 : if ((data[++index] == 'h') && (data[++index] == 'r') && (data[++index] == 'o') && (data[++index] == 'w')) return TokenNamethrow; else return TokenNameIdentifier; case 6 : if ((data[++index] == 'h') && (data[++index] == 'r') && (data[++index] == 'o') && (data[++index] == 'w') && (data[++index] == 's')) return TokenNamethrows; else return TokenNameIdentifier; case 9 : if ((data[++index] == 'r') && (data[++index] == 'a') && (data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 'i') && (data[++index] == 'e') && (data[++index] == 'n') && (data[++index] == 't')) { return TokenNametransient; } else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'v' : //void volatile switch (length) { case 4 : if ((data[++index] == 'o') && (data[++index] == 'i') && (data[++index] == 'd')) return TokenNamevoid; else return TokenNameIdentifier; case 8 : if ((data[++index] == 'o') && (data[++index] == 'l') && (data[++index] == 'a') && (data[++index] == 't') && (data[++index] == 'i') && (data[++index] == 'l') && (data[++index] == 'e')) { return TokenNamevolatile; } else return TokenNameIdentifier; default : return TokenNameIdentifier; } case 'w' : //while widefp switch (length) { case 5 : if ((data[++index] == 'h') && (data[++index] == 'i') && (data[++index] == 'l') && (data[++index] == 'e')) return TokenNamewhile; else return TokenNameIdentifier; //case 6:if ( (data[++index] =='i') && (data[++index]=='d') && (data[++index]=='e') && (data[++index]=='f')&& (data[++index]=='p')) //return TokenNamewidefp ; //else //return TokenNameIdentifier; default : return TokenNameIdentifier; } default : return TokenNameIdentifier; } } public int scanNumber(boolean dotPrefix) throws InvalidInputException { //when entering this method the currentCharacter is the first //digit of the number. It may be preceeded by a '.' when //dotPrefix is true boolean floating = dotPrefix; if (!dotPrefix && (this.currentCharacter == '0')) { if (getNextChar('x', 'X') >= 0) { //----------hexa----------------- int start = this.currentPosition; consumeDigits(16, true); int end = this.currentPosition; if (getNextChar('l', 'L') >= 0) { if (end == start) { throw new InvalidInputException(INVALID_HEXA); } return TokenNameLongLiteral; } else if (getNextChar('.')) { // hexadecimal floating point literal // read decimal part boolean hasNoDigitsBeforeDot = end == start; start = this.currentPosition; consumeDigits(16, true); end = this.currentPosition; if (hasNoDigitsBeforeDot && end == start) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } 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) { unicodeStore(); } } 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) { unicodeStore(); } } } if (!ScannerHelper.isDigit(this.currentCharacter)) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } if (this.currentCharacter == '_') { // wrongly place '_' consumeDigits(10); throw new InvalidInputException(INVALID_UNDERSCORE); } throw new InvalidInputException(INVALID_HEXA); } consumeDigits(10); if (getNextChar('f', 'F') >= 0) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } return TokenNameFloatingPointLiteral; } if (getNextChar('d', 'D') >= 0) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } return TokenNameDoubleLiteral; } if (getNextChar('l', 'L') >= 0) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } throw new InvalidInputException(INVALID_HEXA); } if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } return TokenNameDoubleLiteral; } else { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } throw new InvalidInputException(INVALID_HEXA); } } else 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) { unicodeStore(); } } 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) { unicodeStore(); } } } if (!ScannerHelper.isDigit(this.currentCharacter)) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } if (this.currentCharacter == '_') { // wrongly place '_' consumeDigits(10); throw new InvalidInputException(INVALID_UNDERSCORE); } throw new InvalidInputException(INVALID_FLOAT); } consumeDigits(10); if (getNextChar('f', 'F') >= 0) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } return TokenNameFloatingPointLiteral; } if (getNextChar('d', 'D') >= 0) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } return TokenNameDoubleLiteral; } if (getNextChar('l', 'L') >= 0) { if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } throw new InvalidInputException(INVALID_HEXA); } if (this.sourceLevel < ClassFileConstants.JDK1_5) { throw new InvalidInputException(ILLEGAL_HEXA_LITERAL); } return TokenNameDoubleLiteral; } else { if (end == start) throw new InvalidInputException(INVALID_HEXA); return TokenNameIntegerLiteral; } } else if (getNextChar('b', 'B') >= 0) { //----------binary----------------- int start = this.currentPosition; consumeDigits(2, true); int end = this.currentPosition; if (end == start) { if (this.sourceLevel < ClassFileConstants.JDK1_7) { throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17); } throw new InvalidInputException(INVALID_BINARY); } if (getNextChar('l', 'L') >= 0) { if (this.sourceLevel < ClassFileConstants.JDK1_7) { throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17); } return TokenNameLongLiteral; } if (this.sourceLevel < ClassFileConstants.JDK1_7) { throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17); } return TokenNameIntegerLiteral; } //there is no x or X nor b or B in the number //potential octal if (getNextCharAsDigit()) { //-------------potential octal----------------- consumeDigits(10); if (getNextChar('l', 'L') >= 0) { return TokenNameLongLiteral; } if (getNextChar('f', 'F') >= 0) { return TokenNameFloatingPointLiteral; } if (getNextChar('d', 'D') >= 0) { return TokenNameDoubleLiteral; } else { //make the distinction between octal and float .... boolean isInteger = true; if (getNextChar('.')) { isInteger = false; consumeDigits(10); } if (getNextChar('e', 'E') >= 0) { // consume next character isInteger = false; this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } 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) { unicodeStore(); } } } if (!ScannerHelper.isDigit(this.currentCharacter)) { if (this.currentCharacter == '_') { // wrongly place '_' consumeDigits(10); throw new InvalidInputException(INVALID_UNDERSCORE); } throw new InvalidInputException(INVALID_FLOAT); } consumeDigits(10); } if (getNextChar('f', 'F') >= 0) return TokenNameFloatingPointLiteral; if (getNextChar('d', 'D') >= 0 || !isInteger) return TokenNameDoubleLiteral; return TokenNameIntegerLiteral; } } else { /* carry on */ } } consumeDigits(10); if ((!dotPrefix) && (getNextChar('l', 'L') >= 0)) return TokenNameLongLiteral; if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty consumeDigits(10, true); floating = true; } //if floating is true both exponant and suffix may be optional if (getNextChar('e', 'E') >= 0) { floating = true; // consume next character this.unicodeAsBackSlash = false; if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { getNextUnicodeChar(); } else { if (this.withoutUnicodePtr != 0) { unicodeStore(); } } 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) { unicodeStore(); } } } if (!ScannerHelper.isDigit(this.currentCharacter)) { if (this.currentCharacter == '_') { // wrongly place '_' consumeDigits(10); throw new InvalidInputException(INVALID_UNDERSCORE); } throw new InvalidInputException(INVALID_FLOAT); } // current character is a digit so we expect no digit first (the next character could be an underscore) consumeDigits(10); } if (getNextChar('d', 'D') >= 0) return TokenNameDoubleLiteral; if (getNextChar('f', 'F') >= 0) return TokenNameFloatingPointLiteral; //the long flag has been tested before return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral; } /** * Search the line number corresponding to a specific position * @param position int * @return int */ public final int getLineNumber(int position) { return Util.getLineNumber(position, this.lineEnds, 0, this.linePtr); } public final void setSource(char[] sourceString){ //the source-buffer is set to sourceString int sourceLength; if (sourceString == null) { this.source = CharOperation.NO_CHAR; sourceLength = 0; } else { this.source = sourceString; sourceLength = sourceString.length; } this.startPosition = -1; 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(char[] contents, CompilationResult compilationResult) { if (contents == null) { char[] cuContents = compilationResult.compilationUnit.getContents(); setSource(cuContents); } else { setSource(contents); } int[] lineSeparatorPositions = compilationResult.lineSeparatorPositions; if (lineSeparatorPositions != null) { this.lineEnds = lineSeparatorPositions; this.linePtr = lineSeparatorPositions.length - 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) { setSource(null, compilationResult); } public String toString() { if (this.startPosition == this.eofPosition) return "EOF\n\n" + new String(this.source); //$NON-NLS-1$ if (this.currentPosition > this.eofPosition) return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$ if (this.currentPosition <= 0) return "NOT started!\n\n"+ new String(this.source); //$NON-NLS-1$ StringBuffer buffer = new StringBuffer(); if (this.startPosition < 1000) { buffer.append(this.source, 0, this.startPosition); } else { buffer.append("\n...\n"); //$NON-NLS-1$ int line = Util.getLineNumber(this.startPosition-1000, this.lineEnds, 0, this.linePtr); int lineStart = getLineStart(line); buffer.append(this.source, lineStart, this.startPosition-lineStart); } buffer.append("\n===============================\nStarts here -->"); //$NON-NLS-1$ int middleLength = (this.currentPosition - 1) - this.startPosition + 1; if (middleLength > -1) { buffer.append(this.source, this.startPosition, middleLength); } buffer.append("<-- Ends here\n===============================\n"); //$NON-NLS-1$ buffer.append(this.source, (this.currentPosition - 1) + 1, this.eofPosition - (this.currentPosition - 1) - 1); return buffer.toString(); } public String toStringAction(int act) { switch (act) { case TokenNameIdentifier : return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNameabstract : return "abstract"; //$NON-NLS-1$ case TokenNameboolean : return "boolean"; //$NON-NLS-1$ case TokenNamebreak : return "break"; //$NON-NLS-1$ case TokenNamebyte : return "byte"; //$NON-NLS-1$ case TokenNamecase : return "case"; //$NON-NLS-1$ case TokenNamecatch : return "catch"; //$NON-NLS-1$ case TokenNamechar : return "char"; //$NON-NLS-1$ case TokenNameclass : return "class"; //$NON-NLS-1$ case TokenNamecontinue : return "continue"; //$NON-NLS-1$ case TokenNamedefault : return "default"; //$NON-NLS-1$ case TokenNamedo : return "do"; //$NON-NLS-1$ case TokenNamedouble : return "double"; //$NON-NLS-1$ case TokenNameelse : return "else"; //$NON-NLS-1$ case TokenNameextends : return "extends"; //$NON-NLS-1$ case TokenNamefalse : return "false"; //$NON-NLS-1$ case TokenNamefinal : return "final"; //$NON-NLS-1$ case TokenNamefinally : return "finally"; //$NON-NLS-1$ case TokenNamefloat : return "float"; //$NON-NLS-1$ case TokenNamefor : return "for"; //$NON-NLS-1$ case TokenNameif : return "if"; //$NON-NLS-1$ case TokenNameimplements : return "implements"; //$NON-NLS-1$ case TokenNameimport : return "import"; //$NON-NLS-1$ case TokenNameinstanceof : return "instanceof"; //$NON-NLS-1$ case TokenNameint : return "int"; //$NON-NLS-1$ case TokenNameinterface : return "interface"; //$NON-NLS-1$ case TokenNamelong : return "long"; //$NON-NLS-1$ case TokenNamenative : return "native"; //$NON-NLS-1$ case TokenNamenew : return "new"; //$NON-NLS-1$ case TokenNamenull : return "null"; //$NON-NLS-1$ case TokenNamepackage : return "package"; //$NON-NLS-1$ case TokenNameprivate : return "private"; //$NON-NLS-1$ case TokenNameprotected : return "protected"; //$NON-NLS-1$ case TokenNamepublic : return "public"; //$NON-NLS-1$ case TokenNamereturn : return "return"; //$NON-NLS-1$ case TokenNameshort : return "short"; //$NON-NLS-1$ case TokenNamestatic : return "static"; //$NON-NLS-1$ case TokenNamesuper : return "super"; //$NON-NLS-1$ case TokenNameswitch : return "switch"; //$NON-NLS-1$ case TokenNamesynchronized : return "synchronized"; //$NON-NLS-1$ case TokenNamethis : return "this"; //$NON-NLS-1$ case TokenNamethrow : return "throw"; //$NON-NLS-1$ case TokenNamethrows : return "throws"; //$NON-NLS-1$ case TokenNametransient : return "transient"; //$NON-NLS-1$ case TokenNametrue : return "true"; //$NON-NLS-1$ case TokenNametry : return "try"; //$NON-NLS-1$ case TokenNamevoid : return "void"; //$NON-NLS-1$ case TokenNamevolatile : return "volatile"; //$NON-NLS-1$ case TokenNamewhile : return "while"; //$NON-NLS-1$ case TokenNameIntegerLiteral : return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNameLongLiteral : return "Long(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNameFloatingPointLiteral : return "Float(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNameDoubleLiteral : return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNameCharacterLiteral : return "Char(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNameStringLiteral : return "String(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNamePLUS_PLUS : return "++"; //$NON-NLS-1$ case TokenNameMINUS_MINUS : return "--"; //$NON-NLS-1$ case TokenNameEQUAL_EQUAL : return "=="; //$NON-NLS-1$ case TokenNameLESS_EQUAL : return "<="; //$NON-NLS-1$ case TokenNameGREATER_EQUAL : return ">="; //$NON-NLS-1$ case TokenNameNOT_EQUAL : return "!="; //$NON-NLS-1$ case TokenNameLEFT_SHIFT : return "<<"; //$NON-NLS-1$ case TokenNameRIGHT_SHIFT : return ">>"; //$NON-NLS-1$ case TokenNameUNSIGNED_RIGHT_SHIFT : return ">>>"; //$NON-NLS-1$ case TokenNamePLUS_EQUAL : return "+="; //$NON-NLS-1$ case TokenNameMINUS_EQUAL : return "-="; //$NON-NLS-1$ case TokenNameMULTIPLY_EQUAL : return "*="; //$NON-NLS-1$ case TokenNameDIVIDE_EQUAL : return "/="; //$NON-NLS-1$ case TokenNameAND_EQUAL : return "&="; //$NON-NLS-1$ case TokenNameOR_EQUAL : return "|="; //$NON-NLS-1$ case TokenNameXOR_EQUAL : return "^="; //$NON-NLS-1$ case TokenNameREMAINDER_EQUAL : return "%="; //$NON-NLS-1$ case TokenNameLEFT_SHIFT_EQUAL : return "<<="; //$NON-NLS-1$ case TokenNameRIGHT_SHIFT_EQUAL : return ">>="; //$NON-NLS-1$ case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : return ">>>="; //$NON-NLS-1$ case TokenNameOR_OR : return "||"; //$NON-NLS-1$ case TokenNameAND_AND : return "&&"; //$NON-NLS-1$ case TokenNamePLUS : return "+"; //$NON-NLS-1$ case TokenNameMINUS : return "-"; //$NON-NLS-1$ case TokenNameNOT : return "!"; //$NON-NLS-1$ case TokenNameREMAINDER : return "%"; //$NON-NLS-1$ case TokenNameXOR : return "^"; //$NON-NLS-1$ case TokenNameAND : return "&"; //$NON-NLS-1$ case TokenNameMULTIPLY : return "*"; //$NON-NLS-1$ case TokenNameOR : return "|"; //$NON-NLS-1$ case TokenNameTWIDDLE : return "~"; //$NON-NLS-1$ case TokenNameDIVIDE : return "/"; //$NON-NLS-1$ case TokenNameGREATER : return ">"; //$NON-NLS-1$ case TokenNameLESS : return "<"; //$NON-NLS-1$ case TokenNameLPAREN : return "("; //$NON-NLS-1$ case TokenNameRPAREN : return ")"; //$NON-NLS-1$ case TokenNameLBRACE : return "{"; //$NON-NLS-1$ case TokenNameRBRACE : return "}"; //$NON-NLS-1$ case TokenNameLBRACKET : return "["; //$NON-NLS-1$ case TokenNameRBRACKET : return "]"; //$NON-NLS-1$ case TokenNameSEMICOLON : return ";"; //$NON-NLS-1$ case TokenNameQUESTION : return "?"; //$NON-NLS-1$ case TokenNameCOLON : return ":"; //$NON-NLS-1$ case TokenNameCOMMA : return ","; //$NON-NLS-1$ case TokenNameDOT : return "."; //$NON-NLS-1$ case TokenNameEQUAL : return "="; //$NON-NLS-1$ case TokenNameEOF : return "EOF"; //$NON-NLS-1$ case TokenNameWHITESPACE : return "white_space(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ default : return "not-a-token"; //$NON-NLS-1$ } } public void unicodeInitializeBuffer(int length) { this.withoutUnicodePtr = length; if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[length+(1+10)]; int bLength = this.withoutUnicodeBuffer.length; if (1+length >= bLength) { System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length + (1+10)], 0, bLength); } System.arraycopy(this.source, this.startPosition, this.withoutUnicodeBuffer, 1, length); } public void unicodeStore() { int pos = ++this.withoutUnicodePtr; if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10]; int length = this.withoutUnicodeBuffer.length; if (pos == length) { System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length); } this.withoutUnicodeBuffer[pos] = this.currentCharacter; } public void unicodeStore(char character) { int pos = ++this.withoutUnicodePtr; if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10]; int length = this.withoutUnicodeBuffer.length; if (pos == length) { System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length); } this.withoutUnicodeBuffer[pos] = character; } public static boolean isIdentifier(int token) { return token == TerminalTokens.TokenNameIdentifier; } public static boolean isLiteral(int token) { switch(token) { case TerminalTokens.TokenNameIntegerLiteral: case TerminalTokens.TokenNameLongLiteral: case TerminalTokens.TokenNameFloatingPointLiteral: case TerminalTokens.TokenNameDoubleLiteral: case TerminalTokens.TokenNameStringLiteral: case TerminalTokens.TokenNameCharacterLiteral: return true; default: return false; } } public static boolean isKeyword(int token) { switch(token) { case TerminalTokens.TokenNameabstract: case TerminalTokens.TokenNameassert: case TerminalTokens.TokenNamebyte: case TerminalTokens.TokenNamebreak: case TerminalTokens.TokenNameboolean: case TerminalTokens.TokenNamecase: case TerminalTokens.TokenNamechar: case TerminalTokens.TokenNamecatch: case TerminalTokens.TokenNameclass: case TerminalTokens.TokenNamecontinue: case TerminalTokens.TokenNamedo: case TerminalTokens.TokenNamedouble: case TerminalTokens.TokenNamedefault: case TerminalTokens.TokenNameelse: case TerminalTokens.TokenNameextends: case TerminalTokens.TokenNamefor: case TerminalTokens.TokenNamefinal: case TerminalTokens.TokenNamefloat: case TerminalTokens.TokenNamefalse: case TerminalTokens.TokenNamefinally: case TerminalTokens.TokenNameif: case TerminalTokens.TokenNameint: case TerminalTokens.TokenNameimport: case TerminalTokens.TokenNameinterface: case TerminalTokens.TokenNameimplements: case TerminalTokens.TokenNameinstanceof: case TerminalTokens.TokenNamelong: case TerminalTokens.TokenNamenew: case TerminalTokens.TokenNamenull: case TerminalTokens.TokenNamenative: case TerminalTokens.TokenNamepublic: case TerminalTokens.TokenNamepackage: case TerminalTokens.TokenNameprivate: case TerminalTokens.TokenNameprotected: case TerminalTokens.TokenNamereturn: case TerminalTokens.TokenNameshort: case TerminalTokens.TokenNamesuper: case TerminalTokens.TokenNamestatic: case TerminalTokens.TokenNameswitch: case TerminalTokens.TokenNamestrictfp: case TerminalTokens.TokenNamesynchronized: case TerminalTokens.TokenNametry: case TerminalTokens.TokenNamethis: case TerminalTokens.TokenNametrue: case TerminalTokens.TokenNamethrow: case TerminalTokens.TokenNamethrows: case TerminalTokens.TokenNametransient: case TerminalTokens.TokenNamevoid: case TerminalTokens.TokenNamevolatile: case TerminalTokens.TokenNamewhile: return true; default: return false; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser13.rsc0000644000175000001440000000042412212041344027727 0ustar dokousersÐÐÐÈaÐÐÐÐÐaaaaÐÐÐaÈaaaaaÈaC5aaCaaxxa55ÐÐÐÐÐÐ*a±k7JAAuaÈaakaaaaÈaÈa35 Ðaaaa1,_¯5aWa¯—ßÛÓÈa=—anT—bW—³âÛ'Ó$•""• _•³¯a•ä_WJ¯•W•aaaaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser1.rsc0000644000175000001440000006061212212041344027651 0ustar dokousers ==55''(())76666sãäääääääääääâ⸸·¹¹º““““”˜•™nnnnn88444444444444J>BBCêÓëëÔ»áá¼¼¼¼šÍí½½½½½½½m}}xxÕÖ°²l±±¯¯œžž¿×ØpqqÀÀ³³èï­›vy||RRRRRRRRRRRRK?DDE ""ðððññòòððððððð´ówww$$<;¨¨zzzzzz{rrÙ%®SSSSSSSŸŸŸŸŸŸTTTTTTTTTTTTT\U g]]NNNNNNNVW¡^&&&&''õôôÁÁX¢_Y£øøùÂÂ[[``aabdcheeff)++**,þþú-ûûÃý¥ æªÄÄÅQQççÆÆ~~IOOH  u.Û0/!!!!!""###$$%%&&**++,,22 3ééÚÚ(##ìì99ÎÎooPPîî¾¾ÒÒ!!Çöö÷÷üüL@FF111122ÜÑ433ÉÈÈZ¤jji–¦—§Ð:µµ¶¶€€kkÊʃƒ55ÌÝÝ‚‚ÞÞËË66t88   99 77   :: „„„……………††††‡‡‡‡‡‡‡ˆˆˆˆˆ‰‰‰‰‰‰‰ŠŠŠŠŠŠŠŠŠ‹‹‹ŒŒŒŒŒŽŽŽ‘‘‘’’’  ÿGGGGAM;<<==ßßàÏÏÏÏ---1.>>??@A©©©©««««¬BB/C0ååý%ŒëMMM}}Wèãñ2¤n€Iz —    X ÆÖâ:b   ,, å_{‹‹‹ cYyEE# Å$Œ[~E½â¾êàÅm§~ôöõWS~~~~~~~~~~~~~~~~~~~~ju  (¦   =ì )­i{‹‹‹ ~~o¥%ŒëMMM}}Wèãñ2¤n€Iz½7 „Ö = ® ƒï,, ƒã {‹‹‹ [¿yEE# Å$Œ[_E½â¾êàÅm ÆQ_ôöõW q¾____________________ju  (":Œd ¡ Ë )f›#¾ ¡ Ë__ý%ŒëMMM}}Wèãñ2¤n€Iz…, XX ,ÖÝ, ƒn ì,, K å_{‹‹‹ [ôyEE# Å$Œ[~E½â¾êàÅm¾ +~ôöõW ·þ~~~~~~~~~~~~~~~~~~~~ju  (м     ) ßi{‹‹‹ ~~oý%ŒëMMM}}Wèãñ2¤n€Iz½½8KÖ 5  ¼ è›,, èãê{‹‹‹ [ôyEE# Å$Œ[~E½â¾êàÅmf„~ôöõWm ì }~~~~~~~~~~~~~~~~~~~~ju  ( à’ + “ “ “Q )݃{‹‹‹ ~~o%ŒëMMM}}Wèãñ2¤n€IzGÑ’@ÐÐÖ” ‰_ü¹A,,êã<{‹‹‹ ¦ÖyEE# Å$Œ[ÛE½â¾êàÅmuÛôöõW:i uÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛju  (*  Œ ê ê ê ) ‹{‹‹‹ ÛÛœ+;?/lðŽ| MMM[Œ~U%ŒëMMM}}Wèãñ2¤n€Iz¸Û(,,Ö * )|K ,,#{‹‹‹ 0yEE# Å$Œ[ÛE½â¾êàÅmuÛôöõW_K )ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛju  ( ~ س ± ì ì ì ){‹‹‹ ÛÛœ T}}Ø#¾Ž| MMM z.IÎQ%ŒëMMM}}Wèãñ2¤n€IzÛ,,Ö„[XÎq P,,““#{‹‹‹ ¸0yEE# Å$Œ[ðE½â¾êàÅmÒEðôöõWš„Xððððððððððððððððððððju  (G Z Ë ) ¾[ ¡ Ëððù%ŒëMMM}}Wèãñ2¤n€Iz », †[ÖÝ, ¦n I,, v v¦{‹‹‹ Ž=yEE# Å$Œ[ðE½â¾êàÅmÓìðôöõW Ð+ûððððððððððððððððððððju  († •¼0 § § § ) ë ë ëcðð©%ŒëMMM}}Wèãñ2¤n€Iz æ ø  Ö2 M ω,, â âc{‹‹‹ šiyEE# Å$Œ[ðE½â¾êàÅm ’ðôöõW¥¥šððððððððððððððððððððju  (Ý»[Ž2u )ˆ}} •aýðð‡þ¦}}Wèãñ2¤n€Izš ¾ r PWÖ2{‹‹‹  Cuœ%/l ´ ½ ý=inzR½ZŒ[”ZZZZZ ¥ £ è  ž ž èwà <W ¢  $]$$$$$$””””””””””””fu (‡þ¦}}Wèãñ2¤n€IzŒ= ¡ ËÖš,eɦ ËÕÕÕÕ §Ó 999999Œ[” å€ é ž…, ž„šž Ö, WmŒÇ]””””””””””””fu (‡þ¦}}Wèãñ2¤n€IzÇ = ¡ ËÖ ¡ Ë(N — w w% # ØÞñ°¯Œ[”P ²½+ƒ…, Hì, è = ÆW èm]””””””””””””fu (‡þ¦}}Wèãñ2¤n€Iz $ ¡ ËÊÖ ¡ ˼:Ò @6 B ' $¯S Œ[”=§½… ž,  𠹝 W, è Œ XW è¸3]333333””””””””””””fu (‡þ¦}}Wèãñ2¤n€Iz ( ¡ ËSÖ ž‰¦!¬ Yš W ì5p P (© å 444444Œ[” ¹‚ ¹ë _, +„š© ¹ ­Ôì`Wµƒƒ$]$$$$$$””””””””””””fu (‡þ¦}}Wèãñ2¤n€Izš‰‰6Ö  _  !£¼ œ£ ñ ò £ ½KKKKKKŒ[” Ô;­­ ÔeÜ\ ¹ûŽ ×£ ¹W œá£%]%%%%%%””””””””””””fu (‡þ¦}}Wèãñ2¤n€Iz ¾­££Ö ø 3 Ù å › V Á n o P&&&&&&Œ[”$Q ño£Σ?´ ¼ ¹e=iÙ …W E 6]666666””””””””””””fu (žTËŸŸ « ª ©ÑÓ#¤n£ÒÌI ¨¢¢¢@ &5  ‰ n “  •ù¢¼„  ¹V777777 ®°š¼¼ *  #¤n  I l 3 6 5†: 8 7 @ : ßM¦š}}Wèãñ2¤n€Iz +x”çÖ ¾¢¢¢ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼ ¥ £Œ[ Ê\à åq å N åà ¢  ÝŒ ¦†WŒ i Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Ê Êju  (Mþ¦}}Wèãñ2¤n€Iz *MWUn½Ö[X<<ZV ƒœì ƒH±Ö`ë–Æœ ƒŒ['½µµÝà¶ æ o :: ÔiàiW Ô:ju  (Mþ¦}}Wèãñ2¤n€Iz[E[WÖ è;?  7 á k l … v²9˜™é¿_*pT>Œ[–’êJàÌŒó Ó  5 ð ~  ›†CWÓs™ju  (Mþ¦}}Wèãñ2¤n€IzUÒ¯"óÖDjQ›Ry² 2Áö<¨º2NÞˆ¶ Ð g·Œ[3 º 4F À — Æõ i ÞU-W¢ † t33333333333333333333ju  (Mþ¦}}Wèãñ2¤n€Iz v x  4 –Ö §£ T t£ ”M ´ Ú @ 1 J h Í þ 3ÛN8 Ô ïŒ[%Wvï•u ¸?ªá° æjv놆W‚¹?%%%%%%%%%%%%%%%%%%%%ju  (Mþ¦}}Wèãñ2¤n€Iz`ÚZ I VÖ ºðY ƒ îR à ý±Ä…´ !è '“; ~  ³ ´§«Œ[6° ï # ‰8ò ½ Œ  „ j $ W è éW  ø66666666666666666666ju  (\ ˆTËžž « ª ©Í#¤nÏÌI ¨ÈÈÈ h ,GyŸS} "è:u·|çççç àžTËŠŠ « ª ©‘#¤n’ŽI ¨,, c @ ` ¾ ¾Ls;?Ó íÂÂ#óW ð ð ð ð §Á;žTËŸŸ « ª ©ÑÓ#¤n£ÒÌI ¨¢¢¢C _3ÈÈÈ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼ m m m m ŽªO„¼³-/| MMM´ ÁÎ Œ ¦Ó$GYÆÙäõ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼ ð Ž,, €a ¸{‹‹‹ uˆo½½#0   ð½ ð ¦·|ççççMk:¢¢¢ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼ m ¾Š©l[{‹‹‹ Åuœ,,ÛÊq" mÇ m ¦††#;žTËŸŸ « ª ©ÑÓ#¤n£ÒÌI ¨¢¢¢{‹‹‹ u [œÈN[J † ‡ YðB …µµµµ üžTËŸŸ « ª ©ÑÓ#¤n£ÒÌI ¨¢¢¢{‹‹‹  øËœÒC$Øb Ü| ðnÌÌÌÌ  °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 Ô¹¢¢¢ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼µ?@] lb‰L ŽGz| MMM‰—µ´µ ¦ Á)±¦Ã±‰s¢¢¢ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼Ì ¾,,Ön©{‹‹‹ t¾o î î#Ú{~ÐÌ îÌ ¦’°šRR *VU†#¤n‡‚€IÈTTTTT 3 6 5SÖ 8 7 @ : E A[ , G FSV +ªØSSp°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A H } G Fs ²† ç  \s{ZZZZZ ¥ £Ÿu ñ © ðS  W v ¢   ½ #’Õh™ z {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E Ay³ë G FsÍç,®2s{Á ŒëMMM}} *èãñ2¤n€Iz³2N | {jÖ†¢ÂÞ¾,,^Ûø{‹‹‹ 2 ™ . .# ™êP ’ b . P Q Rº§ ”‚†»Êÿ> ¶7/°š•• *›˜š#¤n–™—I l ä å«« ܶÖ= B ‰ €p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A» G FsmŒ:Yxs{/°š•• *›˜š#¤n–™—I l—O¬¬ {XQp°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A>X{ G Fsn‹ €¨ €s{;°š *!##¤n$" I l£££££ Á {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E AÅ»! G Fs]m¨¯¿s{;°š *!##¤n$" I l¢¢¢¢¢  {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E AÓàÝ G FswBÔsws{;°š *!##¤n$" I l      ý {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A¨¬ð G Fs % BL$s{;°š *!##¤n$" I lŸŸŸŸŸ ÿ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A¡@« G Fs× ˜Nos{;°š *!##¤n$" I l¦¦¦¦¦ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E Aª¼ G FsÎàfL¶s{;°š *!##¤n$" I l¥¥¥¥¥! {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A“v– G Fs¨ºVhØs{;°š *!##¤n$" I l´´´´´# {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E AÌÏä G Fsí,Ús{;°š *!##¤n$" I l³³³³³) {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E Aï¥ù G Fs+?òs{;°š *!##¤n$" I l²²²²²2 {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A 8 G FsAX ž  js{;°š *!##¤n$" I lfffff {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E Aúâù G Fs9%;s{;°š *!##¤n$" I leeeee‘ {Ç°š§§ *ÜÛÔÚ#¤n«Õ¬IȨ¨¨¨¨ 3 6 5ìÖ 8 7 @ : E AQSi G Fì¶S«Ëììp°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E AÖö G Fs6n -|s{$1Qq‘g¿ [ÝQá   G Tì |V‡ëpФ¾Ž ¡˜ { · 7p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A W wì G Fs —Øøßls{;°š *!##¤n$" I lbbbbb™ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A¨D G FsÂàú±s{;°š *!##¤n$" I laaaaaÐ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E AË0[0[ G Fs0[0[0[0[0[s{;°š *!##¤n$" I lmmmmmÑ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[0[ G Fs0[0[0[0[0[s{;°š *!##¤n$" I lkkkkkÒ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[0[ G Fs0[0[0[0[0[s{;°š *!##¤n$" I liiiiiÔ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[0[ G Fs0[0[0[0[0[s{;°š *!##¤n$" I lnnnnnÛ {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[0[ G Fs0[0[0[0[0[s{;°š *!##¤n$" I llllllä {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[0[ G Fs0[0[0[0[0[s{;°š *!##¤n$" I ljjjjjå {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[0[ G Fs0[0[0[0[0[s{;°š *!##¤n$" I l¨¨¨¨¨í {p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[0[ G Fs0[0[0[0[0[s{Á ŒëMMM}} *èãñ2¤n€Iz0[0[0[î {0[Ö0[0[0[0[0[0[,,0[0[0[{‹‹‹ 0[0[ ™ . .# ™0[0[0[0[ .0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[ y°šii *»º´¹#¤n²¸³I ljjjjj 3 6 50[0[ 8 Ùòq°š§§ *ÜÛÔÚ#¤n«Õ¬IȨ¨¨¨¨ 3 6 5 QÖ 8 7 @ : E A0[0[0[ G F Q0[0[0[0[0[ Q Q/°š•• *›˜š#¤n–™—I l0[0[©© g°š%% *IHEG#¤nCFDIÈ''''' 3 6 5ÔÖ 8 7 @ : E A Q0[0[ G FÔ0[0[0[0[0[Ôò0[ò0[0[p°šrr *yx{–#¤n—|zIÈttttt 3 6 5sÖ 8 7 @ : E A0[0[ Q G Fs0[0[0[0[0[s{0[0[0[0[0[0[0[0[0[0[0[Õ0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[C {q°š§§ *ÜÛÔÚ#¤n«Õ¬IȨ¨¨¨¨ 3 6 5 [Ö 8 7 @ : E A0[0[0[ G F [0[0[0[0[0[ [ [q°š§§ *ÜÛÔÚ#¤n«Õ¬IȨ¨¨¨¨ 3 6 5 »Ö 8 7 @ : E A0[0[0[ G F »0[0[0[0[0[ » »0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[ [0[0[2°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5Ö 8 7 @ : E A0[0[0[ G F0[0[0[0[ »0[0[0[ [0[0[œ°šÕÕ *üûöú#¤nòùóIÈñññññ 3 6 5 ÃÖ 8 7 @ : E A0[0[0[ G F Ã0[0[0[0[ » à Ã0[0[0[0[0[0[0[0[0[Ñþ®ýý « ª © #¤n Iz0[0[0[0[0[ Öþ ¹    ýý « ª © #¤n Iz0[0[0[0[0[ Öœ°šÕÕ *üûöú#¤nòùóIÈñññññ 3 6 5hÖ 8 7 @ : E A0[u0[ G Fh0[0[0[0[0[hh0[0[0[0[0[0[0[0[0[0[0[0[0[0[ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼ 0[0[0[0[{‹‹‹  Ã0[œ0[0[0[/l0[ ­ ¬ ° ¯ ² ± · ³ ¹ ¸ ¼ ·°š&& *x0-/#¤n(.,IÈ''''' 3 6 5Ö 8 7 @ : E Au0[0[ G F0[0[0[0[0[/°š•• *›˜š#¤n–™—I l 0[ªª0[0[0[0[0[{‹‹‹  0[œ0[0[0[0[0[0[0[0[0[0[h0[0[ 0[0[0[0[0[0[0[Ÿ0[ 0[0[0[ œ°šÕÕ *üûöú#¤nòùóIÈñññññ 3 6 5JÖ 8 7 @ : E A0[0[0[ G FJ0[0[0[0[0[JJg°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 ÂÖ 8 7 @ : E A0[0[0[ G F Â0[0[0[0[0[  Âg°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 Ö 8 7 @ : E A0[0[0[ G F 0[0[0[0[0[  0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 .Ö 8 7 @ : E A0[0[J G F .0[0[0[0[0[ . .g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 6Ö 8 7 @ : E A0[0[0[ G F 60[0[0[0[0[ 6 6g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 rÖ 8 7 @ : E A0[0[0[ G F r0[0[0[0[0[ r rg°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 sÖ 8 7 @ : E A0[0[0[ G F s0[0[0[0[0[ s sg°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 ~Ö 8 7 @ : E A0[0[0[ G F ~0[0[0[0[0[ ~ ~g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 Ö 8 7 @ : E A0[0[0[ G F 0[0[0[0[0[  g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 ‚Ö 8 7 @ : E A0[0[0[ G F ‚0[0[0[0[0[ ‚ ‚œ°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 ’Ö 8 7 @ : E A0[0[0[ G F ’0[0[0[0[0[ ’ ’g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 áÖ 8 7 @ : E A0[0[0[ G F á0[0[0[0[0[ á ág°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 ÿÖ 8 7 @ : E A0[0[0[ G F ÿ0[0[0[0[0[ ÿ ÿg°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 GÖ 8 7 @ : E A0[0[0[ G F G0[0[0[0[0[ G GÑ°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 Ö 8 7 @ : E A0[0[0[ G F 0[0[0[0[0[  g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5 ÓÖ 8 7 @ : E A0[0[0[ G F Ó0[0[0[0[0[ Ó Ó Œ    Ãà *#¤nÅÆI lÄÄÄÄÄ 3 6 0[0[0[0[0[0[0[0[,{0[0[0[0[0[0[0[0[0[0[0[ #0[0[g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5Ö 8 7 @ : E A0[0[0[ G F0[0[0[0[$0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[$  $0[0[g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5|Ö 8 7 @ : E A0[0[0[ G F|0[0[0[$ ||g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5Ö 8 7 @ : E A0[0[0[ G F0[0[0[0[0[g°šŽŽ *’‘•™#¤n›–”IÈ 3 6 5Ö 8 7 @ : E AJ0[0[ G F0[0[0[0[0[ °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 Õ0[{‹‹‹ 0[0[œ0[0[0[’.ï0[0[0[0[ ÷ ÷ ÷ ÷êàÅm0[0[0[0[0[ °š©© *¯®±ú#¤nû²°I lªªªªª 3 6 50[ ÷ 8 7 @ : E A0[0[ ÷ â0[H0[0[) ËssssJý Ë0[0[0[0[0[0[0[0[0[0[ ÷ ÷ ÷ ÷ ÷ ¥ £0[0[0[0[0[0[0[0[0[ð, ¢  0[0[0[0[, 0[0[{‹‹‹ ² ÷œ S U0[’/0[¹0[0[ÝÝÝÝêàÅm0[0[0[0[0[ ÷0[0[0[0[0[0[0[0[0[0[{0[0[0[0[0[0[0[ ÷ ÷ ÷ ÷0[0[0[ý Ëö0[Ý0[0[Ýl0[0[0[Ý0[0[H0[| MMM0[0[0[0[0[0[0[0[0[0[% X, ÷0[ÝÝÝÝÝ ¥ £0[0[0[0[0[0[0[ ,,0[ ¢  {‹‹‹ 0[0[o ó ó#0[0[0[0[Ý ó S U M°šüü *NML#¤nI l 3 6 5 X0[ 8 7 @ : E ã0[0[ÝÝÝÝ °š©© *¯®±ú#¤nû²°I lªªªªª 3 6 50[0[ 8 7 @ : E A0[0[% 0[Ý ‚°šžž *¡ £¥#¤n¦¤¢I lŸŸŸŸŸ 3 6 50[0[ 8 7 @ : E A0[0[0[ G FÑ ‚°šžž *¡ £¥#¤n¦¤¢I lŸŸŸŸŸ 3 6 50[0[ 8 7 @ : E A0[0[0[ G F ‚°šžž *¡ £¥#¤n¦¤¢I lŸŸŸŸŸ 3 6 500[ 8 7 @ : E A0[0[0[ G Fœ °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 Ö{‹‹‹ 0[0[œ0[0[0[’$0[0[0[0[½â¾êàÅm0[0[ °š©© *¯®±ú#¤nû²°I lªªªªª 3 6 50[ 8 7 @ : E A0[0[0[ H·|çççç0[0[0[0[0[0[0[0[0[0[0[0[0[W0[0[0[0[ ¥ £0[0[0[0[0[0[,¨0[0[0[ ¢  0[0[0[0[0[0[EE#0[0[0[0[0[0[&¿-\ S U{‹‹‹ 0[0[œ0[0[0[.‡0[0[0[0[½â¾êàÅm0[0[$%$%$%$%0[0[0[0[0[0[0[A0[0[0[e|çççç0[0[0[0[0[0[0[0[0[0[0[$%E0[ „l0[0[0[0[$%0[0[H0[0[0[ 0[0[0[,¨0[0[0[0[0[0[0[>0[0[0[ Í#0[0[0[0[0[0[0[0[0[$%gL0[0[0[0[0[0[0[0[0[0[0[{‹‹‹ 0[0[œ0[0[$%.‡I0[0[0[½â¾êàÅm&0[0[0[$%0[0[0[0[0[0[0[0[0[0[0[&((&00[0[0[0[0[0[0[0[0[0[0[0[0[0[ Þl0[$%$%$%0[0[H0[0[Ú°šqq *¾t½#¤nr¼sI l            0[ ÝL0[0[0[0[0[0[$%0[000[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[‡0[0[0[ M°šüü *NML#¤nI l 3 6 50[$¢ 8 7 @ : E ý M°šüü *NML#¤nI l 3 6 5 0[ 8 7 @ : E  ã°šVV *¨`]_#¤nX^\I lWWWWW 3 6 50[0[ 8 7 @ à{‹‹‹ 0[0[œ0[0[0[.‡0[0[0[0[½â¾êàÅm0[0[0[0[0[0[0[0[0[0[0[0[0[0[;|çççç0[0[0[0[0[0[0[0[0[0[0[0[ Þl0[0[0[0[0[0[H0[0[0[0[0[0[,{0[0[0[0[0[0[u0[0[0[0[ #0[0[{‹‹‹ 0[œ ÝL.‡0[0[0[0[½â¾êàÅm0[××××0[0[{‹‹‹ ‡œ0[0[0[/l0[$0[0[0[0[0[0[0[0[0[0[0[0[0[0[×0[0[ „l$  $×0[0[H%0[0[Ç0[0[þ°}} *èãñ2¤n€Iz0[0[×gLÖ0[0[0[0[0[0[0[$ {‹‹‹ 0[0[œ0[0[×.‡0[0[0[0[½â¾êàÅm0[0[ˆˆˆˆ0[0[×<0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[ 0[0[0[0[0[0[ˆ0[0[ Þlu××׈0[0[H0[0[ˆÚ°šqq *¾t½#¤nr¼sI l ¡ ¡ ¡ ¡ ¡ ¡0[ˆ ÝL{‹‹‹ 0[0[œ0[0[0[/l0[0[0[ˆ0[0[0[0[0[0[0[0[0[0[0[0[ˆˆ ®°š¼¼ *  #¤n  I l 3 6 5.0[ 8 7 @ : þ ®°š¼¼ *  #¤n  I l 3 6 50[0[ 8 7 @ : {‹‹‹ 0[0[œ0[0[0[.‡0[­0[0[½â¾êàÅm0[ˆˆˆˆ0[0[0[0[0[0[ 0[0[0[0[d|çççç0[0[0[0[0[È{‹‹‹ ˆ0[œ Þl0[ &0[ˆ0[0[H0[0[ˆ0[0[0[0[,{0[0[0[0[0[0[0[0[0[0[0[ #0[0[{‹‹‹ 0[œˆ ÝL’.æ0[0[0[0[½â¾êàÅmˆ0[0[0[0[0[0[0[0[ˆˆ0[0[0[0[0[0[0[#0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[ Þl#  #0[0[0[0[0[0[ ã°šVV *¨`]_#¤nX^\I lWWWWW 3 6 5 8 7 @ û0[0[0[ž0[0[# 0[0[0[0[0[0[{0[0[0[0[0[ 0[ S U0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[í0[0[0[0[0[$H Ÿ ã°šVV *¨`]_#¤nX^\I lWWWWW 3 6 50[0[ 8 7 @ {‹‹‹ 0[0[œ0[0[0[$0[0[0[0[½â¾êàÅm0[0[-¤-¤-¤-¤ D°š *`bg#¤nhfaI l 3 6 50[-¤ 8 7 Ø °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 ×0[0[ñññññ ¥ £0[0[0[0[0[0[0[0[0[0[0[0[ ¢  0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[-¤ D°š *`bg#¤nhfaI l 3 6 50[0[ 8 7 ü0[0[0[0[0[ñ D°š *`bg#¤nhfaI l 3 6 50[0[ 8 7  y°šii *»º´¹#¤n²¸³I ljjjjj 3 6 50[0[ 8 Ü y°šii *»º´¹#¤n²¸³I ljjjjj 3 6 50[0[ 8 ù y°šii *»º´¹#¤n²¸³I ljjjjj 3 6 50[0[ 8 ú y°šii *»º´¹#¤n²¸³I ljjjjj 3 6 5H0[ 8  y°šii *»º´¹#¤n²¸³I ljjjjj 3 6 50[0[ 8 0[0[0[0[0[0[{‹‹‹ 0[0[œ0[0[0[.æ0[0[0[0[½â¾êàÅm0[¿(—(—(—(— °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 ï(—(—0[ Þl0[0[0[0[{‹‹‹ 0[(—œ0[0[0[.æ0[0[0[0[½â¾êàÅm0[0[««««Ú°šqq *¾t½#¤nr¼sI l í í í í í í(—H««0[ Þl0[0[0[0[0[0[0[0[0[0[«0[0[0[0[0[0[0[0[0[(—0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[$H Ÿ0[{‹‹‹ 0[0[œ0[0[0[$0[0[0[0[½â¾êàÅm«0[ ·|çççç0[0[0[0[0[0[0[0[0[0[0[0[0[«0[0[0[0[0[0[0[0[0[0[ 0[0[0[0[$H Ÿ,,0[0[0[0[0[0[0[0[0[0[0[……#0[0[(— °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 ð °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 ñ °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 ò °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6  °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6  °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 °šÃà *#¤nÅÆI lÄÄÄÄÄ 3 6 dþ°}} *èãñ2¤n€Iz0[0[0[0[0[0[Ödþ°}} *èãñ2¤n€Iz0[0[0[0[0[0[Ö0[0[0[0[0[0[0[0[0[0[0[0[Þ¥°š *! jl#¤npk"I l 3 ˜0[0[Þ¥°š *! jl#¤npk"I l 3 ™¥°š *! jl#¤npk"I l 3 š0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[¥°š *! jl#¤npk"I l 3 ó0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[¥°š *! jl#¤npk"I l 3 ôL0[L¥°š *! jl#¤npk"I l 3 ø¥°š *! jl#¤npk"I l 3 ¥°š *! jl#¤npk"I l 3 C¥°š *! jl#¤npk"I l 3 DÚ°šqq *¾t½#¤nr¼sI l î î î î î îÚ°šqq *¾t½#¤nr¼sI l E E E E E EÚ°šqq *¾t½#¤nr¼sI l F F F F F F|ççççÿ|çççç0[0[0[0[0[0[˜0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[,¨0[0[0[0[0[,¨0[0[0[Ö#0[0[0[0[0[ Í#Ü0[0[{‹‹‹ 0[0[œ0[0[0[$0[0[0[0[½â¾êàÅm0[î-Ö-Ö-Ö-Ö0[0[0[0[0[0[0[#0[{‹‹‹ 0[#œ0[0[0[ &0[0[0[0[0[#ÕÕ#.-Ö0[0[# Ä Ä#.{‹‹‹ 0[0[œ0[0[0[$0[0[0[0[½â¾êàÅm0[0[-û-û-û-û}|çççç#Õ0[0[0[0[0[0[# ÄX| MMM0[0[0[..4-û-Ö0[0[0[..,¨0[0[·|çççç0[Ö#0[,,0[0[0[{‹‹‹ 0[0[Üss#Ü0[0[0[0[s0[0[0[,¨0[.440[ % %0[0[.FII#ž0[0[0[0[0[-û&0[0[0[{0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[&((&00[0[0[0[40[0[0[0[{‹‹‹ 0[0[œ0[@$0[0[0[0[½â¾êàÅml0[\\\\0[D0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0060[\0[0[0[0[0[0[{‹‹‹ 0[œ0[0[0[$0[0[0[0[½â¾êàÅm0[0[\\\\0[0[H0[0[0[0[0[0[0[0[0[0[0[66{‹‹‹ 0[0[œ0[N0[$0[0[\0[½â¾êàÅm0[0[\\\\0[0[0[0[{‹‹‹ 0[0[œ0[0[0[$0[u0[µ½â¾êàÅm0[\\\\\X| MMM0[0[0[0[0[0[0[0[0[0[;|çççç{‹‹‹ 0[\œ0[0[0[.˜,,0[0[0[{‹‹‹ 0[0[Üss#Ü,{0[s | MMM0[ #0[0[0[0[0[S| MMM0[0[0[0[0[0[ Þl0[0[0[0[0[0[,,0[ 0[0[0[0[0[0[0[0[0[÷÷#,,0[0[÷0[&0[0[0[0[0[0[  #0[0[ ÝL 0[0[0[0[&((&0[0[0[0[0[0[0[  | MMM0[| MMM0[0[0[0[/«0[0[0[0[ | MMM0[0[0[0[/«,,0[0[0[0[0[0[,,0[0[###0[0[0[0[0[#kk#,,0[0[k0[0[0[0[0[0[0[0[kk#0[0[0[0[0[k0[0[0[0[0[0[0[0[0[O0[0[0[0[0[ ·|çççç0[0[0[0[/¼0[0[0[0[0[0[0[0[/Å·|ççççŽ| MMM/Ö,¨0[0[0[0[0[0[0[0[0[0[0[××#0[0[0[0[0[,¨0[0[0[0[0[,,0[0[0[ØØ#0[0[0[0[0[ ³ ³#0[0[0[0[0[ ³0[Ï| MMM0[0[0[0[0[0[A0[0[Ï| MMM0[Ž| MMM0[0[@0[E,,0[Ï| MMM0[0[ æ æ#,,0[D æ0[0[0[,,0[0[ ë ë#0[0[0[0[0[ ë J J#,,0[0[ J·|çççç J J#0[0[0[0[0[ J·|çççç·|çççç0[0[0[0[0[0[,{Ž| MMM0[0[0[ Î Î#,{0[0[0[0[0[,{0[0[0[ Ð Ð#0[0[0[0[0[úú#,,0[0[·|çççç0[¹¹#0[0[0[0[0[¹0[0[0[A0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[@,{0[0[0[0[W0[0[0[0[0[0[êê#0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[[ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java0000644000175000001440000001054312212041344031363 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * 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. * The mirror implementation is using the backward compatible ITerminalSymbols constant * 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. * * Disclaimer : These constant values are generated automatically using a Java * grammar, therefore their actual values are subject to change if new keywords * were added to the language (for instance, 'assert' is a keyword in 1.4). */ public interface TerminalTokens { // special tokens not part of grammar - not autogenerated int TokenNameWHITESPACE = 1000, TokenNameCOMMENT_LINE = 1001, TokenNameCOMMENT_BLOCK = 1002, TokenNameCOMMENT_JAVADOC = 1003; int TokenNameIdentifier = 26, TokenNameabstract = 56, TokenNameassert = 74, TokenNameboolean = 32, TokenNamebreak = 75, TokenNamebyte = 33, TokenNamecase = 102, TokenNamecatch = 100, TokenNamechar = 34, TokenNameclass = 72, TokenNamecontinue = 76, TokenNameconst = 108, TokenNamedefault = 97, TokenNamedo = 77, TokenNamedouble = 35, TokenNameelse = 104, TokenNameenum = 98, TokenNameextends = 99, TokenNamefalse = 44, TokenNamefinal = 57, TokenNamefinally = 103, TokenNamefloat = 36, TokenNamefor = 78, TokenNamegoto = 109, TokenNameif = 79, TokenNameimplements = 106, TokenNameimport = 101, TokenNameinstanceof = 13, TokenNameint = 37, TokenNameinterface = 95, TokenNamelong = 38, TokenNamenative = 58, TokenNamenew = 43, TokenNamenull = 45, TokenNamepackage = 96, TokenNameprivate = 59, TokenNameprotected = 60, TokenNamepublic = 61, TokenNamereturn = 80, TokenNameshort = 39, TokenNamestatic = 54, TokenNamestrictfp = 62, TokenNamesuper = 41, TokenNameswitch = 81, TokenNamesynchronized = 55, TokenNamethis = 42, TokenNamethrow = 82, TokenNamethrows = 105, TokenNametransient = 63, TokenNametrue = 46, TokenNametry = 83, TokenNamevoid = 40, TokenNamevolatile = 64, TokenNamewhile = 73, TokenNameIntegerLiteral = 47, TokenNameLongLiteral = 48, TokenNameFloatingPointLiteral = 49, TokenNameDoubleLiteral = 50, TokenNameCharacterLiteral = 51, TokenNameStringLiteral = 52, TokenNamePLUS_PLUS = 8, TokenNameMINUS_MINUS = 9, TokenNameEQUAL_EQUAL = 18, TokenNameLESS_EQUAL = 14, TokenNameGREATER_EQUAL = 15, TokenNameNOT_EQUAL = 19, TokenNameLEFT_SHIFT = 17, TokenNameRIGHT_SHIFT = 10, TokenNameUNSIGNED_RIGHT_SHIFT = 12, TokenNamePLUS_EQUAL = 84, TokenNameMINUS_EQUAL = 85, TokenNameMULTIPLY_EQUAL = 86, TokenNameDIVIDE_EQUAL = 87, TokenNameAND_EQUAL = 88, TokenNameOR_EQUAL = 89, TokenNameXOR_EQUAL = 90, TokenNameREMAINDER_EQUAL = 91, TokenNameLEFT_SHIFT_EQUAL = 92, TokenNameRIGHT_SHIFT_EQUAL = 93, TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 94, TokenNameOR_OR = 25, TokenNameAND_AND = 24, TokenNamePLUS = 1, TokenNameMINUS = 2, TokenNameNOT = 66, TokenNameREMAINDER = 5, TokenNameXOR = 21, TokenNameAND = 20, TokenNameMULTIPLY = 4, TokenNameOR = 22, TokenNameTWIDDLE = 67, TokenNameDIVIDE = 6, TokenNameGREATER = 11, TokenNameLESS = 7, TokenNameLPAREN = 29, TokenNameRPAREN = 28, TokenNameLBRACE = 68, TokenNameRBRACE = 31, TokenNameLBRACKET = 16, TokenNameRBRACKET = 70, TokenNameSEMICOLON = 27, TokenNameQUESTION = 23, TokenNameCOLON = 65, TokenNameCOMMA = 30, TokenNameDOT = 3, TokenNameEQUAL = 71, TokenNameAT = 53, TokenNameELLIPSIS = 107, TokenNameEOF = 69, TokenNameERROR = 110; } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser11.rsc0000644000175000001440000000042412212041344027725 0ustar dokousersWm²¾`p . «««áá. ???Wmm©o¹Áht  «7’ ŸK….HT\tv{™–ßptLQVY^” ÚGNQkx gÈJT d$7$2+÷ ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.j0000644000175000001440000001414412212041344032274 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; /** * Internal local variable structure for parsing recovery */ import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; public class RecoveredLocalVariable extends RecoveredStatement { public RecoveredAnnotation[] annotations; public int annotationCount; public int modifiers; public int modifiersStart; public LocalDeclaration localDeclaration; boolean alreadyCompletedLocalInitialization; public RecoveredLocalVariable(LocalDeclaration localDeclaration, RecoveredElement parent, int bracketBalance){ super(localDeclaration, parent, bracketBalance); this.localDeclaration = localDeclaration; this.alreadyCompletedLocalInitialization = localDeclaration.initialization != null; } /* * Record an expression statement if local variable is expecting an initialization expression. */ public RecoveredElement add(Statement stmt, int bracketBalanceValue) { if (this.alreadyCompletedLocalInitialization || !(stmt instanceof Expression)) { return super.add(stmt, bracketBalanceValue); } else { this.alreadyCompletedLocalInitialization = true; this.localDeclaration.initialization = (Expression)stmt; this.localDeclaration.declarationSourceEnd = stmt.sourceEnd; this.localDeclaration.declarationEnd = stmt.sourceEnd; return this; } } public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) { if (annotCount > 0) { Annotation[] existingAnnotations = this.localDeclaration.annotations; if (existingAnnotations != null) { this.annotations = new RecoveredAnnotation[annotCount]; this.annotationCount = 0; next : for (int i = 0; i < annotCount; i++) { for (int j = 0; j < existingAnnotations.length; j++) { if (annots[i].annotation == existingAnnotations[j]) continue next; } this.annotations[this.annotationCount++] = annots[i]; } } else { this.annotations = annots; this.annotationCount = annotCount; } } if (mods != 0) { this.modifiers = mods; this.modifiersStart = modsSourceStart; } } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.localDeclaration; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.localDeclaration.declarationSourceEnd; } public String toString(int tab) { return tabString(tab) + "Recovered local variable:\n" + this.localDeclaration.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$ } public Statement updatedStatement(int depth, Set knownTypes){ /* update annotations */ if (this.modifiers != 0) { this.localDeclaration.modifiers |= this.modifiers; if (this.modifiersStart < this.localDeclaration.declarationSourceStart) { this.localDeclaration.declarationSourceStart = this.modifiersStart; } } /* update annotations */ if (this.annotationCount > 0){ int existingCount = this.localDeclaration.annotations == null ? 0 : this.localDeclaration.annotations.length; Annotation[] annotationReferences = new Annotation[existingCount + this.annotationCount]; if (existingCount > 0){ System.arraycopy(this.localDeclaration.annotations, 0, annotationReferences, this.annotationCount, existingCount); } for (int i = 0; i < this.annotationCount; i++){ annotationReferences[i] = this.annotations[i].updatedAnnotationReference(); } this.localDeclaration.annotations = annotationReferences; int start = this.annotations[0].annotation.sourceStart; if (start < this.localDeclaration.declarationSourceStart) { this.localDeclaration.declarationSourceStart = start; } } return this.localDeclaration; } /* * A closing brace got consumed, might have closed the current element, * in which case both the currentElement is exited. * * Fields have no associated braces, thus if matches, then update parent. */ public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if (this.bracketBalance > 0){ // was an array initializer this.bracketBalance--; if (this.bracketBalance == 0) this.alreadyCompletedLocalInitialization = true; return this; } if (this.parent != null){ return this.parent.updateOnClosingBrace(braceStart, braceEnd); } return this; } /* * An opening brace got consumed, might be the expected opening one of the current element, * in which case the bodyStart is updated. */ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ if (this.localDeclaration.declarationSourceEnd == 0 && (this.localDeclaration.type instanceof ArrayTypeReference || this.localDeclaration.type instanceof ArrayQualifiedTypeReference) && !this.alreadyCompletedLocalInitialization){ this.bracketBalance++; return null; // no update is necessary (array initializer) } // might be an array initializer this.updateSourceEndIfNecessary(braceStart - 1, braceEnd - 1); return this.parent.updateOnOpeningBrace(braceStart, braceEnd); } public void updateParseTree(){ updatedStatement(0, new HashSet()); } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ if (this.localDeclaration.declarationSourceEnd == 0) { this.localDeclaration.declarationSourceEnd = bodyEnd; this.localDeclaration.declarationEnd = bodyEnd; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/NLSTag.java0000644000175000001440000000177712212041344027525 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; public class NLSTag { public int start; public int end; public int lineNumber; public int index; public NLSTag(int start, int end, int lineNumber, int index) { this.start = start; this.end = end; this.lineNumber = lineNumber; this.index = index; } public String toString() { return "NLSTag(" + this.start + "," + this.end + "," + this.lineNumber + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$ } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser10.rsc0000644000175000001440000000042412212041344027724 0ustar dokousersþçöOO»ÈÏï áî µÂy¬¬èþ%ZZ)C1:a}‰§­±ÖÝã%0˜ÍÑC`;B£9‹‹µÑ6?¥kµµdd)xÚ4=@H¢œ×hœX†H[‚,FFFrr—”ÆËÕÝÕ^nrJOJOJ››ve000õõõõ0ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java0000644000175000001440000004734012212041344031162 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * David Foerster - patch for toUpperCase as described in https://bugs.eclipse.org/bugs/show_bug.cgi?id=153125 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.FileNotFoundException; import java.io.IOException; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; public class ScannerHelper { public final static long[] 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, ASTNode.Bit17, ASTNode.Bit18, ASTNode.Bit19, ASTNode.Bit20, ASTNode.Bit21, ASTNode.Bit22, ASTNode.Bit23, ASTNode.Bit24, ASTNode.Bit25, ASTNode.Bit26, ASTNode.Bit27, ASTNode.Bit28, ASTNode.Bit29, ASTNode.Bit30, ASTNode.Bit31, ASTNode.Bit32, ASTNode.Bit33L, ASTNode.Bit34L, ASTNode.Bit35L, ASTNode.Bit36L, ASTNode.Bit37L, ASTNode.Bit38L, ASTNode.Bit39L, ASTNode.Bit40L, ASTNode.Bit41L, ASTNode.Bit42L, ASTNode.Bit43L, ASTNode.Bit44L, ASTNode.Bit45L, ASTNode.Bit46L, ASTNode.Bit47L, ASTNode.Bit48L, ASTNode.Bit49L, ASTNode.Bit50L, ASTNode.Bit51L, ASTNode.Bit52L, ASTNode.Bit53L, ASTNode.Bit54L, ASTNode.Bit55L, ASTNode.Bit56L, ASTNode.Bit57L, ASTNode.Bit58L, ASTNode.Bit59L, ASTNode.Bit60L, ASTNode.Bit61L, ASTNode.Bit62L, ASTNode.Bit63L, ASTNode.Bit64L, }; private static final int START_INDEX = 0; private static final int PART_INDEX = 1; private static long[][][] Tables; private static long[][][] Tables7; public final static int MAX_OBVIOUS = 128; public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS]; public final static int C_JLS_SPACE = ASTNode.Bit9; public final static int C_SPECIAL = ASTNode.Bit8; public final static int C_IDENT_START = ASTNode.Bit7; public final static int C_UPPER_LETTER = ASTNode.Bit6; public final static int C_LOWER_LETTER = ASTNode.Bit5; public final static int C_IDENT_PART = ASTNode.Bit4; public final static int C_DIGIT = ASTNode.Bit3; public final static int C_SEPARATOR = ASTNode.Bit2; public final static int C_SPACE = ASTNode.Bit1; static { OBVIOUS_IDENT_CHAR_NATURES[0] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[1] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[2] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[3] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[4] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[5] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[6] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[7] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[8] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[14] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[15] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[16] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[17] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[18] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[19] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[20] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[21] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[22] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[23] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[24] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[25] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[26] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[27] = C_IDENT_PART; OBVIOUS_IDENT_CHAR_NATURES[127] = C_IDENT_PART; for (int i = '0'; i <= '9'; i++) OBVIOUS_IDENT_CHAR_NATURES[i] = C_DIGIT | C_IDENT_PART; for (int i = 'a'; i <= 'z'; i++) OBVIOUS_IDENT_CHAR_NATURES[i] = C_LOWER_LETTER | C_IDENT_PART | C_IDENT_START; for (int i = 'A'; i <= 'Z'; i++) OBVIOUS_IDENT_CHAR_NATURES[i] = C_UPPER_LETTER | C_IDENT_PART | C_IDENT_START; OBVIOUS_IDENT_CHAR_NATURES['_'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START; OBVIOUS_IDENT_CHAR_NATURES['$'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START; OBVIOUS_IDENT_CHAR_NATURES[9] = C_SPACE | C_JLS_SPACE; // \ u0009: HORIZONTAL TABULATION OBVIOUS_IDENT_CHAR_NATURES[10] = C_SPACE | C_JLS_SPACE; // \ u000a: LINE FEED OBVIOUS_IDENT_CHAR_NATURES[11] = C_SPACE; OBVIOUS_IDENT_CHAR_NATURES[12] = C_SPACE | C_JLS_SPACE; // \ u000c: FORM FEED OBVIOUS_IDENT_CHAR_NATURES[13] = C_SPACE | C_JLS_SPACE; // \ u000d: CARRIAGE RETURN OBVIOUS_IDENT_CHAR_NATURES[28] = C_SPACE; OBVIOUS_IDENT_CHAR_NATURES[29] = C_SPACE; OBVIOUS_IDENT_CHAR_NATURES[30] = C_SPACE; OBVIOUS_IDENT_CHAR_NATURES[31] = C_SPACE; OBVIOUS_IDENT_CHAR_NATURES[32] = C_SPACE | C_JLS_SPACE; // \ u0020: SPACE OBVIOUS_IDENT_CHAR_NATURES['.'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES[':'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES[';'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES[','] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['['] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES[']'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['('] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES[')'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['{'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['}'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['+'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['-'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['*'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['/'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['='] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['&'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['|'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['?'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['<'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['>'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['!'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['%'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['^'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['~'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['"'] = C_SEPARATOR; OBVIOUS_IDENT_CHAR_NATURES['\''] = C_SEPARATOR; } static void initializeTable() { Tables = new long[2][][]; Tables[START_INDEX] = new long[3][]; Tables[PART_INDEX] = new long[4][]; try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode/start0.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables[START_INDEX][0] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode/start1.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables[START_INDEX][1] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode/start2.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables[START_INDEX][2] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode/part0.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables[PART_INDEX][0] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode/part1.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables[PART_INDEX][1] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode/part2.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables[PART_INDEX][2] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode/part14.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables[PART_INDEX][3] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } static void initializeTable17() { Tables7 = new long[2][][]; Tables7[START_INDEX] = new long[3][]; Tables7[PART_INDEX] = new long[4][]; try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode6/start0.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables7[START_INDEX][0] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode6/start1.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables7[START_INDEX][1] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode6/start2.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables7[START_INDEX][2] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode6/part0.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables7[PART_INDEX][0] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode6/part1.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables7[PART_INDEX][1] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode6/part2.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables7[PART_INDEX][2] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream("unicode6/part14.rsc"))); //$NON-NLS-1$ long[] readValues = new long[1024]; for (int i = 0; i < 1024; i++) { readValues[i] = inputStream.readLong(); } inputStream.close(); Tables7[PART_INDEX][3] = readValues; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private final static boolean isBitSet(long[] values, int i) { try { return (values[i / 64] & Bits[i % 64]) != 0; } catch (NullPointerException e) { return false; } } public static boolean isJavaIdentifierPart(char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0; } return Character.isJavaIdentifierPart(c); } public static boolean isJavaIdentifierPart(long complianceLevel, char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0; } return isJavaIdentifierPart(complianceLevel, (int) c); } public static boolean isJavaIdentifierPart(long complianceLevel, int codePoint) { if (complianceLevel <= ClassFileConstants.JDK1_6) { if (Tables == null) { initializeTable(); } switch((codePoint & 0x1F0000) >> 16) { case 0 : return isBitSet(Tables[PART_INDEX][0], codePoint & 0xFFFF); case 1 : return isBitSet(Tables[PART_INDEX][1], codePoint & 0xFFFF); case 2 : return isBitSet(Tables[PART_INDEX][2], codePoint & 0xFFFF); case 14 : return isBitSet(Tables[PART_INDEX][3], codePoint & 0xFFFF); } } else { // java 7 supports Unicode 6 if (Tables7 == null) { initializeTable17(); } switch((codePoint & 0x1F0000) >> 16) { case 0 : return isBitSet(Tables7[PART_INDEX][0], codePoint & 0xFFFF); case 1 : return isBitSet(Tables7[PART_INDEX][1], codePoint & 0xFFFF); case 2 : return isBitSet(Tables7[PART_INDEX][2], codePoint & 0xFFFF); case 14 : return isBitSet(Tables7[PART_INDEX][3], codePoint & 0xFFFF); } } return false; } public static boolean isJavaIdentifierPart(long complianceLevel, char high, char low) { return isJavaIdentifierPart(complianceLevel, toCodePoint(high, low)); } public static boolean isJavaIdentifierStart(char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0; } return Character.isJavaIdentifierStart(c); } public static boolean isJavaIdentifierStart(long complianceLevel, char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0; } return ScannerHelper.isJavaIdentifierStart(complianceLevel, (int) c); } public static boolean isJavaIdentifierStart(long complianceLevel, char high, char low) { return isJavaIdentifierStart(complianceLevel, toCodePoint(high, low)); } public static boolean isJavaIdentifierStart(long complianceLevel, int codePoint) { if (complianceLevel <= ClassFileConstants.JDK1_6) { if (Tables == null) { initializeTable(); } switch((codePoint & 0x1F0000) >> 16) { case 0 : return isBitSet(Tables[START_INDEX][0], codePoint & 0xFFFF); case 1 : return isBitSet(Tables[START_INDEX][1], codePoint & 0xFFFF); case 2 : return isBitSet(Tables[START_INDEX][2], codePoint & 0xFFFF); } } else { // java 7 supports Unicode 6 if (Tables7 == null) { initializeTable17(); } switch((codePoint & 0x1F0000) >> 16) { case 0 : return isBitSet(Tables7[START_INDEX][0], codePoint & 0xFFFF); case 1 : return isBitSet(Tables7[START_INDEX][1], codePoint & 0xFFFF); case 2 : return isBitSet(Tables7[START_INDEX][2], codePoint & 0xFFFF); } } return false; } private static int toCodePoint(char high, char low) { return (high - Scanner.HIGH_SURROGATE_MIN_VALUE) * 0x400 + (low - Scanner.LOW_SURROGATE_MIN_VALUE) + 0x10000; } public static boolean isDigit(char c) throws InvalidInputException { if(c < ScannerHelper.MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0; } if (Character.isDigit(c)) { throw new InvalidInputException(Scanner.INVALID_DIGIT); } return false; } public static int digit(char c, int radix) { if (c < ScannerHelper.MAX_OBVIOUS) { switch(radix) { case 8 : if (c >= 48 && c <= 55) { return c - 48; } return -1; case 10 : if (c >= 48 && c <= 57) { return c - 48; } return -1; case 16 : if (c >= 48 && c <= 57) { return c - 48; } if (c >= 65 && c <= 70) { return c - 65 + 10; } if (c >= 97 && c <= 102) { return c - 97 + 10; } return -1; } } return Character.digit(c, radix); } public static int getNumericValue(char c) { if (c < ScannerHelper.MAX_OBVIOUS) { switch(ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c]) { case C_DIGIT : return c - '0'; case C_LOWER_LETTER : return 10 + c - 'a'; case C_UPPER_LETTER : return 10 + c - 'A'; } } return Character.getNumericValue(c); } public static int getHexadecimalValue(char c) { switch(c) { case '0' : return 0; case '1' : return 1; case '2' : return 2; case '3' : return 3; case '4' : return 4; case '5' : return 5; case '6' : return 6; case '7' : return 7; case '8' : return 8; case '9' : return 9; case 'A' : case 'a' : return 10; case 'B' : case 'b' : return 11; case 'C' : case 'c' : return 12; case 'D' : case 'd' : return 13; case 'E' : case 'e' : return 14; case 'F' : case 'f' : return 15; default: return -1; } } public static char toUpperCase(char c) { if (c < MAX_OBVIOUS) { if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) { return c; } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) { return (char) (c - 32); } } return Character.toUpperCase(c); } public static char toLowerCase(char c) { if (c < MAX_OBVIOUS) { if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) { return c; } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) { return (char) (32 + c); } } return Character.toLowerCase(c); } public static boolean isLowerCase(char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0; } return Character.isLowerCase(c); } public static boolean isUpperCase(char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0; } return Character.isUpperCase(c); } /** * Include also non JLS whitespaces. * * return true if Character.isWhitespace(c) would return true */ public static boolean isWhitespace(char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_SPACE) != 0; } return Character.isWhitespace(c); } public static boolean isLetter(char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER)) != 0; } return Character.isLetter(c); } public static boolean isLetterOrDigit(char c) { if (c < MAX_OBVIOUS) { return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_DIGIT)) != 0; } return Character.isLetterOrDigit(c); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser16.rsc0000644000175000001440000000374212212041344027740 0ustar dokousers€CB ´®µ¯²³­°§±¬SRÖPLKMQ zy{|}ƒ+~„x)¨*¼©JÕOI×NØ«75Ÿ¦¥p—–ràr)px}BCŠŒ‹’‘”“™˜„DO  ¦ç6Þ§ß§5¦'(N§¦MeBC„zyxöõø÷úùüûþýpÿ§dƒJ§+‚§ †jDWcDcDWb_HD—hª¡HÁpããmp+rᨕp—p)*$£–prD¡AAG“p«5r½··ãã··rpãã   a,§.â«, «`â«`,6pDãããã      «,â«rá•â D%&PY6 §?ª5Y¦v5Z5hjdi˜¦«¡I¡„¨á4á4¡¡+*¨)¨¾¿¾)c<A¡¡d«¦p0¡ëÚ_±¬­o¾*¨)¡p¨¨Ý·œ·‹‹‹ŠŠŒŒŒŒ‘“’¡˜”‘’-««ë-[p«-paŠŠŒŒŒŒ‹‹‹’‘”“¡˜”“’‘ŒŒŒŒ‹‹‹ŠŠ¡˜V§¡-«44[<P&Q66«cÞ Ojigš™«Gá¡pá¨*)¾¾$–£££¡G«CGë_*)ÝžrAEkipE°AAŠ‹¾E¾Q&6)£VÚ¡©¾¾á¾¾¾)c Â×NIOÕHGo®¾¾I•I‰a&§ÚCD¾¾¾¾¾¾$£££hAݾ¾¾ÝI£CG•afb¾o¾)cd¡¡e0ÝGb–3¾££ H  h eecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/0000755000175000001440000000000012212041344027272 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/part1.rsc0000644000175000001440000002000012212041344031022 0ustar dokousers¿ÿÿÿÿÿÿ?ÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ‘¿ÿÿÿÿý??ÿÿÿÿÿ?ÿÿ‡ÿÿþïðoÿÿÿ?ÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãà<çÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÿëÿÞdßÿÿÿÿÿÿÿÿÿÿï{ÿÿÿßßç¿ÿÿÿÿÿýü_ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿ÷ÿÿÿ÷ÿÿýÿßÿÿÿßÿÿÿÿÿÿÿÿÿÿýÿÿÿýÿÿÿÿÿÿÿÏ÷ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/part2.rsc0000644000175000001440000002000012212041344031023 0ustar dokousersÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/start0.rsc0000644000175000001440000002000012212041344031210 0ustar dokousersÿÿþ‡ÿÿþ <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿPÿÃ<ßÿÿÿûÿÿ×@ÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÀÿÿÿÿÿÿÿÿÿœÀ`/ÿÿÿÿÿýÿÿÿÿÿÿà?ÿÿÿÿ0ÿÿÿü?ÿÿÿÿÿ#ÿÿÿÿÿÿðþþÿ#ÅýÿÿùŸà°@mýÿÿù‡à^#íýÿÿû¿à#íýÿÿùŸà°ÿÇÖ=Çè#ïýÿÿýßà#ïýÿÿýßà@'ÿÿÿÿýßàü@/ûÿÿüÿà€ ÿÿÿÿÿþ ì®þð%–0_ÿÿÿþÿ€ÿÿÿÿÿÿáÀb/ü„ÿÿÿÿCàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿxÿÿÿÿÿÿ?ÿÿÿÿ€?ÿÿÿÿÿÿ€>þàÿÿÿÿÿÿÿþÿÿÿþàÿÿ÷ÿÿÿÿÿÿÿÿþ?ÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿ€ÿÿÿÿÿÿÿÿÿyÿüÿÿ÷»ÿÿÿÿÿÿÿÿÿÿÿüüÿÿ?ÿÿüÿÿÿÿÿÿÿÿð€ÿÿÿÿÿÿÿ÷>bÿÿÿÿÿÿ8~~~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_ýÿ øÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿßàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡ÿÿþÿÿÿÀÿÿþÿÿÿÿÿÿÿcüüüecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/part14.rsc0000644000175000001440000002000012212041344031106 0ustar dokousersÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/start1.rsc0000644000175000001440000002000012212041344031211 0ustar dokousers·ÿÿÿÿÿÿ?ÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ‘¿ÿÿÿÿý??ÿÿÿÿÿ?ÿÿÿÿþïÿÿÿ?ÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÿëÿÞdßÿÿÿÿÿÿÿÿÿÿï{ÿÿÿßßç¿ÿÿÿÿÿýü_ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿ÷ÿÿÿ÷ÿÿýÿßÿÿÿßÿÿÿÿÿÿÿÿÿÿýÿÿÿýÿ÷ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/part0.rsc0000644000175000001440000002000012212041344031021 0ustar dokousersÿÿÁÿ‡ÿÿþ‡ÿÿþ $<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿPÿÃÿÿÿÿÿÿÿÿ<ßÿÿÿÿÿÿÿÿÿûÿÿ×@ÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüûÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿ¿ÿÿÿÿþÿÿÿÿ¶ÿÿÿÿÿÿÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿýÿ¿ïÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿçÿÿÿÿÿÿÿ?ÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÏÿÿÿÿóÅýÿÿùŸîÿϰ€yŸÓmýÿÿù‡î?ÿÀ^9‡óíýÿÿû¿îÿÏ;¿óíýÿÿùŸîÿϰÀ9ŸÃÿÇÖ=ÇìÿÀ=ÇãïýÿÿýßîÿÏ`=ßóïýÿÿýßìÿÏ@`=ßçÿÿÿÿýßìüÿÏ€}ß/ûÿÿüÿì ÿ_„‡ÿÿÿÿÿÿþÿÿ;ÿì®þð%–3ÿ?_ ÿÿþÿÿÿþÿÿÿÿþÿÿß@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ==ÿ=ÿÿÿÿ=ÿÿÿÿÿÿÿ=ÿÿÿÿÿ=ÿÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿÿÿÿÿÿÿÿÿÿÿþÇÿÿÿÿÿÿÿßÿ ßÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿøÿÿÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿãÿÿÿÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ??ÿÿ?ÿÿÿªÿ??_ßÿÿÿÿÿÿÜÿÏÜ€|ø€üÿÿÿÿÿâÿóÿ½P>/ü„ÿÿÿÿCàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿ?ÿÿÿÿ€€?ÿÿÿÿÿÿÿÿÿÿ€>ÿþàÿÿÿÿÿÿÿþÿÿÿþæÿÿ÷ÿÿÿÿÿÿÿÿþ?ÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿ€ÿÿÿÿÿÿÿÿÿyÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿ ÿÿÿ?ÿÿÿÿÿÿÿÿÿ8~~~ÿ7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_ýÿàøÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿßàÿÿÿÿÿÿÿÿŸÿÿÿÿÿÿÿ‡ÿÿþÿÿÿÿÀÿÿþÿÿÿÿÿÿÿcüüüecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode6/start2.rsc0000644000175000001440000002000012212041344031212 0ustar dokousersÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser18.rsc0000644000175000001440000002007612212041344027741 0ustar dokousers    !"#$%&'()*+,-./0123456789:;<=>?@DEIJKLMNOPQRS a f   !"#$%&'()*+,-./0123456789:;<=>?@)*DDIJKLMNOPQRS afI cj !"#$%&'()*+,-./0123456789:;<=>?@DHIJKLMNOPQRScG _bTUVWXYZ[\]^+ !"#$%&'()*+,-./0123456789:;<=>?@DEIJKLMNOPQRS    !"#$%&'()*+,-./0123456789:;<=>?@DEIJKLMNOPQRSGD TUVWXYZ[\]^ !"#$%&'()*+,-./0123456789:;<=>?@DEIJKLMNOPQRS d   !"#$%&'()*+,-./0123456789:;<=>?@DEIJKLMNOPQRSGdg TUVWXYZ[\]^ !"#$%&'()*+,-./012347  A IJKLMNOPQRS !"#$%&'()*+,-./012347  E)*IJKLMNOPQRS6 !"#$%&'()*+,-./0123456789:;<=>?@ D   G6TUVWXYZ[\]^ G TUVWXYZ[\]^G !"#$%&'(TUVWXYZ[\]^H _ b k G   TUVWXYZ[\]^AEF !"#$%&'()*+,-./012345 DBC  !"#$%&'()*+,-./012345 BCAD   Fe !"#$%&'()*+,-./012345D BCD   !"#$%&'()*+,-./01234  BCD  !"#$%&'()*+,-./01234c  BCD  !"#$%&'()*+,-./012345 BC  !"#$%&'()*+,-./01234 BCDaf   !"#$%&'()*+,-./01234) BCD   !"#$%&'()*+,-./01234 c BC FA F !"#$%&'()*+,-./01234 BCF)*D  !"#$%&'()*+,-./01234  BCaDf  !"#$%&'()*+,-./012345)+ `BC56789:;<=>?@ !"#$%&'()*+,-./01234`ceBCDg A iAEF AEF H D DAEF    AEF !"#$%&'()*+,-./01234 BC  !"#$%&'()*+,-./01234 BC aFi !"#$%&'()*+,-./01234d  BC _  !"#$%&'()*+,-./01234d  BC G  !"#$%&'()*+,-./01234  BC hG !"#$%&'()*+,-./01234  BC H !"#$%&'()*+,-./01234  BC eH !"#$%&'()*+,-./01234  BC  !"#$%&'()*+,-./01234 _ BC   !"#$%&'()*+,-./01234  BC g !"#$%&'()*+,-./01234 BC h  A !"#$%&'()*+,-./01234 BC ag F !"#$%&'()*+,-./01234 BC  F !"#$%&'()*+,-./01234 BCA  !"#$%&'()*+,-./01234 BCdh A !"#$%&'()*+,-./01234 BC AH !"#$%&'()*+,-./01234_bBC  AEF AEF  AEF AEF  DAEF AEF  AEF AEF  DAEF AEF GD AEFG       !"#$%&'()*+,-./01234 BC  !"#$%&'()*+,-./01234 !"#$%&'()*+,-./01234GG DGBCTUVWXYZ[\]^ !"#$%&'()*+,-./01234            AA A                         A A A A A          !"#$%&'(A56789:;<=>?@ !"#$%&'(56789:;<=>?@ !"#$%&'(56789:;<=>?@56789:;<=>?@            )  cA A                                   56789:;<=>?@E56789:;<=>?@E             +     )*+  A           56789:;<=>?@E `e     56789:;<=>?@DE56789:;<=>?@56789:;<=>?@GEHTUVWXYZ[\]^_be56789:;<=>?@D56789:;<=>?@D     56789:;<=>?@D56789:;<=>?@DBC56789:;<=>?@`` !"#$%&'( !"#$%&'()*AH HH_b_b56789:;<=>?@E56789:;<=>?@D56789:;<=>?@E 56789:;<=>?@E56789:;<=>?@56789:;<=>?@ 56789:;<=>?@E56789:;<=>?@E56789:;<=>?@E  56789:;<=>?@56789:;<=>?@56789:;<=>?@)*`56789:;<=>?@H56789:;<=>?@`56789:;<=>?@  !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'( !"#$%&'(././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.ja0000644000175000001440000017035112212041344032344 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import java.util.ArrayList; import java.util.List; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.util.Util; /** * Parser specialized for decoding javadoc comments */ public abstract class AbstractCommentParser implements JavadocTagConstants { // Kind of comment parser public final static int COMPIL_PARSER = 0x0001; public final static int DOM_PARSER = 0x0002; public final static int SELECTION_PARSER = 0x0004; public final static int COMPLETION_PARSER = 0x0008; public final static int SOURCE_PARSER = 0x0010; public final static int FORMATTER_COMMENT_PARSER = 0x0020; protected final static int PARSER_KIND = 0x00FF; protected final static int TEXT_PARSE = 0x0100; // flag saying that text must be stored protected final static int TEXT_VERIF = 0x0200; // flag saying that text must be verified // Parser recovery states protected final static int QUALIFIED_NAME_RECOVERY = 1; protected final static int ARGUMENT_RECOVERY= 2; protected final static int ARGUMENT_TYPE_RECOVERY = 3; protected final static int EMPTY_ARGUMENT_RECOVERY = 4; // Parse infos public Scanner scanner; public char[] source; protected Parser sourceParser; private int currentTokenType = -1; // Options public boolean checkDocComment = false; public boolean setJavadocPositions = false; public boolean reportProblems; protected long complianceLevel; protected long sourceLevel; // Support for {@inheritDoc} protected long [] inheritedPositions; protected int inheritedPositionsPtr; private final static int INHERITED_POSITIONS_ARRAY_INCREMENT = 4; // Results protected boolean deprecated; protected Object returnStatement; // Positions protected int javadocStart, javadocEnd; protected int javadocTextStart, javadocTextEnd = -1; protected int firstTagPosition; protected int index, lineEnd; protected int tokenPreviousPosition, lastIdentifierEndPosition, starPosition; protected int textStart, memberStart; protected int tagSourceStart, tagSourceEnd; protected int inlineTagStart; protected int[] lineEnds; // Flags protected boolean lineStarted = false; protected boolean inlineTagStarted = false; protected boolean abort = false; protected int kind; protected int tagValue = NO_TAG_VALUE; protected int lastBlockTagValue = NO_TAG_VALUE; // Line pointers private int linePtr, lastLinePtr; // Identifier stack protected int identifierPtr; protected char[][] identifierStack; protected int identifierLengthPtr; protected int[] identifierLengthStack; protected long[] identifierPositionStack; // Ast stack protected final static int AST_STACK_INCREMENT = 10; protected int astPtr; protected Object[] astStack; protected int astLengthPtr; protected int[] astLengthStack; protected AbstractCommentParser(Parser sourceParser) { this.sourceParser = sourceParser; this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true/*taskCaseSensitive*/); this.identifierStack = new char[20][]; this.identifierPositionStack = new long[20]; this.identifierLengthStack = new int[10]; this.astStack = new Object[30]; this.astLengthStack = new int[20]; this.reportProblems = sourceParser != null; if (sourceParser != null) { this.checkDocComment = this.sourceParser.options.docCommentSupport; this.sourceLevel = this.sourceParser.options.sourceLevel; this.scanner.sourceLevel = this.sourceLevel; this.complianceLevel = this.sourceParser.options.complianceLevel; } } /* (non-Javadoc) * Returns true if tag @deprecated is present in javadoc comment. * * 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 commentParse() { boolean validComment = true; try { // Init local variables this.astLengthPtr = -1; this.astPtr = -1; this.identifierPtr = -1; this.currentTokenType = -1; setInlineTagStarted(false); this.inlineTagStart = -1; this.lineStarted = false; this.returnStatement = null; this.inheritedPositions = null; this.lastBlockTagValue = NO_TAG_VALUE; this.deprecated = false; this.lastLinePtr = getLineNumber(this.javadocEnd); this.textStart = -1; this.abort = false; char previousChar = 0; int invalidTagLineEnd = -1; int invalidInlineTagLineEnd = -1; boolean lineHasStar = true; boolean verifText = (this.kind & TEXT_VERIF) != 0; boolean isDomParser = (this.kind & DOM_PARSER) != 0; boolean isFormatterParser = (this.kind & FORMATTER_COMMENT_PARSER) != 0; int lastStarPosition = -1; // Init scanner position this.linePtr = getLineNumber(this.firstTagPosition); int realStart = this.linePtr==1 ? this.javadocStart : this.scanner.getLineEnd(this.linePtr-1)+1; if (realStart < this.javadocStart) realStart = this.javadocStart; this.scanner.resetTo(realStart, this.javadocEnd); this.index = realStart; if (realStart == this.javadocStart) { readChar(); // starting '/' readChar(); // first '*' } int previousPosition = this.index; char nextCharacter = 0; if (realStart == this.javadocStart) { nextCharacter = readChar(); // second '*' while (peekChar() == '*') { nextCharacter = readChar(); // read all contiguous '*' } this.javadocTextStart = this.index; } this.lineEnd = (this.linePtr == this.lastLinePtr) ? this.javadocEnd: this.scanner.getLineEnd(this.linePtr) - 1; this.javadocTextEnd = this.javadocEnd - 2; // supposed text end, it will be refined later... // Loop on each comment character int textEndPosition = -1; while (!this.abort && this.index < this.javadocEnd) { // Store previous position and char previousPosition = this.index; previousChar = nextCharacter; // Calculate line end (cannot use this.scanner.linePtr as scanner does not parse line ends again) if (this.index > (this.lineEnd+1)) { updateLineEnd(); } // Read next char only if token was consumed if (this.currentTokenType < 0) { nextCharacter = readChar(); // consider unicodes } else { previousPosition = this.scanner.getCurrentTokenStartPosition(); switch (this.currentTokenType) { case TerminalTokens.TokenNameRBRACE: nextCharacter = '}'; break; case TerminalTokens.TokenNameMULTIPLY: nextCharacter = '*'; break; default: nextCharacter = this.scanner.currentCharacter; } consumeToken(); } // Consume rules depending on the read character switch (nextCharacter) { case '@' : // Start tag parsing only if we are on line beginning or at inline tag beginning if ((!this.lineStarted || previousChar == '{')) { if (this.inlineTagStarted) { setInlineTagStarted(false); // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279 // Cannot have @ inside inline comment if (this.reportProblems) { int end = previousPosition= this.javadocEnd) end = invalidInlineTagLineEnd; this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end); } if (this.lineStarted && this.textStart != -1 && this.textStart < textEndPosition) { pushText(this.textStart, textEndPosition); } refreshInlineTagPosition(textEndPosition); setInlineTagStarted(false); } else if (this.lineStarted && this.textStart != -1 && this.textStart <= textEndPosition && (this.textStart < this.starPosition || this.starPosition == lastStarPosition)) { pushText(this.textStart, textEndPosition); } updateDocComment(); } catch (Exception ex) { validComment = false; } return validComment; } protected void consumeToken() { this.currentTokenType = -1; // flush token cache updateLineEnd(); } protected abstract Object createArgumentReference(char[] name, int dim, boolean isVarargs, Object typeRef, long[] dimPos, long argNamePos) throws InvalidInputException; protected boolean createFakeReference(int start) { // Do nothing by default return true; } 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 getIndexPosition() { if (this.index > this.lineEnd) { return this.lineEnd; } else { return this.index-1; } } /** * Search the line number corresponding to a specific position. * Warning: returned position is 1-based index! * @see Scanner#getLineNumber(int) We cannot directly use this method * when linePtr field is not initialized. */ private int getLineNumber(int position) { if (this.scanner.linePtr != -1) { return Util.getLineNumber(position, this.scanner.lineEnds, 0, this.scanner.linePtr); } if (this.lineEnds == null) return 1; return Util.getLineNumber(position, this.lineEnds, 0, this.lineEnds.length-1); } private int getTokenEndPosition() { if (this.scanner.getCurrentTokenEndPosition() > this.lineEnd) { return this.lineEnd; } else { return this.scanner.getCurrentTokenEndPosition(); } } /** * @return Returns the currentTokenType. */ protected int getCurrentTokenType() { return this.currentTokenType; } /* * Parse argument in @see tag method reference */ protected Object parseArguments(Object receiver) throws InvalidInputException { // Init int modulo = 0; // should be 2 for (Type,Type,...) or 3 for (Type arg,Type arg,...) int iToken = 0; char[] argName = null; List arguments = new ArrayList(10); int start = this.scanner.getCurrentTokenStartPosition(); Object typeRef = null; int dim = 0; boolean isVarargs = false; long[] dimPositions = new long[20]; // assume that there won't be more than 20 dimensions... char[] name = null; long argNamePos = -1; // Parse arguments declaration if method reference nextArg : while (this.index < this.scanner.eofPosition) { // Read argument type reference try { typeRef = parseQualifiedName(false); if (this.abort) return null; // May be aborted by specialized parser } catch (InvalidInputException e) { break nextArg; } boolean firstArg = modulo == 0; if (firstArg) { // verify position if (iToken != 0) break nextArg; } else if ((iToken % modulo) != 0) { break nextArg; } if (typeRef == null) { if (firstArg && this.currentTokenType == TerminalTokens.TokenNameRPAREN) { // verify characters after arguments declaration (expecting white space or end comment) if (!verifySpaceOrEndComment()) { int end = this.starPosition == -1 ? this.lineEnd : this.starPosition; if (this.source[end]=='\n') end--; if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end); return null; } this.lineStarted = true; return createMethodReference(receiver, null); } break nextArg; } iToken++; // Read possible additional type info dim = 0; isVarargs = false; if (readToken() == TerminalTokens.TokenNameLBRACKET) { // array declaration int dimStart = this.scanner.getCurrentTokenStartPosition(); while (readToken() == TerminalTokens.TokenNameLBRACKET) { consumeToken(); if (readToken() != TerminalTokens.TokenNameRBRACKET) { break nextArg; } consumeToken(); dimPositions[dim++] = (((long) dimStart) << 32) + this.scanner.getCurrentTokenEndPosition(); } } else if (readToken() == TerminalTokens.TokenNameELLIPSIS) { // ellipsis declaration int dimStart = this.scanner.getCurrentTokenStartPosition(); dimPositions[dim++] = (((long) dimStart) << 32) + this.scanner.getCurrentTokenEndPosition(); consumeToken(); isVarargs = true; } // Read argument name argNamePos = -1; if (readToken() == TerminalTokens.TokenNameIdentifier) { consumeToken(); if (firstArg) { // verify position if (iToken != 1) break nextArg; } else if ((iToken % modulo) != 1) { break nextArg; } if (argName == null) { // verify that all arguments name are declared if (!firstArg) { break nextArg; } } argName = this.scanner.getCurrentIdentifierSource(); argNamePos = (((long)this.scanner.getCurrentTokenStartPosition())<<32)+this.scanner.getCurrentTokenEndPosition(); iToken++; } else if (argName != null) { // verify that no argument name is declared break nextArg; } // Verify token position if (firstArg) { modulo = iToken + 1; } else { if ((iToken % modulo) != (modulo - 1)) { break nextArg; } } // Read separator or end arguments declaration int token = readToken(); name = argName == null ? CharOperation.NO_CHAR : argName; if (token == TerminalTokens.TokenNameCOMMA) { // Create new argument Object argument = createArgumentReference(name, dim, isVarargs, typeRef, dimPositions, argNamePos); if (this.abort) return null; // May be aborted by specialized parser arguments.add(argument); consumeToken(); iToken++; } else if (token == TerminalTokens.TokenNameRPAREN) { // verify characters after arguments declaration (expecting white space or end comment) if (!verifySpaceOrEndComment()) { int end = this.starPosition == -1 ? this.lineEnd : this.starPosition; if (this.source[end]=='\n') end--; if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end); return null; } // Create new argument Object argument = createArgumentReference(name, dim, isVarargs, typeRef, dimPositions, argNamePos); if (this.abort) return null; // May be aborted by specialized parser arguments.add(argument); consumeToken(); return createMethodReference(receiver, arguments); } else { break nextArg; } } // Something wrong happened => Invalid input throw new InvalidInputException(); } /** * Parse a possible HTML tag like: *
    *
  • <code> *
  • <br> *
  • <h?> *
* * Note that the default is to do nothing! * * @param previousPosition The position of the '<' character on which the tag might start * @param endTextPosition The position of the end of the previous text * @return true if a valid html tag has been parsed, false * otherwise * @throws InvalidInputException If any problem happens during the parse in this area */ protected boolean parseHtmlTag(int previousPosition, int endTextPosition) throws InvalidInputException { return false; } /* * Parse an URL link reference in @see tag */ protected boolean parseHref() throws InvalidInputException { boolean skipComments = this.scanner.skipComments; this.scanner.skipComments = true; try { int start = this.scanner.getCurrentTokenStartPosition(); char currentChar = readChar(); if (currentChar == 'a' || currentChar == 'A') { this.scanner.currentPosition = this.index; if (readToken() == TerminalTokens.TokenNameIdentifier) { consumeToken(); try { if (CharOperation.equals(this.scanner.getCurrentIdentifierSource(), HREF_TAG, false) && readToken() == TerminalTokens.TokenNameEQUAL) { consumeToken(); if (readToken() == TerminalTokens.TokenNameStringLiteral) { consumeToken(); while (this.index < this.javadocEnd) { // main loop to search for the pattern // Skip all characters after string literal until closing '>' (see bug 68726) 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().javadocInvalidSeeHref(start, this.lineEnd); } return false; } this.currentTokenType = -1; // consume token without updating line end } 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 == '@' || (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().javadocInvalidSeeHref(start, this.lineEnd); } return false; } consumeToken(); } consumeToken(); start = this.scanner.getCurrentTokenStartPosition(); currentChar = readChar(); // search for the pattern and store last char read if (currentChar == '/') { currentChar = readChar(); if (currentChar == 'a' || currentChar =='A') { currentChar = readChar(); if (currentChar == '>') { return true; // valid href } } } // search for invalid char in tags if (currentChar == '\r' || currentChar == '\n' || currentChar == '\t' || currentChar == ' ') { break; } } } } } catch (InvalidInputException ex) { // Do nothing as we want to keep positions for error message } } } // 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().javadocInvalidSeeHref(start, this.lineEnd); } } finally { this.scanner.skipComments = skipComments; } return false; } /* * Parse tag followed by an identifier */ protected boolean parseIdentifierTag(boolean report) { int token = readTokenSafely(); switch (token) { case TerminalTokens.TokenNameIdentifier: pushIdentifier(true, false); return true; } if (report) { this.sourceParser.problemReporter().javadocMissingIdentifier(this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); } return false; } /* * Parse a method reference in @see tag */ protected Object parseMember(Object receiver) throws InvalidInputException { // Init this.identifierPtr = -1; this.identifierLengthPtr = -1; int start = this.scanner.getCurrentTokenStartPosition(); this.memberStart = start; // Get member identifier if (readToken() == TerminalTokens.TokenNameIdentifier) { if (this.scanner.currentCharacter == '.') { // member name may be qualified (inner class constructor reference) parseQualifiedName(true); } else { consumeToken(); pushIdentifier(true, false); } // Look for next token to know whether it's a field or method reference int previousPosition = this.index; if (readToken() == TerminalTokens.TokenNameLPAREN) { consumeToken(); start = this.scanner.getCurrentTokenStartPosition(); try { return parseArguments(receiver); } catch (InvalidInputException e) { int end = this.scanner.getCurrentTokenEndPosition() < this.lineEnd ? this.scanner.getCurrentTokenEndPosition() : this.scanner.getCurrentTokenStartPosition(); end = end < this.lineEnd ? end : this.lineEnd; 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.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end); return null; } return createFieldReference(receiver); } int end = getTokenEndPosition() - 1; end = start > end ? 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; this.currentTokenType = -1; return null; } /* * Parse @param tag declaration */ protected boolean parseParam() throws InvalidInputException { // Store current state int start = this.tagSourceStart; int end = this.tagSourceEnd; boolean tokenWhiteSpace = this.scanner.tokenizeWhiteSpace; this.scanner.tokenizeWhiteSpace = true; try { // Verify that there are whitespaces after tag boolean isCompletionParser = (this.kind & COMPLETION_PARSER) != 0; if (this.scanner.currentCharacter != ' ' && !ScannerHelper.isWhitespace(this.scanner.currentCharacter)) { if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(start, this.scanner.getCurrentTokenEndPosition()); if (!isCompletionParser) { this.scanner.currentPosition = start; this.index = start; } this.currentTokenType = -1; 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; boolean mayBeGeneric = this.sourceLevel >= ClassFileConstants.JDK1_5; int token = -1; nextToken: while (true) { this.currentTokenType = -1; try { token = readToken(); } catch (InvalidInputException e) { valid = false; } switch (token) { case TerminalTokens.TokenNameIdentifier : if (valid) { // store param name id pushIdentifier(true, false); start = this.scanner.getCurrentTokenStartPosition(); end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition(); break nextToken; } // $FALL-THROUGH$ - fall through next case to report error case TerminalTokens.TokenNameLESS: if (valid && mayBeGeneric) { // store '<' in identifiers stack as we need to add it to tag element (bug 79809) pushIdentifier(true, true); start = this.scanner.getCurrentTokenStartPosition(); end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition(); isTypeParam = true; break nextToken; } // $FALL-THROUGH$ - 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; // $FALL-THROUGH$ - 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; // $FALL-THROUGH$ - 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 (mayBeGeneric && isTypeParam) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end); else this.sourceParser.problemReporter().javadocInvalidParamTagName(start, end); if (!isCompletionParser) { this.scanner.currentPosition = start; this.index = start; } this.currentTokenType = -1; return false; } } // Scan more tokens for type parameter declaration if (isTypeParam && mayBeGeneric) { // 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; } // $FALL-THROUGH$ - if not valid fall through next case to report error case TerminalTokens.TokenNameEOF: if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end); if (!isCompletionParser) { this.scanner.currentPosition = start; this.index = start; } this.currentTokenType = -1; return false; case TerminalTokens.TokenNameIdentifier : end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition(); if (valid) { // store param name id pushIdentifier(false, 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; // $FALL-THROUGH$ - if not valid fall through next case to report error case TerminalTokens.TokenNameEOF: if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end); if (!isCompletionParser) { this.scanner.currentPosition = start; this.index = start; } this.currentTokenType = -1; 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, true); 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 = readTokenAndConsume(); } catch (InvalidInputException e) { valid = false; } if (token == TerminalTokens.TokenNameWHITESPACE) { this.scanner.resetTo(restart, this.javadocEnd); this.index = restart; return pushParamName(isTypeParam); } } // Report problem this.currentTokenType = -1; if (isCompletionParser) return false; if (this.reportProblems) { // we only need end if we report problems end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition(); try { while ((token=readToken()) != TerminalTokens.TokenNameWHITESPACE && token != TerminalTokens.TokenNameEOF) { this.currentTokenType = -1; end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition(); } } catch (InvalidInputException e) { end = this.lineEnd; } if (mayBeGeneric && isTypeParam) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end); else this.sourceParser.problemReporter().javadocInvalidParamTagName(start, end); } this.scanner.currentPosition = start; this.index = start; this.currentTokenType = -1; return false; } finally { // we have to make sure that this is reset to the previous value even if an exception occurs this.scanner.tokenizeWhiteSpace = tokenWhiteSpace; } } /* * Parse a qualified name and built a type reference if the syntax is valid. */ protected Object parseQualifiedName(boolean reset) throws InvalidInputException { // Reset identifier stack if requested if (reset) { this.identifierPtr = -1; this.identifierLengthPtr = -1; } // Scan tokens int primitiveToken = -1; int parserKind = this.kind & PARSER_KIND; nextToken : for (int iToken = 0; ; iToken++) { int token = readTokenSafely(); switch (token) { case TerminalTokens.TokenNameIdentifier : if (((iToken & 1) != 0)) { // identifiers must be odd tokens break nextToken; } pushIdentifier(iToken == 0, false); consumeToken(); break; case TerminalTokens.TokenNameDOT : if ((iToken & 1) == 0) { // dots must be even tokens throw new InvalidInputException(); } consumeToken(); break; case TerminalTokens.TokenNameabstract: case TerminalTokens.TokenNameassert: case TerminalTokens.TokenNameboolean: case TerminalTokens.TokenNamebreak: case TerminalTokens.TokenNamebyte: case TerminalTokens.TokenNamecase: case TerminalTokens.TokenNamecatch: case TerminalTokens.TokenNamechar: case TerminalTokens.TokenNameclass: case TerminalTokens.TokenNamecontinue: case TerminalTokens.TokenNamedefault: case TerminalTokens.TokenNamedo: case TerminalTokens.TokenNamedouble: case TerminalTokens.TokenNameelse: case TerminalTokens.TokenNameextends: case TerminalTokens.TokenNamefalse: case TerminalTokens.TokenNamefinal: case TerminalTokens.TokenNamefinally: case TerminalTokens.TokenNamefloat: case TerminalTokens.TokenNamefor: case TerminalTokens.TokenNameif: case TerminalTokens.TokenNameimplements: case TerminalTokens.TokenNameimport: case TerminalTokens.TokenNameinstanceof: case TerminalTokens.TokenNameint: case TerminalTokens.TokenNameinterface: case TerminalTokens.TokenNamelong: case TerminalTokens.TokenNamenative: case TerminalTokens.TokenNamenew: case TerminalTokens.TokenNamenull: case TerminalTokens.TokenNamepackage: case TerminalTokens.TokenNameprivate: case TerminalTokens.TokenNameprotected: case TerminalTokens.TokenNamepublic: case TerminalTokens.TokenNameshort: case TerminalTokens.TokenNamestatic: case TerminalTokens.TokenNamestrictfp: case TerminalTokens.TokenNamesuper: case TerminalTokens.TokenNameswitch: case TerminalTokens.TokenNamesynchronized: case TerminalTokens.TokenNamethis: case TerminalTokens.TokenNamethrow: case TerminalTokens.TokenNametransient: case TerminalTokens.TokenNametrue: case TerminalTokens.TokenNametry: case TerminalTokens.TokenNamevoid: case TerminalTokens.TokenNamevolatile: case TerminalTokens.TokenNamewhile: if (iToken == 0) { pushIdentifier(true, true); primitiveToken = token; consumeToken(); break nextToken; } // Fall through default case to verify that we do not leave on a dot //$FALL-THROUGH$ default : if (iToken == 0) { if (this.identifierPtr>=0) { this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr]; } return null; } if ((iToken & 1) == 0) { // cannot leave on a dot switch (parserKind) { case COMPLETION_PARSER: if (this.identifierPtr>=0) { this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr]; } return syntaxRecoverQualifiedName(primitiveToken); case DOM_PARSER: if (this.currentTokenType != -1) { // Reset position: we want to rescan last token this.index = this.tokenPreviousPosition; this.scanner.currentPosition = this.tokenPreviousPosition; this.currentTokenType = -1; } // $FALL-THROUGH$ - fall through default case to raise exception default: throw new InvalidInputException(); } } break nextToken; } } // Reset position: we want to rescan last token if (parserKind != COMPLETION_PARSER && this.currentTokenType != -1) { this.index = this.tokenPreviousPosition; this.scanner.currentPosition = this.tokenPreviousPosition; this.currentTokenType = -1; } if (this.identifierPtr>=0) { this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr]; } return createTypeReference(primitiveToken); } /* * Parse a reference in @see tag */ 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 = readTokenSafely(); switch (token) { case TerminalTokens.TokenNameStringLiteral : // @see "string" // 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) break nextToken; 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; } // verify end line if (verifyEndLine(previousPosition)) { return createFakeReference(start); } if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedText(this.scanner.currentPosition, this.lineEnd); return false; case TerminalTokens.TokenNameLESS : // @see label // 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) break nextToken; consumeToken(); start = this.scanner.getCurrentTokenStartPosition(); if (parseHref()) { consumeToken(); 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 createFakeReference(start); } 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; case TerminalTokens.TokenNameERROR : consumeToken(); if (this.scanner.currentCharacter == '#') { // @see ...#member reference = parseMember(typeRef); if (reference != null) { return pushSeeRef(reference); } return false; } char[] currentError = this.scanner.getCurrentIdentifierSource(); if (currentError.length>0 && currentError[0] == '"') { if (this.reportProblems) { boolean isUrlRef = false; if (this.tagValue == TAG_SEE_VALUE) { int length=currentError.length, i=1 /* first char is " */; while (i this.javadocStart) { this.index = this.lastIdentifierEndPosition+1; this.scanner.currentPosition = this.index; } this.currentTokenType = -1; // 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; } int currentIndex = this.index; // store current index char ch = readChar(); switch (ch) { // 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 case '(' : if (this.reportProblems) this.sourceParser.problemReporter().javadocMissingHashCharacter(typeRefStartPosition, this.lineEnd, String.valueOf(this.source, typeRefStartPosition, this.lineEnd-typeRefStartPosition+1)); return false; // Search for the :// URL pattern // See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=168849 case ':' : ch = readChar(); if (ch == '/' && ch == readChar()) { if (this.reportProblems) { this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(typeRefStartPosition, this.lineEnd); return false; } } } // revert to last stored index this.index = currentIndex; // 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; this.scanner.currentPosition = this.tokenPreviousPosition; this.currentTokenType = -1; return false; } /* * Parse tag declaration */ protected abstract boolean parseTag(int previousPosition) throws InvalidInputException; /* * Parse @throws tag declaration */ protected boolean parseThrows() { int start = this.scanner.currentPosition; try { Object typeRef = parseQualifiedName(true); if (this.abort) return false; // May be aborted by specialized parser if (typeRef == null) { if (this.reportProblems) this.sourceParser.problemReporter().javadocMissingThrowsClassName(this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); } else { return pushThrowName(typeRef); } } catch (InvalidInputException ex) { if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getTokenEndPosition()); } return false; } /* * Return current character without move index position. */ protected char peekChar() { int idx = this.index; char c = this.source[idx++]; if (c == '\\' && this.source[idx] == 'u') { int c1, c2, c3, c4; idx++; while (this.source[idx] == 'u') idx++; if (!(((c1 = ScannerHelper.getHexadecimalValue(this.source[idx++])) > 15 || c1 < 0) || ((c2 = ScannerHelper.getHexadecimalValue(this.source[idx++])) > 15 || c2 < 0) || ((c3 = ScannerHelper.getHexadecimalValue(this.source[idx++])) > 15 || c3 < 0) || ((c4 = ScannerHelper.getHexadecimalValue(this.source[idx++])) > 15 || c4 < 0))) { c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } } return c; } /* * push the consumeToken on the identifier stack. Increase the total number of identifier in the stack. */ protected void pushIdentifier(boolean newLength, boolean isToken) { int stackLength = this.identifierStack.length; if (++this.identifierPtr >= stackLength) { System.arraycopy( this.identifierStack, 0, this.identifierStack = new char[stackLength + 10][], 0, stackLength); System.arraycopy( this.identifierPositionStack, 0, this.identifierPositionStack = new long[stackLength + 10], 0, stackLength); } this.identifierStack[this.identifierPtr] = isToken ? this.scanner.getCurrentTokenSource() : this.scanner.getCurrentIdentifierSource(); this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32) + (this.scanner.currentPosition - 1); if (newLength) { stackLength = this.identifierLengthStack.length; if (++this.identifierLengthPtr >= stackLength) { System.arraycopy( this.identifierLengthStack, 0, this.identifierLengthStack = new int[stackLength + 10], 0, stackLength); } this.identifierLengthStack[this.identifierLengthPtr] = 1; } else { this.identifierLengthStack[this.identifierLengthPtr]++; } } /* * Add a new obj on top of the ast stack. * If new length is required, then add also a new length in length stack. */ protected void pushOnAstStack(Object node, boolean newLength) { if (node == null) { int stackLength = this.astLengthStack.length; if (++this.astLengthPtr >= stackLength) { System.arraycopy( this.astLengthStack, 0, this.astLengthStack = new int[stackLength + AST_STACK_INCREMENT], 0, stackLength); } this.astLengthStack[this.astLengthPtr] = 0; return; } int stackLength = this.astStack.length; if (++this.astPtr >= stackLength) { System.arraycopy( this.astStack, 0, this.astStack = new Object[stackLength + AST_STACK_INCREMENT], 0, stackLength); this.astPtr = stackLength; } this.astStack[this.astPtr] = node; if (newLength) { stackLength = this.astLengthStack.length; if (++this.astLengthPtr >= stackLength) { System.arraycopy( this.astLengthStack, 0, this.astLengthStack = new int[stackLength + AST_STACK_INCREMENT], 0, stackLength); } this.astLengthStack[this.astLengthPtr] = 1; } else { this.astLengthStack[this.astLengthPtr]++; } } /* * Push a param name in ast node stack. */ protected abstract boolean pushParamName(boolean isTypeParam); /* * Push a reference statement in ast node stack. */ protected abstract boolean pushSeeRef(Object statement); /* * Push a text element in ast node stack */ protected void pushText(int start, int end) { // do not store text by default } /* * Push a throws type ref in ast node stack. */ protected abstract boolean pushThrowName(Object typeRef); /* * Read current character and move index position. * Warning: scanner position is unchanged using this method! */ protected char readChar() { char c = this.source[this.index++]; if (c == '\\' && this.source[this.index] == 'u') { int c1, c2, c3, c4; int pos = this.index; this.index++; while (this.source[this.index] == 'u') this.index++; if (!(((c1 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c1 < 0) || ((c2 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c2 < 0) || ((c3 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c3 < 0) || ((c4 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c4 < 0))) { c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } else { // TODO (frederic) currently reset to previous position, perhaps signal a syntax error would be more appropriate this.index = pos; } } return c; } /* * Read token only if previous was consumed */ protected int readToken() throws InvalidInputException { if (this.currentTokenType < 0) { this.tokenPreviousPosition = this.scanner.currentPosition; this.currentTokenType = this.scanner.getNextToken(); if (this.scanner.currentPosition > (this.lineEnd+1)) { // be sure to be on next line (lineEnd is still on the same line) this.lineStarted = false; while (this.currentTokenType == TerminalTokens.TokenNameMULTIPLY) { this.currentTokenType = this.scanner.getNextToken(); } } this.index = this.scanner.currentPosition; this.lineStarted = true; // after having read a token, line is obviously started... } return this.currentTokenType; } protected int readTokenAndConsume() throws InvalidInputException { int token = readToken(); consumeToken(); return token; } /* * Read token without throwing any InvalidInputException exception. * Returns TerminalTokens.TokenNameERROR instead. */ protected int readTokenSafely() { int token = TerminalTokens.TokenNameERROR; try { token = readToken(); } catch (InvalidInputException iie) { // token is already set to error } return token; } protected void recordInheritedPosition(long position) { if (this.inheritedPositions == null) { this.inheritedPositions = new long[INHERITED_POSITIONS_ARRAY_INCREMENT]; this.inheritedPositionsPtr = 0; } else { if (this.inheritedPositionsPtr == this.inheritedPositions.length) { System.arraycopy( this.inheritedPositions, 0, this.inheritedPositions = new long[this.inheritedPositionsPtr + INHERITED_POSITIONS_ARRAY_INCREMENT], 0, this.inheritedPositionsPtr); } } this.inheritedPositions[this.inheritedPositionsPtr++] = position; } /* * Refresh start position and length of an inline tag. */ protected void refreshInlineTagPosition(int previousPosition) { // do nothing by default } /* * Refresh return statement */ protected void refreshReturnStatement() { // do nothing by default } /** * @param started the inlineTagStarted to set */ protected void setInlineTagStarted(boolean started) { this.inlineTagStarted = started; } /* * Entry point for recovery on invalid syntax */ protected Object syntaxRecoverQualifiedName(int primitiveToken) throws InvalidInputException { // do nothing, just an entry point for recovery return null; } public String toString() { StringBuffer buffer = new StringBuffer(); int startPos = this.scanner.currentPosition this.source.length) return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$ char front[] = new char[startPos]; System.arraycopy(this.source, 0, front, 0, startPos); int middleLength = (endPos - 1) - startPos + 1; char middle[]; if (middleLength > -1) { middle = new char[middleLength]; System.arraycopy( this.source, startPos, middle, 0, middleLength); } else { middle = CharOperation.NO_CHAR; } char end[] = new char[this.source.length - (endPos - 1)]; System.arraycopy( this.source, (endPos - 1) + 1, end, 0, this.source.length - (endPos - 1) - 1); buffer.append(front); if (this.scanner.currentPosition"); //$NON-NLS-1$ } else { buffer.append("\n===============================\nParser index here -->"); //$NON-NLS-1$ } buffer.append(middle); if (this.scanner.currentPosition (this.lineEnd+1)) { // be sure to be on next line (lineEnd is still on the same line) if (this.linePtr < this.lastLinePtr) { this.lineEnd = this.scanner.getLineEnd(++this.linePtr) - 1; } else { this.lineEnd = this.javadocEnd; return; } } } /* * Verify that end of the line only contains space characters or end of comment. * Note that end of comment may be preceding by several contiguous '*' chars. */ protected boolean verifyEndLine(int textPosition) { boolean domParser = (this.kind & DOM_PARSER) != 0; // Special case for inline tag if (this.inlineTagStarted) { // expecting closing brace if (peekChar() == '}') { if (domParser) { createTag(); pushText(textPosition, this.index); } return true; } return false; } int startPosition = this.index; int previousPosition = this.index; this.starPosition = -1; char ch = readChar(); nextChar: while (true) { switch (ch) { case '\r': case '\n': if (domParser) { createTag(); pushText(textPosition, previousPosition); } this.index = previousPosition; return true; case '\u000c' : /* FORM FEED */ case ' ' : /* SPACE */ case '\t' : /* HORIZONTAL TABULATION */ if (this.starPosition >= 0) break nextChar; break; case '*': this.starPosition = previousPosition; break; case '/': if (this.starPosition >= textPosition) { // valid only if a star was the previous character if (domParser) { createTag(); pushText(textPosition, this.starPosition); } return true; } break nextChar; default : // leave loop break nextChar; } 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 * 3- are the end of comment (several contiguous star ('*') characters may be * found before the last slash ('/') character). */ protected boolean verifySpaceOrEndComment() { this.starPosition = -1; int startPosition = this.index; // Whitespace or inline tag closing brace char ch = peekChar(); switch (ch) { case '}': return this.inlineTagStarted; default: if (ScannerHelper.isWhitespace(ch)) { return true; } } // End of comment int previousPosition = this.index; ch = readChar(); while (this.index= startPosition) { // valid only if a star was the previous character return true; } // $FALL-THROUGH$ - fall through to invalid case default : // invalid whatever other character, even white spaces this.index = startPosition; return false; } previousPosition = this.index; ch = readChar(); } this.index = startPosition; return false; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveryScannerData.java0000644000175000001440000000521512212041344032326 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; public class RecoveryScannerData { public int insertedTokensPtr = -1; public int[][] insertedTokens; public int[] insertedTokensPosition; public boolean[] insertedTokenUsed; public int replacedTokensPtr = -1; public int[][] replacedTokens; public int[] replacedTokensStart; public int[] replacedTokensEnd; public boolean[] replacedTokenUsed; public int removedTokensPtr = -1; public int[] removedTokensStart; public int[] removedTokensEnd; public boolean[] removedTokenUsed; public RecoveryScannerData removeUnused() { if(this.insertedTokens != null) { int newInsertedTokensPtr = -1; for (int i = 0; i <= this.insertedTokensPtr; i++) { if(this.insertedTokenUsed[i]) { newInsertedTokensPtr++; this.insertedTokens[newInsertedTokensPtr] = this.insertedTokens[i]; this.insertedTokensPosition[newInsertedTokensPtr] = this.insertedTokensPosition[i]; this.insertedTokenUsed[newInsertedTokensPtr] = this.insertedTokenUsed[i]; } } this.insertedTokensPtr = newInsertedTokensPtr; } if(this.replacedTokens != null) { int newReplacedTokensPtr = -1; for (int i = 0; i <= this.replacedTokensPtr; i++) { if(this.replacedTokenUsed[i]) { newReplacedTokensPtr++; this.replacedTokens[newReplacedTokensPtr] = this.replacedTokens[i]; this.replacedTokensStart[newReplacedTokensPtr] = this.replacedTokensStart[i]; this.replacedTokensEnd[newReplacedTokensPtr] = this.replacedTokensEnd[i]; this.replacedTokenUsed[newReplacedTokensPtr] = this.replacedTokenUsed[i]; } } this.replacedTokensPtr = newReplacedTokensPtr; } if(this.removedTokensStart != null) { int newRemovedTokensPtr = -1; for (int i = 0; i <= this.removedTokensPtr; i++) { if(this.removedTokenUsed[i]) { newRemovedTokensPtr++; this.removedTokensStart[newRemovedTokensPtr] = this.removedTokensStart[i]; this.removedTokensEnd[newRemovedTokensPtr] = this.removedTokensEnd[i]; this.removedTokenUsed[newRemovedTokensPtr] = this.removedTokenUsed[i]; } } this.removedTokensPtr = newRemovedTokensPtr; } return this; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser23.rsc0000644000175000001440000000011212212041344027722 0ustar dokousersgDGecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser21.rsc0000644000175000001440000001324012212041344027726 0ustar dokousers3113003333333ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser15.rsc0000644000175000001440000000174012212041344027733 0ustar dokousersÇUR = &Ò\sðÕÖŠÊñ ò-.Iƒ‹ C ´Ll$H%$%Ù†,W,OĽG ì Pâ¾Ö Ý Þ „gš,%º# D & X Œ=o"·%æ*š $¢(N#¾(—%":$%"·.6$¢":#¾$%% ":$%"·.6%æ$¢(N#¾(—%ІŠÊ%6DŠeÄ™âJ~†P¤²æKN‚¶êŸñRC•Àç9‹Ý/ DÓ!3%!`!Y­ÿQ£õG™ë=?s6¶¾1DÔQÄ ¤ ãH_AÍ zJ õ Z å \ PÇUÛ »WÂ-˜  n Ù DÓ% &wÉm¿c*´*Õ*ó#4%¡§!º'1' 'Æ ~#Æç Ùµá3(å+ø…×)(œ)Œ)«)Ê+(+_+€'é( &c'x#x%`!#Ÿ%†&Ç'¢(/(R)é**'*F+ž+¼+Ú,,2{Í!ú† X(!3!`! Œq=ojêŠeÄ™#âJ~†P¤²æØKN‚¶êŸñRC•Àç9‹Ý/ D$¥Ó%Y­ÿQ£õG™ë=Ã?s*e6¶¾1D*† ¤  zW å P-˜  » n ÙÔQã_ÍJÇUÛ.6 D* ÅLl’$H ÷%Ý,-Ø &Ü ™ X%º\.I Œ=oÚ Ô"·)Qã$¢_!¬ÍJ&¿-\":#¾-¤,e$%%,®-Ö-ûÇUÛ%æ(N(—ÔQ Åã.‡.˜.æJ_.ï/-ÍØ K/l/«/¼)Q/Å/ÖJÜ ™Ø.I0-ÃÇUÛ$%Ù.[00†00Y,W"”/N/d,ü"%-(,OÔQã_ÍØJÃÇUÛecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser19.rsc0000644000175000001440000000021212212041344027730 0ustar dokousershhgFFFDDgAAA!FdAfAID JJD!DDbGG_!!H!Ab!!!!55!ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java0000644000175000001440000006002112212041344031477 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; 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.TypeParameter; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.util.Util; /** * Internal method structure for parsing recovery */ public class RecoveredMethod extends RecoveredElement implements TerminalTokens { public AbstractMethodDeclaration methodDeclaration; public RecoveredAnnotation[] annotations; public int annotationCount; public int modifiers; public int modifiersStart; public RecoveredType[] localTypes; public int localTypeCount; public RecoveredBlock methodBody; public boolean discardBody = true; int pendingModifiers; int pendingModifersSourceStart = -1; RecoveredAnnotation[] pendingAnnotations; int pendingAnnotationCount; public RecoveredMethod(AbstractMethodDeclaration methodDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){ super(parent, bracketBalance, parser); this.methodDeclaration = methodDeclaration; this.foundOpeningBrace = !bodyStartsAtHeaderEnd(); if(this.foundOpeningBrace) { this.bracketBalance++; } } /* * Record a nested block declaration */ public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any, do not consider elements passed the known end (if set) it must be belonging to an enclosing element */ if (this.methodDeclaration.declarationSourceEnd > 0 && nestedBlockDeclaration.sourceStart > this.methodDeclaration.declarationSourceEnd){ resetPendingModifiers(); if (this.parent == null){ return this; // ignore } else { return this.parent.add(nestedBlockDeclaration, bracketBalanceValue); } } /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } this.methodBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); if (nestedBlockDeclaration.sourceEnd == 0) return this.methodBody; return this; } /* * Record a field declaration */ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { resetPendingModifiers(); /* local variables inside method can only be final and non void */ char[][] fieldTypeName; if ((fieldDeclaration.modifiers & ~ClassFileConstants.AccFinal) != 0 // local var can only be final || (fieldDeclaration.type == null) // initializer || ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 // non void && CharOperation.equals(fieldTypeName[0], TypeBinding.VOID.sourceName()))){ if (this.parent == null){ return this; // ignore } else { this.updateSourceEndIfNecessary(previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1)); return this.parent.add(fieldDeclaration, bracketBalanceValue); } } /* default behavior is to delegate recording to parent if any, do not consider elements passed the known end (if set) it must be belonging to an enclosing element */ if (this.methodDeclaration.declarationSourceEnd > 0 && fieldDeclaration.declarationSourceStart > this.methodDeclaration.declarationSourceEnd){ if (this.parent == null){ return this; // ignore } else { return this.parent.add(fieldDeclaration, bracketBalanceValue); } } /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } // still inside method, treat as local variable return this; // ignore } /* * Record a local declaration - regular method should have been created a block body */ public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) { resetPendingModifiers(); /* local variables inside method can only be final and non void */ /* char[][] localTypeName; if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final || (localDeclaration.type == null) // initializer || ((localTypeName = localDeclaration.type.getTypeName()).length == 1 // non void && CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){ if (this.parent == null){ return this; // ignore } else { this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1)); return this.parent.add(localDeclaration, bracketBalance); } } */ /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.methodDeclaration.declarationSourceEnd != 0 && localDeclaration.declarationSourceStart > this.methodDeclaration.declarationSourceEnd){ if (this.parent == null) { return this; // ignore } else { return this.parent.add(localDeclaration, bracketBalanceValue); } } if (this.methodBody == null){ Block block = new Block(0); block.sourceStart = this.methodDeclaration.bodyStart; RecoveredElement currentBlock = this.add(block, 1); if (this.bracketBalance > 0){ for (int i = 0; i < this.bracketBalance - 1; i++){ currentBlock = currentBlock.add(new Block(0), 1); } this.bracketBalance = 1; } return currentBlock.add(localDeclaration, bracketBalanceValue); } return this.methodBody.add(localDeclaration, bracketBalanceValue, true); } /* * Record a statement - regular method should have been created a block body */ public RecoveredElement add(Statement statement, int bracketBalanceValue) { resetPendingModifiers(); /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.methodDeclaration.declarationSourceEnd != 0 && statement.sourceStart > this.methodDeclaration.declarationSourceEnd){ if (this.parent == null) { return this; // ignore } else { return this.parent.add(statement, bracketBalanceValue); } } if (this.methodBody == null){ Block block = new Block(0); block.sourceStart = this.methodDeclaration.bodyStart; RecoveredElement currentBlock = this.add(block, 1); if (this.bracketBalance > 0){ for (int i = 0; i < this.bracketBalance - 1; i++){ currentBlock = currentBlock.add(new Block(0), 1); } this.bracketBalance = 1; } return currentBlock.add(statement, bracketBalanceValue); } return this.methodBody.add(statement, bracketBalanceValue, true); } public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.methodDeclaration.declarationSourceEnd != 0 && typeDeclaration.declarationSourceStart > this.methodDeclaration.declarationSourceEnd){ if (this.parent == null) { return this; // ignore } return this.parent.add(typeDeclaration, bracketBalanceValue); } if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0 || parser().methodRecoveryActivated || parser().statementRecoveryActivated){ if (this.methodBody == null){ Block block = new Block(0); block.sourceStart = this.methodDeclaration.bodyStart; this.add(block, 1); } this.methodBody.attachPendingModifiers( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); resetPendingModifiers(); return this.methodBody.add(typeDeclaration, bracketBalanceValue, true); } switch (TypeDeclaration.kind(typeDeclaration.modifiers)) { case TypeDeclaration.INTERFACE_DECL : case TypeDeclaration.ANNOTATION_TYPE_DECL : resetPendingModifiers(); this.updateSourceEndIfNecessary(previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1)); if (this.parent == null) { return this; // ignore } // close the constructor return this.parent.add(typeDeclaration, bracketBalanceValue); } if (this.localTypes == null) { this.localTypes = new RecoveredType[5]; this.localTypeCount = 0; } else { if (this.localTypeCount == this.localTypes.length) { System.arraycopy( this.localTypes, 0, (this.localTypes = new RecoveredType[2 * this.localTypeCount]), 0, this.localTypeCount); } } RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); this.localTypes[this.localTypeCount++] = element; if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } return element; } public boolean bodyStartsAtHeaderEnd(){ return this.methodDeclaration.bodyStart == this.methodDeclaration.sourceEnd+1; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.methodDeclaration; } public void resetPendingModifiers() { this.pendingAnnotations = null; this.pendingAnnotationCount = 0; this.pendingModifiers = 0; this.pendingModifersSourceStart = -1; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.methodDeclaration.declarationSourceEnd; } public String toString(int tab) { StringBuffer result = new StringBuffer(tabString(tab)); result.append("Recovered method:\n"); //$NON-NLS-1$ this.methodDeclaration.print(tab + 1, result); if (this.annotations != null) { for (int i = 0; i < this.annotationCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.annotations[i].toString(tab + 1)); } } if (this.localTypes != null) { for (int i = 0; i < this.localTypeCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.localTypes[i].toString(tab + 1)); } } if (this.methodBody != null) { result.append("\n"); //$NON-NLS-1$ result.append(this.methodBody.toString(tab + 1)); } return result.toString(); } /* * Update the bodyStart of the corresponding parse node */ public void updateBodyStart(int bodyStart){ this.foundOpeningBrace = true; this.methodDeclaration.bodyStart = bodyStart; } public AbstractMethodDeclaration updatedMethodDeclaration(int depth, Set knownTypes){ /* update annotations */ if (this.modifiers != 0) { this.methodDeclaration.modifiers |= this.modifiers; if (this.modifiersStart < this.methodDeclaration.declarationSourceStart) { this.methodDeclaration.declarationSourceStart = this.modifiersStart; } } /* update annotations */ if (this.annotationCount > 0){ int existingCount = this.methodDeclaration.annotations == null ? 0 : this.methodDeclaration.annotations.length; Annotation[] annotationReferences = new Annotation[existingCount + this.annotationCount]; if (existingCount > 0){ System.arraycopy(this.methodDeclaration.annotations, 0, annotationReferences, this.annotationCount, existingCount); } for (int i = 0; i < this.annotationCount; i++){ annotationReferences[i] = this.annotations[i].updatedAnnotationReference(); } this.methodDeclaration.annotations = annotationReferences; int start = this.annotations[0].annotation.sourceStart; if (start < this.methodDeclaration.declarationSourceStart) { this.methodDeclaration.declarationSourceStart = start; } } if (this.methodBody != null){ Block block = this.methodBody.updatedBlock(depth, knownTypes); if (block != null){ this.methodDeclaration.statements = block.statements; if (this.methodDeclaration.declarationSourceEnd == 0) { this.methodDeclaration.declarationSourceEnd = block.sourceEnd; this.methodDeclaration.bodyEnd = block.sourceEnd; } /* first statement might be an explict constructor call destinated to a special slot */ if (this.methodDeclaration.isConstructor()) { ConstructorDeclaration constructor = (ConstructorDeclaration)this.methodDeclaration; if (this.methodDeclaration.statements != null && this.methodDeclaration.statements[0] instanceof ExplicitConstructorCall){ constructor.constructorCall = (ExplicitConstructorCall)this.methodDeclaration.statements[0]; int length = this.methodDeclaration.statements.length; System.arraycopy( this.methodDeclaration.statements, 1, (this.methodDeclaration.statements = new Statement[length-1]), 0, length-1); } if (constructor.constructorCall == null){ // add implicit constructor call constructor.constructorCall = SuperReference.implicitSuperConstructorCall(); } } } } else { if (this.methodDeclaration.declarationSourceEnd == 0) { if (this.methodDeclaration.sourceEnd + 1 == this.methodDeclaration.bodyStart) { // right brace is missing this.methodDeclaration.declarationSourceEnd = this.methodDeclaration.sourceEnd; this.methodDeclaration.bodyStart = this.methodDeclaration.sourceEnd; this.methodDeclaration.bodyEnd = this.methodDeclaration.sourceEnd; } else { this.methodDeclaration.declarationSourceEnd = this.methodDeclaration.bodyStart; this.methodDeclaration.bodyEnd = this.methodDeclaration.bodyStart; } } } if (this.localTypeCount > 0) this.methodDeclaration.bits |= ASTNode.HasLocalType; return this.methodDeclaration; } /* * Update the corresponding parse node from parser state which * is about to disappear because of restarting recovery */ public void updateFromParserState(){ // if parent is null then recovery already occured in diet parser. if(bodyStartsAtHeaderEnd() && this.parent != null){ Parser parser = parser(); /* might want to recover arguments or thrown exceptions */ if (parser.listLength > 0 && parser.astLengthPtr > 0){ // awaiting interface type references /* has consumed the arguments - listed elements must be thrown exceptions */ if (this.methodDeclaration.sourceEnd == parser.rParenPos) { // protection for bugs 15142 int length = parser.astLengthStack[parser.astLengthPtr]; int astPtr = parser.astPtr - length; boolean canConsume = astPtr >= 0; if(canConsume) { if((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) { canConsume = false; } for (int i = 1, max = length + 1; i < max; i++) { if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) { canConsume = false; } } } if (canConsume){ parser.consumeMethodHeaderThrowsClause(); // will reset typeListLength to zero // thus this check will only be performed on first errorCheck after void foo() throws X, Y, } else { parser.listLength = 0; } } else { /* has not consumed arguments yet, listed elements must be arguments */ if (parser.currentToken == TokenNameLPAREN || parser.currentToken == TokenNameSEMICOLON){ /* if currentToken is parenthesis this last argument is a method/field signature */ parser.astLengthStack[parser.astLengthPtr] --; parser.astPtr --; parser.listLength --; parser.currentToken = 0; } int argLength = parser.astLengthStack[parser.astLengthPtr]; int argStart = parser.astPtr - argLength + 1; boolean needUpdateRParenPos = parser.rParenPos < parser.lParenPos; // 12387 : rParenPos will be used // remove unfinished annotation nodes MemberValuePair[] memberValuePairs = null; while (argLength > 0 && parser.astStack[parser.astPtr] instanceof MemberValuePair) { System.arraycopy(parser.astStack, argStart, memberValuePairs = new MemberValuePair[argLength], 0, argLength); parser.astLengthPtr--; parser.astPtr -= argLength; argLength = parser.astLengthStack[parser.astLengthPtr]; argStart = parser.astPtr - argLength + 1; needUpdateRParenPos = true; } // to compute bodyStart, and thus used to set next checkpoint. int count; for (count = 0; count < argLength; count++){ ASTNode aNode = parser.astStack[argStart+count]; if(aNode instanceof Argument) { Argument argument = (Argument)aNode; /* cannot be an argument if non final */ char[][] argTypeName = argument.type.getTypeName(); if ((argument.modifiers & ~ClassFileConstants.AccFinal) != 0 || (argTypeName.length == 1 && CharOperation.equals(argTypeName[0], TypeBinding.VOID.sourceName()))){ parser.astLengthStack[parser.astLengthPtr] = count; parser.astPtr = argStart+count-1; parser.listLength = count; parser.currentToken = 0; break; } if (needUpdateRParenPos) parser.rParenPos = argument.sourceEnd + 1; } else { parser.astLengthStack[parser.astLengthPtr] = count; parser.astPtr = argStart+count-1; parser.listLength = count; parser.currentToken = 0; break; } } if (parser.listLength > 0 && parser.astLengthPtr > 0){ // protection for bugs 15142 int length = parser.astLengthStack[parser.astLengthPtr]; int astPtr = parser.astPtr - length; boolean canConsume = astPtr >= 0; if(canConsume) { if((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) { canConsume = false; } for (int i = 1, max = length + 1; i < max; i++) { if(!(parser.astStack[astPtr + i ] instanceof Argument)) { canConsume = false; } } } if(canConsume) { 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 */ this.methodDeclaration.sourceEnd = this.methodDeclaration.arguments[this.methodDeclaration.arguments.length-1].sourceEnd; this.methodDeclaration.bodyStart = this.methodDeclaration.sourceEnd+1; parser.lastCheckPoint = this.methodDeclaration.bodyStart; } } } if(memberValuePairs != null) { System.arraycopy(memberValuePairs, 0, parser.astStack, parser.astPtr + 1, memberValuePairs.length); parser.astPtr += memberValuePairs.length; parser.astLengthStack[++parser.astLengthPtr] = memberValuePairs.length; } } } } } 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; } if(this.parent != null && this.parent instanceof RecoveredType) { int mods = ((RecoveredType)this.parent).typeDeclaration.modifiers; if (TypeDeclaration.kind(mods) == TypeDeclaration.INTERFACE_DECL) { if (!this.foundOpeningBrace) { this.updateSourceEndIfNecessary(braceStart - 1, braceStart - 1); return this.parent.updateOnClosingBrace(braceStart, braceEnd); } } } 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. */ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ /* in case the opening brace is close enough to the signature */ if (this.bracketBalance == 0){ /* if (parser.scanner.searchLineNumber(methodDeclaration.sourceEnd) != parser.scanner.searchLineNumber(braceEnd)){ */ switch(parser().lastIgnoredToken){ case -1 : case TokenNamethrows : break; default: this.foundOpeningBrace = true; this.bracketBalance = 1; // pretend the brace was already there } } return super.updateOnOpeningBrace(braceStart, braceEnd); } public void updateParseTree(){ updatedMethodDeclaration(0, new HashSet()); } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int braceStart, int braceEnd){ if (this.methodDeclaration.declarationSourceEnd == 0) { if(parser().rBraceSuccessorStart >= braceEnd) { this.methodDeclaration.declarationSourceEnd = parser().rBraceEnd; this.methodDeclaration.bodyEnd = parser().rBraceStart; } else { this.methodDeclaration.declarationSourceEnd = braceEnd; this.methodDeclaration.bodyEnd = braceStart - 1; } } } public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) { if (this.pendingAnnotations == null) { this.pendingAnnotations = new RecoveredAnnotation[5]; this.pendingAnnotationCount = 0; } else { if (this.pendingAnnotationCount == this.pendingAnnotations.length) { System.arraycopy( this.pendingAnnotations, 0, (this.pendingAnnotations = new RecoveredAnnotation[2 * this.pendingAnnotationCount]), 0, this.pendingAnnotationCount); } } RecoveredAnnotation element = new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue); this.pendingAnnotations[this.pendingAnnotationCount++] = element; return element; } public void addModifier(int flag, int modifiersSourceStart) { this.pendingModifiers |= flag; if (this.pendingModifersSourceStart < 0) { this.pendingModifersSourceStart = modifiersSourceStart; } } void attach(TypeParameter[] parameters, int startPos) { if(this.methodDeclaration.modifiers != ClassFileConstants.AccDefault) return; int lastParameterEnd = parameters[parameters.length - 1].sourceEnd; Parser parser = parser(); Scanner scanner = parser.scanner; if(Util.getLineNumber(this.methodDeclaration.declarationSourceStart, scanner.lineEnds, 0, scanner.linePtr) != Util.getLineNumber(lastParameterEnd, scanner.lineEnds, 0, scanner.linePtr)) return; if(parser.modifiersSourceStart > lastParameterEnd && parser.modifiersSourceStart < this.methodDeclaration.declarationSourceStart) return; if (this.methodDeclaration instanceof MethodDeclaration) { ((MethodDeclaration)this.methodDeclaration).typeParameters = parameters; this.methodDeclaration.declarationSourceStart = startPos; } else if (this.methodDeclaration instanceof ConstructorDeclaration){ ((ConstructorDeclaration)this.methodDeclaration).typeParameters = parameters; this.methodDeclaration.declarationSourceStart = startPos; } } public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) { if (annotCount > 0) { Annotation[] existingAnnotations = this.methodDeclaration.annotations; if (existingAnnotations != null) { this.annotations = new RecoveredAnnotation[annotCount]; this.annotationCount = 0; next : for (int i = 0; i < annotCount; i++) { for (int j = 0; j < existingAnnotations.length; j++) { if (annots[i].annotation == existingAnnotations[j]) continue next; } this.annotations[this.annotationCount++] = annots[i]; } } else { this.annotations = annots; this.annotationCount = annotCount; } } if (mods != 0) { this.modifiers = mods; this.modifiersStart = modsSourceStart; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser20.rsc0000644000175000001440000003244012212041344027730 0ustar dokousers++ -- == <= >= != << >> >>> += -= *= /= &= |= ^= %= <<= >>= >>>= || && + - ! % ^ & * | ~ / > < ( ) { } [ ] ; ? : , . = @ ... $empty Identifier abstract assert boolean break byte case catch char class continue const default do double else enum extends false final finally float for goto if implements import instanceof int interface long native new null package private protected public return short static strictfp super switch synchronized this throw throws transient true try void volatile while IntegerLiteral LongLiteral FloatingPointLiteral DoubleLiteral CharacterLiteral StringLiteral Unexpected End Of File Invalid Character Goal CompilationUnit MethodBody StaticInitializer Initializer Header1 Modifiersopt Header2 BlockStatements CatchHeader FieldDeclaration ImportDeclaration PackageDeclaration TypeDeclaration GenericMethodDeclaration ClassBodyDeclarations Expression ArrayInitializer BlockStatementsopt MemberValue AnnotationTypeMemberDeclaration Literal BooleanLiteral Type PrimitiveType ReferenceType NumericType IntegralType FloatingPointType ClassOrInterfaceType ArrayType ClassOrInterface GenericType Name TypeArguments ArrayTypeWithTypeArgumentsName Dims ClassType SimpleName QualifiedName EnterCompilationUnit InternalCompilationUnit ImportDeclarations ReduceImports TypeDeclarations Header ClassHeader InterfaceHeader EnumHeader AnnotationTypeDeclarationHeader RecoveryMethodHeader AllocationHeader ArrayCreationHeader ConstructorHeader EnumConstantHeader CatchFormalParameter PackageDeclarationName Modifiers PushRealModifiers PackageComment SingleTypeImportDeclaration TypeImportOnDemandDeclaration SingleStaticImportDeclaration StaticImportOnDemandDeclaration SingleTypeImportDeclarationName TypeImportOnDemandDeclarationName ClassDeclaration InterfaceDeclaration EnumDeclaration AnnotationTypeDeclaration Modifier Annotation ClassBody ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt ClassHeaderName1 TypeParameters ClassHeaderExtends ClassHeaderImplements InterfaceTypeList InterfaceType ClassBodyDeclarationsopt ClassBodyDeclaration ClassMemberDeclaration ConstructorDeclaration Diet NestedMethod CreateInitializer Block MethodDeclaration VariableDeclarators VariableDeclarator VariableDeclaratorId EnterVariable ExitVariableWithoutInitialization ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization Dimsopt AbstractMethodDeclaration MethodHeader MethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClauseopt MethodHeaderThrowsClause ClassTypeList ConstructorHeaderName FormalParameterList FormalParameter CatchType UnionType ClassTypeElt StaticOnly ExplicitConstructorInvocation ArgumentListopt OnlyTypeArguments Primary InterfaceBody InterfaceHeaderName InterfaceHeaderExtendsopt InterfaceHeaderName1 InterfaceHeaderExtends InterfaceMemberDeclarationsopt InterfaceMemberDeclarations InterfaceMemberDeclaration ConstantDeclaration InvalidConstructorDeclaration InvalidInitializer PushLeftBrace ,opt VariableInitializers OpenBlock BlockStatement LocalVariableDeclarationStatement Statement LocalVariableDeclaration PushModifiers PushModifiersForHeader StatementWithoutTrailingSubstatement LabeledStatement IfThenStatement IfThenElseStatement WhileStatement ForStatement EnhancedForStatement StatementNoShortIf LabeledStatementNoShortIf IfThenElseStatementNoShortIf WhileStatementNoShortIf ForStatementNoShortIf EnhancedForStatementNoShortIf AssertStatement EmptyStatement ExpressionStatement SwitchStatement DoStatement BreakStatement ContinueStatement ReturnStatement SynchronizedStatement ThrowStatement TryStatement TryStatementWithResources Label StatementExpression Assignment PreIncrementExpression PreDecrementExpression PostIncrementExpression PostDecrementExpression MethodInvocation ClassInstanceCreationExpression SwitchBlock SwitchBlockStatements SwitchLabels SwitchBlockStatement SwitchLabel ConstantExpression ForInitopt Expressionopt ForUpdateopt ForInit StatementExpressionList ForUpdate OnlySynchronized TryBlock Catches Catchesopt Finally ResourceSpecification Resources ;opt Resource TrailingSemiColon ExitTryBlock CatchClause PushLPAREN PushRPAREN PrimaryNoNewArray ArrayCreationWithArrayInitializer ArrayCreationWithoutArrayInitializer Expression_NotName FieldAccess ArrayAccess EnterInstanceCreationArgumentList UnqualifiedClassBodyopt QualifiedClassBodyopt ClassInstanceCreationExpressionName UnqualifiedEnterAnonymousClassBody QualifiedEnterAnonymousClassBody ArgumentList DimWithOrWithOutExprs DimWithOrWithOutExpr DimsLoop OneDimLoop PostfixExpression PushPosition UnaryExpression UnaryExpressionNotPlusMinus CastExpression InsideCastExpression OnlyTypeArgumentsForCastExpression InsideCastExpressionWithQualifiedGenerics InsideCastExpressionLL1 MultiplicativeExpression AdditiveExpression ShiftExpression RelationalExpression InstanceofExpression EqualityExpression AndExpression ExclusiveOrExpression InclusiveOrExpression ConditionalAndExpression ConditionalOrExpression ConditionalExpression AssignmentExpression AssignmentOperator InvalidArrayInitializerAssignement NestedType EnumBody EnumHeaderName EnumBodyDeclarationsopt EnumConstants EnumConstant EnumConstantHeaderName Argumentsopt Arguments EnumDeclarations EnhancedForStatementHeader EnhancedForStatementHeaderInit SingleStaticImportDeclarationName StaticImportOnDemandDeclarationName TypeArgumentList1 TypeArgument1 TypeArgumentList TypeArgument Wildcard ReferenceType1 Wildcard1 TypeArgumentList2 TypeArgument2 ReferenceType2 Wildcard2 TypeArgumentList3 TypeArgument3 ReferenceType3 Wildcard3 WildcardBounds WildcardBounds1 WildcardBounds2 WildcardBounds3 TypeParameterHeader TypeParameterList1 TypeParameterList TypeParameter AdditionalBoundList AdditionalBound TypeParameter1 AdditionalBoundList1 AdditionalBound1 PostfixExpression_NotName UnaryExpression_NotName UnaryExpressionNotPlusMinus_NotName MultiplicativeExpression_NotName AdditiveExpression_NotName ShiftExpression_NotName RelationalExpression_NotName InstanceofExpression_NotName EqualityExpression_NotName AndExpression_NotName ExclusiveOrExpression_NotName InclusiveOrExpression_NotName ConditionalAndExpression_NotName ConditionalOrExpression_NotName ConditionalExpression_NotName AssignmentExpression_NotName AnnotationTypeDeclarationHeaderName AnnotationTypeBody AnnotationTypeMemberDeclarationsopt AnnotationTypeMemberDeclarations AnnotationMethodHeaderName AnnotationMethodHeaderDefaultValueopt DefaultValue AnnotationMethodHeader NormalAnnotation MarkerAnnotation SingleMemberAnnotation AnnotationName MemberValuePairsopt MemberValuePairs MemberValuePair EnterMemberValue ExitMemberValue MemberValueArrayInitializer EnterMemberValueArrayInitializer MemberValues SingleMemberAnnotationMemberValue RecoveryMethodHeaderNameecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java0000644000175000001440000002151412212041344032324 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import org.eclipse.jdt.core.compiler.CharOperation; /** * Javadoc tag constants. * * @since 3.2 */ public interface JavadocTagConstants { // recognized tags public static final char[] TAG_DEPRECATED = "deprecated".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_PARAM = "param".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_RETURN = "return".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_THROWS = "throws".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_EXCEPTION = "exception".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_SEE = "see".toCharArray(); //$NON-NLS-1$ 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$ public static final char[] TAG_AUTHOR = "author".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_CODE = "code".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_DOC_ROOT = "docRoot".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_LITERAL = "literal".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_SERIAL = "serial".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_SERIAL_DATA = "serialData".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_SERIAL_FIELD = "serialField".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_SINCE = "since".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_VERSION = "version".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_CATEGORY = "category".toCharArray(); //$NON-NLS-1$ // tags lengthes public static final int TAG_DEPRECATED_LENGTH = TAG_DEPRECATED.length; public static final int TAG_PARAM_LENGTH = TAG_PARAM.length; public static final int TAG_RETURN_LENGTH = TAG_RETURN.length; public static final int TAG_THROWS_LENGTH = TAG_THROWS.length; public static final int TAG_EXCEPTION_LENGTH = TAG_EXCEPTION.length; public static final int TAG_SEE_LENGTH = TAG_SEE.length; public static final int TAG_LINK_LENGTH = TAG_LINK.length; public static final int TAG_LINKPLAIN_LENGTH = TAG_LINKPLAIN.length; public static final int TAG_INHERITDOC_LENGTH = TAG_INHERITDOC.length; public static final int TAG_VALUE_LENGTH = TAG_VALUE.length; public static final int TAG_CATEGORY_LENGTH = TAG_CATEGORY.length; public static final int TAG_AUTHOR_LENGTH = TAG_AUTHOR.length; public static final int TAG_SERIAL_LENGTH = TAG_SERIAL.length; public static final int TAG_SERIAL_DATA_LENGTH = TAG_SERIAL_DATA.length; public static final int TAG_SERIAL_FIELD_LENGTH = TAG_SERIAL_FIELD.length; public static final int TAG_SINCE_LENGTH = TAG_SINCE.length; public static final int TAG_VERSION_LENGTH = TAG_VERSION.length; public static final int TAG_CODE_LENGTH = TAG_CODE.length; public static final int TAG_LITERAL_LENGTH = TAG_LITERAL.length; public static final int TAG_DOC_ROOT_LENGTH = TAG_DOC_ROOT.length; // 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_CATEGORY_VALUE = 11; public static final int TAG_AUTHOR_VALUE = 12; public static final int TAG_SERIAL_VALUE = 13; public static final int TAG_SERIAL_DATA_VALUE = 14; public static final int TAG_SERIAL_FIELD_VALUE = 15; public static final int TAG_SINCE_VALUE = 16; public static final int TAG_VERSION_VALUE = 17; public static final int TAG_CODE_VALUE = 18; public static final int TAG_LITERAL_VALUE = 19; public static final int TAG_DOC_ROOT_VALUE = 20; public static final int TAG_OTHERS_VALUE = 100; // Tag names array public static final char[][] TAG_NAMES = { CharOperation.NO_CHAR, TAG_DEPRECATED, /* 1 */ TAG_PARAM, /* 2 */ TAG_RETURN, /* 3 */ TAG_THROWS, /* 4 */ TAG_EXCEPTION, /* 5 */ TAG_SEE, /* 6 */ TAG_LINK, /* 7 */ TAG_LINKPLAIN, /* 8 */ TAG_INHERITDOC, /* 9 */ TAG_VALUE, /* 10 */ TAG_CATEGORY, /* 11 */ TAG_AUTHOR, /* 12 */ TAG_SERIAL, /* 13 */ TAG_SERIAL_DATA, /* 14 */ TAG_SERIAL_FIELD, /* 15 */ TAG_SINCE, /* 16 */ TAG_VERSION, /* 17 */ TAG_CODE, /* 18 */ TAG_LITERAL, /* 19 */ TAG_DOC_ROOT, /* 20 */ }; // tags expected positions public final static int ORDERED_TAGS_NUMBER = 3; public final static int PARAM_TAG_EXPECTED_ORDER = 0; public final static int THROWS_TAG_EXPECTED_ORDER = 1; public final static int SEE_TAG_EXPECTED_ORDER = 2; /* * Tag kinds indexes */ public final static int BLOCK_IDX = 0; public final static int INLINE_IDX = 1; // href tag public final static char[] HREF_TAG = {'h', 'r', 'e', 'f'}; /* * Tags versions */ public static final char[][][] BLOCK_TAGS = { // since 1.0 { TAG_AUTHOR, TAG_DEPRECATED, TAG_EXCEPTION, TAG_PARAM, TAG_RETURN, TAG_SEE, TAG_VERSION, TAG_CATEGORY /* 1.6 tag but put here as we support it for all compliances */ }, // since 1.1 { TAG_SINCE }, // since 1.2 { TAG_SERIAL, TAG_SERIAL_DATA, TAG_SERIAL_FIELD , TAG_THROWS }, // since 1.3 {}, // since 1.4 {}, // since 1.5 {}, // since 1.6 {}, // since 1.7 {}, }; public static final char[][][] INLINE_TAGS = { // since 1.0 {}, // since 1.1 {}, // since 1.2 { TAG_LINK }, // since 1.3 { TAG_DOC_ROOT }, // since 1.4 { TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE }, // since 1.5 { TAG_CODE, TAG_LITERAL }, // since 1.6 {}, // since 1.7 {}, }; public final static int INLINE_TAGS_LENGTH = INLINE_TAGS.length; public final static int BLOCK_TAGS_LENGTH = BLOCK_TAGS.length; public final static int ALL_TAGS_LENGTH = BLOCK_TAGS_LENGTH+INLINE_TAGS_LENGTH; public final static short TAG_TYPE_NONE = 0; public final static short TAG_TYPE_INLINE = 1; public final static short TAG_TYPE_BLOCK = 2; public static final short[] JAVADOC_TAG_TYPE = { TAG_TYPE_NONE, // NO_TAG_VALUE = 0; TAG_TYPE_BLOCK, // TAG_DEPRECATED_VALUE = 1; TAG_TYPE_BLOCK, // TAG_PARAM_VALUE = 2; TAG_TYPE_BLOCK, // TAG_RETURN_VALUE = 3; TAG_TYPE_BLOCK, // TAG_THROWS_VALUE = 4; TAG_TYPE_BLOCK, // TAG_EXCEPTION_VALUE = 5; TAG_TYPE_BLOCK, // TAG_SEE_VALUE = 6; TAG_TYPE_INLINE, // TAG_LINK_VALUE = 7; TAG_TYPE_INLINE, // TAG_LINKPLAIN_VALUE = 8; TAG_TYPE_INLINE, // TAG_INHERITDOC_VALUE = 9; TAG_TYPE_INLINE, // TAG_VALUE_VALUE = 10; TAG_TYPE_BLOCK, // TAG_CATEGORY_VALUE = 11; TAG_TYPE_BLOCK, // TAG_AUTHOR_VALUE = 12; TAG_TYPE_BLOCK, // TAG_SERIAL_VALUE = 13; TAG_TYPE_BLOCK, // TAG_SERIAL_DATA_VALUE = 14; TAG_TYPE_BLOCK, // TAG_SERIAL_FIELD_VALUE = 15; TAG_TYPE_BLOCK, // TAG_SINCE_VALUE = 16; TAG_TYPE_BLOCK, // TAG_VERSION_VALUE = 17; TAG_TYPE_INLINE, // TAG_CODE_VALUE = 18; TAG_TYPE_INLINE, // TAG_LITERAL_VALUE = 19; TAG_TYPE_INLINE // TAG_DOC_ROOT_VALUE = 20; }; /* * Tags usage */ public static final char[][] PACKAGE_TAGS = { TAG_SEE, TAG_SINCE, TAG_SERIAL, TAG_AUTHOR, TAG_VERSION, TAG_CATEGORY, TAG_LINK, TAG_LINKPLAIN, TAG_DOC_ROOT, TAG_VALUE, }; public static final char[][] COMPILATION_UNIT_TAGS = {}; public static final char[][] CLASS_TAGS = { TAG_SEE, TAG_SINCE, TAG_DEPRECATED, TAG_SERIAL, TAG_AUTHOR, TAG_VERSION, TAG_PARAM, TAG_CATEGORY, TAG_LINK, TAG_LINKPLAIN, TAG_DOC_ROOT, TAG_VALUE, TAG_CODE, TAG_LITERAL }; public static final char[][] FIELD_TAGS = { TAG_SEE, TAG_SINCE, TAG_DEPRECATED, TAG_SERIAL, TAG_SERIAL_FIELD, TAG_CATEGORY, TAG_LINK, TAG_LINKPLAIN, TAG_DOC_ROOT, TAG_VALUE, TAG_CODE, TAG_LITERAL }; public static final char[][] METHOD_TAGS = { TAG_SEE, TAG_SINCE, TAG_DEPRECATED, TAG_PARAM, TAG_RETURN, TAG_THROWS, TAG_EXCEPTION, TAG_SERIAL_DATA, TAG_CATEGORY, TAG_LINK, TAG_LINKPLAIN, TAG_INHERITDOC, TAG_DOC_ROOT, TAG_VALUE, TAG_CODE, TAG_LITERAL }; } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser12.rsc0000644000175000001440000000042412212041344027726 0ustar dokousers£Y RRRR _¡WRRRR£Y«1f[«RR0.i11 )e&<w­m’’,Ãc¢XVwRR^j¡W£Y;41~edb[Á&&»&pà1[_ÏM̃k¤ZÜLõ]{ñK|œJ65ƒkµF Eè³qC7ßiFr³qžmßGžGRRRRþecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/readableNames.props0000644000175000001440000002625312212041344031376 0ustar dokousers,opt=, ;opt=; AbstractMethodDeclaration=MethodDeclaration AdditionalBound1=AdditionalBound1 AdditionalBound=AdditionalBound AdditionalBoundList1=AdditionalBoundList1 AdditionalBoundList=AdditionalBoundList AdditiveExpression=Expression AdditiveExpression_NotName=Expression AllocationHeader=AllocationHeader AndExpression=Expression AndExpression_NotName=Expression Annotation=Annotation AnnotationMethodHeader=AnnotationMethodHeader AnnotationMethodHeaderDefaultValueopt=MethodHeaderDefaultValue AnnotationMethodHeaderName=MethodHeaderName AnnotationName=AnnotationName AnnotationTypeBody=AnnotationTypeBody AnnotationTypeDeclaration=AnnotationTypeDeclaration AnnotationTypeDeclarationHeader=AnnotationTypeDeclarationHeader AnnotationTypeDeclarationHeaderName=AnnotationTypeDeclarationHeaderName AnnotationTypeMemberDeclaration=AnnotationTypeMemberDeclaration AnnotationTypeMemberDeclarations=AnnotationTypeMemberDeclarations AnnotationTypeMemberDeclarationsopt=AnnotationTypeMemberDeclarations ArgumentList=ArgumentList ArgumentListopt=ArgumentList Arguments=Arguments Argumentsopt=Argumentsopt ArrayAccess=ArrayAccess ArrayCreationHeader=ArrayCreationHeader ArrayCreationWithArrayInitializer=ArrayCreationWithArrayInitializer ArrayCreationWithoutArrayInitializer=ArrayCreationWithoutArrayInitializer ArrayInitializer=ArrayInitializer ArrayType=ArrayType ArrayTypeWithTypeArgumentsName=ArrayTypeWithTypeArgumentsName AssertStatement=AssertStatement Assignment=Assignment AssignmentExpression=Expression AssignmentExpression_NotName=Expression AssignmentOperator=AssignmentOperator Block=Block BlockStatement=BlockStatement BlockStatements=BlockStatements BlockStatementsopt=BlockStatements BooleanLiteral=BooleanLiteral BreakStatement=BreakStatement CastExpression=CastExpression CatchClause=CatchClause CatchFormalParameter=FormalParameter CatchHeader=CatchHeader CatchType=CatchType Catches=Catches Catchesopt=Catches ClassBody=ClassBody ClassBodyDeclaration=ClassBodyDeclaration ClassBodyDeclarations=ClassBodyDeclarations ClassBodyDeclarationsopt=ClassBodyDeclarations ClassDeclaration=ClassDeclaration ClassHeader=ClassHeader ClassHeaderExtends=ClassHeaderExtends ClassHeaderExtendsopt=ClassHeaderExtends ClassHeaderImplements=ClassHeaderImplements ClassHeaderImplementsopt=ClassHeaderImplements ClassHeaderName1=ClassHeaderName ClassHeaderName=ClassHeaderName ClassInstanceCreationExpression=ClassInstanceCreationExpression ClassInstanceCreationExpressionName=ClassInstanceCreationExpressionName ClassMemberDeclaration=ClassMemberDeclaration ClassOrInterface=Type ClassOrInterfaceType=Type ClassType=ClassType ClassTypeElt=ClassType ClassTypeList=ClassTypeList CompilationUnit=CompilationUnit ConditionalAndExpression=Expression ConditionalAndExpression_NotName=Expression ConditionalExpression=Expression ConditionalExpression_NotName=Expression ConditionalOrExpression=Expression ConditionalOrExpression_NotName=Expression ConstantDeclaration=ConstantDeclaration ConstantExpression=ConstantExpression ConstructorDeclaration=ConstructorDeclaration ConstructorHeader=ConstructorDeclaration ConstructorHeaderName=ConstructorHeaderName ContinueStatement=ContinueStatement CreateInitializer=CreateInitializer DefaultValue=DefaultValue Diet=Diet DimWithOrWithOutExpr=Dimension DimWithOrWithOutExprs=Dimensions Dims=Dimensions DimsLoop=Dimensions Dimsopt=Dimensions DoStatement=DoStatement EmptyStatement=EmptyStatement EnhancedForStatement=EnhancedForStatement EnhancedForStatementHeader=EnhancedForStatementHeader EnhancedForStatementHeaderInit=EnhancedForStatementHeaderInit EnhancedForStatementNoShortIf=EnhancedForStatementNoShortIf EnterCompilationUnit=EnterCompilationUnit EnterInstanceCreationArgumentList=EnterInstanceCreationArgumentList EnterMemberValue=EnterMemberValue EnterMemberValueArrayInitializer=EnterMemberValueArrayInitializer EnterVariable=EnterVariable EnumBody=EnumBody EnumBodyDeclarationsopt=EnumBodyDeclarationsopt EnumConstant=EnumConstant EnumConstantHeader=EnumConstantHeader EnumConstantHeaderName=EnumConstantHeaderName EnumConstants=EnumConstants EnumDeclaration=EnumDeclaration EnumDeclarations=EnumDeclarations EnumHeader=EnumHeader EnumHeaderName=EnumHeaderName EqualityExpression=Expression EqualityExpression_NotName=Expression ExclusiveOrExpression=Expression ExclusiveOrExpression_NotName=Expression ExitMemberValue=ExitMemberValue ExitTryBlock=ExitTryBlock ExitVariableWithInitialization=ExitVariableWithInitialization ExitVariableWithoutInitialization=ExitVariableWithoutInitialization ExplicitConstructorInvocation=ExplicitConstructorInvocation Expression=Expression ExpressionStatement=Statement Expression_NotName=Expression Expressionopt=Expression FieldAccess=FieldAccess FieldDeclaration=FieldDeclaration Finally=Finally FloatingPointType=FloatingPointType ForInit=ForInit ForInitopt=ForInit ForStatement=ForStatement ForStatementNoShortIf=ForStatement ForUpdate=ForUpdate ForUpdateopt=ForUpdate ForceNoDiet=ForceNoDiet FormalParameter=FormalParameter FormalParameterList=FormalParameterList FormalParameterListopt=FormalParameterList GenericMethodDeclaration=GenericMethodDeclaration GenericType=GenericType Goal=Goal Header1=Header1 Header2=Header2 Header=Header IfThenElseStatement=IfStatement IfThenElseStatementNoShortIf=IfStatement IfThenStatement=IfStatement ImportDeclaration=ImportDeclaration ImportDeclarations=ImportDeclarations InclusiveOrExpression=Expression InclusiveOrExpression_NotName=Expression Initializer=Initializer InsideCastExpression=InsideCastExpression InsideCastExpressionLL1=InsideCastExpression InsideCastExpressionWithQualifiedGenerics=InsideCastExpression InstanceofExpression=Expression InstanceofExpression_NotName=Expression IntegralType=IntegralType InterfaceBody=InterfaceBody InterfaceDeclaration=InterfaceDeclaration InterfaceHeader=InterfaceHeader InterfaceHeaderExtends=InterfaceHeaderExtends InterfaceHeaderExtendsopt=InterfaceHeaderExtends InterfaceHeaderName1=InterfaceHeaderName InterfaceHeaderName=InterfaceHeaderName InterfaceMemberDeclaration=InterfaceMemberDeclaration InterfaceMemberDeclarations=InterfaceMemberDeclarations InterfaceMemberDeclarationsopt=InterfaceMemberDeclarations InterfaceType=InterfaceType InterfaceTypeList=InterfaceTypeList InternalCompilationUnit=CompilationUnit InvalidArrayInitializerAssignement=ArrayInitializerAssignment InvalidConstructorDeclaration=InvalidConstructorDeclaration InvalidInitializer=InvalidInitializer Label=Label LabeledStatement=LabeledStatement LabeledStatementNoShortIf=LabeledStatement Literal=Literal LocalVariableDeclaration=LocalVariableDeclaration LocalVariableDeclarationStatement=LocalVariableDeclarationStatement MarkerAnnotation=MarkerAnnotation MemberValue=MemberValue MemberValueArrayInitializer=MemberValueArrayInitializer MemberValuePair=MemberValuePair MemberValuePairs=MemberValuePairs MemberValuePairsopt=MemberValuePairsopt MemberValues=MemberValues MethodBody=MethodBody MethodDeclaration=MethodDeclaration MethodHeader=MethodDeclaration MethodHeaderExtendedDims=MethodHeaderExtendedDims MethodHeaderName=MethodHeaderName MethodHeaderRightParen=) MethodHeaderThrowsClause=MethodHeaderThrowsClause MethodHeaderThrowsClauseopt=MethodHeaderThrowsClause MethodInvocation=MethodInvocation Modifier=Modifier Modifiers=Modifiers Modifiersopt=Modifiers MultiplicativeExpression=Expression MultiplicativeExpression_NotName=Expression Name=Name NestedMethod=NestedMethod NestedType=NestedType NormalAnnotation=NormalAnnotation NumericType=NumericType OneDimLoop=Dimension OnlySynchronized=OnlySynchronized OnlyTypeArguments=TypeArguments OnlyTypeArgumentsForCastExpression=TypeArguments OpenBlock=OpenBlock PackageComment=PackageComment PackageDeclaration=PackageDeclaration PackageDeclarationName=PackageDeclarationName PostDecrementExpression=PostDecrementExpression PostIncrementExpression=PostIncrementExpression PostfixExpression=Expression PostfixExpression_NotName=Expression PreDecrementExpression=PreDecrementExpression PreIncrementExpression=PreIncrementExpression Primary=Expression PrimaryNoNewArray=Expression PrimitiveType=PrimitiveType PushLPAREN=( PushLeftBrace=PushLeftBrace PushModifiers=PushModifiers PushModifiersForHeader=PushModifiersForHeader PushPosition=PushPosition PushRPAREN=) PushRealModifiers=PushRealModifiers QualifiedClassBodyopt=ClassBody QualifiedEnterAnonymousClassBody=EnterAnonymousClassBody QualifiedName=QualifiedName RecoveryMethodHeader=MethodHeader RecoveryMethodHeaderName=MethodHeaderName ReduceImports=ReduceImports ReferenceType1=ReferenceType1 ReferenceType2=ReferenceType2 ReferenceType3=ReferenceType3 ReferenceType=ReferenceType RelationalExpression=Expression RelationalExpression_NotName=Expression Resource=Resource ResourceSpecification=ResourceSpecification Resources=Resources RestoreDiet=RestoreDiet ReturnStatement=ReturnStatement ShiftExpression=Expression ShiftExpression_NotName=Expression SimpleName=SimpleName SingleMemberAnnotation=SingleMemberAnnotation SingleMemberAnnotationMemberValue=MemberValue SingleStaticImportDeclaration=SingleStaticImportDeclaration SingleStaticImportDeclarationName=SingleStaticImportDeclarationName SingleTypeImportDeclaration=SingleTypeImportDeclaration SingleTypeImportDeclarationName=SingleTypeImportDeclarationName Statement=Statement StatementExpression=Expression StatementExpressionList=StatementExpressionList StatementNoShortIf=Statement StatementWithoutTrailingSubstatement=Statement StaticImportOnDemandDeclaration=StaticImportOnDemandDeclaration StaticImportOnDemandDeclarationName=StaticImportOnDemandDeclarationName StaticInitializer=StaticInitializer StaticOnly=StaticOnly SwitchBlock=SwitchBlock SwitchBlockStatement=SwitchBlockStatement SwitchBlockStatements=SwitchBlockStatements SwitchLabel=SwitchLabel SwitchLabels=SwitchLabels SwitchStatement=SwitchStatement SynchronizedStatement=SynchronizedStatement ThrowStatement=ThrowStatement TrailingSemiColon=; TryBlock=Block TryStatement=TryStatement TryStatementWithResources=TryStatementWithResources Type=Type TypeArgument1=TypeArgument1 TypeArgument2=TypeArgument2 TypeArgument3=TypeArgument3 TypeArgument=TypeArgument TypeArgumentList1=TypeArgumentList1 TypeArgumentList2=TypeArgumentList2 TypeArgumentList3=TypeArgumentList3 TypeArgumentList=TypeArgumentList TypeArguments=TypeArguments TypeDeclaration=TypeDeclaration TypeDeclarations=TypeDeclarations TypeImportOnDemandDeclaration=TypeImportOnDemandDeclaration TypeImportOnDemandDeclarationName=TypeImportOnDemandDeclarationName TypeParameter1=TypeParameter1 TypeParameter=TypeParameter TypeParameterHeader=TypeParameter TypeParameterList1=TypeParameterList1 TypeParameterList=TypeParameterList TypeParameters=TypeParameters UnaryExpression=Expression UnaryExpressionNotPlusMinus=Expression UnaryExpressionNotPlusMinus_NotName=Expression UnaryExpression_NotName=Expression UnionType=UnionType UnqualifiedClassBodyopt=ClassBody UnqualifiedEnterAnonymousClassBody=EnterAnonymousClassBody VariableDeclarator=VariableDeclarator VariableDeclaratorId=VariableDeclaratorId VariableDeclarators=VariableDeclarators VariableInitializer=VariableInitializer VariableInitializers=VariableInitializers WhileStatement=WhileStatement WhileStatementNoShortIf=WhileStatement Wildcard1=Wildcard1 Wildcard2=Wildcard2 Wildcard3=Wildcard3 Wildcard=Wildcard WildcardBounds1=WildcardBounds1 WildcardBounds2=WildcardBounds2 WildcardBounds3=WildcardBound3 WildcardBounds=WildcardBounds ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java0000644000175000001440000000352612212041344031540 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; /** * Internal import structure for parsing recovery */ import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.ImportReference; public class RecoveredImport extends RecoveredElement { public ImportReference importReference; public RecoveredImport(ImportReference importReference, RecoveredElement parent, int bracketBalance){ super(parent, bracketBalance); this.importReference = importReference; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.importReference; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.importReference.declarationSourceEnd; } public String toString(int tab) { return tabString(tab) + "Recovered import: " + this.importReference.toString(); //$NON-NLS-1$ } public ImportReference updatedImportReference(){ return this.importReference; } public void updateParseTree(){ updatedImportReference(); } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ if (this.importReference.declarationSourceEnd == 0) { this.importReference.declarationSourceEnd = bodyEnd; this.importReference.declarationEnd = bodyEnd; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java0000644000175000001440000011070112212041344031145 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; 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.*; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.util.Util; /** * Parser specialized for decoding javadoc comments */ public class JavadocParser extends AbstractCommentParser { // Public fields public Javadoc docComment; // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600 // Store param references for tag with invalid syntax private int invalidParamReferencesPtr = -1; private ASTNode[] invalidParamReferencesStack; // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=153399 // Store value tag positions private long validValuePositions, invalidValuePositions; // returns whether this JavadocParser should report errors or not (overrides reportProblems) // see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=192449" public boolean shouldReportProblems = true; // flag to let the parser know that the current tag is waiting for a description // see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=222900" private int tagWaitingForDescription; public JavadocParser(Parser sourceParser) { super(sourceParser); this.kind = COMPIL_PARSER | TEXT_VERIF; if (sourceParser != null && sourceParser.options != null) { this.setJavadocPositions = sourceParser.options.processAnnotations; } } /* (non-Javadoc) * Returns true if tag @deprecated is present in javadoc comment. * * If javadoc checking is enabled, will also construct an Javadoc node, which will be stored into Parser.javadoc * slot for being consumed later on. */ public boolean checkDeprecation(int commentPtr) { // Store javadoc positions this.javadocStart = this.sourceParser.scanner.commentStarts[commentPtr]; this.javadocEnd = this.sourceParser.scanner.commentStops[commentPtr]-1; this.firstTagPosition = this.sourceParser.scanner.commentTagStarts[commentPtr]; this.validValuePositions = -1; this.invalidValuePositions = -1; this.tagWaitingForDescription = NO_TAG_VALUE; // Init javadoc if necessary if (this.checkDocComment) { this.docComment = new Javadoc(this.javadocStart, this.javadocEnd); } else if (this.setJavadocPositions) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=189459 // if annotation processors are there, javadoc object is required but // they need not be resolved this.docComment = new Javadoc(this.javadocStart, this.javadocEnd); this.docComment.bits &= ~ASTNode.ResolveJavadoc; } else { this.docComment = null; } // If there's no tag in javadoc, return without parsing it if (this.firstTagPosition == 0) { switch (this.kind & PARSER_KIND) { case COMPIL_PARSER: case SOURCE_PARSER: return false; } } // Parse try { this.source = this.sourceParser.scanner.source; this.scanner.setSource(this.source); // updating source in scanner if (this.checkDocComment) { // Initialization this.scanner.lineEnds = this.sourceParser.scanner.lineEnds; this.scanner.linePtr = this.sourceParser.scanner.linePtr; this.lineEnds = this.scanner.lineEnds; commentParse(); } else { // Parse comment Scanner sourceScanner = this.sourceParser.scanner; int firstLineNumber = Util.getLineNumber(this.javadocStart, sourceScanner.lineEnds, 0, sourceScanner.linePtr); int lastLineNumber = Util.getLineNumber(this.javadocEnd, sourceScanner.lineEnds, 0, sourceScanner.linePtr); this.index = this.javadocStart +3; // scan line per line, since tags must be at beginning of lines only this.deprecated = false; nextLine : for (int line = firstLineNumber; line <= lastLineNumber; line++) { int lineStart = line == firstLineNumber ? this.javadocStart + 3 // skip leading /** : this.sourceParser.scanner.getLineStart(line); this.index = lineStart; this.lineEnd = line == lastLineNumber ? this.javadocEnd - 2 // remove trailing * / : this.sourceParser.scanner.getLineEnd(line); nextCharacter : while (this.index < this.lineEnd) { char c = readChar(); // consider unicodes switch (c) { 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 '@' : parseSimpleTag(); if (this.tagValue == TAG_DEPRECATED_VALUE) { if (this.abort) break nextCharacter; } } continue nextLine; } } return this.deprecated; } } finally { this.source = null; // release source as soon as finished this.scanner.setSource((char[]) null); //release source in scanner } return this.deprecated; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createArgumentReference(char[], java.lang.Object, int) */ protected Object createArgumentReference(char[] name, int dim, boolean isVarargs, Object typeRef, long[] dimPositions, long argNamePos) throws InvalidInputException { try { TypeReference argTypeRef = (TypeReference) typeRef; if (dim > 0) { long pos = (((long) argTypeRef.sourceStart) << 32) + argTypeRef.sourceEnd; if (typeRef instanceof JavadocSingleTypeReference) { JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef; argTypeRef = new JavadocArraySingleTypeReference(singleRef.token, dim, pos); } else { JavadocQualifiedTypeReference qualifRef = (JavadocQualifiedTypeReference) typeRef; argTypeRef = new JavadocArrayQualifiedTypeReference(qualifRef, dim); } } int argEnd = argTypeRef.sourceEnd; if (dim > 0) { argEnd = (int) dimPositions[dim-1]; if (isVarargs) { argTypeRef.bits |= ASTNode.IsVarArgs; // set isVarArgs } } if (argNamePos >= 0) argEnd = (int) argNamePos; return new JavadocArgumentExpression(name, argTypeRef.sourceStart, argEnd, argTypeRef); } catch (ClassCastException ex) { throw new InvalidInputException(); } } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createFieldReference() */ protected Object createFieldReference(Object receiver) throws InvalidInputException { try { // Get receiver type TypeReference typeRef = (TypeReference) receiver; if (typeRef == null) { char[] name = this.sourceParser.compilationUnit.getMainTypeName(); typeRef = new JavadocImplicitTypeReference(name, this.memberStart); } // Create field JavadocFieldReference field = new JavadocFieldReference(this.identifierStack[0], this.identifierPositionStack[0]); field.receiver = typeRef; field.tagSourceStart = this.tagSourceStart; field.tagSourceEnd = this.tagSourceEnd; field.tagValue = this.tagValue; return field; } catch (ClassCastException ex) { throw new InvalidInputException(); } } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createMethodReference(java.lang.Object[]) */ protected Object createMethodReference(Object receiver, List arguments) throws InvalidInputException { try { // Get receiver type TypeReference typeRef = (TypeReference) receiver; // Decide whether we have a constructor or not boolean isConstructor = false; int length = this.identifierLengthStack[0]; // may be > 1 for member class constructor reference if (typeRef == null) { char[] name = this.sourceParser.compilationUnit.getMainTypeName(); TypeDeclaration typeDecl = getParsedTypeDeclaration(); if (typeDecl != null) { name = typeDecl.name; } isConstructor = CharOperation.equals(this.identifierStack[length-1], name); typeRef = new JavadocImplicitTypeReference(name, this.memberStart); } else { if (typeRef instanceof JavadocSingleTypeReference) { char[] name = ((JavadocSingleTypeReference)typeRef).token; isConstructor = CharOperation.equals(this.identifierStack[length-1], name); } else if (typeRef instanceof JavadocQualifiedTypeReference) { char[][] tokens = ((JavadocQualifiedTypeReference)typeRef).tokens; int last = tokens.length-1; isConstructor = CharOperation.equals(this.identifierStack[length-1], tokens[last]); if (isConstructor) { boolean valid = true; if (valid) { for (int i=0; i>>32), (int)this.identifierPositionStack[length-1], -1); } return null; } } } else { throw new InvalidInputException(); } } // Create node if (arguments == null) { if (isConstructor) { JavadocAllocationExpression allocation = new JavadocAllocationExpression(this.identifierPositionStack[length-1]); allocation.type = typeRef; allocation.tagValue = this.tagValue; allocation.sourceEnd = this.scanner.getCurrentTokenEndPosition(); if (length == 1) { allocation.qualification = new char[][] { this.identifierStack[0] }; } else { System.arraycopy(this.identifierStack, 0, allocation.qualification = new char[length][], 0, length); allocation.sourceStart = (int) (this.identifierPositionStack[0] >>> 32); } allocation.memberStart = this.memberStart; return allocation; } else { JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[length-1], this.identifierPositionStack[length-1]); msg.receiver = typeRef; msg.tagValue = this.tagValue; msg.sourceEnd = this.scanner.getCurrentTokenEndPosition(); return msg; } } else { JavadocArgumentExpression[] expressions = new JavadocArgumentExpression[arguments.size()]; arguments.toArray(expressions); if (isConstructor) { JavadocAllocationExpression allocation = new JavadocAllocationExpression(this.identifierPositionStack[length-1]); allocation.arguments = expressions; allocation.type = typeRef; allocation.tagValue = this.tagValue; allocation.sourceEnd = this.scanner.getCurrentTokenEndPosition(); if (length == 1) { allocation.qualification = new char[][] { this.identifierStack[0] }; } else { System.arraycopy(this.identifierStack, 0, allocation.qualification = new char[length][], 0, length); allocation.sourceStart = (int) (this.identifierPositionStack[0] >>> 32); } allocation.memberStart = this.memberStart; return allocation; } else { JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[length-1], this.identifierPositionStack[length-1], expressions); msg.receiver = typeRef; msg.tagValue = this.tagValue; msg.sourceEnd = this.scanner.getCurrentTokenEndPosition(); return msg; } } } catch (ClassCastException ex) { throw new InvalidInputException(); } } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createReturnStatement() */ protected Object createReturnStatement() { return new JavadocReturnStatement(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseTagName() */ protected void createTag() { this.tagValue = TAG_OTHERS_VALUE; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTypeReference() */ protected Object createTypeReference(int primitiveToken) { TypeReference typeRef = null; int size = this.identifierLengthStack[this.identifierLengthPtr]; if (size == 1) { // Single Type ref typeRef = new JavadocSingleTypeReference( this.identifierStack[this.identifierPtr], this.identifierPositionStack[this.identifierPtr], this.tagSourceStart, this.tagSourceEnd); } else if (size > 1) { // Qualified Type ref char[][] tokens = new char[size][]; System.arraycopy(this.identifierStack, this.identifierPtr - size + 1, tokens, 0, size); long[] positions = new long[size]; System.arraycopy(this.identifierPositionStack, this.identifierPtr - size + 1, positions, 0, size); typeRef = new JavadocQualifiedTypeReference(tokens, positions, this.tagSourceStart, this.tagSourceEnd); } return typeRef; } /* * Get current parsed type declaration. */ protected TypeDeclaration getParsedTypeDeclaration() { int ptr = this.sourceParser.astPtr; while (ptr >= 0) { Object node = this.sourceParser.astStack[ptr]; if (node instanceof TypeDeclaration) { TypeDeclaration typeDecl = (TypeDeclaration) node; if (typeDecl.bodyEnd == 0) { // type declaration currenly parsed return typeDecl; } } ptr--; } return null; } /* * Parse @throws tag declaration and flag missing description if corresponding option is enabled */ protected boolean parseThrows() { boolean valid = super.parseThrows(); this.tagWaitingForDescription = valid && this.reportProblems ? TAG_THROWS_VALUE : NO_TAG_VALUE; return valid; } /* * Parse @return tag declaration */ protected boolean parseReturn() { if (this.returnStatement == null) { this.returnStatement = createReturnStatement(); return true; } if (this.reportProblems) { this.sourceParser.problemReporter().javadocDuplicatedReturnTag( this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); } return false; } protected void parseSimpleTag() { // Read first char // readChar() code is inlined to balance additional method call in checkDeprectation(int) char first = this.source[this.index++]; if (first == '\\' && this.source[this.index] == 'u') { int c1, c2, c3, c4; int pos = this.index; this.index++; while (this.source[this.index] == 'u') this.index++; if (!(((c1 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c1 < 0) || ((c2 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c2 < 0) || ((c3 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c3 < 0) || ((c4 = ScannerHelper.getHexadecimalValue(this.source[this.index++])) > 15 || c4 < 0))) { first = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } else { this.index = pos; } } // switch on first tag char switch (first) { case 'd': if ((readChar() == 'e') && (readChar() == 'p') && (readChar() == 'r') && (readChar() == 'e') && (readChar() == 'c') && (readChar() == 'a') && (readChar() == 't') && (readChar() == 'e') && (readChar() == 'd')) { // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk. char c = readChar(); if (ScannerHelper.isWhitespace(c) || c == '*') { this.abort = true; this.deprecated = true; this.tagValue = TAG_DEPRECATED_VALUE; } } break; } } protected boolean parseTag(int previousPosition) throws InvalidInputException { // Complain when tag is missing a description // Note that if the parse of an inline tag has already started, consider it // as the expected description, hence do not report any warning switch (this.tagWaitingForDescription) { case TAG_PARAM_VALUE: case TAG_THROWS_VALUE: if (!this.inlineTagStarted) { int start = (int) (this.identifierPositionStack[0] >>> 32); int end = (int) this.identifierPositionStack[this.identifierPtr]; this.sourceParser.problemReporter().javadocMissingTagDescriptionAfterReference(start, end, this.sourceParser.modifiers); } break; case NO_TAG_VALUE: break; default: if (!this.inlineTagStarted) { this.sourceParser.problemReporter().javadocMissingTagDescription(TAG_NAMES[this.tagWaitingForDescription], this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); } break; } this.tagWaitingForDescription = NO_TAG_VALUE; // Verify first character this.tagSourceStart = this.index; this.tagSourceEnd = previousPosition; this.scanner.startPosition = this.index; int currentPosition = this.index; char firstChar = readChar(); switch (firstChar) { case ' ': case '*': case '}': case '#': // the first character is not valid, hence report invalid empty tag if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(previousPosition, currentPosition); if (this.textStart == -1) this.textStart = currentPosition; this.scanner.currentCharacter = firstChar; return false; default: if (ScannerHelper.isWhitespace(firstChar)) { // the first character is not valid, hence report invalid empty tag if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(previousPosition, currentPosition); if (this.textStart == -1) this.textStart = currentPosition; this.scanner.currentCharacter = firstChar; return false; } break; } // Read tag name char[] tagName = new char[32]; int length = 0; char currentChar = firstChar; int tagNameLength = tagName.length; boolean validTag = true; tagLoop: while (true) { if (length == tagNameLength) { System.arraycopy(tagName, 0, tagName = new char[tagNameLength+32], 0, tagNameLength); tagNameLength = tagName.length; } tagName[length++] = currentChar; currentPosition = this.index; currentChar = readChar(); switch (currentChar) { case ' ': case '*': case '}': // these characters mark the end of the tag reading break tagLoop; case '#': // invalid tag character, mark the tag as invalid but continue until the end of the tag validTag = false; break; default: if (ScannerHelper.isWhitespace(currentChar)) { // whitespace characters mark the end of the tag reading break tagLoop; } break; } } // Init positions this.tagSourceEnd = currentPosition - 1; this.scanner.currentCharacter = currentChar; this.scanner.currentPosition = currentPosition; this.index = this.tagSourceEnd+1; // Return if the tag is not valid if (!validTag) { if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(this.tagSourceStart, this.tagSourceEnd); if (this.textStart == -1) this.textStart = this.index; this.scanner.currentCharacter = currentChar; return false; } // Decide which parse to perform depending on tag name this.tagValue = TAG_OTHERS_VALUE; boolean valid = false; switch (firstChar) { case 'a': if (length == TAG_AUTHOR_LENGTH && CharOperation.equals(TAG_AUTHOR, tagName, 0, length)) { this.tagValue = TAG_AUTHOR_VALUE; this.tagWaitingForDescription = this.tagValue; } break; case 'c': if (length == TAG_CATEGORY_LENGTH && CharOperation.equals(TAG_CATEGORY, tagName, 0, length)) { this.tagValue = TAG_CATEGORY_VALUE; if (!this.inlineTagStarted) { valid = parseIdentifierTag(false); // TODO (frederic) reconsider parameter value when @category will be significant in spec } } else if (length == TAG_CODE_LENGTH && this.inlineTagStarted && CharOperation.equals(TAG_CODE, tagName, 0, length)) { this.tagValue = TAG_CODE_VALUE; this.tagWaitingForDescription = this.tagValue; } break; case 'd': if (length == TAG_DEPRECATED_LENGTH && CharOperation.equals(TAG_DEPRECATED, tagName, 0, length)) { this.deprecated = true; valid = true; this.tagValue = TAG_DEPRECATED_VALUE; this.tagWaitingForDescription = this.tagValue; } else if (length == TAG_DOC_ROOT_LENGTH && CharOperation.equals(TAG_DOC_ROOT, tagName, 0, length)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=227730 // identify @docRoot tag as a base tag that does not expect any argument valid = true; this.tagValue = TAG_DOC_ROOT_VALUE; } break; case 'e': if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName, 0, length)) { this.tagValue = TAG_EXCEPTION_VALUE; if (!this.inlineTagStarted) { valid = parseThrows(); } } break; case 'i': if (length == TAG_INHERITDOC_LENGTH && CharOperation.equals(TAG_INHERITDOC, tagName, 0, length)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=247037, @inheritDoc usage is illegal // outside of few block tags and the main description. switch (this.lastBlockTagValue) { case TAG_RETURN_VALUE: case TAG_THROWS_VALUE: case TAG_EXCEPTION_VALUE: case TAG_PARAM_VALUE: case NO_TAG_VALUE: // Still in main description valid = true; if (this.reportProblems) { recordInheritedPosition((((long) this.tagSourceStart) << 32) + this.tagSourceEnd); } if (this.inlineTagStarted) { // parse a 'valid' inheritDoc tag parseInheritDocTag(); } break; default: valid = false; if (this.reportProblems) { this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); } } this.tagValue = TAG_INHERITDOC_VALUE; } break; case 'l': if (length == TAG_LINK_LENGTH && CharOperation.equals(TAG_LINK, tagName, 0, length)) { this.tagValue = TAG_LINK_VALUE; if (this.inlineTagStarted || (this.kind & COMPLETION_PARSER) != 0) { valid= parseReference(); } } else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, tagName, 0, length)) { this.tagValue = TAG_LINKPLAIN_VALUE; if (this.inlineTagStarted) { valid = parseReference(); } } else if (length == TAG_LITERAL_LENGTH && this.inlineTagStarted && CharOperation.equals(TAG_LITERAL, tagName, 0, length)) { this.tagValue = TAG_LITERAL_VALUE; this.tagWaitingForDescription = this.tagValue; } break; case 'p': if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName, 0, length)) { this.tagValue = TAG_PARAM_VALUE; if (!this.inlineTagStarted) { valid = parseParam(); } } break; case 'r': if (length == TAG_RETURN_LENGTH && CharOperation.equals(TAG_RETURN, tagName, 0, length)) { this.tagValue = TAG_RETURN_VALUE; if (!this.inlineTagStarted) { valid = parseReturn(); } } break; case 's': if (length == TAG_SEE_LENGTH && CharOperation.equals(TAG_SEE, tagName, 0, length)) { this.tagValue = TAG_SEE_VALUE; if (!this.inlineTagStarted) { valid = parseReference(); } } else if (length == TAG_SERIAL_LENGTH && CharOperation.equals(TAG_SERIAL, tagName, 0, length)) { this.tagValue = TAG_SERIAL_VALUE; this.tagWaitingForDescription = this.tagValue; } else if (length == TAG_SERIAL_DATA_LENGTH && CharOperation.equals(TAG_SERIAL_DATA, tagName, 0, length)) { this.tagValue = TAG_SERIAL_DATA_VALUE; this.tagWaitingForDescription = this.tagValue; } else if (length == TAG_SERIAL_FIELD_LENGTH && CharOperation.equals(TAG_SERIAL_FIELD, tagName, 0, length)) { this.tagValue = TAG_SERIAL_FIELD_VALUE; this.tagWaitingForDescription = this.tagValue; } else if (length == TAG_SINCE_LENGTH && CharOperation.equals(TAG_SINCE, tagName, 0, length)) { this.tagValue = TAG_SINCE_VALUE; this.tagWaitingForDescription = this.tagValue; } break; case 't': if (length == TAG_THROWS_LENGTH && CharOperation.equals(TAG_THROWS, tagName, 0, length)) { this.tagValue = TAG_THROWS_VALUE; if (!this.inlineTagStarted) { valid = parseThrows(); } } break; case 'v': if (length == TAG_VALUE_LENGTH && CharOperation.equals(TAG_VALUE, tagName, 0, length)) { this.tagValue = TAG_VALUE_VALUE; if (this.sourceLevel >= ClassFileConstants.JDK1_5) { if (this.inlineTagStarted) { valid = parseReference(); } } else { if (this.validValuePositions == -1) { if (this.invalidValuePositions != -1) { if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedTag((int) (this.invalidValuePositions>>>32), (int) this.invalidValuePositions); } if (valid) { this.validValuePositions = (((long) this.tagSourceStart) << 32) + this.tagSourceEnd; this.invalidValuePositions = -1; } else { this.invalidValuePositions = (((long) this.tagSourceStart) << 32) + this.tagSourceEnd; } } else { if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); } } } else if (length == TAG_VERSION_LENGTH && CharOperation.equals(TAG_VERSION, tagName, 0, length)) { this.tagValue = TAG_VERSION_VALUE; this.tagWaitingForDescription = this.tagValue; } else { createTag(); } break; default: createTag(); break; } this.textStart = this.index; if (this.tagValue != TAG_OTHERS_VALUE) { if (!this.inlineTagStarted) { this.lastBlockTagValue = this.tagValue; } // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=267833 // Report a problem if a block tag is being used in the context of an inline tag and vice versa. if ((this.inlineTagStarted && JAVADOC_TAG_TYPE[this.tagValue] == TAG_TYPE_BLOCK) || (!this.inlineTagStarted && JAVADOC_TAG_TYPE[this.tagValue] == TAG_TYPE_INLINE)) { valid = false; this.tagValue = TAG_OTHERS_VALUE; this.tagWaitingForDescription = NO_TAG_VALUE; if (this.reportProblems) { this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); } } } return valid; } protected void parseInheritDocTag() { // do nothing } /* * Parse @param tag declaration and flag missing description if corresponding option is enabled */ protected boolean parseParam() throws InvalidInputException { boolean valid = super.parseParam(); this.tagWaitingForDescription = valid && this.reportProblems ? TAG_PARAM_VALUE : NO_TAG_VALUE; return valid; } /* * Push a param name in ast node stack. */ protected boolean pushParamName(boolean isTypeParam) { // Create param reference ASTNode nameRef = null; if (isTypeParam) { JavadocSingleTypeReference ref = new JavadocSingleTypeReference(this.identifierStack[1], this.identifierPositionStack[1], this.tagSourceStart, this.tagSourceEnd); nameRef = ref; } else { JavadocSingleNameReference ref = new JavadocSingleNameReference(this.identifierStack[0], this.identifierPositionStack[0], this.tagSourceStart, this.tagSourceEnd); nameRef = ref; } // Push ref on stack if (this.astLengthPtr == -1) { // First push pushOnAstStack(nameRef, true); } else { // Verify that no @throws has been declared before 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.reportProblems) 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 + AST_STACK_INCREMENT], 0, stackLength); } this.invalidParamReferencesStack[this.invalidParamReferencesPtr] = nameRef; return false; } } } switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) { case PARAM_TAG_EXPECTED_ORDER : // previous push was a @param tag => push another param name pushOnAstStack(nameRef, false); break; case SEE_TAG_EXPECTED_ORDER : // previous push was a @see tag => push new param name pushOnAstStack(nameRef, true); break; default: return false; } } return true; } /* * Push a reference statement in ast node stack. */ protected boolean pushSeeRef(Object statement) { if (this.astLengthPtr == -1) { // First push pushOnAstStack(null, true); pushOnAstStack(null, true); pushOnAstStack(statement, true); } else { switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) { case PARAM_TAG_EXPECTED_ORDER : // previous push was a @param tag => push empty @throws tag and new @see tag pushOnAstStack(null, true); pushOnAstStack(statement, true); break; case THROWS_TAG_EXPECTED_ORDER : // previous push was a @throws tag => push new @see tag pushOnAstStack(statement, true); break; case SEE_TAG_EXPECTED_ORDER : // previous push was a @see tag => push another @see tag pushOnAstStack(statement, false); break; default: return false; } } return true; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int) */ protected void pushText(int start, int end) { // The tag gets its description => clear the flag this.tagWaitingForDescription = NO_TAG_VALUE; } /* * Push a throws type ref in ast node stack. */ protected boolean pushThrowName(Object typeRef) { if (this.astLengthPtr == -1) { // First push pushOnAstStack(null, true); pushOnAstStack(typeRef, true); } else { switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) { case PARAM_TAG_EXPECTED_ORDER : // previous push was a @param tag => push new @throws tag pushOnAstStack(typeRef, true); break; case THROWS_TAG_EXPECTED_ORDER : // previous push was a @throws tag => push another @throws tag pushOnAstStack(typeRef, false); break; case SEE_TAG_EXPECTED_ORDER : // previous push was a @see tag => push empty @param and new @throws tags pushOnAstStack(null, true); pushOnAstStack(typeRef, true); break; default: return false; } } return true; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#refreshInlineTagPosition(int) */ protected void refreshInlineTagPosition(int previousPosition) { // Signal tag missing description if necessary if (this.tagWaitingForDescription!= NO_TAG_VALUE) { this.sourceParser.problemReporter().javadocMissingTagDescription(TAG_NAMES[this.tagWaitingForDescription], this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); this.tagWaitingForDescription = NO_TAG_VALUE; } } /* * Refresh return statement */ protected void refreshReturnStatement() { ((JavadocReturnStatement) this.returnStatement).bits &= ~ASTNode.Empty; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("check javadoc: ").append(this.checkDocComment).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$ buffer.append("javadoc: ").append(this.docComment).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$ buffer.append(super.toString()); return buffer.toString(); } /* * Fill associated comment fields with ast nodes information stored in stack. */ protected void updateDocComment() { // Complain when tag is missing a description // Note that if the parse of an inline tag has already started, consider it // as the expected description, hence do not report any warning switch (this.tagWaitingForDescription) { case TAG_PARAM_VALUE: case TAG_THROWS_VALUE: if (!this.inlineTagStarted) { int start = (int) (this.identifierPositionStack[0] >>> 32); int end = (int) this.identifierPositionStack[this.identifierPtr]; this.sourceParser.problemReporter().javadocMissingTagDescriptionAfterReference(start, end, this.sourceParser.modifiers); } break; case NO_TAG_VALUE: break; default: if (!this.inlineTagStarted) { this.sourceParser.problemReporter().javadocMissingTagDescription(TAG_NAMES[this.tagWaitingForDescription], this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); } break; } this.tagWaitingForDescription = NO_TAG_VALUE; // Set positions if (this.inheritedPositions != null && this.inheritedPositionsPtr != this.inheritedPositions.length) { // Compact array by shrinking. System.arraycopy(this.inheritedPositions, 0, this.inheritedPositions = new long[this.inheritedPositionsPtr], 0, this.inheritedPositionsPtr); } this.docComment.inheritedPositions = this.inheritedPositions; this.docComment.valuePositions = this.validValuePositions != -1 ? this.validValuePositions : this.invalidValuePositions; // Set return node if present if (this.returnStatement != null) { this.docComment.returnStatement = (JavadocReturnStatement) this.returnStatement; } // Copy array of invalid syntax param tags 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 if (this.astLengthPtr == -1) { return; } // Initialize arrays int[] sizes = new int[ORDERED_TAGS_NUMBER]; for (int i=0; i<=this.astLengthPtr; i++) { sizes[i%ORDERED_TAGS_NUMBER] += this.astLengthStack[i]; } this.docComment.seeReferences = new Expression[sizes[SEE_TAG_EXPECTED_ORDER]]; this.docComment.exceptionReferences = new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]]; int paramRefPtr = sizes[PARAM_TAG_EXPECTED_ORDER]; this.docComment.paramReferences = new JavadocSingleNameReference[paramRefPtr]; int paramTypeParamPtr = sizes[PARAM_TAG_EXPECTED_ORDER]; this.docComment.paramTypeParameters = new JavadocSingleTypeReference[paramTypeParamPtr]; // Store nodes in arrays while (this.astLengthPtr >= 0) { int ptr = this.astLengthPtr % ORDERED_TAGS_NUMBER; // Starting with the stack top, so get references (Expression) coming from @see declarations switch(ptr) { case 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); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser5.rsc0000644000175000001440000000374212212041344027656 0ustar dokousersihP>’ôÒ¹ò3P_¥Øš:@hM<ûhûhhhžžhhhhùh•hhvhhhhJhhûhhhhhh h2hœhžžhhùžžhhhhhhhhhhhvȬ¯¥{=h¥¯¦g{hhh{¯hhhghhžžhhhhžžhhhhhhhhhhh3h{x¯4{¦hn5áš5Í5Gšhhh= Öíhûhhhhûûûåä–858hhûû>˜˜ûhhûhhœ$Phûû\û hh'CBhéûhûgJhhûûhh˜ãûûûûûûûûûû3ûûûûûûûûûûûû6Ð3h3 hÐÜhg3 CÐghÈûûûûûûûûûûûûûûûûûû3ûûûûûûûûûûûû3ûûûûûûûûûûûûûû z}Ð3 h8h83ÜPqÒ¨hãhãhxhÇhhhh…h’ ÆhÞJ2hhhh5ÊûhÊ1ghhh–hhhhhhhûûhçÚhûhhh2hhhÚhhhhh hhhhhhhhhhhåhåEFhhhhhhhhhhhhhhhhhhh phhhÔ=hhhgh1÷hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh3ûhËûË=h¨Òv5hháM¼ëŸ¥¥¬ÆÞ=zûhhC =ûÄhhûhhû5ûhhhûhûhûhhhhœh#hhhµû C_ îàÒhhûhhhûç5åçûûûÔ h5hh1hhûûh hhhhvÒhmh ÚhðhûhûhhhûûûhûhhhæÙ~~hhµhhhhh xh÷hûûûhûçûh÷÷3Ò¢=Úhh²ûhhûhhhhhhhhh"hh\ûûµ_hûhhhhhåû5hhxhûOhsMhûhhå}}hhhhhhhhxûOhsMshhhûµµkûûshhk_µkhµhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser9.rsc0000644000175000001440000003776012212041344027671 0ustar dokousersí0[¡0[ 0]0[$ 2––¸µµ[±±±µ–– c¿ (1r^1´P1…wMMMMMMMx$ó }}}}}}}}}÷y Oyyyyyyyyy¸µµî±±±0ZØ™šw ¤é¿Ä»eÄí¸%#40[Áù$ 2äÀ¼ì¾*Õ¼*´¶¼¼*Õ*ó*´H0[ (1r*ó1´0[1†wMMMMMMMx$ó }}}}}}}}}÷y Oyyyyyyyyy›  îœÐ,Ø™šw ¤é¿Ä»eÄ.'x’˜•˜$ 2Î ÙÎì,\··¶ 5c¿––N (1rÝ1´ JwMMMMMMMx$ó }}}}}}}}}÷y Oyyyyyyyyy›0[úî ‘0[0[íØ™šw ¤é¿Ä»eÄíH–%`˜•˜$ 21µí Ä1œí––––––––––– (1rç1´ ïwMMMMMMMx$ó }}}}}}}}}÷y Oyyyyyyyyy›¶™îïc¿Ø™šw ¤é¿Ä»eÄíÏ&c’˜•˜$ 2!!µ![[±±±0[––––î Ù (1r^1´~ðwMMMMMMMx$ó }}}}}}}}}÷y Oyyyyyyyyy›r˜îðc¿Ø™šw ¤é¿Ä»eÄí–[‹˜#x˜$ 2  Æ –––––––––––– (1r /1´'ÆwMMMMMMMx$ó }}}}}}}}}÷y Oyyyyyyyyy»%#4î–GD[Ø™šw ¤é¿Ä»eÄíj—0[‘ $ 2Á$""0[" ½'1N ¡!º1õ1ö§¡ (1rT1´KwMMMMMMMx$ó }}}}}}}}}÷y Oyyyyyyyyysp0[îc¿Ø™šw ¤é¿Ä»eÄî22 -0[0[s$ 2c¿.[262723242;2=2<2528292:î (1rý1´ Å1š$ó }}}}}}}}}¡-1¡[ïî¨)––ü$ 2 z^2Ž2ˆ2”Ø™šw ¤é¿Ä»eÄ (1r0[1´ð0[$ó }}}}}}}}}ž ¨1¡µ þ[±±±Ð–– 2ð ¾ ©0[k`™šw ¤_aÄ»eÄÂ1´ç¢wMMMMMMMx Â1º }}}}}}}}}í ™ ™ ™ ™ ™ ™ ™ ™ ™ ™ ™›oo 4hhht––ttt„{{õt‡‡Œ’˜•˜Òµµ±±±¼1õ1ö¸¼¸Á¼¼=¸ÃÃÆÈÊÎÌÎ2Ž2ˆ2”›ooÀhhht™™ttt„{{–t‡‡Œ’˜•˜0[›1–––––––––––û220[0[‡‡Œ’˜•˜®0Ž262723242;2=2<2528292:h q K™c¿ççççççççç™™™™™™™™™™™›oo Áhhht˜˜ttt„{{)t‡‡Œ’˜•˜ À2ˆ) ¿–µµ[±±±¼2Ž2ˆ¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌÎ ãÒÒµÒÒ[±±±¿––0[0[˜Ê ‡ Ij*Õ$*´0[ 2 0*󘘘˜˜˜˜˜˜˜˜Ò yÁžÒÒ1´ ï3$ Â1º ŠŠŠŠŠŠŠŠŠíÊ ‡ IÒ0[ÇÈ 2nÿÝ +¸µµ[±±±––'Æž' 0[1´k1˜ Â1º ŸŸŸŸŸŸŸŸŸí¸µµ]±±±––<–Ý + 4R» ‡ I2Ž2ˆ2” 2õµ]±±±¼––¸¼¸Á¼¼Æ¸1å1´? Â1º žžžžžžžžžíép,Ê%º0 2ˆNÝ +ʸµµ[±±±2±––#ư0[1´ äj Â1º RRRRRRRRR0[p,¡â›[0[ 2 ––ã ¸µµk±±± ™™ýê1´!ú1E Â1º §§§§§§§§§Ê ‡ I¡0û[0 2ˆ––ã ¸µµj±±± ˜˜ž0[0[1´ý3! Â1º ŸŸŸŸŸŸŸŸŸí0[p,%1D1ƒë 2Ÿ0[Ý +¸µµ[±±±––'Æn1´c0[ Â1º ŽŽŽŽŽŽŽŽŽ0[p,º%#4µ 2±±±ã µ:ì]±±±¶––22™1´0[0[ Â1º %%%%%%%%%0[p,{0ô/N1µø 20[0[µã ±±±µ™™0[±±±˜˜1´1õ1ö Â1º ŽŽŽŽŽŽŽŽŽ0[p,±‡O]0[ 2/d––ã µ2ˆ1å[±±±––0Y0[1ð1´0[c Â1º ŽŽŽŽŽŽŽŽŽ0[p, ×1„0[: 2{0ñã ¤1á Ù Ø:0[Íh1õ1öÎ 1´00[          Â1º ÃÃÃÃÃÃÃÃÃÊ ‡ I¡11v[ˆ 2.––ã í:%Ùìc4ò¤¶ë]ž2™0[1´–– Â1º ŸŸŸŸŸŸŸŸŸí0[p,0æ¹%#4 25­Ý +÷ Nœœœœœœœœœœ0[õ1´0[0à Â1º §§§§§§§§§0˜y%#4`w%#40?u%#4ã –µµ[±±±¼ õ¸¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎ!3ÒÒ_ÒÒ–µµ[±±±¼0[¼¸¼¸Á¼¼j¸ÃÃÆÈÊÎÌΤÒÒ0[ÒÒÇÒz%#4ÒÒÃ,2,‘{Í*F——+¼*'+ž)Q*)éN+Ú(R(/'¢&Ç%†¶#Ÿ!ÒÃKÒÒ–µµ[±±±¼ K1ĸ¼¸Á¼¼c¸ÃÃÆÈÊÎÌÎJÒÒ0[ÒÒ–µµ[±±±¼0[0[¸¼¸Á¼¼b¸ÃÃÆÈÊÎÌβÒÒ¾ÒÒ¡Ò›1R0[ÒÒ*Õ2e*´0[p,Ž*ó„)Œ(œ 2‡‡Œ’˜•˜x%#4'ÆÒo3"ÒÒ1´0[® Â1º ŽŽŽŽŽŽŽŽŽæp,v%#4æ0[ 290[ã ¸µµ[±±±/––Í0[1´0[b Â1º ÕÕÕÕÕÕÕÕÕ0[ ‡ IñØÌQ 2 µã [±±± ––= 1ï0[þ ~b1´Ǿ Â1º ýýýýýýýýý0[ ‡ I: -1¡ 2[——Ý +––=, „0[¹ bˆ,Wþ2Ž2ˆ1´Íà         Â1º ýýýýýýýýý0[p,:‡ - &± 2[——Ý +––<6 ¤ ‘^0[n2Ž2ˆ1´¾Ã Â1º óp,±10[[± 2[––ã ––5 Pk ”<¡j0[G ”0[1´™™ Â1º rrrrrrrrr0[p,±0[[± 2[––ã ––0[fc ‘Û¡b1Â0[0[0[1´˜˜ Â1º 0[p,¤Ÿ3[¤ 2[––ã ––0[,^?0[±k1Ã,O0[0[1´™™ Â1º qqqqqqqqq0[p,¤ñ10[¤ 2[––ã ––ò_j ”ˆ±c 0[ "I1´˜˜ Â1º ÃÃÃÃÃÃÃÃÃ0[p,¤½[# 2 Ö––ã *Õ¤*´Åb#¤*óý™™1n1´ˆ K Â1º 0[p,¤‚€$ 2˘˜ã *Õ*Õ*´*´0[$^*ó*óˆ õU®1´0[#Æ Â1º iiiiiiiii0[p, –~|[ 20[ñÄã *Õ*Õ*´*´=^*ó*ó0[ K 0[1´2ˆ!` Â1º ¼¼¼¼¼¼¼¼¼0[p,0[–ƒ[ 20[ÉŠã *Õ*Õ*´*´=k¡*ó*ó K1în1´0¸'  Â1º VVVVVVVVV0[p,0[–}[ 20[ˆ‹ã *Õ*Õ*´*´0[c*ó*ó K K1à0[1´3 0[ Â1º ©©©©©©©©©0[p,002|:; 2‰}0[ã –0[0[]:;0! K;0[0[1´0[0[ Â1º üüüüüüüüü0[p,0[2z0Â0á 2<n£ã U0 n0[:0[2ˆ0[0[-0[' 0[1´0À0[ Â1º žžžžžžžžž0[p,10[“~ 2S0[0[ã 0[0[0[0[0[0[2ˆ0[ø#Æ0[1´î2¥ Â1º &&&&&&&&&îþî0[–µµ[±±±¼ã ¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌÎ1Ÿãã0[ã–µµ[±±±¼š0[¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎ Zãã0[ã0[ Ù0[ã1.‚0[ãã̵µ[±±±¼––¸¼¸Á¼¼^¸ÃÃÆÈÊ0Û1Hã¿0[ãã–µµ[±±±¼0[0[¸¼¸Á¼¼j¸ÃÃÆÈÊÎÌÎCãã0[ã–µµ[±±±¼0[0[¸¼¸Á¼¼c¸ÃÃÆÈÊÎÌÎ $ãã0[ã0[0[Ôã1ž10[ãã̵µ[±±±¼––¸¼¸Á¼¼k¸ÃÃÆÈÊ¿1›ã0[0[0[ãã–µµ[±±±¼0[0[¸¼¸Á¼¼b¸ÃÃÆÈÊÎÌΕãã0[ã–µµ]±±±¼ 0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎ ÀÒÒ0[ÒÒ0³0[ã Kôüãã̵µ[±±±¼––¸¼¸Á¼¼j¸ÃÃÆÈÊ 1CÒ ‘0[ÒÒ–µµ]±±±¼0[0[¸¼¸Á¼¼' ¸ÃÃÆÈÊÎÌÎ\ãã0[㙵µ “±±±¼0[0[¸¼¸Á¼¼‡¸ÃÃÆÈÊÎÌÎ ÃÒÒ0[ÒÒˆ0[ã PW0[ãã̵µ[±±±¼––¸¼¸Á¼¼c¸ÃÃÆÈÊ é1Ò”0[0[ÒÒ˜µµ0[±±±¼0[0[¸¼¸Á¼¼#ƸÃÃÆÈÊÎÌÎÀÒÒ êÒÒ™µµ ¬±±±¼0[0[¸¼¸Á¼¼ ¸ÃÃÆÈÊÎÌÎÍããuã0[RÒ ì ®8ÒÒ—,2,‘{Í*F ~+¼*'+ž)Q*)éN+Ú(R(/'¢&Ç%†¶#Ÿ!ã$¥1µKã㘵µ±±±¼0[0[¸¼¸Á¼¼Ü¸ÃÃÆÈÊÎÌÎwãã0[ã–µµ[±±±¼0[0[¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌΠ夤0[¤¤0[0[ã2køçãã–µµ[±±±¼¤0[¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎø¤¤‹¤¤–µµ[±±±¼2f0[¸¼¸Á¼¼j¸ÃÃÆÈÊÎÌÎ9¤¤0[¤¤–µµ[±±±¼2h0[¸¼¸Á¼¼c¸ÃÃÆÈÊÎÌ΋¤¤0[¤¤–µµ[±±±¼3#0[¸¼¸Á¼¼b¸ÃÃÆÈÊÎÌÎݤ¤Œ¤¤–µµ]±±±¼2g0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎ/¤¤¼¤¤—,2,‘{͆aL+¼*'+ž)Q*)éN+Ú(R(/'¢&Ç%†¶#Ÿ!0[ ·1µK0[0[0[0[¯0[ {¯0[0[¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯0[—00˜C:2y0[ 20[:0[¯¯0[0[N:——0[0[x0[0[þ0[0[1´K1  Â1º }}}}}}}}} §"”1´0[0[ Â1º •••••••••0[— ¿0[2}3* ô 2Pz Vã ———————————þ0˜0[1´0YD Â1º }}}}}}}}}Âoo[hhht––ttt„{{^t‡‡Œ’˜•˜Âoo[hhht––ttt„{{kt‡‡Œ’˜•˜Âoo[hhht––ttt„{{jt‡‡Œ’˜•˜Âoo[hhht––ttt„{{ct‡‡Œ’˜•˜Âoo[hhht––ttt„{{bt‡‡Œ’˜•˜–µµ[±±±¼0[ù¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌÎ0[0[{0[{–µµ[±±±¼ø®¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎ30[{0[{–µµ[±±±¼Y0[¸¼¸Á¼¼j¸ÃÃÆÈÊÎÌÎ1è{d{–µµ[±±±¼,ü-¸¼¸Á¼¼c¸ÃÃÆÈÊÎÌÎ$¥{e{–µµ[±±±¼)0[¸¼¸Á¼¼b¸ÃÃÆÈÊÎÌÎ0[Ó{0[{–µµ[±±±¼£0[¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌÎ0[10[0[ëë–µµ[±±±¼0[0[¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎY0[10[ëë–µµ[±±±¼0[¸¼¸Á¼¼j¸ÃÃÆÈÊÎÌέ1Œ0[0[ëë–µµ[±±±¼0[0[¸¼¸Á¼¼c¸ÃÃÆÈÊÎÌÎÿ0[0[0[ëë–µµ[±±±¼0[0[¸¼¸Á¼¼b¸ÃÃÆÈÊÎÌÎQ0[0[0[ëëеµ[±±±¼––¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌÎеµ[±±±¼––¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎеµ[±±±¼––¸¼¸Á¼¼j¸ÃÃÆÈÊÎÌÎеµ[±±±¼––¸¼¸Á¼¼c¸ÃÃÆÈÊÎÌÎеµ[±±±¼––¸¼¸Á¼¼b¸ÃÃÆÈÊÎÌΙµµ0[±±±¼0[0[¸¼¸Á¼¼™¸ÃÃÆÈÊÎÌΖ¤¤ *¤¤˜µµ ×±±±¼ Ù0[¸¼¸Á¼¼ ~¸ÃÃÆÈÊÎÌΗ¤¤0[¤¤Âoo]hhht––ttt„{{ ~t‡‡Œ’˜•˜–µµ[±±±¼0[0[¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌÎ0[ç–µµ[±±±¼ ñ¾¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎ1¦ç–µµ[±±±¼17P¸¼¸Á¼¼j¸ÃÃÆÈÊÎÌÎ0[ç–µµ[±±±¼0[M¸¼¸Á¼¼c¸ÃÃÆÈÊÎÌÎ3ç–µµ[±±±¼0[£¸¼¸Á¼¼b¸ÃÃÆÈÊÎÌÎ0[ç–oo[hhht0[õttt„{{^t‡‡Œ’˜•˜40[ –oo[hhhtG0[ttt„{{kt‡‡Œ’˜•˜0[™ –oo[hhht0[ëttt„{{jt‡‡Œ’˜•˜10[ –oo[hhht30[ttt„{{ct‡‡Œ’˜•˜2o0[ –oo[hhht0[3+ttt„{{bt‡‡Œ’˜•˜1Ç0[ –µµ]±±±¼=8¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎ \0[{0[{–µµ]±±±¼;0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌη0[0[ëëеµ]±±±¼––¸¼¸Á¼¼0-¸ÃÃÆÈÊÎÌΖµµ[±±±¼0[0[¸¼¸Á¼¼^¸ÃÃÆÈÊÎÌΖµµ[±±±¼ ¨ Ú¸¼¸Á¼¼k¸ÃÃÆÈÊÎÌÎ0[0[0[0[–µµ[±±±¼0[踼¸Á¼¼j¸ÃÃÆÈÊÎÌΖµµ[±±±¼ Û踼¸Á¼¼c¸ÃÃÆÈÊÎÌÎ0[0[0[0[–µµ[±±±¼0[踼¸Á¼¼b¸ÃÃÆÈÊÎÌΖµµ]±±±¼ ë踼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎ0[ç0[0[–oo]hhht¼èttt„{{ñt‡‡Œ’˜•˜1 0[ ™µµ ±±±¼0[½¸¼¸Á¼¼1¸ÃÃÆÈÊÎÌΖ0[{0[{˜µµ þ±±±¼0[0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎò0[{0[{™µµ ¶±±±¼0[0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎ1ë0[0[0[ë똵µ1±±±¼0[0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎÃ0[0[0[ëëеµ1™±±±¼™™¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎеµ0[±±±¼˜˜¸¼¸Á¼¼Ž¸ÃÃÆÈÊÎÌΖµµ]±±±¼0[0[¸¼¸Á¼¼î¸ÃÃÆÈÊÎÌÎʵµ]±±±¼––¸¼¸Á¼¼¸ÃÃÆÈwMMMMMMMx0[0[0[0[0[0[0[0[è0[0[0[;0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê›0[ úí vÀwMMMMMMMx0[( '錒˜•˜0[0[1!íÜÜÜÜÜÜÜÜÜÜÜ0[0[0[0[0[0[0[wMMMMMMMx휜œœœœœœœœœí0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê™µµ0[±±±¼0[0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎ0[瘵µÓ±±±¼1íÚ¸¼¸Á¼¼ç¸ÃÃÆÈÊÎÌÎDç̵µ[±±±¼––¸¼¸Á¼¼b¸ÃÃÆÈÊtoo[hhh0[––ñ0[0[„{{^0[‡‡Œ’˜•˜ 0[0[0[ËËtoo[hhh3––ñ0[1„{{k0[‡‡Œ’˜•˜ 0[0[0[ËËtoo[hhh3,––0[0[*e„{{j0[‡‡Œ’˜•˜?0[0[0[ËËtoo[hhhs––0[0[1„{{c:‡‡Œ’˜•˜¾22™2¡ËËtoo[hhh™––0[0[0[„{{b0[‡‡Œ’˜•˜"%0[0[0[ËË™µµ0[±±±¼0[0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌΘµµ0[±±±¼0[1&¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎ-(0[0[0[›oo0[)…×t0[èttt„{{0[t‡‡Œ’˜•˜ãµµ0[±±±¼0[踼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎÂoo0[hhht0[1"ttt„{{0[t‡‡Œ’˜•˜Òµµ0[±±±¼0[0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎtoo[hhh0[––1êï0[„{{^1(‡‡Œ’˜•˜0[0[Îtoo[hhh0[––0[ð0[„{{k0[‡‡Œ’˜•˜1ì0[Îtoo[hhh0[––0[1é0[„{{j0[‡‡Œ’˜•˜0[Îtoo[hhh0[––0[0[„{{c0[‡‡Œ’˜•˜¯0[Îtoo[hhh0[––1$0[0[„{{b0[‡‡Œ’˜•˜m0[Î̵µ]±±±¼––¸¼¸Á¼¼˜¸ÃÃÆÈÊʵµ[±±±¼––¸¼¸Á¼¼^¸ÃÃÆÈʵµ[±±±¼––¸¼¸Á¼¼k¸ÃÃÆÈʵµ[±±±¼––¸¼¸Á¼¼j¸ÃÃÆÈʵµ[±±±¼––¸¼¸Á¼¼c¸ÃÃÆÈʵµ[±±±¼––¸¼¸Á¼¼b¸ÃÃÆÈtoo]hhh0[––0[0[0[„{{0[0[‡‡Œ’˜•˜0[0[0[0[ËËеµ ±±±¼0[0[¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌΤµµ0[±±±¼0[1'¸¼¸Á¼¼0[¸ÃÃÆÈÊÎÌÎtoo]hhh0[–– »0[0[„{{0[1#‡‡Œ’˜•˜0[0[Îȵµ[±±±¼––¸¼¸Á¼¼^¸ÃÃÆÈµµ[±±±¼––¸¼¸Á¼¼k¸ÃÃÆÈµµ[±±±¼––¸¼¸Á¼¼j¸ÃÃÆÈµµ[±±±¼––¸¼¸Á¼¼c¸ÃÃÆÈµµ[±±±¼––¸¼¸Á¼¼b¸ÃÃÆÌµµ0[±±±¼™™¸¼¸Á¼¼0[¸ÃÃÆÈÊ̵µ0[±±±¼˜˜¸¼¸Á¼¼:¸ÃÃÆÈÊ———‘0[0[—0 G;;00[00[0[N0——ÃÃ;ÃÃ0[00[0[K0100[0[;0ÃÃ1)ÃÃ1%0[0[0[ÃÃÃÃÃÃÃÃÃÃÃÃ0[0[*†0[ÃÃÃÃÃÃÃÃÃÃÃÃò¼µµÃ±±±0[0[0[¸ Ù¸Á0[0[0[¸ÃÃÆÈÊÎÌÎ0[ø{0[{ȵµ]±±±¼––¸¼¸Á¼¼0[¸ÃÃÆÆµµ[±±±¼––¸¼¸Á¼¼^¸ÃÃÆµµ[±±±¼––¸¼¸Á¼¼k¸ÃÃÆµµ[±±±¼––¸¼¸Á¼¼j¸ÃÃÆµµ[±±±¼––¸¼¸Á¼¼c¸ÃÃÆµµ[±±±¼––¸¼¸Á¼¼b¸ÃÃʵµ0[±±±¼™™¸¼¸Á¼¼0[¸ÃÃÆÈʵµ;±±±¼˜˜¸¼¸Á¼¼0[¸ÃÃÆÈ¼µµ0[±±±0[0[¸0[¸Á0[0[0[¸ÃÃÆÈÊÎÌΛ+ø(å0[ëë0[t0[0[ttt„{{$t‡‡Œ’˜•˜¼µµ0[±±±0[0[ t¸0[¸Á0[0[0[¸ÃÃÆÈÊÎÌÎ …çȵµ0[±±±¼™™¸¼¸Á¼¼0[¸ÃÃÆÈµµ0[±±±¼˜˜¸¼¸Á¼¼0[¸ÃÃÆÆµµ]±±±¼––¸¼¸Á¼¼0[¸ÃÃ̵µ0[±±±¼0[0[¸¼¸Á¼¼$¸ÃÃÆÈÊtoo0[hhh0[0[0[0[0[ t„{{0[0[‡‡Œ’˜•˜0[ w u …Ë˼µµ0[±±±0[0[0[¸0[¸Á0[0[0[¸ÃÃÆÈÊÎÌÎtoo0[hhh0[0[0[0[0[0[„{{0[0[‡‡Œ’˜•˜0[0[ too0[hhh0[0[0[è0[0[„{{0[0[‡‡Œ’˜•˜0[0[Îõµ[±±±¼––¸¼¸Á¼¼^¸Ãµµ[±±±¼––¸¼¸Á¼¼k¸Ãµµ[±±±¼––¸¼¸Á¼¼j¸Ãµµ[±±±¼––¸¼¸Á¼¼c¸Ãµµ[±±±¼––¸¼¸Á¼¼b¸Æµµ0[±±±¼™™¸¼¸Á¼¼0[¸ÃÃÆµµ0[±±±¼˜˜¸¼¸Á¼¼0[¸ÃÃʵµ0[±±±¼0[0[¸¼¸Á¼¼›¸ÃÃÆÈí)Ê0[0[+_)«+(„{{0[+€‡‡Œ’˜•˜0[0[0[0[0[0[0[0ÆÁµµ[±±±¼––¸¼¸0[¼¼^¸0[0[0[0[0[0[0[÷œœœœœœœœœœœ0[0[0[0[FÁµµ[±±±¼––¸¼¸0[¼¼k¸0[0[0[0[0[0[0[0[`0[0[0[0[?Áµµ[±±±¼––¸¼¸0[¼¼j¸Áµµ[±±±¼––¸¼¸0[¼¼c¸Áµµ[±±±¼––¸¼¸í¼¼b¸Èµµ0[±±±¼0[0[¸¼¸Á¼¼í¸ÃÃÆ0[0ñ0[0[0[0[0[0[0[;0[ní0[0[0[0[——0[0[0[0[0[Á÷ Nœœœœœœœœœœ0ÆF0[0[0[0[0[휜œœœœœœœœœ0[í0[0[0[÷œœœœœœœœœœœí0[0[—?0[î0[0[0[0[130[0[0[ü———————————0ñ0[î0[ìî0[0[0[?÷ Nœœœœœœœœœœ0[0[0[÷ NœœœœœœœœœœÃµµ±±±¼™™¸¼¸Á¼¼0[¸Ãµµ0[±±±¼˜˜¸¼¸Á¼¼0[¸Áµµ]±±±¼––¸¼¸í¼¼0[¸Æµµ0[±±±¼0[0[¸¼¸Á¼¼î¸ÃÃ0[)0ñ0[QŠ.60[Ö Æ0 0[:í0[0[0[0["·0[0[%æ* D0[:÷ Nœœœœœœœœœœ1 0[0Æ0[0[0[0[0[nnnnnnnnnnnn0[0[0[À0[šÔ÷œœœœœœœœœœœ0[—0[0[:0[0[n:0[0[0[n—0[0[;:t0[0[0[n0[0[$ :0[;:`wMMMMMMMx ";0[0˜0[0[wMMMMMMMx0[0[0[ Ží0[0[0[0[0[0[õµ Á±±±¼0[í¸¼¸Á¼¼0[¸ Á0Æ0[1Á0[0[0[0[ À0[0[ ¿í0[0[0[0[0[130[0[0[0[ À0[0[ ¿÷œœœœœœœœœœœ0Æ0[0[0[D÷ Nœœœœœœœœœœí0[0[0[0[0[0[0[÷œœœœœœœœœœœí0[0[0[B0[0Æ0[0[Áµµ0[±±±¼0[í¸¼¸0[¼¼0[¸0[0[0[÷œœœœœœœœœœœ0[0Æ0[0[C©0[0[0[휜œœœœœœœœœí0[0[0[0[0[÷œœœœœœœœœœœí—0[—:—:0[C0Æ00[00[00[0[:0[:íN0[0[0[0[0[0Æ0[0:0:0K÷œœœœœœœœœœœ0Æ0[0[0[@0[÷œœœœœœœœœœœ0[0[0[0[E0[0[í÷œœœœœœœœœœœ0[ÁµµA±±±¼™™¸¼¸0Ƽ¼î¸Áµµ0[±±±¼˜˜¸¼¸í¼¼0[¸0[0[0[÷œœœœœœœœœœœ0[0[0[0[0[t0[0[÷î0[0[$0[0[0[0[0[;0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Êî0˜0[휜œœœœœœœœœ0[1À1¿0[0[0[0[0[î0[0[0[0[0[0[0[nnnnnnnnnnnn0[0[0[1Á0[0[0[0[0[;0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0[0[0[0[0[0[0[0[0[0[ní0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0Ê0[0[0[0[0[0[0[0[0[0[0[0Ž0[0[0[0[0[0[0[0[0[0[0[ À0[0[0[0[0Ž0[0[ççççççççç Ÿ0[–0[[0[0[$çççççççççb0[0[0[0[0[0[0[0[0[##0[#sssssssssh0[0[0[0[0[0[nççççççççç0[0[0[0[0[0[0[0[0[ 0[0[0[0[0[wMMMMMMMx À0[0[0[0[0[0[0[ççççççççç0[0[0[0[0[0[ Ÿ0[0[0[0[0[0[0[ççççççççç0[0[0[0[0[0[0[wMMMMMMMx0[0[0[0[0[0[0[0[0[0[0[0[0[0[ÕÕÕÕÕÕÕÕÕ0[0[0[0[0[0[0[ççççççççç0[0[0[0[0[0[0[0[0[ ç0[0[0[0[0[wMMMMMMMxecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java0000644000175000001440000002267512212041344031545 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; public class RecoveryScanner extends Scanner { public static final char[] FAKE_IDENTIFIER = "$missing$".toCharArray(); //$NON-NLS-1$ private RecoveryScannerData data; private int[] pendingTokens; private int pendingTokensPtr = -1; private char[] fakeTokenSource = null; private boolean isInserted = true; private boolean precededByRemoved = false; private int skipNextInsertedTokens = -1; public boolean record = true; public RecoveryScanner(Scanner scanner, RecoveryScannerData data) { super(false, scanner.tokenizeWhiteSpace, scanner.checkNonExternalizedStringLiterals, scanner.sourceLevel, scanner.complianceLevel, scanner.taskTags, scanner.taskPriorities, scanner.isTaskCaseSensitive); setData(data); } public RecoveryScanner( boolean tokenizeWhiteSpace, boolean checkNonExternalizedStringLiterals, long sourceLevel, long complianceLevel, char[][] taskTags, char[][] taskPriorities, boolean isTaskCaseSensitive, RecoveryScannerData data) { super(false, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, sourceLevel, complianceLevel, taskTags, taskPriorities, isTaskCaseSensitive); setData(data); } public void insertToken(int token, int completedToken, int position) { insertTokens(new int []{token}, completedToken, position); } private int[] reverse(int[] tokens) { int length = tokens.length; for(int i = 0, max = length / 2; i < max; i++) { int tmp = tokens[i]; tokens[i] = tokens[length - i - 1]; tokens[length - i - 1] = tmp; } return tokens; } public void insertTokens(int[] tokens, int completedToken, int position) { if(!this.record) return; if(completedToken > -1 && Parser.statements_recovery_filter[completedToken] != 0) return; this.data.insertedTokensPtr++; if(this.data.insertedTokens == null) { this.data.insertedTokens = new int[10][]; this.data.insertedTokensPosition = new int[10]; this.data.insertedTokenUsed = new boolean[10]; } else if(this.data.insertedTokens.length == this.data.insertedTokensPtr) { int length = this.data.insertedTokens.length; System.arraycopy(this.data.insertedTokens, 0, this.data.insertedTokens = new int[length * 2][], 0, length); System.arraycopy(this.data.insertedTokensPosition, 0, this.data.insertedTokensPosition = new int[length * 2], 0, length); System.arraycopy(this.data.insertedTokenUsed, 0, this.data.insertedTokenUsed = new boolean[length * 2], 0, length); } this.data.insertedTokens[this.data.insertedTokensPtr] = reverse(tokens); this.data.insertedTokensPosition[this.data.insertedTokensPtr] = position; this.data.insertedTokenUsed[this.data.insertedTokensPtr] = false; } public void replaceTokens(int token, int start, int end) { replaceTokens(new int []{token}, start, end); } public void replaceTokens(int[] tokens, int start, int end) { if(!this.record) return; this.data.replacedTokensPtr++; if(this.data.replacedTokensStart == null) { this.data.replacedTokens = new int[10][]; this.data.replacedTokensStart = new int[10]; this.data.replacedTokensEnd = new int[10]; this.data.replacedTokenUsed= new boolean[10]; } else if(this.data.replacedTokensStart.length == this.data.replacedTokensPtr) { int length = this.data.replacedTokensStart.length; System.arraycopy(this.data.replacedTokens, 0, this.data.replacedTokens = new int[length * 2][], 0, length); System.arraycopy(this.data.replacedTokensStart, 0, this.data.replacedTokensStart = new int[length * 2], 0, length); System.arraycopy(this.data.replacedTokensEnd, 0, this.data.replacedTokensEnd = new int[length * 2], 0, length); System.arraycopy(this.data.replacedTokenUsed, 0, this.data.replacedTokenUsed = new boolean[length * 2], 0, length); } this.data.replacedTokens[this.data.replacedTokensPtr] = reverse(tokens); this.data.replacedTokensStart[this.data.replacedTokensPtr] = start; this.data.replacedTokensEnd[this.data.replacedTokensPtr] = end; this.data.replacedTokenUsed[this.data.replacedTokensPtr] = false; } public void removeTokens(int start, int end) { if(!this.record) return; this.data.removedTokensPtr++; if(this.data.removedTokensStart == null) { this.data.removedTokensStart = new int[10]; this.data.removedTokensEnd = new int[10]; this.data.removedTokenUsed = new boolean[10]; } else if(this.data.removedTokensStart.length == this.data.removedTokensPtr) { int length = this.data.removedTokensStart.length; System.arraycopy(this.data.removedTokensStart, 0, this.data.removedTokensStart = new int[length * 2], 0, length); System.arraycopy(this.data.removedTokensEnd, 0, this.data.removedTokensEnd = new int[length * 2], 0, length); System.arraycopy(this.data.removedTokenUsed, 0, this.data.removedTokenUsed = new boolean[length * 2], 0, length); } this.data.removedTokensStart[this.data.removedTokensPtr] = start; this.data.removedTokensEnd[this.data.removedTokensPtr] = end; this.data.removedTokenUsed[this.data.removedTokensPtr] = false; } public int getNextToken() throws InvalidInputException { if(this.pendingTokensPtr > -1) { int nextToken = this.pendingTokens[this.pendingTokensPtr--]; if(nextToken == TerminalTokens.TokenNameIdentifier){ this.fakeTokenSource = FAKE_IDENTIFIER; } else { this.fakeTokenSource = CharOperation.NO_CHAR; } return nextToken; } this.fakeTokenSource = null; this.precededByRemoved = false; if(this.data.insertedTokens != null) { for (int i = 0; i <= this.data.insertedTokensPtr; i++) { if(this.data.insertedTokensPosition[i] == this.currentPosition - 1 && i > this.skipNextInsertedTokens) { this.data.insertedTokenUsed[i] = true; this.pendingTokens = this.data.insertedTokens[i]; this.pendingTokensPtr = this.data.insertedTokens[i].length - 1; this.isInserted = true; this.startPosition = this.currentPosition; this.skipNextInsertedTokens = i; int nextToken = this.pendingTokens[this.pendingTokensPtr--]; if(nextToken == TerminalTokens.TokenNameIdentifier){ this.fakeTokenSource = FAKE_IDENTIFIER; } else { this.fakeTokenSource = CharOperation.NO_CHAR; } return nextToken; } } this.skipNextInsertedTokens = -1; } int previousLocation = this.currentPosition; int currentToken = super.getNextToken(); if(this.data.replacedTokens != null) { for (int i = 0; i <= this.data.replacedTokensPtr; i++) { if(this.data.replacedTokensStart[i] >= previousLocation && this.data.replacedTokensStart[i] <= this.startPosition && this.data.replacedTokensEnd[i] >= this.currentPosition - 1) { this.data.replacedTokenUsed[i] = true; this.pendingTokens = this.data.replacedTokens[i]; this.pendingTokensPtr = this.data.replacedTokens[i].length - 1; this.fakeTokenSource = FAKE_IDENTIFIER; this.isInserted = false; this.currentPosition = this.data.replacedTokensEnd[i] + 1; int nextToken = this.pendingTokens[this.pendingTokensPtr--]; if(nextToken == TerminalTokens.TokenNameIdentifier){ this.fakeTokenSource = FAKE_IDENTIFIER; } else { this.fakeTokenSource = CharOperation.NO_CHAR; } return nextToken; } } } if(this.data.removedTokensStart != null) { for (int i = 0; i <= this.data.removedTokensPtr; i++) { if(this.data.removedTokensStart[i] >= previousLocation && this.data.removedTokensStart[i] <= this.startPosition && this.data.removedTokensEnd[i] >= this.currentPosition - 1) { this.data.removedTokenUsed[i] = true; this.currentPosition = this.data.removedTokensEnd[i] + 1; this.precededByRemoved = false; return getNextToken(); } } } return currentToken; } public char[] getCurrentIdentifierSource() { if(this.fakeTokenSource != null) return this.fakeTokenSource; return super.getCurrentIdentifierSource(); } public char[] getCurrentTokenSourceString() { if(this.fakeTokenSource != null) return this.fakeTokenSource; return super.getCurrentTokenSourceString(); } public char[] getCurrentTokenSource() { if(this.fakeTokenSource != null) return this.fakeTokenSource; return super.getCurrentTokenSource(); } public RecoveryScannerData getData() { return this.data; } public boolean isFakeToken() { return this.fakeTokenSource != null; } public boolean isInsertedToken() { return this.fakeTokenSource != null && this.isInserted; } public boolean isReplacedToken() { return this.fakeTokenSource != null && !this.isInserted; } public boolean isPrecededByRemovedToken() { return this.precededByRemoved; } public void setData(RecoveryScannerData data) { if(data == null) { this.data = new RecoveryScannerData(); } else { this.data = data; } } public void setPendingTokens(int[] pendingTokens) { this.pendingTokens = pendingTokens; this.pendingTokensPtr = pendingTokens.length - 1; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredAnnotation.java0000644000175000001440000002032012212041344032367 0ustar dokousers/******************************************************************************* * Copyright (c) 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; public class RecoveredAnnotation extends RecoveredElement { public static final int MARKER = 0; public static final int NORMAL = 1; public static final int SINGLE_MEMBER = 2; private int kind; private int identifierPtr; private int identifierLengthPtr; private int sourceStart; public boolean hasPendingMemberValueName; public int memberValuPairEqualEnd = -1; public Annotation annotation; public RecoveredAnnotation(int identifierPtr, int identifierLengthPtr, int sourceStart, RecoveredElement parent, int bracketBalance) { super(parent, bracketBalance); this.kind = MARKER; this.identifierPtr = identifierPtr; this.identifierLengthPtr = identifierLengthPtr; this.sourceStart = sourceStart; } public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { if (this.annotation == null && (typeDeclaration.bits & ASTNode.IsAnonymousType) != 0){ // ignore anonymous type in annotations when annotation isn't fully recovered return this; } return super.add(typeDeclaration, bracketBalanceValue); } public RecoveredElement addAnnotationName(int identPtr, int identLengthPtr, int annotationStart, int bracketBalanceValue) { RecoveredAnnotation element = new RecoveredAnnotation(identPtr, identLengthPtr, annotationStart, this, bracketBalanceValue); return element; } public RecoveredElement addAnnotation(Annotation annot, int index) { this.annotation = annot; if (this.parent != null) return this.parent; return this; } public void updateFromParserState() { Parser parser = parser(); if (this.annotation == null && this.identifierPtr <= parser.identifierPtr) { Annotation annot = null; boolean needUpdateRParenPos = false; MemberValuePair pendingMemberValueName = null; if (this.hasPendingMemberValueName && this.identifierPtr < parser.identifierPtr) { char[] memberValueName = parser.identifierStack[this.identifierPtr + 1]; long pos = parser.identifierPositionStack[this.identifierPtr + 1]; int start = (int) (pos >>> 32); int end = (int)pos; int valueEnd = this.memberValuPairEqualEnd > -1 ? this.memberValuPairEqualEnd : end; SingleNameReference fakeExpression = new SingleNameReference(RecoveryScanner.FAKE_IDENTIFIER, (((long) valueEnd + 1) << 32) + (valueEnd)); pendingMemberValueName = new MemberValuePair(memberValueName, start, end, fakeExpression); } parser.identifierPtr = this.identifierPtr; parser.identifierLengthPtr = this.identifierLengthPtr; TypeReference typeReference = parser.getAnnotationType(); switch (this.kind) { case NORMAL: if (parser.astPtr > -1 && parser.astStack[parser.astPtr] instanceof MemberValuePair) { MemberValuePair[] memberValuePairs = null; int argLength = parser.astLengthStack[parser.astLengthPtr]; int argStart = parser.astPtr - argLength + 1; if (argLength > 0) { int annotationEnd; if (pendingMemberValueName != null) { memberValuePairs = new MemberValuePair[argLength + 1]; System.arraycopy(parser.astStack, argStart, memberValuePairs, 0, argLength); parser.astLengthPtr--; parser.astPtr -= argLength; memberValuePairs[argLength] = pendingMemberValueName; annotationEnd = pendingMemberValueName.sourceEnd; } else { memberValuePairs = new MemberValuePair[argLength]; System.arraycopy(parser.astStack, argStart, memberValuePairs, 0, argLength); parser.astLengthPtr--; parser.astPtr -= argLength; MemberValuePair lastMemberValuePair = memberValuePairs[memberValuePairs.length - 1]; annotationEnd = lastMemberValuePair.value != null ? lastMemberValuePair.value instanceof Annotation ? ((Annotation)lastMemberValuePair.value).declarationSourceEnd : lastMemberValuePair.value.sourceEnd : lastMemberValuePair.sourceEnd; } NormalAnnotation normalAnnotation = new NormalAnnotation(typeReference, this.sourceStart); normalAnnotation.memberValuePairs = memberValuePairs; normalAnnotation.declarationSourceEnd = annotationEnd; normalAnnotation.bits |= ASTNode.IsRecovered; annot = normalAnnotation; needUpdateRParenPos = true; } } break; case SINGLE_MEMBER: if (parser.expressionPtr > -1) { Expression memberValue = parser.expressionStack[parser.expressionPtr--]; SingleMemberAnnotation singleMemberAnnotation = new SingleMemberAnnotation(typeReference, this.sourceStart); singleMemberAnnotation.memberValue = memberValue; singleMemberAnnotation.declarationSourceEnd = memberValue.sourceEnd; singleMemberAnnotation.bits |= ASTNode.IsRecovered; annot = singleMemberAnnotation; needUpdateRParenPos = true; } break; } if (!needUpdateRParenPos) { if (pendingMemberValueName != null) { NormalAnnotation normalAnnotation = new NormalAnnotation(typeReference, this.sourceStart); normalAnnotation.memberValuePairs = new MemberValuePair[]{pendingMemberValueName}; normalAnnotation.declarationSourceEnd = pendingMemberValueName.value.sourceEnd; normalAnnotation.bits |= ASTNode.IsRecovered; annot = normalAnnotation; } else { MarkerAnnotation markerAnnotation = new MarkerAnnotation(typeReference, this.sourceStart); markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd; markerAnnotation.bits |= ASTNode.IsRecovered; annot = markerAnnotation; } } parser.currentElement = addAnnotation(annot, this.identifierPtr); parser.annotationRecoveryCheckPoint(annot.sourceStart, annot.declarationSourceEnd); if (this.parent != null) { this.parent.updateFromParserState(); } } } public ASTNode parseTree() { return this.annotation; } public void resetPendingModifiers() { if (this.parent != null) this.parent.resetPendingModifiers(); } public void setKind(int kind) { this.kind = kind; } public int sourceEnd() { if (this.annotation == null) { Parser parser = parser(); if (this.identifierPtr < parser.identifierPositionStack.length) { return (int) parser.identifierPositionStack[this.identifierPtr]; } else { return this.sourceStart; } } return this.annotation.declarationSourceEnd; } public String toString(int tab) { if (this.annotation != null) { return tabString(tab) + "Recovered annotation:\n" + this.annotation.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$ } else { return tabString(tab) + "Recovered annotation: identiferPtr=" + this.identifierPtr + " identiferlengthPtr=" + this.identifierLengthPtr + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } public Annotation updatedAnnotationReference() { return this.annotation; } public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if (this.bracketBalance > 0){ // was an member value array initializer this.bracketBalance--; return this; } if (this.parent != null){ return this.parent.updateOnClosingBrace(braceStart, braceEnd); } return this; } public void updateParseTree() { updatedAnnotationReference(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java0000644000175000001440000002253412212041344031205 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; /** * Internal field structure for parsing recovery */ import java.util.HashSet; import java.util.Set; 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 { public CompilationUnitDeclaration unitDeclaration; public RecoveredImport[] imports; public int importCount; public RecoveredType[] types; public int typeCount; int pendingModifiers; int pendingModifersSourceStart = -1; RecoveredAnnotation[] pendingAnnotations; int pendingAnnotationCount; public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){ super(null, bracketBalance, parser); this.unitDeclaration = unitDeclaration; } public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) { if (this.pendingAnnotations == null) { this.pendingAnnotations = new RecoveredAnnotation[5]; this.pendingAnnotationCount = 0; } else { if (this.pendingAnnotationCount == this.pendingAnnotations.length) { System.arraycopy( this.pendingAnnotations, 0, (this.pendingAnnotations = new RecoveredAnnotation[2 * this.pendingAnnotationCount]), 0, this.pendingAnnotationCount); } } RecoveredAnnotation element = new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue); this.pendingAnnotations[this.pendingAnnotationCount++] = element; return element; } public void addModifier(int flag, int modifiersSourceStart) { this.pendingModifiers |= flag; if (this.pendingModifersSourceStart < 0) { this.pendingModifersSourceStart = modifiersSourceStart; } } /* * Record a method declaration: should be attached to last type */ public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) { /* 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; int kind = TypeDeclaration.kind(type.typeDeclaration.modifiers); if(start > 0 && start < end && kind != TypeDeclaration.INTERFACE_DECL && kind != TypeDeclaration.ANNOTATION_TYPE_DECL) { // the } of the last type can be considered as the end of an initializer Initializer initializer = new Initializer(new Block(0), 0); initializer.bodyStart = end; initializer.bodyEnd = end; initializer.declarationSourceStart = end; initializer.declarationSourceEnd = end; initializer.sourceStart = end; initializer.sourceEnd = end; type.add(initializer, bracketBalanceValue); } resetPendingModifiers(); return type.add(methodDeclaration, bracketBalanceValue); } return this; // ignore } /* * Record a field declaration: should be attached to last type */ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { /* attach it to last type - if any */ if (this.typeCount > 0){ RecoveredType type = this.types[this.typeCount -1]; type.bodyEnd = 0; // reset position type.typeDeclaration.declarationSourceEnd = 0; // reset position type.typeDeclaration.bodyEnd = 0; resetPendingModifiers(); return type.add(fieldDeclaration, bracketBalanceValue); } return this; // ignore } public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) { resetPendingModifiers(); if (this.imports == null) { this.imports = new RecoveredImport[5]; this.importCount = 0; } else { if (this.importCount == this.imports.length) { System.arraycopy( this.imports, 0, (this.imports = new RecoveredImport[2 * this.importCount]), 0, this.importCount); } } RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue); this.imports[this.importCount++] = element; /* if import not finished, then import becomes current */ if (importReference.declarationSourceEnd == 0) return element; return this; } public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0){ if (this.typeCount > 0) { // add it to the last type RecoveredType lastType = this.types[this.typeCount-1]; lastType.bodyEnd = 0; // reopen type lastType.typeDeclaration.bodyEnd = 0; // reopen type lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type lastType.bracketBalance++; // expect one closing brace resetPendingModifiers(); return lastType.add(typeDeclaration, bracketBalanceValue); } } if (this.types == null) { this.types = new RecoveredType[5]; this.typeCount = 0; } else { if (this.typeCount == this.types.length) { System.arraycopy( this.types, 0, (this.types = new RecoveredType[2 * this.typeCount]), 0, this.typeCount); } } RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); this.types[this.typeCount++] = element; if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); /* if type not finished, then type becomes current */ if (typeDeclaration.declarationSourceEnd == 0) return element; return this; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.unitDeclaration; } public void resetPendingModifiers() { this.pendingAnnotations = null; this.pendingAnnotationCount = 0; this.pendingModifiers = 0; this.pendingModifersSourceStart = -1; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.unitDeclaration.sourceEnd; } public String toString(int tab) { StringBuffer result = new StringBuffer(tabString(tab)); result.append("Recovered unit: [\n"); //$NON-NLS-1$ this.unitDeclaration.print(tab + 1, result); result.append(tabString(tab + 1)); result.append("]"); //$NON-NLS-1$ if (this.imports != null) { for (int i = 0; i < this.importCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.imports[i].toString(tab + 1)); } } if (this.types != null) { for (int i = 0; i < this.typeCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.types[i].toString(tab + 1)); } } return result.toString(); } public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){ /* update imports */ if (this.importCount > 0){ ImportReference[] importRefences = new ImportReference[this.importCount]; for (int i = 0; i < this.importCount; i++){ importRefences[i] = this.imports[i].updatedImportReference(); } this.unitDeclaration.imports = importRefences; } /* update types */ if (this.typeCount > 0){ int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length; TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + this.typeCount]; if (existingCount > 0){ System.arraycopy(this.unitDeclaration.types, 0, typeDeclarations, 0, existingCount); } // may need to update the declarationSourceEnd of the last type if (this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd == 0){ this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd = this.unitDeclaration.sourceEnd; this.types[this.typeCount - 1].typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd; } Set knownTypes = new HashSet(); int actualCount = existingCount; for (int i = 0; i < this.typeCount; i++){ TypeDeclaration typeDecl = this.types[i].updatedTypeDeclaration(0, knownTypes); // filter out local types (12454) if (typeDecl != null && (typeDecl.bits & ASTNode.IsLocalType) == 0){ typeDeclarations[actualCount++] = typeDecl; } } if (actualCount != this.typeCount){ System.arraycopy( typeDeclarations, 0, typeDeclarations = new TypeDeclaration[existingCount+actualCount], 0, existingCount+actualCount); } this.unitDeclaration.types = typeDeclarations; } return this.unitDeclaration; } public void updateParseTree(){ updatedCompilationUnitDeclaration(); } /* * Update the sourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ if (this.unitDeclaration.sourceEnd == 0) this.unitDeclaration.sourceEnd = bodyEnd; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser14.rsc0000644000175000001440000000236612212041344027737 0ustar dokousers±Ÿ$°aD&,&¬ŸN),MÚ§ˆ3#¾ˆ3#ªD¯Ÿ¦/P3¾/P3¡p+`¡ÿ£ $,~–"},z"y!,s¡AØØ+$¦Nˆ3×û¾36 D6 D D6D6DC3¾C3®e„b‚ba¡™¡(¡~¡p¾)¾¨)¾x¾¨x¾¨p¾p¡4•+‚4r+¾á¨+ƒ¾á+ƒ¾á+x¾á¨+x¾á+¾á¨+m}:Vd$ʈÎ.Ò™˜jh—S1jhShS/¡Ö¡RHP¡A¡J¡J+)eHdN$HdN)$dN))$$û)$û))$û¡IÁM$)ÁMh#$)¡I–f+byb•D•D#&bD¡Q$! ¡OB¡O$BBû$Bû¼ˆÌà<D©’aDÞDP3­ê¾*¨p¾*p¾*¨xx-è`#$)¾*x-`#$)¾)¨p¾)p¾)¨x-è]#$)¾)x-]#$)¾)¨¾)¾*¨¾*<D âΈ0ΈÎ3#¾3#,ß,  ë«§ˆÌ)ZD<3¬¹¥•—-’ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser2.rsc0000644000175000001440000005574212212041344027662 0ustar dokousersý€€€€€€€€€€€€€€€€€€€€€€€€”€€€~}V€€^FÀ€€€€€€+Y퀀€€€–€€€€€€€€€€€€€€€€€€œþ€€€€€½ç»€€€€€€€€€€€€€€€€€€€€€€€€€‰€€€!€€}›€€€€€€€€õ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€G€â€à€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}+߀€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€'ì}ú€€€€äë€}©€€€€€2€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~ö}À€€€€€€€€€€€€€€€€€€€€€€€€€€€€“€€€€€€€º€€€€€€€€€€€€€€€€€€€€€€€€€€€€€&€€€€~RX€€€€€€€€~¯€€€€€€€€€€€€€€€€€€€€€€€€€€€€€3€€€€ê_€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ž€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~–€€€€Ý€倀€€€€€€€}/€€€€€€€€€€€€€€€€€€€€€€€€怀Ú€€€€Ù€è¸ÿ€€€€Ø€} €€€€€€}•€€€€€€€€€€€€€€€€€€€€~;~¨€€€€€~Ž~5€€€€€€€€€€€€€€€€€€€€€€€€€€×€€~ñ€€€€€€€€€€€€€€}-€€€€Õr€€€€€€€€€€}€€€€€€€€€€€€€€€€€€€€€€€€Ó€€€€€€€€€€€Ñn€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~º~¥€€€€€Ò€€€€€€€€€€€€€€€€€€€€€€€€€€€€~ª€~쀀€€¡€€€€€€€€€~¹€€€€€~€€€€€€€€€é¶€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ï€³€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€¹€€€€€Ü€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}³€€€€€Ðc}6€€€€€q€€€€€€€€€€€€€€€€€€€€€€€€€€€6€]€€€€€W}_€€€€€€~š€€€€€€€€€€€€€€€€€€€€€€€€€€€}Ì€€€€€I}±€€€€€€€€€€€€€€€€€€€€€€€€€€€€~‡€€€€~0€€€ñ€€€€}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€~¬€€€€€h€€€€€Û}ÿ€€€€€€€€€€€€€€€€€€€€~ïÏ€€€€€€€µ€€€€€€€€€€€€€€€€€€€€€€€€€€}ö€€€€ž€€€€}¦}Y€t€€}Æ€€€€€€€€€€€€€€€€€€€€€€€€´€€€€~™€€€€€€€€€€€ €€€€€€~ˆ€~aÎ~§€€€€€€€€€€€€€€€€~ú~ô€€€€}¼€N€€€€€€€€€€€€€€€€€€€€€€€€€€€}y€€€€€€€€€€€€€€€€€€€€€€€€~-€e€€€€€®€€k€€€€€€€€€D~6~êÍV€€€€€€€€€€€~»€€~퀀€~¸€­€€€€€€ð~€€€€€€€€€€€€€€€€€€€€€€€€}C€€€€€€€€€€€€€€€€€€€€€€€€€€`€€€€€b€€€€€€€€Ë€€€Ê}¬€€€€€€€€€€€€€È~¶€}€€€€€~”€€€€€€€€5€€€€€€€€€€€€€€€€€€€€€€€€€€€} €€€€€€€€€€€€€€€€€€€€€€€€€E€€€€€€~€€€~h~óÇ€€€~°€€€€€€~‰€€€€€€€€€€~´~²€Æ€€€}q†~=€€€€€€€€4€Ä€€€€€€€€€€€€€€€€€€€€€€€€€} €€€€€€€€€€€€€€€€€€€€€€€€€}Ú€€€€€€€€€€À}¾…€€~o€€€€€€~b€€€€€€€€€€~/€~~—€€€}€€€~i€€~TÁ~7€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}’€€€€€€€€€€€€€€€€€€€€€€~1€~€€€€~<}í€}s}½€€}g€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|ý€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€}n€€€€€}怀€€€€€€}´€€€€€€€€€€€€¿€%€~m€}¯€#€}ô}¿}¥€}ã€}€¼·€€€€€€€€€€€€€€€€€€€€€€€€€€÷€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}±€€€€}>€}\€€€€€€}@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€J~Š€€€€€Þ€€€€€€€€€€€€€€€€€€€€€€€€}}Ê}ò€€€ò€€€€€€€€€€€€€€€€€€€€€€€€€€}r~}«€€}Ÿ€}“}–€€},€}瀀}œ€}Â}3}쀀€€€€€€€€€€€€€€€€€€€€€€€Å€€€€€€€€€€€€€€€€€€€€€€€€€€°€}f€€€€€}¬|ÿ«ª©¨€§€€}2€€¦¥€€€¤£¢€€€€€€š€}}€’€‘}}â}Û€}å}}]€€}‰€€€€€€€€€€€€€€€€€€€€€€€€€€0€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Œ€‹Š€ˆ‡€„ƒ‚~}€|{zyx€€€wvu€}spg\[ZTRQP~V€€€OC€€€€€€€€€€€€€€€€€€€€€€€€€}Å€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€B€;:871*)$ ~ø~õ~ò~뀀€~µ~³~«~©~¦~¤~¢~¡~ ~Ÿ~œ~˜~“>=€€€~’~‘€€€€€€€€€€€€€€€€€€€€€€€€€}G€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€~‹~†~…~„~‚~~€~~~~}~|~y~t~r~q~p~l~k~j~g~f~e~d~c~a€€€~`~_~^~]~\~[~Z~Y~X~W~U~P~O~N~S}²}8€}J~M~L€€€€€€€€€€€€€€€€€€€€€€€€€} €€€€€€€€€€€€€€€€€€€€€€€€~K~J~I~H~G~F€€~E™~D~C~B~A~@~?~>~:~9~8~4~3~2~.~+~*~)~(~'~&~%~$€€€~#~"~!~ ~~~~~~~~~~~~~€~~~€€€€€€€€€€€€€€€€€€€€€€€€€(€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~~ ~ ~ ~ ~ ~€€€€€€€€€€€€~,€€€€€€€€€€€€€€€€€€€€€€€€€€€€}þ}ù}ø€€}é}耀}á}à€€€}Þ}ñ€€€€€€€}o€€€€€€€€€€€€€€€€€€€€€€€€€€}Ý}Ø}×€€€€€€€€€€€€€€€€€€€€}Ö}Ô}Ò}Ð}Ï}Î};€€€€€€€}Ë}É€}È€€}Ç}»€}º}¸}·}¶}ª}¨€€€€€€€€€€€€€€€}§€€€}¤}£} €€€€€o}ž€€€€}}›}š}—€€€€~×€€€€€€€}”}‘}€€€€€€€€€€€€€€€€}}‹}Š}ˆ€€€€€}„ö€€€€€€€}‚}}€€€€€}{€€€}c€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}ë}z€}x}w}v€€€€}u}ð}t€€€€€€}b€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}p}m€}i}d}[€€}Z€}W}U€}S€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}R€€€€€€€€€€€€€€€}Q}P}O}N}M}L}K}I}H}A}=}<~•€€€€€€€};}:€}9€€}5}4}1}.}*}(}'}ý}#€€€€€€€€€€€€€€€€€€€}"}!} €€€€€}}€€€€€}}}€€€€~û€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€}€€€}}}|þ|ü€€<€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|û|ú|ù€€€|ø|÷|ö|õ|ô€€€€€€€€€|ó|ò|ñ|ð|ï|î|í|ì€|ë|ê|退|è|ç|æ|å|ä|ã| |á|à9€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|ß|Þ€€€€|Ý|Ü|Û€|Ú€€-€€€€€€€€€€€€€€€€€€€€€€€€|Ù|Ø|×€€|Ö€€|Õ|Ô|Ó|Ò|Ñ|Ѐ€€|Ï|Î|Í€€€€€|Ì|Ë€€€€€|Ê|É|È|Ç€|Æ|Å|Ä|Ã|Â|Á|À|¿|¾|½|¼|»|º|¹|¸|·€|¶}°€€€€€€€€€€€€€€€€€€€€€€€€€€|µ|´|³|²|±|°|¯€"€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|®|­|¬€€€|«|ª|©|¨|§€€}e€€€€€€€€€€€€€€€€€€€€€€|¦|¥€€€€€|¤|£~{€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|¢|¡| €€€|Ÿ|ž€|€€€L€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~z€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|œ|›|š€€€|™|˜|—|–|•€€K€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|”|“|’€€€|‘|||Ž|€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|Œ|‹|Š€€€|‰|ˆ|‡|†|…€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}߀€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|„|ƒ|‚€€€||€||~|}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}Ü€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|||{|z€€€|y|x|w|v|u€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}Ù€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|t|s|r€€€|q|p|o|n|m€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}Õ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|l|k|j€€€|i|h|g|f|e€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}Ó€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|d|c|b€€€|a|`|_|^|]€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}¹€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|\|[|Z€€€|Y|X|W|V|U€€~退€€€€€€€€€€€€€€€€€€€€€€€€€€€}µ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|T|S|R€€€|Q|P|O|N|M€€~耀€€€€€€€€€€€€€€€€€€€€€€€€€€€}­€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|L|K|J€€€|I|H|G|F|E€€}Ž€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|D|C|B€€€|A|@|?|>|=€€|<|;|:|9|8|7|6|5|4|3|2|1|0|/|.€|-|,|+|*|)|(|'|&|%|$|#|"€€|!| }Œ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€||€€€€|||||€€~瀀€€€€€€€€€€€€€€€€€€€€€€€€€€€}‡€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|||€€€|||||€€~怀€€€€€€€€€€€€€€€€€€€€€€€€€€€}†€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€|€€€€€€€€€€€€~ €€€€€€€€€€€€€€€€€€€€€€€€€€€}…€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~ €€€€€€€€€€€€€€€€€€€€€€€€€€€}ƒ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~က€€€€€€€€€€€€€€€€€€€€€€€€€€€}l€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~À€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}k€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~¿€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}j€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~¾€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}X€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}h€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}T€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}F€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}?€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}7€€€€€€€€€€€€€€€€€€€€€€€€€€€?€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€})€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ü€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€က€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ö€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€¯€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}Ä€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€—€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}0€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€j€€€€€€€€€€€€} €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€É€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€S€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€M€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€A€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€/€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€.€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€,€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~þ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ò€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~½€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Œ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~s€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Q€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}䀀€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}Ñ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}E€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}D€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ô€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~ý€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ô€€€€€€€óH€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~ƒ€€€€€€€€€€€€€€€€€€€~n€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~ü€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ñ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}®€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}¢€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}¡€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€f€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~¼€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}%€€€€€€€€€€€€€€€€€€€€~ž€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€û€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ô€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ѐ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~›€€€€€€€~ÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ì€€€€€€€€€€€€}ò€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ÿ€€}Á€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€m€€€€€€€€€€ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ó€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€€€€~Ï€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}÷€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ø€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ö€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~®€€€€€€€~΀€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Õ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Í€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ù€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ø€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ì€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~£€€€~Ë€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}õ€€€€~à€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~倀€€€€€€€€€€€€€€€€€€€€€€€€€€€ù€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ê€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~߀€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Þ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ý€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~É€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~È€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ç€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Æ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}B€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ü€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Û€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ú€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Å€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Ä€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~À€€€€€€€€€€€€€€€€€€€€€€€€€€€€~䀀€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€~Á€€€€€€€€€€€€€€€€€€€€€€€€€€€€}~€€€€€€€~w€€€€€€€€€€€€€}û€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€d€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}™€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}&€€€€€€€€€€€€€€€€€U€€€€€€€€€€€€€€€€€€€€€€€€€}$€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~­€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}ü€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}˜€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}`€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ú€€€€€€€€€€€€€€€€€€}ꀀ€€€€€€€€€€€€€€€~x€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€˜€€€€€€€€€€€€€€€€•€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€l€€€€€€€€€€€€€€€€i€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}}€€€€€€€€€€€€€€€€€€€€€}|€€€€€€€~ù€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~÷€€€€€€€€€€€€€€€€~ð€€€€€€€€~·€€€€€€€€€€€€€€€€~±€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~v€€€€€€€€€€€€€€€€~u€€€€€€€}ó€€€€€€€€€€€€€€€€}a€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}^€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java0000644000175000001440000007066612212041344031220 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for Bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import java.util.HashSet; import java.util.Set; 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.Annotation; 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.QualifiedAllocationExpression; 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.classfmt.ClassFileConstants; /** * Internal type structure for parsing recovery */ public class RecoveredType extends RecoveredStatement implements TerminalTokens { public static final int MAX_TYPE_DEPTH = 256; public TypeDeclaration typeDeclaration; public RecoveredAnnotation[] annotations; public int annotationCount; public int modifiers; public int modifiersStart; public RecoveredType[] memberTypes; public int memberTypeCount; public RecoveredField[] fields; public int fieldCount; public RecoveredMethod[] methods; public int methodCount; public boolean preserveContent = false; // only used for anonymous types public int bodyEnd; public boolean insideEnumConstantPart = false; public TypeParameter[] pendingTypeParameters; public int pendingTypeParametersStart; int pendingModifiers; int pendingModifersSourceStart = -1; RecoveredAnnotation[] pendingAnnotations; int pendingAnnotationCount; public RecoveredType(TypeDeclaration typeDeclaration, RecoveredElement parent, int bracketBalance){ super(typeDeclaration, parent, bracketBalance); this.typeDeclaration = typeDeclaration; if(typeDeclaration.allocation != null && typeDeclaration.allocation.type == null) { // an enum constant body can not exist if there is no opening brace this.foundOpeningBrace = true; } else { this.foundOpeningBrace = !bodyStartsAtHeaderEnd(); } this.insideEnumConstantPart = TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL; if(this.foundOpeningBrace) { this.bracketBalance++; } this.preserveContent = parser().methodRecoveryActivated || parser().statementRecoveryActivated; } public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) { /* do not consider a method starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.typeDeclaration.declarationSourceEnd != 0 && methodDeclaration.declarationSourceStart > this.typeDeclaration.declarationSourceEnd){ this.pendingTypeParameters = null; resetPendingModifiers(); return this.parent.add(methodDeclaration, bracketBalanceValue); } if (this.methods == null) { this.methods = new RecoveredMethod[5]; this.methodCount = 0; } else { if (this.methodCount == this.methods.length) { System.arraycopy( this.methods, 0, (this.methods = new RecoveredMethod[2 * this.methodCount]), 0, this.methodCount); } } RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser); this.methods[this.methodCount++] = element; if(this.pendingTypeParameters != null) { element.attach(this.pendingTypeParameters, this.pendingTypeParametersStart); this.pendingTypeParameters = null; } if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); this.insideEnumConstantPart = false; /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } /* if method not finished, then method becomes current */ if (methodDeclaration.declarationSourceEnd == 0) return element; return this; } public RecoveredElement add(Block nestedBlockDeclaration,int bracketBalanceValue) { this.pendingTypeParameters = null; resetPendingModifiers(); int mods = ClassFileConstants.AccDefault; if(parser().recoveredStaticInitializerStart != 0) { mods = ClassFileConstants.AccStatic; } return this.add(new Initializer(nestedBlockDeclaration, mods), bracketBalanceValue); } public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { this.pendingTypeParameters = null; /* do not consider a field starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.typeDeclaration.declarationSourceEnd != 0 && fieldDeclaration.declarationSourceStart > this.typeDeclaration.declarationSourceEnd) { resetPendingModifiers(); return this.parent.add(fieldDeclaration, bracketBalanceValue); } if (this.fields == null) { this.fields = new RecoveredField[5]; this.fieldCount = 0; } else { if (this.fieldCount == this.fields.length) { System.arraycopy( this.fields, 0, (this.fields = new RecoveredField[2 * this.fieldCount]), 0, this.fieldCount); } } 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; } this.fields[this.fieldCount++] = element; if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } /* if field not finished, then field becomes current */ if (fieldDeclaration.declarationSourceEnd == 0) return element; return this; } public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBalanceValue) { this.pendingTypeParameters = null; /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.typeDeclaration.declarationSourceEnd != 0 && memberTypeDeclaration.declarationSourceStart > this.typeDeclaration.declarationSourceEnd){ resetPendingModifiers(); return this.parent.add(memberTypeDeclaration, bracketBalanceValue); } this.insideEnumConstantPart = false; if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousType) != 0){ if (this.methodCount > 0) { // add it to the last method body RecoveredMethod lastMethod = this.methods[this.methodCount-1]; lastMethod.methodDeclaration.bodyEnd = 0; // reopen method lastMethod.methodDeclaration.declarationSourceEnd = 0; // reopen method lastMethod.bracketBalance++; // expect one closing brace resetPendingModifiers(); return lastMethod.add(memberTypeDeclaration, bracketBalanceValue); } else { // ignore return this; } } if (this.memberTypes == null) { this.memberTypes = new RecoveredType[5]; this.memberTypeCount = 0; } else { if (this.memberTypeCount == this.memberTypes.length) { System.arraycopy( this.memberTypes, 0, (this.memberTypes = new RecoveredType[2 * this.memberTypeCount]), 0, this.memberTypeCount); } } RecoveredType element = new RecoveredType(memberTypeDeclaration, this, bracketBalanceValue); this.memberTypes[this.memberTypeCount++] = element; if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } /* if member type not finished, then member type becomes current */ if (memberTypeDeclaration.declarationSourceEnd == 0) return element; return this; } public void add(TypeParameter[] parameters, int startPos) { this.pendingTypeParameters = parameters; this.pendingTypeParametersStart = startPos; } public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) { if (this.pendingAnnotations == null) { this.pendingAnnotations = new RecoveredAnnotation[5]; this.pendingAnnotationCount = 0; } else { if (this.pendingAnnotationCount == this.pendingAnnotations.length) { System.arraycopy( this.pendingAnnotations, 0, (this.pendingAnnotations = new RecoveredAnnotation[2 * this.pendingAnnotationCount]), 0, this.pendingAnnotationCount); } } RecoveredAnnotation element = new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue); this.pendingAnnotations[this.pendingAnnotationCount++] = element; return element; } public void addModifier(int flag, int modifiersSourceStart) { this.pendingModifiers |= flag; if (this.pendingModifersSourceStart < 0) { this.pendingModifersSourceStart = modifiersSourceStart; } } public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) { if (annotCount > 0) { Annotation[] existingAnnotations = this.typeDeclaration.annotations; if (existingAnnotations != null) { this.annotations = new RecoveredAnnotation[annotCount]; this.annotationCount = 0; next : for (int i = 0; i < annotCount; i++) { for (int j = 0; j < existingAnnotations.length; j++) { if (annots[i].annotation == existingAnnotations[j]) continue next; } this.annotations[this.annotationCount++] = annots[i]; } } else { this.annotations = annots; this.annotationCount = annotCount; } } if (mods != 0) { this.modifiers = mods; this.modifiersStart = modsSourceStart; } } /* * Answer the body end of the corresponding parse node */ public int bodyEnd(){ if (this.bodyEnd == 0) return this.typeDeclaration.declarationSourceEnd; return this.bodyEnd; } public boolean bodyStartsAtHeaderEnd(){ if (this.typeDeclaration.superInterfaces == null){ if (this.typeDeclaration.superclass == null){ if(this.typeDeclaration.typeParameters == null) { return this.typeDeclaration.bodyStart == this.typeDeclaration.sourceEnd+1; } else { return this.typeDeclaration.bodyStart == this.typeDeclaration.typeParameters[this.typeDeclaration.typeParameters.length-1].sourceEnd+1; } } else { return this.typeDeclaration.bodyStart == this.typeDeclaration.superclass.sourceEnd+1; } } else { return this.typeDeclaration.bodyStart == this.typeDeclaration.superInterfaces[this.typeDeclaration.superInterfaces.length-1].sourceEnd+1; } } /* * Answer the enclosing type node, or null if none */ public RecoveredType enclosingType(){ RecoveredElement current = this.parent; while (current != null){ if (current instanceof RecoveredType){ return (RecoveredType) current; } current = current.parent; } return null; } public int lastMemberEnd() { int lastMemberEnd = this.typeDeclaration.bodyStart; if (this.fieldCount > 0) { FieldDeclaration lastField = this.fields[this.fieldCount - 1].fieldDeclaration; if (lastMemberEnd < lastField.declarationSourceEnd && lastField.declarationSourceEnd != 0) { lastMemberEnd = lastField.declarationSourceEnd; } } if (this.methodCount > 0) { AbstractMethodDeclaration lastMethod = this.methods[this.methodCount - 1].methodDeclaration; if (lastMemberEnd < lastMethod.declarationSourceEnd && lastMethod.declarationSourceEnd != 0) { lastMemberEnd = lastMethod.declarationSourceEnd; } } if (this.memberTypeCount > 0) { TypeDeclaration lastType = this.memberTypes[this.memberTypeCount - 1].typeDeclaration; if (lastMemberEnd < lastType.declarationSourceEnd && lastType.declarationSourceEnd != 0) { lastMemberEnd = lastType.declarationSourceEnd; } } return lastMemberEnd; } public char[] name(){ return this.typeDeclaration.name; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.typeDeclaration; } public void resetPendingModifiers() { this.pendingAnnotations = null; this.pendingAnnotationCount = 0; this.pendingModifiers = 0; this.pendingModifersSourceStart = -1; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.typeDeclaration.declarationSourceEnd; } public String toString(int tab) { StringBuffer result = new StringBuffer(tabString(tab)); result.append("Recovered type:\n"); //$NON-NLS-1$ if ((this.typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) { result.append(tabString(tab)); result.append(" "); //$NON-NLS-1$ } this.typeDeclaration.print(tab + 1, result); if (this.annotations != null) { for (int i = 0; i < this.annotationCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.annotations[i].toString(tab + 1)); } } if (this.memberTypes != null) { for (int i = 0; i < this.memberTypeCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.memberTypes[i].toString(tab + 1)); } } if (this.fields != null) { for (int i = 0; i < this.fieldCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.fields[i].toString(tab + 1)); } } if (this.methods != null) { for (int i = 0; i < this.methodCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.methods[i].toString(tab + 1)); } } return result.toString(); } /* * Update the bodyStart of the corresponding parse node */ public void updateBodyStart(int bodyStart){ this.foundOpeningBrace = true; this.typeDeclaration.bodyStart = bodyStart; } public Statement updatedStatement(int depth, Set knownTypes){ // ignore closed anonymous type if ((this.typeDeclaration.bits & ASTNode.IsAnonymousType) != 0 && !this.preserveContent){ return null; } TypeDeclaration updatedType = updatedTypeDeclaration(depth + 1, knownTypes); if (updatedType != null && (updatedType.bits & ASTNode.IsAnonymousType) != 0){ /* in presence of an anonymous type, we want the full allocation expression */ QualifiedAllocationExpression allocation = updatedType.allocation; if (allocation.statementEnd == -1) { allocation.statementEnd = updatedType.declarationSourceEnd; } return allocation; } return updatedType; } public TypeDeclaration updatedTypeDeclaration(int depth, Set knownTypes){ if (depth >= MAX_TYPE_DEPTH) return null; if(knownTypes.contains(this.typeDeclaration)) return null; knownTypes.add(this.typeDeclaration); int lastEnd = this.typeDeclaration.bodyStart; /* update annotations */ if (this.modifiers != 0) { this.typeDeclaration.modifiers |= this.modifiers; if (this.modifiersStart < this.typeDeclaration.declarationSourceStart) { this.typeDeclaration.declarationSourceStart = this.modifiersStart; } } /* update annotations */ if (this.annotationCount > 0){ int existingCount = this.typeDeclaration.annotations == null ? 0 : this.typeDeclaration.annotations.length; Annotation[] annotationReferences = new Annotation[existingCount + this.annotationCount]; if (existingCount > 0){ System.arraycopy(this.typeDeclaration.annotations, 0, annotationReferences, this.annotationCount, existingCount); } for (int i = 0; i < this.annotationCount; i++){ annotationReferences[i] = this.annotations[i].updatedAnnotationReference(); } this.typeDeclaration.annotations = annotationReferences; int start = this.annotations[0].annotation.sourceStart; if (start < this.typeDeclaration.declarationSourceStart) { this.typeDeclaration.declarationSourceStart = start; } } /* update member types */ if (this.memberTypeCount > 0){ int existingCount = this.typeDeclaration.memberTypes == null ? 0 : this.typeDeclaration.memberTypes.length; TypeDeclaration[] memberTypeDeclarations = new TypeDeclaration[existingCount + this.memberTypeCount]; if (existingCount > 0){ System.arraycopy(this.typeDeclaration.memberTypes, 0, memberTypeDeclarations, 0, existingCount); } // may need to update the declarationSourceEnd of the last type if (this.memberTypes[this.memberTypeCount - 1].typeDeclaration.declarationSourceEnd == 0){ int bodyEndValue = bodyEnd(); this.memberTypes[this.memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEndValue; this.memberTypes[this.memberTypeCount - 1].typeDeclaration.bodyEnd = bodyEndValue; } int updatedCount = 0; for (int i = 0; i < this.memberTypeCount; i++){ TypeDeclaration updatedTypeDeclaration = this.memberTypes[i].updatedTypeDeclaration(depth + 1, knownTypes); if (updatedTypeDeclaration != null) { memberTypeDeclarations[existingCount + (updatedCount++)] = updatedTypeDeclaration; } } if (updatedCount < this.memberTypeCount) { int length = existingCount + updatedCount; System.arraycopy(memberTypeDeclarations, 0, memberTypeDeclarations = new TypeDeclaration[length], 0, length); } if (memberTypeDeclarations.length > 0) { this.typeDeclaration.memberTypes = memberTypeDeclarations; if(memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd > lastEnd) { lastEnd = memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd; } } } /* update fields */ if (this.fieldCount > 0){ int existingCount = this.typeDeclaration.fields == null ? 0 : this.typeDeclaration.fields.length; FieldDeclaration[] fieldDeclarations = new FieldDeclaration[existingCount + this.fieldCount]; if (existingCount > 0){ System.arraycopy(this.typeDeclaration.fields, 0, fieldDeclarations, 0, existingCount); } // may need to update the declarationSourceEnd of the last field if (this.fields[this.fieldCount - 1].fieldDeclaration.declarationSourceEnd == 0){ int temp = bodyEnd(); this.fields[this.fieldCount - 1].fieldDeclaration.declarationSourceEnd = temp; this.fields[this.fieldCount - 1].fieldDeclaration.declarationEnd = temp; } for (int i = 0; i < this.fieldCount; i++){ fieldDeclarations[existingCount + i] = this.fields[i].updatedFieldDeclaration(depth, knownTypes); } for (int i = this.fieldCount - 1; 0 < i; i--) { if (fieldDeclarations[existingCount + i - 1].declarationSourceStart == fieldDeclarations[existingCount + i].declarationSourceStart) { fieldDeclarations[existingCount + i - 1].declarationSourceEnd = fieldDeclarations[existingCount + i].declarationSourceEnd; fieldDeclarations[existingCount + i - 1].declarationEnd = fieldDeclarations[existingCount + i].declarationEnd; } } this.typeDeclaration.fields = fieldDeclarations; if(fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd > lastEnd) { lastEnd = fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd; } } /* update methods */ int existingCount = this.typeDeclaration.methods == null ? 0 : this.typeDeclaration.methods.length; boolean hasConstructor = false, hasRecoveredConstructor = false; boolean hasAbstractMethods = false; int defaultConstructorIndex = -1; if (this.methodCount > 0){ AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[existingCount + this.methodCount]; for (int i = 0; i < existingCount; i++){ AbstractMethodDeclaration m = this.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 if (this.methods[this.methodCount - 1].methodDeclaration.declarationSourceEnd == 0){ int bodyEndValue = bodyEnd(); this.methods[this.methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEndValue; this.methods[this.methodCount - 1].methodDeclaration.bodyEnd = bodyEndValue; } for (int i = 0; i < this.methodCount; i++){ AbstractMethodDeclaration updatedMethod = this.methods[i].updatedMethodDeclaration(depth, knownTypes); if (updatedMethod.isConstructor()) hasRecoveredConstructor = true; if (updatedMethod.isAbstract()) hasAbstractMethods = true; methodDeclarations[existingCount + i] = updatedMethod; } this.typeDeclaration.methods = methodDeclarations; if(methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd > lastEnd) { lastEnd = methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd; } if (hasAbstractMethods) this.typeDeclaration.bits |= ASTNode.HasAbstractMethods; hasConstructor = this.typeDeclaration.checkConstructors(parser()); } else { for (int i = 0; i < existingCount; i++){ if (this.typeDeclaration.methods[i].isConstructor()) hasConstructor = true; } } /* add clinit ? */ if (this.typeDeclaration.needClassInitMethod()){ boolean alreadyHasClinit = false; for (int i = 0; i < existingCount; i++){ if (this.typeDeclaration.methods[i].isClinit()){ alreadyHasClinit = true; break; } } if (!alreadyHasClinit) this.typeDeclaration.addClinit(); } /* add default constructor ? */ if (defaultConstructorIndex >= 0 && hasRecoveredConstructor){ /* should discard previous default construtor */ AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[this.typeDeclaration.methods.length - 1]; if (defaultConstructorIndex != 0){ System.arraycopy(this.typeDeclaration.methods, 0, methodDeclarations, 0, defaultConstructorIndex); } if (defaultConstructorIndex != this.typeDeclaration.methods.length-1){ System.arraycopy( this.typeDeclaration.methods, defaultConstructorIndex+1, methodDeclarations, defaultConstructorIndex, this.typeDeclaration.methods.length - defaultConstructorIndex - 1); } this.typeDeclaration.methods = methodDeclarations; } else { int kind = TypeDeclaration.kind(this.typeDeclaration.modifiers); if (!hasConstructor && kind != TypeDeclaration.INTERFACE_DECL && kind != TypeDeclaration.ANNOTATION_TYPE_DECL && this.typeDeclaration.allocation == null) {// if was already reduced, then constructor boolean insideFieldInitializer = false; RecoveredElement parentElement = this.parent; while (parentElement != null){ if (parentElement instanceof RecoveredField){ insideFieldInitializer = true; break; } parentElement = parentElement.parent; } this.typeDeclaration.createDefaultConstructor(!parser().diet || insideFieldInitializer, true); } } if (this.parent instanceof RecoveredType){ this.typeDeclaration.bits |= ASTNode.IsMemberType; } else if (this.parent instanceof RecoveredMethod){ this.typeDeclaration.bits |= ASTNode.IsLocalType; } if(this.typeDeclaration.declarationSourceEnd == 0) { this.typeDeclaration.declarationSourceEnd = lastEnd; this.typeDeclaration.bodyEnd = lastEnd; } return this.typeDeclaration; } /* * Update the corresponding parse node from parser state which * is about to disappear because of restarting recovery */ public void updateFromParserState(){ // anymous type and enum constant doesn't need to be updated if(bodyStartsAtHeaderEnd() && this.typeDeclaration.allocation == null){ Parser parser = parser(); /* might want to recover implemented interfaces */ // protection for bugs 15142 if (parser.listLength > 0 && parser.astLengthPtr > 0){ // awaiting interface type references int length = parser.astLengthStack[parser.astLengthPtr]; int astPtr = parser.astPtr - length; boolean canConsume = astPtr >= 0; if(canConsume) { if((!(parser.astStack[astPtr] instanceof TypeDeclaration))) { canConsume = false; } for (int i = 1, max = length + 1; i < max; i++) { if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) { canConsume = false; } } } if(canConsume) { parser.consumeClassHeaderImplements(); // 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; } } } } /* * A closing brace got consumed, might have closed the current element, * in which case both the currentElement is exited */ public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if ((--this.bracketBalance <= 0) && (this.parent != null)){ this.updateSourceEndIfNecessary(braceStart, braceEnd); this.bodyEnd = braceStart - 1; return this.parent; } return this; } /* * An opening brace got consumed, might be the expected opening one of the current element, * in which case the bodyStart is updated. */ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ /* in case the opening brace is not close enough to the signature, ignore it */ if (this.bracketBalance == 0){ /* if (parser.scanner.searchLineNumber(typeDeclaration.sourceEnd) != parser.scanner.searchLineNumber(braceEnd)){ */ Parser parser = parser(); switch(parser.lastIgnoredToken){ case -1 : case TokenNameextends : case TokenNameimplements : case TokenNameGREATER : case TokenNameRIGHT_SHIFT : case TokenNameUNSIGNED_RIGHT_SHIFT : if (parser.recoveredStaticInitializerStart == 0) break; //$FALL-THROUGH$ default: this.foundOpeningBrace = true; this.bracketBalance = 1; // pretend the brace was already there } } // might be an initializer if (this.bracketBalance == 1){ Block block = new Block(0); Parser parser = parser(); block.sourceStart = parser.scanner.startPosition; Initializer init; if (parser.recoveredStaticInitializerStart == 0){ init = new Initializer(block, ClassFileConstants.AccDefault); } else { init = new Initializer(block, ClassFileConstants.AccStatic); init.declarationSourceStart = parser.recoveredStaticInitializerStart; } init.bodyStart = parser.scanner.currentPosition; return this.add(init, 1); } return super.updateOnOpeningBrace(braceStart, braceEnd); } public void updateParseTree(){ updatedTypeDeclaration(0, new HashSet()); } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int start, int end){ if (this.typeDeclaration.declarationSourceEnd == 0){ this.bodyEnd = 0; this.typeDeclaration.declarationSourceEnd = end; this.typeDeclaration.bodyEnd = end; } } public void annotationsConsumed(Annotation[] consumedAnnotations) { RecoveredAnnotation[] keep = new RecoveredAnnotation[this.pendingAnnotationCount]; int numKeep = 0; int pendingCount = this.pendingAnnotationCount; int consumedLength = consumedAnnotations.length; outerLoop: for (int i = 0; i < pendingCount; i++) { Annotation pendingAnnotationAST = this.pendingAnnotations[i].annotation; for (int j = 0; j < consumedLength; j++) { if (consumedAnnotations[j] == pendingAnnotationAST) continue outerLoop; } keep[numKeep++] = this.pendingAnnotations[i]; } if (numKeep != this.pendingAnnotationCount) { this.pendingAnnotations = keep; this.pendingAnnotationCount = numKeep; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java0000644000175000001440000002637112212041344031662 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; /** * Internal structure for parsing recovery */ 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.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.util.Util; public class RecoveredElement { public RecoveredElement parent; public int bracketBalance; public boolean foundOpeningBrace; protected Parser recoveringParser; public RecoveredElement(RecoveredElement parent, int bracketBalance){ this(parent, bracketBalance, null); } public RecoveredElement(RecoveredElement parent, int bracketBalance, Parser parser){ this.parent = parent; this.bracketBalance = bracketBalance; this.recoveringParser = parser; } public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(annotationStart - 1)); return this.parent.addAnnotationName(identifierPtr, identifierLengthPtr, annotationStart, bracketBalanceValue); } /* * Record a method declaration */ public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(methodDeclaration.declarationSourceStart - 1)); return this.parent.add(methodDeclaration, bracketBalanceValue); } /* * Record a nested block declaration */ public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(nestedBlockDeclaration.sourceStart - 1)); return this.parent.add(nestedBlockDeclaration, bracketBalanceValue); } /* * Record a field declaration */ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1)); return this.parent.add(fieldDeclaration, bracketBalanceValue); } /* * Record an import reference */ public RecoveredElement add(ImportReference importReference, int bracketBalanceValue){ /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(importReference.declarationSourceStart - 1)); return this.parent.add(importReference, bracketBalanceValue); } /* * Record a local declaration */ public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1)); return this.parent.add(localDeclaration, bracketBalanceValue); } /* * Record a statement */ public RecoveredElement add(Statement statement, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore if (this instanceof RecoveredType) { TypeDeclaration typeDeclaration = ((RecoveredType) this).typeDeclaration; if (typeDeclaration != null && (typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291040, new X() { ??? if (statement.sourceStart > typeDeclaration.sourceStart && statement.sourceEnd < typeDeclaration.sourceEnd) { return this; } } } this.updateSourceEndIfNecessary(previousAvailableLineEnd(statement.sourceStart - 1)); return this.parent.add(statement, bracketBalanceValue); } /* * Record a type declaration */ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue){ /* default behavior is to delegate recording to parent if any */ resetPendingModifiers(); if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1)); return this.parent.add(typeDeclaration, bracketBalanceValue); } protected void addBlockStatement(RecoveredBlock recoveredBlock) { Block block = recoveredBlock.blockDeclaration; if(block.statements != null) { Statement[] statements = block.statements; for (int i = 0; i < statements.length; i++) { recoveredBlock.add(statements[i], 0); } } } public void addModifier(int flag, int modifiersSourceStart) { // default implementation: do nothing } /* * Answer the depth of this element, considering the parent link. */ public int depth(){ int depth = 0; RecoveredElement current = this; while ((current = current.parent) != null) depth++; return depth; } /* * Answer the enclosing method node, or null if none */ public RecoveredInitializer enclosingInitializer(){ RecoveredElement current = this; while (current != null){ if (current instanceof RecoveredInitializer){ return (RecoveredInitializer) current; } current = current.parent; } return null; } /* * Answer the enclosing method node, or null if none */ public RecoveredMethod enclosingMethod(){ RecoveredElement current = this; while (current != null){ if (current instanceof RecoveredMethod){ return (RecoveredMethod) current; } current = current.parent; } return null; } /* * Answer the enclosing type node, or null if none */ public RecoveredType enclosingType(){ RecoveredElement current = this; while (current != null){ if (current instanceof RecoveredType){ return (RecoveredType) current; } current = current.parent; } return null; } /* * Answer the closest specified parser */ public Parser parser(){ RecoveredElement current = this; while (current != null){ if (current.recoveringParser != null){ return current.recoveringParser; } current = current.parent; } return null; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return null; } public void resetPendingModifiers() { // default implementation: do nothing // recovered elements which have pending modifiers must override this method } /* * Iterate the enclosing blocks and tag them so as to preserve their content */ public void preserveEnclosingBlocks(){ RecoveredElement current = this; while (current != null){ if (current instanceof RecoveredBlock){ ((RecoveredBlock)current).preserveContent = true; } if (current instanceof RecoveredType){ // for anonymous types ((RecoveredType)current).preserveContent = true; } current = current.parent; } } /* * Answer the position of the previous line end if * there is nothing but spaces in between it and the * line end. Used to trim spaces on unclosed elements. */ public int previousAvailableLineEnd(int position){ Parser parser = parser(); if (parser == null) return position; Scanner scanner = parser.scanner; if (scanner.lineEnds == null) return position; int index = Util.getLineNumber(position, scanner.lineEnds, 0, scanner.linePtr); if (index < 2) return position; int previousLineEnd = scanner.lineEnds[index-2]; char[] source = scanner.source; for (int i = previousLineEnd+1; i < position; i++){ if (!(source[i] == ' ' || source[i] == '\t')) return position; } return previousLineEnd; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return 0; } protected String tabString(int tab) { StringBuffer result = new StringBuffer(); for (int i = tab; i > 0; i--) { result.append(" "); //$NON-NLS-1$ } return result.toString(); } /* * Answer the top node */ public RecoveredElement topElement(){ RecoveredElement current = this; while (current.parent != null){ current = current.parent; } return current; } public String toString() { return toString(0); } public String toString(int tab) { return super.toString(); } /* * Answer the enclosing type node, or null if none */ public RecoveredType type(){ RecoveredElement current = this; while (current != null){ if (current instanceof RecoveredType){ return (RecoveredType) current; } current = current.parent; } return null; } /* * Update the bodyStart of the corresponding parse node */ public void updateBodyStart(int bodyStart){ this.foundOpeningBrace = true; } /* * Update the corresponding parse node from parser state which * is about to disappear because of restarting recovery */ public void updateFromParserState(){ // default implementation: do nothing } /* * A closing brace got consumed, might have closed the current element, * in which case both the currentElement is exited */ public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if ((--this.bracketBalance <= 0) && (this.parent != null)){ this.updateSourceEndIfNecessary(braceStart, braceEnd); return this.parent; } return this; } /* * An opening brace got consumed, might be the expected opening one of the current element, * in which case the bodyStart is updated. */ /*public RecoveredElement updateOnOpeningBrace(int braceEnd){return null;}*/ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ if (this.bracketBalance++ == 0){ updateBodyStart(braceEnd + 1); return this; } return null; // no update is necessary } /* * Final update the corresponding parse node */ public void updateParseTree(){ // default implementation: do nothing } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int braceStart, int braceEnd){ // default implementation: do nothing } public void updateSourceEndIfNecessary(int sourceEnd){ this.updateSourceEndIfNecessary(sourceEnd + 1, sourceEnd); } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.jav0000644000175000001440000002772512212041344032417 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import java.util.Set; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.ast.ASTNode; 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.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class RecoveredInitializer extends RecoveredField implements TerminalTokens { public RecoveredType[] localTypes; public int localTypeCount; public RecoveredBlock initializerBody; int pendingModifiers; int pendingModifersSourceStart = -1; RecoveredAnnotation[] pendingAnnotations; int pendingAnnotationCount; public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance){ this(fieldDeclaration, parent, bracketBalance, null); } public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){ super(fieldDeclaration, parent, bracketBalance, parser); this.foundOpeningBrace = true; } /* * Record a nested block declaration */ public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { /* default behavior is to delegate recording to parent if any, do not consider elements passed the known end (if set) it must be belonging to an enclosing element */ if (this.fieldDeclaration.declarationSourceEnd > 0 && nestedBlockDeclaration.sourceStart > this.fieldDeclaration.declarationSourceEnd){ resetPendingModifiers(); if (this.parent == null) return this; // ignore return this.parent.add(nestedBlockDeclaration, bracketBalanceValue); } /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } this.initializerBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); if (nestedBlockDeclaration.sourceEnd == 0) return this.initializerBody; return this; } /* * Record a field declaration (act like inside method body) */ public RecoveredElement add(FieldDeclaration newFieldDeclaration, int bracketBalanceValue) { resetPendingModifiers(); /* local variables inside initializer can only be final and non void */ char[][] fieldTypeName; if ((newFieldDeclaration.modifiers & ~ClassFileConstants.AccFinal) != 0 /* local var can only be final */ || (newFieldDeclaration.type == null) // initializer || ((fieldTypeName = newFieldDeclaration.type.getTypeName()).length == 1 // non void && CharOperation.equals(fieldTypeName[0], TypeBinding.VOID.sourceName()))){ if (this.parent == null) return this; // ignore this.updateSourceEndIfNecessary(previousAvailableLineEnd(newFieldDeclaration.declarationSourceStart - 1)); return this.parent.add(newFieldDeclaration, bracketBalanceValue); } /* default behavior is to delegate recording to parent if any, do not consider elements passed the known end (if set) it must be belonging to an enclosing element */ if (this.fieldDeclaration.declarationSourceEnd > 0 && newFieldDeclaration.declarationSourceStart > this.fieldDeclaration.declarationSourceEnd){ if (this.parent == null) return this; // ignore return this.parent.add(newFieldDeclaration, bracketBalanceValue); } // still inside initializer, treat as local variable return this; // ignore } /* * Record a local declaration - regular method should have been created a block body */ public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) { /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.fieldDeclaration.declarationSourceEnd != 0 && localDeclaration.declarationSourceStart > this.fieldDeclaration.declarationSourceEnd){ resetPendingModifiers(); if (this.parent == null) return this; // ignore return this.parent.add(localDeclaration, bracketBalanceValue); } /* method body should have been created */ Block block = new Block(0); block.sourceStart = ((Initializer)this.fieldDeclaration).sourceStart; RecoveredElement element = this.add(block, 1); if (this.initializerBody != null) { this.initializerBody.attachPendingModifiers( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); return element.add(localDeclaration, bracketBalanceValue); } /* * Record a statement - regular method should have been created a block body */ public RecoveredElement add(Statement statement, int bracketBalanceValue) { /* do not consider a statement starting passed the initializer end (if set) it must be belonging to an enclosing type */ if (this.fieldDeclaration.declarationSourceEnd != 0 && statement.sourceStart > this.fieldDeclaration.declarationSourceEnd){ resetPendingModifiers(); if (this.parent == null) return this; // ignore return this.parent.add(statement, bracketBalanceValue); } /* initializer body should have been created */ Block block = new Block(0); block.sourceStart = ((Initializer)this.fieldDeclaration).sourceStart; RecoveredElement element = this.add(block, 1); if (this.initializerBody != null) { this.initializerBody.attachPendingModifiers( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); return element.add(statement, bracketBalanceValue); } public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { /* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type */ if (this.fieldDeclaration.declarationSourceEnd != 0 && typeDeclaration.declarationSourceStart > this.fieldDeclaration.declarationSourceEnd){ resetPendingModifiers(); if (this.parent == null) return this; // ignore return this.parent.add(typeDeclaration, bracketBalanceValue); } if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0 || parser().methodRecoveryActivated || parser().statementRecoveryActivated){ /* method body should have been created */ Block block = new Block(0); block.sourceStart = ((Initializer)this.fieldDeclaration).sourceStart; RecoveredElement element = this.add(block, 1); if (this.initializerBody != null) { this.initializerBody.attachPendingModifiers( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); return element.add(typeDeclaration, bracketBalanceValue); } if (this.localTypes == null) { this.localTypes = new RecoveredType[5]; this.localTypeCount = 0; } else { if (this.localTypeCount == this.localTypes.length) { System.arraycopy( this.localTypes, 0, (this.localTypes = new RecoveredType[2 * this.localTypeCount]), 0, this.localTypeCount); } } RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); this.localTypes[this.localTypeCount++] = element; if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); /* consider that if the opening brace was not found, it is there */ if (!this.foundOpeningBrace){ this.foundOpeningBrace = true; this.bracketBalance++; } return element; } public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) { if (this.pendingAnnotations == null) { this.pendingAnnotations = new RecoveredAnnotation[5]; this.pendingAnnotationCount = 0; } else { if (this.pendingAnnotationCount == this.pendingAnnotations.length) { System.arraycopy( this.pendingAnnotations, 0, (this.pendingAnnotations = new RecoveredAnnotation[2 * this.pendingAnnotationCount]), 0, this.pendingAnnotationCount); } } RecoveredAnnotation element = new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue); this.pendingAnnotations[this.pendingAnnotationCount++] = element; return element; } public void addModifier(int flag, int modifiersSourceStart) { this.pendingModifiers |= flag; if (this.pendingModifersSourceStart < 0) { this.pendingModifersSourceStart = modifiersSourceStart; } } public void resetPendingModifiers() { this.pendingAnnotations = null; this.pendingAnnotationCount = 0; this.pendingModifiers = 0; this.pendingModifersSourceStart = -1; } public String toString(int tab) { StringBuffer result = new StringBuffer(tabString(tab)); result.append("Recovered initializer:\n"); //$NON-NLS-1$ this.fieldDeclaration.print(tab + 1, result); if (this.annotations != null) { for (int i = 0; i < this.annotationCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.annotations[i].toString(tab + 1)); } } if (this.initializerBody != null) { result.append("\n"); //$NON-NLS-1$ result.append(this.initializerBody.toString(tab + 1)); } return result.toString(); } public FieldDeclaration updatedFieldDeclaration(int depth, Set knownTypes){ if (this.initializerBody != null){ Block block = this.initializerBody.updatedBlock(depth, knownTypes); if (block != null){ Initializer initializer = (Initializer) this.fieldDeclaration; initializer.block = block; if (initializer.declarationSourceEnd == 0) { initializer.declarationSourceEnd = block.sourceEnd; initializer.bodyEnd = block.sourceEnd; } } if (this.localTypeCount > 0) this.fieldDeclaration.bits |= ASTNode.HasLocalType; } if (this.fieldDeclaration.sourceEnd == 0){ this.fieldDeclaration.sourceEnd = this.fieldDeclaration.declarationSourceEnd; } return this.fieldDeclaration; } /* * A closing brace got consumed, might have closed the current element, * in which case both the currentElement is exited */ public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if ((--this.bracketBalance <= 0) && (this.parent != null)){ this.updateSourceEndIfNecessary(braceStart, braceEnd); return this.parent; } return this; } /* * An opening brace got consumed, might be the expected opening one of the current element, * in which case the bodyStart is updated. */ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ this.bracketBalance++; return this; // request to restart } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int braceStart, int braceEnd){ if (this.fieldDeclaration.declarationSourceEnd == 0) { Initializer initializer = (Initializer)this.fieldDeclaration; if(parser().rBraceSuccessorStart >= braceEnd) { if (initializer.bodyStart < parser().rBraceEnd) { initializer.declarationSourceEnd = parser().rBraceEnd; } else { initializer.declarationSourceEnd = initializer.bodyStart; } if (initializer.bodyStart < parser().rBraceStart) { initializer.bodyEnd = parser().rBraceStart; } else { initializer.bodyEnd = initializer.bodyStart; } } else { initializer.declarationSourceEnd = braceEnd; initializer.bodyEnd = braceStart - 1; } if(initializer.block != null) { initializer.block.sourceEnd = initializer.declarationSourceEnd; } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser7.rsc0000644000175000001440000000033612212041344027654 0ustar dokousers- "! N'*3)$#,&68;AHOQZf]`SETdijklmn/[_4FRVWX\cg+%o(.<h57=@IKY^ae PU?CD:M9GBbL0>Jpecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser6.rsc0000644000175000001440000000202012212041344027643 0ustar dokousers!Ǫ%lìÇé1O:Ù/¨rjig;: hCEGF17)Æ;)<;®07,+»ÁFGECh:;gijr¨17) Ö:9³1ÄŰè13zFGECh ;gij17r):ÒÐuû  ­›“㧦™˜1À'ôj: hTig;ýów~<Ç¿@î-ÕíÃ.O¥ÛH &“§¦™˜1¬ ASjig;: hÍvyš²Øõô6ÞÝ? 1¬m1#wµ7)ܧ¦™˜¹1ºCEFGyq§¦™˜¹1ºCEFGy·º¹â˜™¦§¸CEFG1̃k7)"1žpqšyCEFGáGFECž1ypqšðGFECyšqpž1¼šqpy1žCEFG·¹ºÏàCEFGqp1ß=ß1pqGFECànGFE1C5µ7)Ü1ÈÊ7)*7)1qp1žþ17)7)tecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser8.rsc0000644000175000001440000000121212212041344027647 0ustar dokousers—’˜‰‹Œ†‡é 9;<=?@DLPONUVWcXYZ[\]Ž‘^_`¸¦§¨©a·Š”ªwèøÊˆŸ ¡¢º½ëífžK•³´µ¶JçGæûÿ  -nowÎ{~Õ¦ßü–¾Mt‚ÍåùúÆÌIsuvx{Ž‘’“”•–—˜™š›œ|­®¯°±²ÇÈÖר   :pqy„A¯°s«ËÑÒÓáòrt}©¬¹ÄÅÙÚà%+8CFHdgmz|uƒ…“§¼ÀÂÏÔÛÝý(Qj‚¢¥€›œž£¤¥¨»¿ÁÃÉÜäñóôõ#$')*,./015>BEbiy~€ƒ…ˆŠ‹£¤¬³qrvxz™šÐÞâãêìîïðö÷þ!"&23467RSTehkl}„†‡‰ŒŸ ¡ª«­®±²1ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/diagnose/0000755000175000001440000000000012212041344027347 5ustar dokousers././@LongLink0000644000000000000000000000015112251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.0000644000175000001440000024771312212041344032274 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ 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.RecoveryScanner; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.util.Util; public class DiagnoseParser implements ParserBasicInformation, TerminalTokens { private static final boolean DEBUG = false; private boolean DEBUG_PARSECHECK = false; private static final int STACK_INCREMENT = 256; // private static final int ERROR_CODE = 1; private static final int BEFORE_CODE = 2; private static final int INSERTION_CODE = 3; private static final int INVALID_CODE = 4; private static final int SUBSTITUTION_CODE = 5; private static final int DELETION_CODE = 6; private static final int MERGE_CODE = 7; private static final int MISPLACED_CODE = 8; private static final int SCOPE_CODE = 9; private static final int SECONDARY_CODE = 10; private static final int EOF_CODE = 11; private static final int BUFF_UBOUND = 31; private static final int BUFF_SIZE = 32; 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; private int currentToken = 0; private int stackLength; private int stateStackTop; private int[] stack; private int[] locationStack; private int[] locationStartStack; private int tempStackTop; private int[] tempStack; private int prevStackTop; private int[] prevStack; private int nextStackTop; private int[] nextStack; private int scopeStackTop; private int[] scopeIndex; private int[] scopePosition; int[] list = new int[NUM_SYMBOLS + 1]; int[] buffer = new int[BUFF_SIZE]; private static final int NIL = -1; int[] stateSeen; int statePoolTop; StateInfo[] statePool; private Parser parser; private RecoveryScanner recoveryScanner; private boolean reportProblem; private static class RepairCandidate { public int symbol; public int location; public RepairCandidate(){ this.symbol = 0; this.location = 0; } } private static class PrimaryRepairInfo { public int distance; public int misspellIndex; public int code; public int bufferPosition; public int symbol; public PrimaryRepairInfo(){ this.distance = 0; this.misspellIndex = 0; this.code = 0; this.bufferPosition = 0; this.symbol = 0; } public PrimaryRepairInfo copy(){ PrimaryRepairInfo c = new PrimaryRepairInfo(); c.distance = this.distance; c.misspellIndex = this.misspellIndex; c.code = this.code; c.bufferPosition = this .bufferPosition; c.symbol = this.symbol; return c; } } static class SecondaryRepairInfo { public int code; public int distance; public int bufferPosition; public int stackPosition; public int numDeletions; public int symbol; boolean recoveryOnNextStack; } private static class StateInfo { int state; int next; public StateInfo(int state, int next){ this.state = state; this.next = next; } } public DiagnoseParser(Parser parser, int firstToken, int start, int end, CompilerOptions options) { this(parser, firstToken, start, end, Util.EMPTY_INT_ARRAY, Util.EMPTY_INT_ARRAY, Util.EMPTY_INT_ARRAY, options); } 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); this.recoveryScanner = parser.recoveryScanner; } private ProblemReporter problemReporter(){ return this.parser.problemReporter(); } private void reallocateStacks() { int old_stack_length = this.stackLength; this.stackLength += STACK_INCREMENT; if(old_stack_length == 0){ this.stack = new int[this.stackLength]; this.locationStack = new int[this.stackLength]; this.locationStartStack = new int[this.stackLength]; this.tempStack = new int[this.stackLength]; this.prevStack = new int[this.stackLength]; this.nextStack = new int[this.stackLength]; this.scopeIndex = new int[this.stackLength]; this.scopePosition = new int[this.stackLength]; } else { System.arraycopy(this.stack, 0, this.stack = new int[this.stackLength], 0, old_stack_length); System.arraycopy(this.locationStack, 0, this.locationStack = new int[this.stackLength], 0, old_stack_length); System.arraycopy(this.locationStartStack, 0, this.locationStartStack = new int[this.stackLength], 0, old_stack_length); System.arraycopy(this.tempStack, 0, this.tempStack = new int[this.stackLength], 0, old_stack_length); System.arraycopy(this.prevStack, 0, this.prevStack = new int[this.stackLength], 0, old_stack_length); System.arraycopy(this.nextStack, 0, this.nextStack = new int[this.stackLength], 0, old_stack_length); System.arraycopy(this.scopeIndex, 0, this.scopeIndex = new int[this.stackLength], 0, old_stack_length); System.arraycopy(this.scopePosition, 0, this.scopePosition = new int[this.stackLength], 0, old_stack_length); } return; } public void diagnoseParse(boolean record) { this.reportProblem = true; boolean oldRecord = false; if(this.recoveryScanner != null) { oldRecord = this.recoveryScanner.record; this.recoveryScanner.record = record; } try { this.lexStream.reset(); this.currentToken = this.lexStream.getToken(); int prev_pos; int pos; int next_pos; int act = START_STATE; reallocateStacks(); // // Start parsing // this.stateStackTop = 0; this.stack[this.stateStackTop] = act; int tok = this.lexStream.kind(this.currentToken); this.locationStack[this.stateStackTop] = this.currentToken; this.locationStartStack[this.stateStackTop] = this.lexStream.start(this.currentToken); boolean forceRecoveryAfterLBracketMissing = false; // int forceRecoveryToken = -1; // // Process a terminal // do { // // Synchronize state stacks and update the location stack // prev_pos = -1; this.prevStackTop = -1; next_pos = -1; this.nextStackTop = -1; pos = this.stateStackTop; this.tempStackTop = this.stateStackTop - 1; for (int i = 0; i <= this.stateStackTop; i++) this.tempStack[i] = this.stack[i]; act = Parser.tAction(act, tok); // // When a reduce action is encountered, we compute all REDUCE // and associated goto actions induced by the current token. // Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is // computed... // while (act <= NUM_RULES) { do { this.tempStackTop -= (Parser.rhs[act]-1); act = Parser.ntAction(this.tempStack[this.tempStackTop], Parser.lhs[act]); } while(act <= NUM_RULES); // // ... Update the maximum useful position of the // (STATE_)STACK, push goto state into stack, and // compute next action on current symbol ... // if (this.tempStackTop + 1 >= this.stackLength) reallocateStacks(); pos = pos < this.tempStackTop ? pos : this.tempStackTop; this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } // // At this point, we have a shift, shift-reduce, accept or error // action. STACK contains the configuration of the state stack // prior to executing any action on curtok. next_stack contains // the configuration of the state stack after executing all // reduce actions induced by curtok. The variable pos indicates // the highest position in STACK that is still useful after the // reductions are executed. // while(act > ERROR_ACTION || act < ACCEPT_ACTION) { // SHIFT-REDUCE action or SHIFT action ? this.nextStackTop = this.tempStackTop + 1; for (int i = next_pos + 1; i <= this.nextStackTop; i++) this.nextStack[i] = this.tempStack[i]; for (int i = pos + 1; i <= this.nextStackTop; i++) { this.locationStack[i] = this.locationStack[this.stateStackTop]; this.locationStartStack[i] = this.locationStartStack[this.stateStackTop]; } // // If we have a shift-reduce, process it as well as // the goto-reduce actions that follow it. // if (act > ERROR_ACTION) { act -= ERROR_ACTION; do { this.nextStackTop -= (Parser.rhs[act]-1); act = Parser.ntAction(this.nextStack[this.nextStackTop], Parser.lhs[act]); } while(act <= NUM_RULES); pos = pos < this.nextStackTop ? pos : this.nextStackTop; } if (this.nextStackTop + 1 >= this.stackLength) reallocateStacks(); this.tempStackTop = this.nextStackTop; this.nextStack[++this.nextStackTop] = act; next_pos = this.nextStackTop; // // Simulate the parser through the next token without // destroying STACK or next_stack. // this.currentToken = this.lexStream.getToken(); tok = this.lexStream.kind(this.currentToken); act = Parser.tAction(act, tok); while(act <= NUM_RULES) { // // ... Process all goto-reduce actions following // reduction, until a goto action is computed ... // do { int lhs_symbol = Parser.lhs[act]; if(DEBUG) { System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); } this.tempStackTop -= (Parser.rhs[act]-1); act = (this.tempStackTop > next_pos ? this.tempStack[this.tempStackTop] : this.nextStack[this.tempStackTop]); act = Parser.ntAction(act, lhs_symbol); } while(act <= NUM_RULES); // // ... Update the maximum useful position of the // (STATE_)STACK, push GOTO state into stack, and // compute next action on current symbol ... // if (this.tempStackTop + 1 >= this.stackLength) reallocateStacks(); next_pos = next_pos < this.tempStackTop ? next_pos : this.tempStackTop; this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } // if((tok != TokenNameRBRACE || (forceRecoveryToken != currentToken && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0)) // && (lexStream.flags(currentToken) & LexStream.IS_AFTER_JUMP) !=0) { // act = ERROR_ACTION; // if(forceRecoveryToken != currentToken // && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0) { // forceRecoveryAfterLBracketMissing = true; // forceRecoveryToken = currentToken; // } // } // // No error was detected, Read next token into // PREVTOK element, advance CURTOK pointer and // update stacks. // if (act != ERROR_ACTION) { this.prevStackTop = this.stateStackTop; for (int i = prev_pos + 1; i <= this.prevStackTop; i++) this.prevStack[i] = this.stack[i]; prev_pos = pos; this.stateStackTop = this.nextStackTop; for (int i = pos + 1; i <= this.stateStackTop; i++) this.stack[i] = this.nextStack[i]; this.locationStack[this.stateStackTop] = this.currentToken; this.locationStartStack[this.stateStackTop] = this.lexStream.start(this.currentToken); pos = next_pos; } } // // At this stage, either we have an ACCEPT or an ERROR // action. // if (act == ERROR_ACTION) { // // An error was detected. // RepairCandidate candidate = errorRecovery(this.currentToken, forceRecoveryAfterLBracketMissing); forceRecoveryAfterLBracketMissing = false; if(this.parser.reportOnlyOneSyntaxError) { return; } if(this.parser.problemReporter().options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) { if(this.recoveryScanner == null || !this.recoveryScanner.record) return; this.reportProblem = false; } act = this.stack[this.stateStackTop]; // // If the recovery was successful on a nonterminal candidate, // parse through that candidate and "read" the next token. // if (candidate.symbol == 0) { break; } else if (candidate.symbol > NT_OFFSET) { int lhs_symbol = candidate.symbol - NT_OFFSET; if(DEBUG) { System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); } act = Parser.ntAction(act, lhs_symbol); while(act <= NUM_RULES) { this.stateStackTop -= (Parser.rhs[act]-1); act = Parser.ntAction(this.stack[this.stateStackTop], Parser.lhs[act]); } this.stack[++this.stateStackTop] = act; this.currentToken = this.lexStream.getToken(); tok = this.lexStream.kind(this.currentToken); this.locationStack[this.stateStackTop] = this.currentToken; this.locationStartStack[this.stateStackTop] = this.lexStream.start(this.currentToken); } else { tok = candidate.symbol; this.locationStack[this.stateStackTop] = candidate.location; this.locationStartStack[this.stateStackTop] = this.lexStream.start(candidate.location); } } } while (act != ACCEPT_ACTION); } finally { if(this.recoveryScanner != null) { this.recoveryScanner.record = oldRecord; } } return; } private static char[] displayEscapeCharacters(char[] tokenSource, int start, int end) { StringBuffer tokenSourceBuffer = new StringBuffer(); for (int i = 0; i < start; i++) { tokenSourceBuffer.append(tokenSource[i]); } for (int i = start; i < end; i++) { char c = tokenSource[i]; switch (c) { case '\r' : tokenSourceBuffer.append("\\r"); //$NON-NLS-1$ break; case '\n' : tokenSourceBuffer.append("\\n"); //$NON-NLS-1$ break; case '\b' : tokenSourceBuffer.append("\\b"); //$NON-NLS-1$ break; case '\t' : tokenSourceBuffer.append("\t"); //$NON-NLS-1$ break; case '\f' : tokenSourceBuffer.append("\\f"); //$NON-NLS-1$ break; case '\"' : tokenSourceBuffer.append("\\\""); //$NON-NLS-1$ break; case '\'' : tokenSourceBuffer.append("\\'"); //$NON-NLS-1$ break; case '\\' : tokenSourceBuffer.append("\\\\"); //$NON-NLS-1$ break; default : tokenSourceBuffer.append(c); } } for (int i = end; i < tokenSource.length; i++) { tokenSourceBuffer.append(tokenSource[i]); } return tokenSourceBuffer.toString().toCharArray(); } // // This routine is invoked when an error is encountered. It // tries to diagnose the error and recover from it. If it is // successful, the state stack, the current token and the buffer // are readjusted; i.e., after a successful recovery, // state_stack_top points to the location in the state stack // that contains the state on which to recover; curtok // identifies the symbol on which to recover. // // Up to three configurations may be available when this routine // is invoked. PREV_STACK may contain the sequence of states // preceding any action on prevtok, STACK always contains the // sequence of states preceding any action on curtok, and // NEXT_STACK may contain the sequence of states preceding any // action on the successor of curtok. // private RepairCandidate errorRecovery(int error_token, boolean forcedError) { this.errorToken = error_token; this.errorTokenStart = this.lexStream.start(error_token); int prevtok = this.lexStream.previous(error_token); int prevtokKind = this.lexStream.kind(prevtok); if(forcedError) { int name_index = Parser.terminal_index[TokenNameLBRACE]; reportError(INSERTION_CODE, name_index, prevtok, prevtok); RepairCandidate candidate = new RepairCandidate(); candidate.symbol = TokenNameLBRACE; candidate.location = error_token; this.lexStream.reset(error_token); this.stateStackTop = this.nextStackTop; for (int j = 0; j <= this.stateStackTop; j++) { this.stack[j] = this.nextStack[j]; } this.locationStack[this.stateStackTop] = error_token; this.locationStartStack[this.stateStackTop] = this.lexStream.start(error_token); return candidate; } // // Try primary phase recoveries. If not successful, try secondary // phase recoveries. If not successful and we are at end of the // file, we issue the end-of-file error and quit. Otherwise, ... // RepairCandidate candidate = primaryPhase(error_token); if (candidate.symbol != 0) { return candidate; } candidate = secondaryPhase(error_token); if (candidate.symbol != 0) { return candidate; } if (this.lexStream.kind(error_token) == EOFT_SYMBOL) { reportError(EOF_CODE, Parser.terminal_index[EOFT_SYMBOL], prevtok, prevtok); candidate.symbol = 0; candidate.location = error_token; return candidate; } // // At this point, primary and (initial attempt at) secondary // recovery did not work. We will now get into "panic mode" and // keep trying secondary phase recoveries until we either find // a successful recovery or have consumed the remaining input // tokens. // while(this.lexStream.kind(this.buffer[BUFF_UBOUND]) != EOFT_SYMBOL) { candidate = secondaryPhase(this.buffer[MAX_DISTANCE - MIN_DISTANCE + 2]); if (candidate.symbol != 0) { return candidate; } } // // We reached the end of the file while panicking. Delete all // remaining tokens in the input. // int i; for (i = BUFF_UBOUND; this.lexStream.kind(this.buffer[i]) == EOFT_SYMBOL; i--){/*empty*/} reportError(DELETION_CODE, Parser.terminal_index[prevtokKind],//Parser.terminal_index[lexStream.kind(prevtok)], error_token, this.buffer[i]); candidate.symbol = 0; candidate.location = this.buffer[i]; return candidate; } // // This function tries primary and scope recovery on each // available configuration. If a successful recovery is found // and no secondary phase recovery can do better, a diagnosis is // issued, the configuration is updated and the function returns // "true". Otherwise, it returns "false". // private RepairCandidate primaryPhase(int error_token) { PrimaryRepairInfo repair = new PrimaryRepairInfo(); RepairCandidate candidate = new RepairCandidate(); // // Initialize the buffer. // int i = (this.nextStackTop >= 0 ? 3 : 2); this.buffer[i] = error_token; for (int j = i; j > 0; j--) this.buffer[j - 1] = this.lexStream.previous(this.buffer[j]); for (int k = i + 1; k < BUFF_SIZE; k++) this.buffer[k] = this.lexStream.next(this.buffer[k - 1]); // // If NEXT_STACK_TOP > 0 then the parse was successful on CURTOK // and the error was detected on the successor of CURTOK. In // that case, first check whether or not primary recovery is // possible on next_stack ... // if (this.nextStackTop >= 0) { repair.bufferPosition = 3; repair = checkPrimaryDistance(this.nextStack, this.nextStackTop, repair); } // // ... Next, try primary recovery on the current token... // PrimaryRepairInfo new_repair = repair.copy(); new_repair.bufferPosition = 2; new_repair = checkPrimaryDistance(this.stack, this.stateStackTop, new_repair); if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) { repair = new_repair; } // // Finally, if prev_stack_top >= 0 then try primary recovery on // the prev_stack configuration. // if (this.prevStackTop >= 0) { new_repair = repair.copy(); new_repair.bufferPosition = 1; new_repair = checkPrimaryDistance(this.prevStack,this.prevStackTop, new_repair); if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) { repair = new_repair; } } // // Before accepting the best primary phase recovery obtained, // ensure that we cannot do better with a similar secondary // phase recovery. // if (this.nextStackTop >= 0) {// next_stack available if (secondaryCheck(this.nextStack,this.nextStackTop,3,repair.distance)) { return candidate; } } else if (secondaryCheck(this.stack, this.stateStackTop, 2, repair.distance)) { return candidate; } // // First, adjust distance if the recovery is on the error token; // it is important that the adjustment be made here and not at // each primary trial to prevent the distance tests from being // biased in favor of deferred recoveries which have access to // more input tokens... // repair.distance = repair.distance - repair.bufferPosition + 1; // // ...Next, adjust the distance if the recovery is a deletion or // (some form of) substitution... // if (repair.code == INVALID_CODE || repair.code == DELETION_CODE || repair.code == SUBSTITUTION_CODE || repair.code == MERGE_CODE) { repair.distance--; } // // ... After adjustment, check if the most successful primary // recovery can be applied. If not, continue with more radical // recoveries... // if (repair.distance < MIN_DISTANCE) { return candidate; } // // When processing an insertion error, if the token preceeding // the error token is not available, we change the repair code // into a BEFORE_CODE to instruct the reporting routine that it // indicates that the repair symbol should be inserted before // the error token. // if (repair.code == INSERTION_CODE) { if (this.buffer[repair.bufferPosition - 1] == 0) { repair.code = BEFORE_CODE; } } // // Select the proper sequence of states on which to recover, // update stack accordingly and call diagnostic routine. // if (repair.bufferPosition == 1) { this.stateStackTop = this.prevStackTop; for (int j = 0; j <= this.stateStackTop; j++) { this.stack[j] = this.prevStack[j]; } } else if (this.nextStackTop >= 0 && repair.bufferPosition >= 3) { this.stateStackTop = this.nextStackTop; for (int j = 0; j <= this.stateStackTop; j++) { this.stack[j] = this.nextStack[j]; } this.locationStack[this.stateStackTop] = this.buffer[3]; this.locationStartStack[this.stateStackTop] = this.lexStream.start(this.buffer[3]); } return primaryDiagnosis(repair); } // // This function checks whether or not a given state has a // candidate, whose string representaion is a merging of the two // tokens at positions buffer_position and buffer_position+1 in // the buffer. If so, it returns the candidate in question; // otherwise it returns 0. // private int mergeCandidate(int state, int buffer_position) { char[] name1 = this.lexStream.name(this.buffer[buffer_position]); char[] name2 = this.lexStream.name(this.buffer[buffer_position + 1]); int len = name1.length + name2.length; char[] str = CharOperation.concat(name1, name2); for (int k = Parser.asi(state); Parser.asr[k] != 0; k++) { int l = Parser.terminal_index[Parser.asr[k]]; if (len == Parser.name[l].length()) { char[] name = Parser.name[l].toCharArray(); if (CharOperation.equals(str, name, false)) { return Parser.asr[k]; } } } return 0; } // // This procedure takes as arguments a parsing configuration // consisting of a state stack (stack and stack_top) and a fixed // number of input tokens (starting at buffer_position) in the // input BUFFER; and some reference arguments: repair_code, // distance, misspell_index, candidate, and stack_position // which it sets based on the best possible recovery that it // finds in the given configuration. The effectiveness of a // a repair is judged based on two criteria: // // 1) the number of tokens that can be parsed after the repair // is applied: distance. // 2) how close to perfection is the candidate that is chosen: // misspell_index. // When this procedure is entered, distance, misspell_index and // repair_code are assumed to be initialized. // private PrimaryRepairInfo checkPrimaryDistance(int stck[], int stack_top, PrimaryRepairInfo repair) { int i, j, k, next_state, max_pos, act, root, symbol, tok; // // First, try scope and manual recovery. // PrimaryRepairInfo scope_repair = scopeTrial(stck, stack_top, repair.copy()); if (scope_repair.distance > repair.distance) repair = scope_repair; // // Next, try merging the error token with its successor. // if(this.buffer[repair.bufferPosition] != 0 && this.buffer[repair.bufferPosition + 1] != 0) {// do not merge the first token symbol = mergeCandidate(stck[stack_top], repair.bufferPosition); if (symbol != 0) { j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+2); if ((j > repair.distance) || (j == repair.distance && repair.misspellIndex < 10)) { repair.misspellIndex = 10; repair.symbol = symbol; repair.distance = j; repair.code = MERGE_CODE; } } } // // Next, try deletion of the error token. // j = parseCheck( stck, stack_top, this.lexStream.kind(this.buffer[repair.bufferPosition + 1]), repair.bufferPosition + 2); if (this.lexStream.kind(this.buffer[repair.bufferPosition]) == EOLT_SYMBOL && this.lexStream.afterEol(this.buffer[repair.bufferPosition+1])) { k = 10; } else { k = 0; } if (j > repair.distance || (j == repair.distance && k > repair.misspellIndex)) { repair.misspellIndex = k; repair.code = DELETION_CODE; repair.distance = j; } // // Update the error configuration by simulating all reduce and // goto actions induced by the error token. Then assign the top // most state of the new configuration to next_state. // next_state = stck[stack_top]; max_pos = stack_top; this.tempStackTop = stack_top - 1; tok = this.lexStream.kind(this.buffer[repair.bufferPosition]); this.lexStream.reset(this.buffer[repair.bufferPosition + 1]); act = Parser.tAction(next_state, tok); while(act <= NUM_RULES) { do { this.tempStackTop -= (Parser.rhs[act]-1); symbol = Parser.lhs[act]; act = (this.tempStackTop > max_pos ? this.tempStack[this.tempStackTop] : stck[this.tempStackTop]); act = Parser.ntAction(act, symbol); } while(act <= NUM_RULES); max_pos = max_pos < this.tempStackTop ? max_pos : this.tempStackTop; this.tempStack[this.tempStackTop + 1] = act; next_state = act; act = Parser.tAction(next_state, tok); } // // Next, place the list of candidates in proper order. // root = 0; for (i = Parser.asi(next_state); Parser.asr[i] != 0; i++) { symbol = Parser.asr[i]; if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL) { if (root == 0) { this.list[symbol] = symbol; } else { this.list[symbol] = this.list[root]; this.list[root] = symbol; } root = symbol; } } if (stck[stack_top] != next_state) { for (i = Parser.asi(stck[stack_top]); Parser.asr[i] != 0; i++) { symbol = Parser.asr[i]; if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL && this.list[symbol] == 0) { if (root == 0) { this.list[symbol] = symbol; } else { this.list[symbol] = this.list[root]; this.list[root] = symbol; } root = symbol; } } } i = this.list[root]; this.list[root] = 0; root = i; // // Next, try insertion for each possible candidate available in // the current state, except EOFT and ERROR_SYMBOL. // symbol = root; while(symbol != 0) { if (symbol == EOLT_SYMBOL && this.lexStream.afterEol(this.buffer[repair.bufferPosition])) { k = 10; } else { k = 0; } j = parseCheck(stck, stack_top, symbol, repair.bufferPosition); if (j > repair.distance) { repair.misspellIndex = k; repair.distance = j; repair.symbol = symbol; repair.code = INSERTION_CODE; } else if (j == repair.distance && k > repair.misspellIndex) { repair.misspellIndex = k; repair.distance = j; repair.symbol = symbol; repair.code = INSERTION_CODE; } symbol = this.list[symbol]; } // // Next, Try substitution for each possible candidate available // in the current state, except EOFT and ERROR_SYMBOL. // symbol = root; if(this.buffer[repair.bufferPosition] != 0) {// do not replace the first token while(symbol != 0) { if (symbol == EOLT_SYMBOL && this.lexStream.afterEol(this.buffer[repair.bufferPosition+1])) { k = 10; } else { k = misspell(symbol, this.buffer[repair.bufferPosition]); } j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1); if (j > repair.distance) { repair.misspellIndex = k; repair.distance = j; repair.symbol = symbol; repair.code = SUBSTITUTION_CODE; } else if (j == repair.distance && k > repair.misspellIndex) { repair.misspellIndex = k; repair.symbol = symbol; repair.code = SUBSTITUTION_CODE; } i = symbol; symbol = this.list[symbol]; this.list[i] = 0; // reset element } } // // Next, we try to insert a nonterminal candidate in front of the // error token, or substituting a nonterminal candidate for the // error token. Precedence is given to insertion. // for (i = Parser.nasi(stck[stack_top]); Parser.nasr[i] != 0; i++) { symbol = Parser.nasr[i] + NT_OFFSET; j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1); if (j > repair.distance) { repair.misspellIndex = 0; repair.distance = j; repair.symbol = symbol; repair.code = INVALID_CODE; } j = parseCheck(stck, stack_top, symbol, repair.bufferPosition); if ((j > repair.distance) || (j == repair.distance && repair.code == INVALID_CODE)) { repair.misspellIndex = 0; repair.distance = j; repair.symbol = symbol; repair.code = INSERTION_CODE; } } return repair; } // // This procedure is invoked to issue a diagnostic message and // adjust the input buffer. The recovery in question is either // the insertion of one or more scopes, the merging of the error // token with its successor, the deletion of the error token, // the insertion of a single token in front of the error token // or the substitution of another token for the error token. // private RepairCandidate primaryDiagnosis(PrimaryRepairInfo repair) { int name_index; // // Issue diagnostic. // int prevtok = this.buffer[repair.bufferPosition - 1]; int curtok = this.buffer[repair.bufferPosition]; switch(repair.code) { case INSERTION_CODE: case BEFORE_CODE: { if (repair.symbol > NT_OFFSET) name_index = getNtermIndex(this.stack[this.stateStackTop], repair.symbol, repair.bufferPosition); else name_index = getTermIndex(this.stack, this.stateStackTop, repair.symbol, repair.bufferPosition); int t = (repair.code == INSERTION_CODE ? prevtok : curtok); reportError(repair.code, name_index, t, t); break; } case INVALID_CODE: { name_index = getNtermIndex(this.stack[this.stateStackTop], repair.symbol, repair.bufferPosition + 1); reportError(repair.code, name_index, curtok, curtok); break; } case SUBSTITUTION_CODE: { if (repair.misspellIndex >= 6) name_index = Parser.terminal_index[repair.symbol]; else { name_index = getTermIndex(this.stack, this.stateStackTop, repair.symbol, repair.bufferPosition + 1); if (name_index != Parser.terminal_index[repair.symbol]) repair.code = INVALID_CODE; } reportError(repair.code, name_index, curtok, curtok); break; } case MERGE_CODE: { reportError(repair.code, Parser.terminal_index[repair.symbol], curtok, this.lexStream.next(curtok)); break; } case SCOPE_CODE: { for (int i = 0; i < this.scopeStackTop; i++) { reportError(repair.code, -this.scopeIndex[i], this.locationStack[this.scopePosition[i]], prevtok, Parser.non_terminal_index[Parser.scope_lhs[this.scopeIndex[i]]]); } repair.symbol = Parser.scope_lhs[this.scopeIndex[this.scopeStackTop]] + NT_OFFSET; this.stateStackTop = this.scopePosition[this.scopeStackTop]; reportError(repair.code, -this.scopeIndex[this.scopeStackTop], this.locationStack[this.scopePosition[this.scopeStackTop]], prevtok, getNtermIndex(this.stack[this.stateStackTop], repair.symbol, repair.bufferPosition) ); break; } default: {// deletion reportError(repair.code, Parser.terminal_index[ERROR_SYMBOL], curtok, curtok); } } // // Update buffer. // RepairCandidate candidate = new RepairCandidate(); switch (repair.code) { case INSERTION_CODE: case BEFORE_CODE: case SCOPE_CODE: { candidate.symbol = repair.symbol; candidate.location = this.buffer[repair.bufferPosition]; this.lexStream.reset(this.buffer[repair.bufferPosition]); break; } case INVALID_CODE: case SUBSTITUTION_CODE: { candidate.symbol = repair.symbol; candidate.location = this.buffer[repair.bufferPosition]; this.lexStream.reset(this.buffer[repair.bufferPosition + 1]); break; } case MERGE_CODE: { candidate.symbol = repair.symbol; candidate.location = this.buffer[repair.bufferPosition]; this.lexStream.reset(this.buffer[repair.bufferPosition + 2]); break; } default: {// deletion candidate.location = this.buffer[repair.bufferPosition + 1]; candidate.symbol = this.lexStream.kind(this.buffer[repair.bufferPosition + 1]); this.lexStream.reset(this.buffer[repair.bufferPosition + 2]); break; } } return candidate; } // // This function takes as parameter an integer STACK_TOP that // points to a STACK element containing the state on which a // primary recovery will be made; the terminal candidate on which // to recover; and an integer: buffer_position, which points to // the position of the next input token in the BUFFER. The // parser is simulated until a shift (or shift-reduce) action // is computed on the candidate. Then we proceed to compute the // the name index of the highest level nonterminal that can // directly or indirectly produce the candidate. // private int getTermIndex(int stck[], int stack_top, int tok, int buffer_position) { // // Initialize stack index of temp_stack and initialize maximum // position of state stack that is still useful. // int act = stck[stack_top], max_pos = stack_top, highest_symbol = tok; this.tempStackTop = stack_top - 1; // // Compute all reduce and associated actions induced by the // candidate until a SHIFT or SHIFT-REDUCE is computed. ERROR // and ACCEPT actions cannot be computed on the candidate in // this context, since we know that it is suitable for recovery. // this.lexStream.reset(this.buffer[buffer_position]); act = Parser.tAction(act, tok); while(act <= NUM_RULES) { // // Process all goto-reduce actions following reduction, // until a goto action is computed ... // do { this.tempStackTop -= (Parser.rhs[act]-1); int lhs_symbol = Parser.lhs[act]; act = (this.tempStackTop > max_pos ? this.tempStack[this.tempStackTop] : stck[this.tempStackTop]); act = Parser.ntAction(act, lhs_symbol); } while(act <= NUM_RULES); // // Compute new maximum useful position of (STATE_)stack, // push goto state into the stack, and compute next // action on candidate ... // max_pos = max_pos < this.tempStackTop ? max_pos : this.tempStackTop; this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } // // At this stage, we have simulated all actions induced by the // candidate and we are ready to shift or shift-reduce it. First, // set tok and next_ptr appropriately and identify the candidate // as the initial highest_symbol. If a shift action was computed // on the candidate, update the stack and compute the next // action. Next, simulate all actions possible on the next input // token until we either have to shift it or are about to reduce // below the initial starting point in the stack (indicated by // max_pos as computed in the previous loop). At that point, // return the highest_symbol computed. // this.tempStackTop++; // adjust top of stack to reflect last goto // next move is shift or shift-reduce. int threshold = this.tempStackTop; tok = this.lexStream.kind(this.buffer[buffer_position]); this.lexStream.reset(this.buffer[buffer_position + 1]); if (act > ERROR_ACTION) { // shift-reduce on candidate? act -= ERROR_ACTION; } else { this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } while(act <= NUM_RULES) { // // Process all goto-reduce actions following reduction, // until a goto action is computed ... // do { this.tempStackTop -= (Parser.rhs[act]-1); if (this.tempStackTop < threshold) { return (highest_symbol > NT_OFFSET ? Parser.non_terminal_index[highest_symbol - NT_OFFSET] : Parser.terminal_index[highest_symbol]); } int lhs_symbol = Parser.lhs[act]; if (this.tempStackTop == threshold) highest_symbol = lhs_symbol + NT_OFFSET; act = (this.tempStackTop > max_pos ? this.tempStack[this.tempStackTop] : stck[this.tempStackTop]); act = Parser.ntAction(act, lhs_symbol); } while(act <= NUM_RULES); this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } return (highest_symbol > NT_OFFSET ? Parser.non_terminal_index[highest_symbol - NT_OFFSET] : Parser.terminal_index[highest_symbol]); } // // This function takes as parameter a starting state number: // start, a nonterminal symbol, A (candidate), and an integer, // buffer_position, which points to the position of the next // input token in the BUFFER. // It returns the highest level non-terminal B such that // B =>*rm A. I.e., there does not exists a nonterminal C such // that C =>+rm B. (Recall that for an LALR(k) grammar if // C =>+rm B, it cannot be the case that B =>+rm C) // private int getNtermIndex(int start, int sym, int buffer_position) { int highest_symbol = sym - NT_OFFSET, tok = this.lexStream.kind(this.buffer[buffer_position]); this.lexStream.reset(this.buffer[buffer_position + 1]); // // Initialize stack index of temp_stack and initialize maximum // position of state stack that is still useful. // this.tempStackTop = 0; this.tempStack[this.tempStackTop] = start; int act = Parser.ntAction(start, highest_symbol); if (act > NUM_RULES) { // goto action? this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } while(act <= NUM_RULES) { // // Process all goto-reduce actions following reduction, // until a goto action is computed ... // do { this.tempStackTop -= (Parser.rhs[act]-1); if (this.tempStackTop < 0) return Parser.non_terminal_index[highest_symbol]; if (this.tempStackTop == 0) highest_symbol = Parser.lhs[act]; act = Parser.ntAction(this.tempStack[this.tempStackTop], Parser.lhs[act]); } while(act <= NUM_RULES); this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } return Parser.non_terminal_index[highest_symbol]; } // // Check whether or not there is a high probability that a // given string is a misspelling of another. // Certain singleton symbols (such as ":" and ";") are also // considered to be misspelling of each other. // private int misspell(int sym, int tok) { // // // char[] name = Parser.name[Parser.terminal_index[sym]].toCharArray(); int n = name.length; char[] s1 = new char[n + 1]; for (int k = 0; k < n; k++) { char c = name[k]; s1[k] = ScannerHelper.toLowerCase(c); } s1[n] = '\0'; // // // char[] tokenName = this.lexStream.name(tok); int len = tokenName.length; int m = len < MAX_NAME_LENGTH ? len : MAX_NAME_LENGTH; char[] s2 = new char[m + 1]; for (int k = 0; k < m; k++) { char c = tokenName[k]; s2[k] = ScannerHelper.toLowerCase(c); } s2[m] = '\0'; // // Singleton mispellings: // // ; <----> , // // ; <----> : // // . <----> , // // ' <----> " // // if (n == 1 && m == 1) { if ((s1[0] == ';' && s2[0] == ',') || (s1[0] == ',' && s2[0] == ';') || (s1[0] == ';' && s2[0] == ':') || (s1[0] == ':' && s2[0] == ';') || (s1[0] == '.' && s2[0] == ',') || (s1[0] == ',' && s2[0] == '.') || (s1[0] == '\'' && s2[0] == '\"') || (s1[0] == '\"' && s2[0] == '\'')) { return 3; } } // // Scan the two strings. Increment "match" count for each match. // When a transposition is encountered, increase "match" count // by two but count it as an error. When a typo is found, skip // it and count it as an error. Otherwise we have a mismatch; if // one of the strings is longer, increment its index, otherwise, // increment both indices and continue. // // This algorithm is an adaptation of a boolean misspelling // algorithm proposed by Juergen Uhl. // int count = 0; int prefix_length = 0; int num_errors = 0; int i = 0; int j = 0; while ((i < n) && (j < m)) { if (s1[i] == s2[j]) { count++; i++; j++; if (num_errors == 0) { prefix_length++; } } else if (s1[i+1] == s2[j] && s1[i] == s2[j+1]) { count += 2; i += 2; j += 2; num_errors++; } else if (s1[i+1] == s2[j+1]) { i++; j++; num_errors++; } else { if ((n - i) > (m - j)) { i++; } else if ((m - j) > (n - i)) { j++; } else { i++; j++; } num_errors++; } } if (i < n || j < m) num_errors++; if (num_errors > ((n < m ? n : m) / 6 + 1)) count = prefix_length; return(count * 10 / ((n < len ? len : n) + num_errors)); } private PrimaryRepairInfo scopeTrial(int stck[], int stack_top, PrimaryRepairInfo repair) { this.stateSeen = new int[this.stackLength]; for (int i = 0; i < this.stackLength; i++) this.stateSeen[i] = NIL; this.statePoolTop = 0; this.statePool = new StateInfo[this.stackLength]; scopeTrialCheck(stck, stack_top, repair, 0); this.stateSeen = null; this.statePoolTop = 0; repair.code = SCOPE_CODE; repair.misspellIndex = 10; return repair; } private void scopeTrialCheck(int stck[], int stack_top, PrimaryRepairInfo repair, int indx) { if(indx > 20) return; // avoid too much recursive call to improve performance int act = stck[stack_top]; for (int i = this.stateSeen[stack_top]; i != NIL; i = this.statePool[i].next) { if (this.statePool[i].state == act) return; } int old_state_pool_top = this.statePoolTop++; if(this.statePoolTop >= this.statePool.length) { System.arraycopy(this.statePool, 0, this.statePool = new StateInfo[this.statePoolTop * 2], 0, this.statePoolTop); } this.statePool[old_state_pool_top] = new StateInfo(act, this.stateSeen[stack_top]); this.stateSeen[stack_top] = old_state_pool_top; next : for (int i = 0; i < SCOPE_SIZE; i++) { // // Use the scope lookahead symbol to force all reductions // inducible by that symbol. // act = stck[stack_top]; this.tempStackTop = stack_top - 1; int max_pos = stack_top; int tok = Parser.scope_la[i]; this.lexStream.reset(this.buffer[repair.bufferPosition]); act = Parser.tAction(act, tok); while(act <= NUM_RULES) { // // ... Process all goto-reduce actions following // reduction, until a goto action is computed ... // do { this.tempStackTop -= (Parser.rhs[act]-1); int lhs_symbol = Parser.lhs[act]; act = (this.tempStackTop > max_pos ? this.tempStack[this.tempStackTop] : stck[this.tempStackTop]); act = Parser.ntAction(act, lhs_symbol); } while(act <= NUM_RULES); if (this.tempStackTop + 1 >= this.stackLength) return; max_pos = max_pos < this.tempStackTop ? max_pos : this.tempStackTop; this.tempStack[this.tempStackTop + 1] = act; act = Parser.tAction(act, tok); } // // If the lookahead symbol is parsable, then we check // whether or not we have a match between the scope // prefix and the transition symbols corresponding to // the states on top of the stack. // if (act != ERROR_ACTION) { int j, k; k = Parser.scope_prefix[i]; for (j = this.tempStackTop + 1; j >= (max_pos + 1) && Parser.in_symbol(this.tempStack[j]) == Parser.scope_rhs[k]; j--) { k++; } if (j == max_pos) { for (j = max_pos; j >= 1 && Parser.in_symbol(stck[j]) == Parser.scope_rhs[k]; j--) { k++; } } // // If the prefix matches, check whether the state // newly exposed on top of the stack, (after the // corresponding prefix states are popped from the // stack), is in the set of "source states" for the // scope in question and that it is at a position // below the threshold indicated by MARKED_POS. // int marked_pos = (max_pos < stack_top ? max_pos + 1 : stack_top); if (Parser.scope_rhs[k] == 0 && j < marked_pos) { // match? int stack_position = j; for (j = Parser.scope_state_set[i]; stck[stack_position] != Parser.scope_state[j] && Parser.scope_state[j] != 0; j++){/*empty*/} // // If the top state is valid for scope recovery, // the left-hand side of the scope is used as // starting symbol and we calculate how far the // parser can advance within the forward context // after parsing the left-hand symbol. // if (Parser.scope_state[j] != 0) { // state was found int previous_distance = repair.distance; int distance = parseCheck(stck, stack_position, Parser.scope_lhs[i]+NT_OFFSET, repair.bufferPosition); // // if the recovery is not successful, we // update the stack with all actions induced // by the left-hand symbol, and recursively // call SCOPE_TRIAL_CHECK to try again. // Otherwise, the recovery is successful. If // the new distance is greater than the // initial SCOPE_DISTANCE, we update // SCOPE_DISTANCE and set scope_stack_top to INDX // to indicate the number of scopes that are // to be applied for a succesful recovery. // NOTE that this procedure cannot get into // an infinite loop, since each prefix match // is guaranteed to take us to a lower point // within the stack. // if ((distance - repair.bufferPosition + 1) < MIN_DISTANCE) { int top = stack_position; act = Parser.ntAction(stck[top], Parser.scope_lhs[i]); while(act <= NUM_RULES) { if(Parser.rules_compliance[act] > this.options.sourceLevel) { continue next; } top -= (Parser.rhs[act]-1); act = Parser.ntAction(stck[top], Parser.lhs[act]); } top++; j = act; act = stck[top]; // save stck[top] = j; // swap scopeTrialCheck(stck, top, repair, indx+1); stck[top] = act; // restore } else if (distance > repair.distance) { this.scopeStackTop = indx; repair.distance = distance; } if (this.lexStream.kind(this.buffer[repair.bufferPosition]) == EOFT_SYMBOL && repair.distance == previous_distance) { this.scopeStackTop = indx; repair.distance = MAX_DISTANCE; } // // If this scope recovery has beaten the // previous distance, then we have found a // better recovery (or this recovery is one // of a list of scope recoveries). Record // its information at the proper location // (INDX) in SCOPE_INDEX and SCOPE_STACK. // if (repair.distance > previous_distance) { this.scopeIndex[indx] = i; this.scopePosition[indx] = stack_position; return; } } } } } } // // This function computes the ParseCheck distance for the best // possible secondary recovery for a given configuration that // either deletes none or only one symbol in the forward context. // If the recovery found is more effective than the best primary // recovery previously computed, then the function returns true. // Only misplacement, scope and manual recoveries are attempted; // simple insertion or substitution of a nonterminal are tried // in CHECK_PRIMARY_DISTANCE as part of primary recovery. // private boolean secondaryCheck(int stck[], int stack_top, int buffer_position, int distance) { int top, j; for (top = stack_top - 1; top >= 0; top--) { j = parseCheck(stck, top, this.lexStream.kind(this.buffer[buffer_position]), buffer_position + 1); if (((j - buffer_position + 1) > MIN_DISTANCE) && (j > distance)) return true; } PrimaryRepairInfo repair = new PrimaryRepairInfo(); repair.bufferPosition = buffer_position + 1; repair.distance = distance; repair = scopeTrial(stck, stack_top, repair); if ((repair.distance - buffer_position) > MIN_DISTANCE && repair.distance > distance) return true; return false; } // // Secondary_phase is a boolean function that checks whether or // not some form of secondary recovery is applicable to one of // the error configurations. First, if "next_stack" is available, // misplacement and secondary recoveries are attempted on it. // Then, in any case, these recoveries are attempted on "stack". // If a successful recovery is found, a diagnosis is issued, the // configuration is updated and the function returns "true". // Otherwise, the function returns false. // private RepairCandidate secondaryPhase(int error_token) { SecondaryRepairInfo repair = new SecondaryRepairInfo(); SecondaryRepairInfo misplaced = new SecondaryRepairInfo(); RepairCandidate candidate = new RepairCandidate(); int i, j, k, top; int next_last_index = 0; int last_index; candidate.symbol = 0; repair.code = 0; repair.distance = 0; repair.recoveryOnNextStack = false; misplaced.distance = 0; misplaced.recoveryOnNextStack = false; // // If the next_stack is available, try misplaced and secondary // recovery on it first. // if (this.nextStackTop >= 0) { int save_location; this.buffer[2] = error_token; this.buffer[1] = this.lexStream.previous(this.buffer[2]); this.buffer[0] = this.lexStream.previous(this.buffer[1]); for (k = 3; k < BUFF_UBOUND; k++) this.buffer[k] = this.lexStream.next(this.buffer[k - 1]); this.buffer[BUFF_UBOUND] = this.lexStream.badtoken();// elmt not available // // If we are at the end of the input stream, compute the // index position of the first EOFT symbol (last useful // index). // for (next_last_index = MAX_DISTANCE - 1; next_last_index >= 1 && this.lexStream.kind(this.buffer[next_last_index]) == EOFT_SYMBOL; next_last_index--){/*empty*/} next_last_index = next_last_index + 1; save_location = this.locationStack[this.nextStackTop]; int save_location_start = this.locationStartStack[this.nextStackTop]; this.locationStack[this.nextStackTop] = this.buffer[2]; this.locationStartStack[this.nextStackTop] = this.lexStream.start(this.buffer[2]); misplaced.numDeletions = this.nextStackTop; misplaced = misplacementRecovery(this.nextStack, this.nextStackTop, next_last_index, misplaced, true); if (misplaced.recoveryOnNextStack) misplaced.distance++; repair.numDeletions = this.nextStackTop + BUFF_UBOUND; repair = secondaryRecovery(this.nextStack, this.nextStackTop, next_last_index, repair, true); if (repair.recoveryOnNextStack) repair.distance++; this.locationStack[this.nextStackTop] = save_location; this.locationStartStack[this.nextStackTop] = save_location_start; } else { // next_stack not available, initialize ... misplaced.numDeletions = this.stateStackTop; repair.numDeletions = this.stateStackTop + BUFF_UBOUND; } // // Try secondary recovery on the "stack" configuration. // this.buffer[3] = error_token; this.buffer[2] = this.lexStream.previous(this.buffer[3]); this.buffer[1] = this.lexStream.previous(this.buffer[2]); this.buffer[0] = this.lexStream.previous(this.buffer[1]); for (k = 4; k < BUFF_SIZE; k++) this.buffer[k] = this.lexStream.next(this.buffer[k - 1]); for (last_index = MAX_DISTANCE - 1; last_index >= 1 && this.lexStream.kind(this.buffer[last_index]) == EOFT_SYMBOL; last_index--){/*empty*/} last_index++; misplaced = misplacementRecovery(this.stack, this.stateStackTop, last_index, misplaced, false); repair = secondaryRecovery(this.stack, this.stateStackTop, last_index, repair, false); // // If a successful misplaced recovery was found, compare it with // the most successful secondary recovery. If the misplaced // recovery either deletes fewer symbols or parse-checks further // then it is chosen. // if (misplaced.distance > MIN_DISTANCE) { if (misplaced.numDeletions <= repair.numDeletions || (misplaced.distance - misplaced.numDeletions) >= (repair.distance - repair.numDeletions)) { repair.code = MISPLACED_CODE; repair.stackPosition = misplaced.stackPosition; repair.bufferPosition = 2; repair.numDeletions = misplaced.numDeletions; repair.distance = misplaced.distance; repair.recoveryOnNextStack = misplaced.recoveryOnNextStack; } } // // If the successful recovery was on next_stack, update: stack, // buffer, location_stack and last_index. // if (repair.recoveryOnNextStack) { this.stateStackTop = this.nextStackTop; for (i = 0; i <= this.stateStackTop; i++) this.stack[i] = this.nextStack[i]; this.buffer[2] = error_token; this.buffer[1] = this.lexStream.previous(this.buffer[2]); this.buffer[0] = this.lexStream.previous(this.buffer[1]); for (k = 3; k < BUFF_UBOUND; k++) this.buffer[k] = this.lexStream.next(this.buffer[k - 1]); this.buffer[BUFF_UBOUND] = this.lexStream.badtoken();// elmt not available this.locationStack[this.nextStackTop] = this.buffer[2]; this.locationStartStack[this.nextStackTop] = this.lexStream.start(this.buffer[2]); last_index = next_last_index; } // // Next, try scope recoveries after deletion of one, two, three, // four ... buffer_position tokens from the input stream. // if (repair.code == SECONDARY_CODE || repair.code == DELETION_CODE) { PrimaryRepairInfo scope_repair = new PrimaryRepairInfo(); scope_repair.distance = 0; for (scope_repair.bufferPosition = 2; scope_repair.bufferPosition <= repair.bufferPosition && repair.code != SCOPE_CODE; scope_repair.bufferPosition++) { scope_repair = scopeTrial(this.stack, this.stateStackTop, scope_repair); j = (scope_repair.distance == MAX_DISTANCE ? last_index : scope_repair.distance); k = scope_repair.bufferPosition - 1; if ((j - k) > MIN_DISTANCE && (j - k) > (repair.distance - repair.numDeletions)) { repair.code = SCOPE_CODE; i = this.scopeIndex[this.scopeStackTop]; // upper bound repair.symbol = Parser.scope_lhs[i] + NT_OFFSET; repair.stackPosition = this.stateStackTop; repair.bufferPosition = scope_repair.bufferPosition; } } } // // If no successful recovery is found and we have reached the // end of the file, check whether or not scope recovery is // applicable at the end of the file after discarding some // states. // if (repair.code == 0 && this.lexStream.kind(this.buffer[last_index]) == EOFT_SYMBOL) { PrimaryRepairInfo scope_repair = new PrimaryRepairInfo(); scope_repair.bufferPosition = last_index; scope_repair.distance = 0; for (top = this.stateStackTop; top >= 0 && repair.code == 0; top--) { scope_repair = scopeTrial(this.stack, top, scope_repair); if (scope_repair.distance > 0) { repair.code = SCOPE_CODE; i = this.scopeIndex[this.scopeStackTop]; // upper bound repair.symbol = Parser.scope_lhs[i] + NT_OFFSET; repair.stackPosition = top; repair.bufferPosition = scope_repair.bufferPosition; } } } // // If a successful repair was not found, quit! Otherwise, issue // diagnosis and adjust configuration... // if (repair.code == 0) return candidate; secondaryDiagnosis(repair); // // Update buffer based on number of elements that are deleted. // switch(repair.code) { case MISPLACED_CODE: candidate.location = this.buffer[2]; candidate.symbol = this.lexStream.kind(this.buffer[2]); this.lexStream.reset(this.lexStream.next(this.buffer[2])); break; case DELETION_CODE: candidate.location = this.buffer[repair.bufferPosition]; candidate.symbol = this.lexStream.kind(this.buffer[repair.bufferPosition]); this.lexStream.reset(this.lexStream.next(this.buffer[repair.bufferPosition])); break; default: // SCOPE_CODE || SECONDARY_CODE candidate.symbol = repair.symbol; candidate.location = this.buffer[repair.bufferPosition]; this.lexStream.reset(this.buffer[repair.bufferPosition]); break; } return candidate; } // // This boolean function checks whether or not a given // configuration yields a better misplacement recovery than // the best misplacement recovery computed previously. // private SecondaryRepairInfo misplacementRecovery(int stck[], int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) { int previous_loc = this.buffer[2]; int stack_deletions = 0; for (int top = stack_top - 1; top >= 0; top--) { if (this.locationStack[top] < previous_loc) { stack_deletions++; } previous_loc = this.locationStack[top]; int j = parseCheck(stck, top, this.lexStream.kind(this.buffer[2]), 3); if (j == MAX_DISTANCE) { j = last_index; } if ((j > MIN_DISTANCE) && (j - stack_deletions) > (repair.distance - repair.numDeletions)) { repair.stackPosition = top; repair.distance = j; repair.numDeletions = stack_deletions; repair.recoveryOnNextStack = stack_flag; } } return repair; } // // This boolean function checks whether or not a given // configuration yields a better secondary recovery than the // best misplacement recovery computed previously. // private SecondaryRepairInfo secondaryRecovery(int stck[],int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) { int previous_loc; int stack_deletions = 0; previous_loc = this.buffer[2]; for (int top = stack_top; top >= 0 && repair.numDeletions >= stack_deletions; top--) { if (this.locationStack[top] < previous_loc) { stack_deletions++; } previous_loc = this.locationStack[top]; for (int i = 2; i <= (last_index - MIN_DISTANCE + 1) && (repair.numDeletions >= (stack_deletions + i - 1)); i++) { int j = parseCheck(stck, top, this.lexStream.kind(this.buffer[i]), i + 1); if (j == MAX_DISTANCE) { j = last_index; } if ((j - i + 1) > MIN_DISTANCE) { int k = stack_deletions + i - 1; if ((k < repair.numDeletions) || (j - k) > (repair.distance - repair.numDeletions) || ((repair.code == SECONDARY_CODE) && (j - k) == (repair.distance - repair.numDeletions))) { repair.code = DELETION_CODE; repair.distance = j; repair.stackPosition = top; repair.bufferPosition = i; repair.numDeletions = k; repair.recoveryOnNextStack = stack_flag; } } for (int l = Parser.nasi(stck[top]); l >= 0 && Parser.nasr[l] != 0; l++) { int symbol = Parser.nasr[l] + NT_OFFSET; j = parseCheck(stck, top, symbol, i); if (j == MAX_DISTANCE) { j = last_index; } if ((j - i + 1) > MIN_DISTANCE) { int k = stack_deletions + i - 1; if (k < repair.numDeletions || (j - k) > (repair.distance - repair.numDeletions)) { repair.code = SECONDARY_CODE; repair.symbol = symbol; repair.distance = j; repair.stackPosition = top; repair.bufferPosition = i; repair.numDeletions = k; repair.recoveryOnNextStack = stack_flag; } } } } } return repair; } // // This procedure is invoked to issue a secondary diagnosis and // adjust the input buffer. The recovery in question is either // an automatic scope recovery, a manual scope recovery, a // secondary substitution or a secondary deletion. // private void secondaryDiagnosis(SecondaryRepairInfo repair) { switch(repair.code) { case SCOPE_CODE: { if (repair.stackPosition < this.stateStackTop) { reportError(DELETION_CODE, Parser.terminal_index[ERROR_SYMBOL], this.locationStack[repair.stackPosition], this.buffer[1]); } for (int i = 0; i < this.scopeStackTop; i++) { reportError(SCOPE_CODE, -this.scopeIndex[i], this.locationStack[this.scopePosition[i]], this.buffer[1], Parser.non_terminal_index[Parser.scope_lhs[this.scopeIndex[i]]]); } repair.symbol = Parser.scope_lhs[this.scopeIndex[this.scopeStackTop]] + NT_OFFSET; this.stateStackTop = this.scopePosition[this.scopeStackTop]; reportError(SCOPE_CODE, -this.scopeIndex[this.scopeStackTop], this.locationStack[this.scopePosition[this.scopeStackTop]], this.buffer[1], getNtermIndex(this.stack[this.stateStackTop], repair.symbol, repair.bufferPosition) ); break; } default: { reportError(repair.code, (repair.code == SECONDARY_CODE ? getNtermIndex(this.stack[repair.stackPosition], repair.symbol, repair.bufferPosition) : Parser.terminal_index[ERROR_SYMBOL]), this.locationStack[repair.stackPosition], this.buffer[repair.bufferPosition - 1]); this.stateStackTop = repair.stackPosition; } } } // // Try to parse until first_token and all tokens in BUFFER have // been consumed, or an error is encountered. Return the number // of tokens that were expended before the parse blocked. // private int parseCheck(int stck[], int stack_top, int first_token, int buffer_position) { int max_pos; int indx; int ct; int act; // // Initialize pointer for temp_stack and initialize maximum // position of state stack that is still useful. // act = stck[stack_top]; if (first_token > NT_OFFSET) { this.tempStackTop = stack_top; if(this.DEBUG_PARSECHECK) { System.out.println(this.tempStackTop); } max_pos = stack_top; indx = buffer_position; ct = this.lexStream.kind(this.buffer[indx]); this.lexStream.reset(this.lexStream.next(this.buffer[indx])); int lhs_symbol = first_token - NT_OFFSET; act = Parser.ntAction(act, lhs_symbol); if (act <= NUM_RULES) { // same loop as 'process_non_terminal' do { this.tempStackTop -= (Parser.rhs[act]-1); if(this.DEBUG_PARSECHECK) { System.out.print(this.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 = (this.tempStackTop > max_pos ? this.tempStack[this.tempStackTop] : stck[this.tempStackTop]); act = Parser.ntAction(act, lhs_symbol); } while(act <= NUM_RULES); max_pos = max_pos < this.tempStackTop ? max_pos : this.tempStackTop; } } else { this.tempStackTop = stack_top - 1; if(this.DEBUG_PARSECHECK) { System.out.println(this.tempStackTop); } max_pos = this.tempStackTop; indx = buffer_position - 1; ct = first_token; this.lexStream.reset(this.buffer[buffer_position]); } process_terminal: for (;;) { if(this.DEBUG_PARSECHECK) { System.out.print(this.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 (++this.tempStackTop >= this.stackLength) // Stack overflow!!! return indx; this.tempStack[this.tempStackTop] = act; act = Parser.tAction(act, ct); if (act <= NUM_RULES) { // reduce action this.tempStackTop--; if(this.DEBUG_PARSECHECK) { System.out.print(this.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) return indx; indx++; ct = this.lexStream.kind(this.buffer[indx]); this.lexStream.reset(this.lexStream.next(this.buffer[indx])); if (act > ERROR_ACTION) { act -= ERROR_ACTION; if(this.DEBUG_PARSECHECK) { System.out.print(this.tempStackTop); System.out.print("\tshift reduce"); //$NON-NLS-1$ System.out.println(); } } else { if(this.DEBUG_PARSECHECK) { System.out.println("\tshift"); //$NON-NLS-1$ } continue process_terminal; } } else if (act == ACCEPT_ACTION) { // accept action return MAX_DISTANCE; } else { return indx; // error action } // same loop as first token initialization // process_non_terminal: do { this.tempStackTop -= (Parser.rhs[act]-1); if(this.DEBUG_PARSECHECK) { System.out.print(this.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 = (this.tempStackTop > max_pos ? this.tempStack[this.tempStackTop] : stck[this.tempStackTop]); act = Parser.ntAction(act, lhs_symbol); } while(act <= NUM_RULES); max_pos = max_pos < this.tempStackTop ? max_pos : this.tempStackTop; } // process_terminal; } private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken) { reportError(msgCode, nameIndex, leftToken, rightToken, 0); } private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken, int scopeNameIndex) { int lToken = (leftToken > rightToken ? rightToken : leftToken); if (lToken < rightToken) { reportSecondaryError(msgCode, nameIndex, lToken, rightToken, scopeNameIndex); } else { reportPrimaryError(msgCode, nameIndex, rightToken, scopeNameIndex); } } private void reportPrimaryError(int msgCode, int nameIndex, int token, int scopeNameIndex) { String name; if (nameIndex >= 0) { name = Parser.readableName[nameIndex]; } else { name = Util.EMPTY_STRING; } int errorStart = this.lexStream.start(token); int errorEnd = this.lexStream.end(token); int currentKind = this.lexStream.kind(token); String errorTokenName = Parser.name[Parser.terminal_index[this.lexStream.kind(token)]]; char[] errorTokenSource = this.lexStream.name(token); if (currentKind == TerminalTokens.TokenNameStringLiteral) { errorTokenSource = displayEscapeCharacters(errorTokenSource, 1, errorTokenSource.length - 1); } int addedToken = -1; if(this.recoveryScanner != null) { if (nameIndex >= 0) { addedToken = Parser.reverse_index[nameIndex]; } } switch(msgCode) { case BEFORE_CODE: if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.insertToken(addedToken, -1, errorStart); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.insertTokens(template, -1, errorStart); } } } if(this.reportProblem) problemReporter().parseErrorInsertBeforeToken( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName, name); break; case INSERTION_CODE: if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.insertToken(addedToken, -1, errorEnd); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.insertTokens(template, -1, errorEnd); } } } if(this.reportProblem) problemReporter().parseErrorInsertAfterToken( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName, name); break; case DELETION_CODE: if(this.recoveryScanner != null) { this.recoveryScanner.removeTokens(errorStart, errorEnd); } if(this.reportProblem) problemReporter().parseErrorDeleteToken( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName); break; case INVALID_CODE: if (name.length() == 0) { if(this.recoveryScanner != null) { this.recoveryScanner.removeTokens(errorStart, errorEnd); } if(this.reportProblem) problemReporter().parseErrorReplaceToken( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName, name); } else { if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.replaceTokens(template, errorStart, errorEnd); } } } if(this.reportProblem) problemReporter().parseErrorInvalidToken( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName, name); } break; case SUBSTITUTION_CODE: if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.replaceTokens(template, errorStart, errorEnd); } } } if(this.reportProblem) problemReporter().parseErrorReplaceToken( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName, name); break; case SCOPE_CODE: StringBuffer buf = new StringBuffer(); int[] addedTokens = null; int addedTokenCount = 0; if(this.recoveryScanner != null) { addedTokens = new int[Parser.scope_rhs.length - Parser.scope_suffix[- nameIndex]]; } for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) { buf.append(Parser.readableName[Parser.scope_rhs[i]]); if (Parser.scope_rhs[i + 1] != 0) // any more symbols to print? buf.append(' '); if(addedTokens != null) { int tmpAddedToken = Parser.reverse_index[Parser.scope_rhs[i]]; if (tmpAddedToken > -1) { int length = addedTokens.length; if(addedTokenCount == length) { System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); } addedTokens[addedTokenCount++] = tmpAddedToken; } else { int[] template = getNTermTemplate(-tmpAddedToken); if(template != null) { for (int j = 0; j < template.length; j++) { int length = addedTokens.length; if(addedTokenCount == length) { System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); } addedTokens[addedTokenCount++] = template[j]; } } else { addedTokenCount = 0; addedTokens = null; } } } } if(addedTokenCount > 0) { System.arraycopy(addedTokens, 0, addedTokens = new int[addedTokenCount], 0, addedTokenCount); int completedToken = -1; if(scopeNameIndex != 0) { completedToken = -Parser.reverse_index[scopeNameIndex]; } this.recoveryScanner.insertTokens(addedTokens, completedToken, errorEnd); } if (scopeNameIndex != 0) { if(this.reportProblem) problemReporter().parseErrorInsertToComplete( errorStart, errorEnd, buf.toString(), Parser.readableName[scopeNameIndex]); } else { if(this.reportProblem) problemReporter().parseErrorInsertToCompleteScope( errorStart, errorEnd, buf.toString()); } break; case EOF_CODE: if(this.reportProblem) problemReporter().parseErrorUnexpectedEnd( errorStart, errorEnd); break; case MERGE_CODE: if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.replaceTokens(template, errorStart, errorEnd); } } } if(this.reportProblem) problemReporter().parseErrorMergeTokens( errorStart, errorEnd, name); break; case MISPLACED_CODE: if(this.recoveryScanner != null) { this.recoveryScanner.removeTokens(errorStart, errorEnd); } if(this.reportProblem) problemReporter().parseErrorMisplacedConstruct( errorStart, errorEnd); break; default: if (name.length() == 0) { if(this.recoveryScanner != null) { this.recoveryScanner.removeTokens(errorStart, errorEnd); } if(this.reportProblem) problemReporter().parseErrorNoSuggestion( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName); } else { if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.replaceTokens(template, errorStart, errorEnd); } } } if(this.reportProblem) problemReporter().parseErrorReplaceToken( errorStart, errorEnd, currentKind, errorTokenSource, errorTokenName, name); } break; } } private void reportSecondaryError(int msgCode, int nameIndex, int leftToken, int rightToken, int scopeNameIndex) { String name; if (nameIndex >= 0) { name = Parser.readableName[nameIndex]; } else { name = Util.EMPTY_STRING; } int errorStart = -1; if(this.lexStream.isInsideStream(leftToken)) { if(leftToken == 0) { errorStart = this.lexStream.start(leftToken + 1); } else { errorStart = this.lexStream.start(leftToken); } } else { if(leftToken == this.errorToken) { errorStart = this.errorTokenStart; } else { for (int i = 0; i <= this.stateStackTop; i++) { if(this.locationStack[i] == leftToken) { errorStart = this.locationStartStack[i]; } } } if(errorStart == -1) { errorStart = this.lexStream.start(rightToken); } } int errorEnd = this.lexStream.end(rightToken); int addedToken = -1; if(this.recoveryScanner != null) { if (nameIndex >= 0) { addedToken = Parser.reverse_index[nameIndex]; } } switch(msgCode) { case MISPLACED_CODE: if(this.recoveryScanner != null) { this.recoveryScanner.removeTokens(errorStart, errorEnd); } if(this.reportProblem) problemReporter().parseErrorMisplacedConstruct( errorStart, errorEnd); break; case SCOPE_CODE: // error start is on the last token start errorStart = this.lexStream.start(rightToken); StringBuffer buf = new StringBuffer(); int[] addedTokens = null; int addedTokenCount = 0; if(this.recoveryScanner != null) { addedTokens = new int[Parser.scope_rhs.length - Parser.scope_suffix[- nameIndex]]; } for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) { buf.append(Parser.readableName[Parser.scope_rhs[i]]); if (Parser.scope_rhs[i+1] != 0) buf.append(' '); if(addedTokens != null) { int tmpAddedToken = Parser.reverse_index[Parser.scope_rhs[i]]; if (tmpAddedToken > -1) { int length = addedTokens.length; if(addedTokenCount == length) { System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); } addedTokens[addedTokenCount++] = tmpAddedToken; } else { int[] template = getNTermTemplate(-tmpAddedToken); if(template != null) { for (int j = 0; j < template.length; j++) { int length = addedTokens.length; if(addedTokenCount == length) { System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); } addedTokens[addedTokenCount++] = template[j]; } } else { addedTokenCount = 0; addedTokens = null; } } } } if(addedTokenCount > 0) { System.arraycopy(addedTokens, 0, addedTokens = new int[addedTokenCount], 0, addedTokenCount); int completedToken = -1; if(scopeNameIndex != 0) { completedToken = -Parser.reverse_index[scopeNameIndex]; } this.recoveryScanner.insertTokens(addedTokens, completedToken, errorEnd); } if (scopeNameIndex != 0) { if(this.reportProblem) problemReporter().parseErrorInsertToComplete( errorStart, errorEnd, buf.toString(), Parser.readableName[scopeNameIndex]); } else { if(this.reportProblem) problemReporter().parseErrorInsertToCompletePhrase( errorStart, errorEnd, buf.toString()); } break; case MERGE_CODE: if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.replaceTokens(template, errorStart, errorEnd); } } } if(this.reportProblem) problemReporter().parseErrorMergeTokens( errorStart, errorEnd, name); break; case DELETION_CODE: if(this.recoveryScanner != null) { this.recoveryScanner.removeTokens(errorStart, errorEnd); } if(this.reportProblem) problemReporter().parseErrorDeleteTokens( errorStart, errorEnd); break; default: if (name.length() == 0) { if(this.recoveryScanner != null) { this.recoveryScanner.removeTokens(errorStart, errorEnd); } if(this.reportProblem) problemReporter().parseErrorNoSuggestionForTokens( errorStart, errorEnd); } else { if(this.recoveryScanner != null) { if(addedToken > -1) { this.recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); } else { int[] template = getNTermTemplate(-addedToken); if(template != null) { this.recoveryScanner.replaceTokens(template, errorStart, errorEnd); } } } if(this.reportProblem) problemReporter().parseErrorReplaceTokens( errorStart, errorEnd, name); } } return; } private int[] getNTermTemplate(int sym) { int templateIndex = Parser.recovery_templates_index[sym]; if(templateIndex > 0) { int[] result = new int[Parser.recovery_templates.length]; int count = 0; for(int j = templateIndex; Parser.recovery_templates[j] != 0; j++) { result[count++] = Parser.recovery_templates[j]; } System.arraycopy(result, 0, result = new int[count], 0, count); return result; } else { return null; } } public String toString() { StringBuffer res = new StringBuffer(); res.append(this.lexStream.toString()); return res.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/diagnose/LexStream.java0000644000175000001440000002055712212041344032127 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser.diagnose; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.parser.Scanner; import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; import org.eclipse.jdt.internal.compiler.util.Util; public class LexStream implements TerminalTokens { public static final int IS_AFTER_JUMP = 1; public static final int LBRACE_MISSING = 2; public static class Token{ int kind; char[] name; int start; int end; int line; int flags; public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(this.name).append('[').append(this.kind).append(']'); buffer.append('{').append(this.start).append(',').append(this.end).append('}').append(this.line); return buffer.toString(); } } private int tokenCacheIndex; private int tokenCacheEOFIndex; private Token[] tokenCache; private int currentIndex = -1; private Scanner scanner; private int[] intervalStartToSkip; private int[] intervalEndToSkip; private int[] intervalFlagsToSkip; private int previousInterval = -1; private int currentInterval = -1; public LexStream(int size, Scanner scanner, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip, int firstToken, int init, int eof) { this.tokenCache = new Token[size]; this.tokenCacheIndex = 0; this.tokenCacheEOFIndex = Integer.MAX_VALUE; this.tokenCache[0] = new Token(); this.tokenCache[0].kind = firstToken; this.tokenCache[0].name = CharOperation.NO_CHAR; this.tokenCache[0].start = init; this.tokenCache[0].end = init; this.tokenCache[0].line = 0; this.intervalStartToSkip = intervalStartToSkip; this.intervalEndToSkip = intervalEndToSkip; this.intervalFlagsToSkip = intervalFlagsToSkip; scanner.resetTo(init, eof); this.scanner = scanner; } private void readTokenFromScanner(){ int length = this.tokenCache.length; boolean tokenNotFound = true; while(tokenNotFound) { try { int tokenKind = this.scanner.getNextToken(); if(tokenKind != TokenNameEOF) { int start = this.scanner.getCurrentTokenStartPosition(); int end = this.scanner.getCurrentTokenEndPosition(); int nextInterval = this.currentInterval + 1; if(this.intervalStartToSkip.length == 0 || nextInterval >= this.intervalStartToSkip.length || start < this.intervalStartToSkip[nextInterval]) { Token token = new Token(); token.kind = tokenKind; token.name = this.scanner.getCurrentTokenSource(); token.start = start; token.end = end; token.line = Util.getLineNumber(end, this.scanner.lineEnds, 0, this.scanner.linePtr); if(this.currentInterval != this.previousInterval && (this.intervalFlagsToSkip[this.currentInterval] & RangeUtil.IGNORE) == 0){ token.flags = IS_AFTER_JUMP; if((this.intervalFlagsToSkip[this.currentInterval] & RangeUtil.LBRACE_MISSING) != 0){ token.flags |= LBRACE_MISSING; } } this.previousInterval = this.currentInterval; this.tokenCache[++this.tokenCacheIndex % length] = token; tokenNotFound = false; } else { this.scanner.resetTo(this.intervalEndToSkip[++this.currentInterval] + 1, this.scanner.eofPosition - 1); } } else { int start = this.scanner.getCurrentTokenStartPosition(); int end = this.scanner.getCurrentTokenEndPosition(); Token token = new Token(); token.kind = tokenKind; token.name = CharOperation.NO_CHAR; token.start = start; token.end = end; token.line = Util.getLineNumber(end, this.scanner.lineEnds, 0, this.scanner.linePtr); this.tokenCache[++this.tokenCacheIndex % length] = token; this.tokenCacheEOFIndex = this.tokenCacheIndex; tokenNotFound = false; } } catch (InvalidInputException e) { // return next token } } } public Token token(int index) { if(index < 0) { Token eofToken = new Token(); eofToken.kind = TokenNameEOF; eofToken.name = CharOperation.NO_CHAR; return eofToken; } if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) { return token(this.tokenCacheEOFIndex); } int length = this.tokenCache.length; if(index > this.tokenCacheIndex) { int tokensToRead = index - this.tokenCacheIndex; while(tokensToRead-- != 0) { readTokenFromScanner(); } } else if(this.tokenCacheIndex - length >= index) { return null; } return this.tokenCache[index % length]; } public int getToken() { return this.currentIndex = next(this.currentIndex); } public int previous(int tokenIndex) { return tokenIndex > 0 ? tokenIndex - 1 : 0; } public int next(int tokenIndex) { return tokenIndex < this.tokenCacheEOFIndex ? tokenIndex + 1 : this.tokenCacheEOFIndex; } public boolean afterEol(int i) { return i < 1 ? true : line(i - 1) < line(i); } public void reset() { this.currentIndex = -1; } public void reset(int i) { this.currentIndex = previous(i); } public int badtoken() { return 0; } public int kind(int tokenIndex) { return token(tokenIndex).kind; } public char[] name(int tokenIndex) { return token(tokenIndex).name; } public int line(int tokenIndex) { return token(tokenIndex).line; } public int start(int tokenIndex) { return token(tokenIndex).start; } public int end(int tokenIndex) { return token(tokenIndex).end; } public int flags(int tokenIndex) { return token(tokenIndex).flags; } public boolean isInsideStream(int index) { if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) { return false; } else if(index > this.tokenCacheIndex) { return true; } else if(this.tokenCacheIndex - this.tokenCache.length >= index) { return false; } else { return true; } } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { StringBuffer res = new StringBuffer(); String source = new String(this.scanner.source); if(this.currentIndex < 0) { int previousEnd = -1; for (int i = 0; i < this.intervalStartToSkip.length; i++) { int intervalStart = this.intervalStartToSkip[i]; int intervalEnd = this.intervalEndToSkip[i]; res.append(source.substring(previousEnd + 1, intervalStart)); res.append('<'); res.append('@'); res.append(source.substring(intervalStart, intervalEnd + 1)); res.append('@'); res.append('>'); previousEnd = intervalEnd; } res.append(source.substring(previousEnd + 1)); } else { Token token = token(this.currentIndex); int curtokKind = token.kind; int curtokStart = token.start; int curtokEnd = token.end; int previousEnd = -1; for (int i = 0; i < this.intervalStartToSkip.length; i++) { int intervalStart = this.intervalStartToSkip[i]; int intervalEnd = this.intervalEndToSkip[i]; if(curtokStart >= previousEnd && curtokEnd <= intervalStart) { res.append(source.substring(previousEnd + 1, curtokStart)); res.append('<'); res.append('#'); res.append(source.substring(curtokStart, curtokEnd + 1)); res.append('#'); res.append('>'); res.append(source.substring(curtokEnd+1, intervalStart)); } else { res.append(source.substring(previousEnd + 1, intervalStart)); } res.append('<'); res.append('@'); res.append(source.substring(intervalStart, intervalEnd + 1)); res.append('@'); res.append('>'); previousEnd = intervalEnd; } if(curtokStart >= previousEnd) { res.append(source.substring(previousEnd + 1, curtokStart)); res.append('<'); res.append('#'); if(curtokKind == TokenNameEOF) { res.append("EOF#>"); //$NON-NLS-1$ } else { res.append(source.substring(curtokStart, curtokEnd + 1)); res.append('#'); res.append('>'); res.append(source.substring(curtokEnd+1)); } } else { res.append(source.substring(previousEnd + 1)); } } return res.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java0000644000175000001440000001343712212041344032114 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser.diagnose; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; public class RangeUtil { // flags public static final int NO_FLAG = 0; public static final int LBRACE_MISSING = 1; public static final int IGNORE = 2; static class RangeResult { private static final int INITIAL_SIZE = 10; int pos; int[] intervalStarts; int[] intervalEnds; int[] intervalFlags; RangeResult() { this.pos = 0; this.intervalStarts = new int[INITIAL_SIZE]; this.intervalEnds = new int[INITIAL_SIZE]; this.intervalFlags = new int[INITIAL_SIZE]; } void addInterval(int start, int end){ addInterval(start, end, NO_FLAG); } void addInterval(int start, int end, int flags){ if(this.pos >= this.intervalStarts.length) { System.arraycopy(this.intervalStarts, 0, this.intervalStarts = new int[this.pos * 2], 0, this.pos); System.arraycopy(this.intervalEnds, 0, this.intervalEnds = new int[this.pos * 2], 0, this.pos); System.arraycopy(this.intervalFlags, 0, this.intervalFlags = new int[this.pos * 2], 0, this.pos); } this.intervalStarts[this.pos] = start; this.intervalEnds[this.pos] = end; this.intervalFlags[this.pos] = flags; this.pos++; } int[][] getRanges() { int[] resultStarts = new int[this.pos]; int[] resultEnds = new int[this.pos]; int[] resultFlags = new int[this.pos]; System.arraycopy(this.intervalStarts, 0, resultStarts, 0, this.pos); System.arraycopy(this.intervalEnds, 0, resultEnds, 0, this.pos); System.arraycopy(this.intervalFlags, 0, resultFlags, 0, this.pos); if (resultStarts.length > 1) { quickSort(resultStarts, resultEnds, resultFlags, 0, resultStarts.length - 1); } return new int[][]{resultStarts, resultEnds, resultFlags}; } private void quickSort(int[] list, int[] list2, int[] list3, int left, int right) { int original_left= left; int original_right= right; int mid= list[left + (right - left) / 2]; do { while (compare(list[left], mid) < 0) { left++; } while (compare(mid, list[right]) < 0) { right--; } if (left <= right) { int tmp= list[left]; list[left]= list[right]; list[right]= tmp; tmp = list2[left]; list2[left]= list2[right]; list2[right]= tmp; tmp = list3[left]; list3[left]= list3[right]; list3[right]= tmp; left++; right--; } } while (left <= right); if (original_left < right) { quickSort(list, list2, list3, original_left, right); } if (left < original_right) { quickSort(list, list2, list3, left, original_right); } } private int compare(int i1, int i2) { return i1 - i2; } } public static boolean containsErrorInSignature(AbstractMethodDeclaration method){ return method.sourceEnd + 1 == method.bodyStart || method.bodyEnd == method.declarationSourceEnd; } public static int[][] computeDietRange(TypeDeclaration[] types) { if(types == null || types.length == 0) { return new int[3][0]; } else { RangeResult result = new RangeResult(); computeDietRange0(types, result); return result.getRanges(); } } private static void computeDietRange0(TypeDeclaration[] types, RangeResult result) { for (int j = 0; j < types.length; j++) { //members TypeDeclaration[] memberTypeDeclarations = types[j].memberTypes; if(memberTypeDeclarations != null && memberTypeDeclarations.length > 0) { computeDietRange0(types[j].memberTypes, result); } //methods AbstractMethodDeclaration[] methods = types[j].methods; if (methods != null) { int length = methods.length; for (int i = 0; i < length; i++) { AbstractMethodDeclaration method = methods[i]; if(containsIgnoredBody(method)) { if(containsErrorInSignature(method)) { method.bits |= ASTNode.ErrorInSignature; result.addInterval(method.declarationSourceStart, method.declarationSourceEnd, IGNORE); } else { int flags = method.sourceEnd + 1 == method.bodyStart ? LBRACE_MISSING : NO_FLAG; result.addInterval(method.bodyStart, method.bodyEnd, flags); } } } } //initializers FieldDeclaration[] fields = types[j].fields; if (fields != null) { int length = fields.length; for (int i = 0; i < length; i++) { if (fields[i] instanceof Initializer) { Initializer initializer = (Initializer)fields[i]; if(initializer.declarationSourceEnd == initializer.bodyEnd && initializer.declarationSourceStart != initializer.declarationSourceEnd){ initializer.bits |= ASTNode.ErrorInSignature; result.addInterval(initializer.declarationSourceStart, initializer.declarationSourceEnd, IGNORE); } else { result.addInterval(initializer.bodyStart, initializer.bodyEnd); } } } } } } public static boolean containsIgnoredBody(AbstractMethodDeclaration method){ return !method.isDefaultConstructor() && !method.isClinit() && (method.modifiers & ExtraCompilerModifiers.AccSemicolonBody) == 0; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/0000755000175000001440000000000012212041344027204 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/part1.rsc0000644000175000001440000002000012212041344030734 0ustar dokousers¿ÿÿÿÿÿÿ?ÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ‘¿ÿÿÿÿý?‡ÿÿþïðoÿÿãà<çÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÿëÿÞdßÿÿÿÿÿÿÿÿÿÿï{ÿÿÿßßç¿ÿÿÿÿÿýü_ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿ÷ÿÿÿ÷ÿÿýÿßÿÿÿßÿÿÿÿÿÿÿÿÿÿýÿÿÿýÿÿÿÿÿÿÿÃ÷ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/part2.rsc0000644000175000001440000002000012212041344030735 0ustar dokousersÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/start0.rsc0000644000175000001440000002000012212041344031122 0ustar dokousersÿÿþ‡ÿÿþ <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿÃÿÿÿûÿÿ×@ÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿþÀÿÿÿÿÿÿÿÿÿœÀ`/ÿÿÿÿÿý?ÿÿÿà?ÿÿÿÿ#ÿÿÿÿÿÿð ÿ#ÅýÿÿùŸà°@mýÿÿù‡à^#íýÿÿû¿à#íýÿÿùŸà°ÿÇÖ=Çèïýÿÿýßà#ïýÿÿýßà@ÿýÿÿýßà/ûÿÿüÿà€ ÿÿÿÿÿþ ì®þð%–0_ÿÿÿþÿûÿÿÿÿ?ÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ==ÿ=ÿÿÿÿ=ÿÿÿÿÿÿÿ=ÿÿÿÿÿ=ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿÿÿÿÿÿÿÿÿÿÿþÇÿÿÿÿÿÿÿßÿßÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ??ÿÿ?ÿÿÿªÿ??_ßÿÿÿÿÿÿÜÿÏÜ€€?ÿÿóû½P>/ü„ÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿ€?ÿÿÿÿÿÿ>þàÿÿÿÿÿÿÿþÿÿÿþàÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_ýÿ øÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿßàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡ÿÿþÿÿÿàÿÿþÿÿÿÿÿÿÿcüüüecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/part14.rsc0000644000175000001440000002000012212041344031020 0ustar dokousersÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/start1.rsc0000644000175000001440000002000012212041344031123 0ustar dokousers·ÿÿÿÿÿÿ?ÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿ‘¿ÿÿÿÿý?ÿÿþïÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÿëÿÞdßÿÿÿÿÿÿÿÿÿÿï{ÿÿÿßßç¿ÿÿÿÿÿýü_ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿ÷ÿÿÿ÷ÿÿýÿßÿÿÿßÿÿÿÿÿÿÿÿÿÿýÿÿÿýÿ÷ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/part0.rsc0000644000175000001440000002000012212041344030733 0ustar dokousersÿÿÁÿ‡ÿÿþ‡ÿÿþ $<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿÿ×@ÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü{ÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿ»ÿÿÿÿþÿÿÿÿ¶ÿÿþ?ÿÿÃÿÿÿÿÿÿÿÿÿÿÿÿŸÿýÿ¿ïÿÿÿÿÿÿÿÿ€?ÿÿÿçÿÿÿÿÿÿÿóÿÿÿÿÿÿþ ÿÏÿ?ÿóÅýÿÿùŸîÿϰ€yŸÓmýÿÿù‡îÿÀ^9‡óíýÿÿû¿îÿÏ;¿óíýÿÿùŸîÿðÀ9ÃÿÇÖ=ÇìÿÀ€=ÇÃïýÿÿýßîÿÃ`=ßóïýÿÿýßìÿÃ@`=ßÃÿýÿÿýßìÿÀ=Ï/ûÿÿüÿì ÿ_„‡ÿÿÿÿÿÿþÿÿ;ÿì®þð%–3ÿ?_ ÿÿþÿÿÿþÿÿÿÿþÿß@Çöûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ==ÿ=ÿÿÿÿ=ÿÿÿÿÿÿÿ=ÿÿÿÿÿ=ÿÿþ‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿÿÿÿÿÿÿÿÿÿÿþÇÿÿÿÿÿÿÿßÿ ßÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ??ÿÿ?ÿÿÿªÿ??_ßÿÿÿÿÿÿÜÿÏÜ€|ð€ü?ÿÿâÿóû½P>/ü„ÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿ€?ÿÿÿÿÿÿ>ÿþàÿÿÿÿÿÿÿþÿÿÿþæÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_ýÿàøÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿßàÿÿÿÿÿÿÿÿŸÿÿÿÿÿÿÿ‡ÿÿþÿÿÿÿàÿÿþÿÿÿÿÿÿÿcüüüecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/unicode/start2.rsc0000644000175000001440000002000012212041344031124 0ustar dokousersÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser24.rsc0000644000175000001440000000121212212041344027725 0ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java0000644000175000001440000000406412212041344032230 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; /** * Internal statement structure for parsing recovery */ import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Statement; public class RecoveredStatement extends RecoveredElement { public Statement statement; public RecoveredStatement(Statement statement, RecoveredElement parent, int bracketBalance){ super(parent, bracketBalance); this.statement = statement; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.statement; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.statement.sourceEnd; } public String toString(int tab){ return tabString(tab) + "Recovered statement:\n" + this.statement.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$ } public Statement updatedStatement(int depth, Set knownTypes){ return this.statement; } public void updateParseTree(){ updatedStatement(0, new HashSet()); } /* * Update the declarationSourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ if (this.statement.sourceEnd == 0) this.statement.sourceEnd = bodyEnd; } public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if ((--this.bracketBalance <= 0) && (this.parent != null)){ this.updateSourceEndIfNecessary(braceStart, braceEnd); return this.parent.updateOnClosingBrace(braceStart, braceEnd); } return this; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser4.rsc0000644000175000001440000000657612212041344027665 0ustar dokousersE5D@?7>6=<;:j98cH)*+dSRPLKMQ *+).,/01234-JOIND (!'%&"$#5=<;689:7?@>_bHCB43210/(.*)'-+&%$,#"! AFE5@?7>6=<;:98G^]\[ZYXWVUT   E5D@?7>6=<;:98ccE5D@?7>6=<;:j98 BC^]\[ZYXWVUT GDEFG^]\[ZYXWVUT    AD_bHENIOJQMKLPRS *+).,/01234-('&%$#"! =<;89:7?@>56kAF jE5@?7>=<;:98D6dg('&%$#"! =<;689:7?@>5faE5@?7>6=<;:98    DCB 43210/(.*)'-&%$,#"! +5@?7>6=<;:98DEAFG^]\[ZYXWVUT    5D CB43210/(.'-+&%$,#"! *)dgEhfa_bH5=<;689:?@>DSR7PLKMQJOIN+/01234-.,)* (!'%&"$#`e_bHE=<;689:7?@>5DiaE5@?7>6=<;:98iaG5@(?7>6'=<;:&_%$9b#H"! 8GkGAG^]\[ZYXWVUT    kGAF   aE5@?7>6=<;:98iDAG^]\[ZYXWVUT D*+)$#!'%&" (.,/01234-CB 5e E5AF@?7>6=<;: 98 5@(?7>6'=<;:&_%$9b#H"! 8D`IE5D@?7>6=<;:98jE_bH`=<;689:7?@>5$#!'%&" ( E5@?7>6=<;:98    G )c 5CB 43210/(.*)'-+&%$,#"! DhkCB+/01234-.,) (!'%&"$#* EAFG^]\[ZYXWVUT    ED('&%$#"! bH=<;689:7?@>5_G^]\[ZYXWVUT    Djk  E5AF@?7>6=<;:98 AF   =<;689:7?@>5EEAF   G^]\[ZYXWVUT       GVW[TU\]^XZY    A ^]\[ZYXWVUT   G CB+/01234-.,) (!'%&"$#* CB+/01234-.,) (!'%&"$#*F*+).,/01234-CB  (!'%&"$#`+65=<;89:7?@>e (!'%&"$#Hb__bHDE('&%$#"! =<;689:7?@>5 (!'%&"$# ('&_%$b#H"! `=<;689:7?@>5=<;689:7?@>5ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/Parser.java0000644000175000001440000145143012212041344027665 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Tom Tromey - patch for readTable(String) as described in http://bugs.eclipse.org/bugs/show_bug.cgi?id=32196 * Stephan Herrmann - Contributions for * bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639) * bug 374605 - Unreasonable warning for enum-based switch statements * bug 393719 - [compiler] inconsistent warnings on iteration variables * * Jesper S Moller - Contributions for * bug 393192 - Incomplete type hierarchy with > 10 annotations *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import java.io.*; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Properties; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.ASTVisitor; 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.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.Messages; import org.eclipse.jdt.internal.compiler.util.Util; public class Parser implements ParserBasicInformation, TerminalTokens, OperatorIds, TypeIds { protected static final int THIS_CALL = ExplicitConstructorCall.This; protected static final int SUPER_CALL = ExplicitConstructorCall.Super; public static final char[] FALL_THROUGH_TAG = "$FALL-THROUGH$".toCharArray(); //$NON-NLS-1$ public static final char[] CASES_OMITTED_TAG = "$CASES-OMITTED$".toCharArray(); //$NON-NLS-1$ 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; private static final boolean DEBUG = false; private static final boolean DEBUG_AUTOMATON = 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$ public static String readableName[] = null; public static byte rhs[] = null; public static int[] reverse_index = null; public static char[] recovery_templates_index = null; public static char[] recovery_templates = null; public static char[] statements_recovery_filter = 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; 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; static { try{ initTables(); } catch(java.io.IOException ex){ throw new ExceptionInInitializerError(ex.getMessage()); } } public static int asi(int state) { return asb[original_state(state)]; } public final static short base_check(int i) { return check_table[i - (NUM_RULES + 1)]; } private final static void buildFile(String filename, List listToDump) { BufferedWriter writer = null; try { writer = new BufferedWriter(new FileWriter(filename)); for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) { writer.write(String.valueOf(iterator.next())); } writer.flush(); } catch(IOException e) { // ignore } finally { if (writer != null) { try { writer.close(); } catch (IOException e1) { // ignore } } } System.out.println(filename + " creation complete"); //$NON-NLS-1$ } private static void buildFileForCompliance( String file, int length, String[] tokens) { 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("1.6".equals(token)) { //$NON-NLS-1$ compliance = ClassFileConstants.JDK1_6; } else if("1.7".equals(token)) { //$NON-NLS-1$ compliance = ClassFileConstants.JDK1_7; } else if("1.8".equals(token)) { //$NON-NLS-1$ compliance = ClassFileConstants.JDK1_8; } 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); } private final static String[] buildFileForName(String filename, String contents) { String[] result = new String[contents.length()]; result[0] = null; int resultCount = 1; StringBuffer buffer = new StringBuffer(); int start = contents.indexOf("name[]"); //$NON-NLS-1$ start = contents.indexOf('\"', start); int end = contents.indexOf("};", start); //$NON-NLS-1$ contents = contents.substring(start, end); boolean addLineSeparator = false; int tokenStart = -1; StringBuffer currentToken = new StringBuffer(); for (int i = 0; i < contents.length(); i++) { char c = contents.charAt(i); if(c == '\"') { if(tokenStart == -1) { tokenStart = i + 1; } else { if(addLineSeparator) { buffer.append('\n'); result[resultCount++] = currentToken.toString(); currentToken = new StringBuffer(); } String token = contents.substring(tokenStart, i); if(token.equals(ERROR_TOKEN)){ token = INVALID_CHARACTER; } else if(token.equals(EOF_TOKEN)) { token = UNEXPECTED_EOF; } buffer.append(token); currentToken.append(token); addLineSeparator = true; tokenStart = -1; } } if(tokenStart == -1 && c == '+'){ addLineSeparator = false; } } if(currentToken.length() > 0) { result[resultCount++] = currentToken.toString(); } buildFileForTable(filename, buffer.toString().toCharArray()); System.arraycopy(result, 0, result = new String[resultCount], 0, resultCount); return result; } private static void buildFileForReadableName( String file, char[] newLhs, char[] newNonTerminalIndex, String[] newName, String[] tokens) { ArrayList entries = new ArrayList(); boolean[] alreadyAdded = new boolean[newName.length]; 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; while(!INVALID_CHARACTER.equals(newName[i])) i++; i++; for (; i < alreadyAdded.length; i++) { if(!alreadyAdded[i]) { System.out.println(newName[i] + " has no readable name"); //$NON-NLS-1$ } } Collections.sort(entries); buildFile(file, entries); } private final static void buildFileForTable(String filename, byte[] bytes) { java.io.FileOutputStream stream = null; try { stream = new java.io.FileOutputStream(filename); stream.write(bytes); } catch(IOException e) { // ignore } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // ignore } } } System.out.println(filename + " creation complete"); //$NON-NLS-1$ } private final static void buildFileForTable(String filename, char[] chars) { byte[] bytes = new byte[chars.length * 2]; for (int i = 0; i < chars.length; i++) { bytes[2 * i] = (byte) (chars[i] >>> 8); bytes[2 * i + 1] = (byte) (chars[i] & 0xFF); } java.io.FileOutputStream stream = null; try { stream = new java.io.FileOutputStream(filename); stream.write(bytes); } catch(IOException e) { // ignore } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // ignore } } } System.out.println(filename + " creation complete"); //$NON-NLS-1$ } private final static byte[] buildFileOfByteFor(String filename, String tag, String[] tokens) { //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) { //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) { //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); } private static void buildFilesForRecoveryTemplates( String indexFilename, String templatesFilename, char[] newTerminalIndex, char[] newNonTerminalIndex, String[] newName, char[] newLhs, String[] tokens) { int[] newReverse = computeReverseTable(newTerminalIndex, newNonTerminalIndex, newName); char[] newRecoveyTemplatesIndex = new char[newNonTerminalIndex.length]; char[] newRecoveyTemplates = new char[newNonTerminalIndex.length]; int newRecoveyTemplatesPtr = 0; for (int i = 0; i < tokens.length; i = i + 3) { if("3".equals(tokens[i])) { //$NON-NLS-1$ int length = newRecoveyTemplates.length; if(length == newRecoveyTemplatesPtr + 1) { System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length); } newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0; int index = newLhs[Integer.parseInt(tokens[i + 1])]; newRecoveyTemplatesIndex[index] = (char)newRecoveyTemplatesPtr; String token = tokens[i + 2].trim(); java.util.StringTokenizer st = new java.util.StringTokenizer(token, " "); //$NON-NLS-1$ String[] terminalNames = new String[st.countTokens()]; int t = 0; while (st.hasMoreTokens()) { terminalNames[t++] = st.nextToken(); } for (int j = 0; j < terminalNames.length; j++) { int symbol = getSymbol(terminalNames[j], newName, newReverse); if(symbol > -1) { length = newRecoveyTemplates.length; if(length == newRecoveyTemplatesPtr + 1) { System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length); } newRecoveyTemplates[newRecoveyTemplatesPtr++] = (char)symbol; } } } } newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0; System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[newRecoveyTemplatesPtr], 0, newRecoveyTemplatesPtr); buildFileForTable(indexFilename, newRecoveyTemplatesIndex); buildFileForTable(templatesFilename, newRecoveyTemplates); } private static void buildFilesForStatementsRecoveryFilter( String filename, char[] newNonTerminalIndex, char[] newLhs, String[] tokens) { char[] newStatementsRecoveryFilter = new char[newNonTerminalIndex.length]; for (int i = 0; i < tokens.length; i = i + 3) { if("4".equals(tokens[i])) { //$NON-NLS-1$ int index = newLhs[Integer.parseInt(tokens[i + 1])]; newStatementsRecoveryFilter[index] = 1; } } buildFileForTable(filename, newStatementsRecoveryFilter); } public final static void buildFilesFromLPG(String dataFilename, String dataFilename2) { //RUN THIS METHOD TO GENERATE PARSER*.RSC FILES //build from the lpg javadcl.java files that represents the parser tables //lhs check_table asb asr symbol_index //[org.eclipse.jdt.internal.compiler.parser.Parser.buildFilesFromLPG("d:/leapfrog/grammar/javadcl.java")] char[] contents = CharOperation.NO_CHAR; try { contents = Util.getFileCharContent(new File(dataFilename), null); } catch (IOException ex) { System.out.println(Messages.parser_incorrectPath); return; } java.util.StringTokenizer st = new java.util.StringTokenizer(new String(contents), " \t\n\r[]={,;"); //$NON-NLS-1$ String[] tokens = new String[st.countTokens()]; int j = 0; while (st.hasMoreTokens()) { tokens[j++] = st.nextToken(); } final String prefix = FILEPREFIX; 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$ buildFileOfIntFor(prefix + (++i) + ".rsc", "asb", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "asr", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "nasb", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "nasr", tokens); //$NON-NLS-2$ //$NON-NLS-1$ char[] newTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "terminal_index", tokens); //$NON-NLS-2$ //$NON-NLS-1$ char[] newNonTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "non_terminal_index", tokens); //$NON-NLS-1$ //$NON-NLS-2$ buildFileOfIntFor(prefix + (++i) + ".rsc", "term_action", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_prefix", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_suffix", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_lhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state_set", tokens); //$NON-NLS-2$ //$NON-NLS-1$ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$ 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$ 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$ String[] newName = buildFileForName(prefix + (++i) + ".rsc", new String(contents)); //$NON-NLS-1$ contents = CharOperation.NO_CHAR; try { contents = Util.getFileCharContent(new File(dataFilename2), null); } catch (IOException ex) { System.out.println(Messages.parser_incorrectPath); return; } st = new java.util.StringTokenizer(new String(contents), "\t\n\r#"); //$NON-NLS-1$ tokens = new String[st.countTokens()]; j = 0; while (st.hasMoreTokens()) { tokens[j++] = st.nextToken(); } buildFileForCompliance(prefix + (++i) + ".rsc", newRhs.length, tokens);//$NON-NLS-1$ buildFileForReadableName(READABLE_NAMES_FILE+".props", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$ buildFilesForRecoveryTemplates( prefix + (++i) + ".rsc", //$NON-NLS-1$ prefix + (++i) + ".rsc", //$NON-NLS-1$ newTerminalIndex, newNonTerminalIndex, newName, newLhs, tokens); buildFilesForStatementsRecoveryFilter( prefix + (++i) + ".rsc", //$NON-NLS-1$ newNonTerminalIndex, newLhs, tokens); System.out.println(Messages.parser_moveFiles); } protected static int[] computeReverseTable(char[] newTerminalIndex, char[] newNonTerminalIndex, String[] newName) { int[] newReverseTable = new int[newName.length]; for (int j = 0; j < newName.length; j++) { found : { for (int k = 0; k < newTerminalIndex.length; k++) { if(newTerminalIndex[k] == j) { newReverseTable[j] = k; break found; } } for (int k = 0; k < newNonTerminalIndex.length; k++) { if(newNonTerminalIndex[k] == j) { newReverseTable[j] = -k; break found; } } } } return newReverseTable; } private static int getSymbol(String terminalName, String[] newName, int[] newReverse) { for (int j = 0; j < newName.length; j++) { if(terminalName.equals(newName[j])) { return newReverse[j]; } } return -1; } public static int in_symbol(int state) { return in_symb[original_state(state)]; } 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$ rules_compliance = readLongTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$ readableName = readReadableNameTable(READABLE_NAMES_FILE + ".props"); //$NON-NLS-1$ reverse_index = computeReverseTable(terminal_index, non_terminal_index, name); recovery_templates_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$ recovery_templates = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$ statements_recovery_filter = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$ 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 { //files are located at Parser.class directory InputStream stream = Parser.class.getResourceAsStream(filename); if (stream == null) { throw new java.io.IOException(Messages.bind(Messages.parser_missingFile, filename)); } 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 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(Messages.bind(Messages.parser_missingFile, filename)); } 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(Messages.bind(Messages.parser_corruptedFile, filename)); // 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; } 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]; InputStream is = Parser.class.getResourceAsStream(filename); Properties props = new Properties(); try { props.load(is); } catch (IOException e) { result = name; return result; } for (int i = 0; i < NT_OFFSET + 1; i++) { result[i] = name[i]; } for (int i = NT_OFFSET; i < name.length; i++) { String n = props.getProperty(name[i]); if (n != null && n.length() > 0) { result[i] = n; } else { 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(Messages.bind(Messages.parser_missingFile, filename)); } 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 & 1) != 0) throw new java.io.IOException(Messages.bind(Messages.parser_corruptedFile, filename)); // 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; } 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]]; } protected int astLengthPtr; protected int[] astLengthStack; protected int astPtr; protected ASTNode[] astStack = new ASTNode[AstStackIncrement]; public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/ 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; 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 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; 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 modifiers; protected int modifiersSourceStart; protected int[] nestedMethod; //the ptr is nestedType 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 int[] realBlockStack; protected int recoveredStaticInitializerStart; public ReferenceContext referenceContext; public boolean reportOnlyOneSyntaxError = false; public boolean reportSyntaxErrorIsRequired = true; protected boolean restartRecovery; protected boolean annotationRecoveryActivated = true; protected int lastPosistion; // statement recovery public boolean methodRecoveryActivated = false; protected boolean statementRecoveryActivated = false; protected TypeDeclaration[] recoveredTypes; protected int recoveredTypePtr; protected int nextTypeStart; protected TypeDeclaration pendingRecoveredType; public RecoveryScanner recoveryScanner; //scanner token public Scanner scanner; protected int[] stack = new int[StackIncrement]; protected int stateStackTop; protected int synchronizedBlockSourceStart; protected int[] variablesCounter; protected boolean checkExternalizeStrings; protected boolean recordStringLiterals; // javadoc public Javadoc javadoc; public JavadocParser javadocParser; // used for recovery protected int lastJavadocEnd; public org.eclipse.jdt.internal.compiler.ReadManager readManager; private boolean shouldDeferRecovery = false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291040 public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) { this.problemReporter = problemReporter; this.options = problemReporter.options; this.optimizeStringLiterals = optimizeStringLiterals; 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 = createJavadocParser(); } protected void annotationRecoveryCheckPoint(int start, int end) { if(this.lastCheckPoint < end) { this.lastCheckPoint = end + 1; } } 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 */ // 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; } else { if (this.referenceContext instanceof AbstractMethodDeclaration){ element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this); this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart; if(this.statementRecoveryActivated) { element = element.add(new Block(0), 0); } } 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; FieldDeclaration[] fieldDeclarations = type.fields; int length = fieldDeclarations == null ? 0 : fieldDeclarations.length; for (int i = 0; i < length; i++){ FieldDeclaration field = fieldDeclarations[i]; if (field != null && field.getKind() == AbstractVariableDeclaration.INITIALIZER && ((Initializer) field).block != null && 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); this.lastCheckPoint = method.bodyStart; } else { element = element.add(method, 0); this.lastCheckPoint = method.declarationSourceEnd + 1; } continue; } if (node instanceof Initializer){ Initializer initializer = (Initializer) node; // ignore initializer with no block if (initializer.block == null) continue; if (initializer.declarationSourceEnd == 0){ element = element.add(initializer, 1); this.lastCheckPoint = initializer.sourceStart; } else { element = element.add(initializer, 0); this.lastCheckPoint = initializer.declarationSourceEnd + 1; } continue; } if (node instanceof FieldDeclaration){ FieldDeclaration field = (FieldDeclaration) node; if (field.declarationSourceEnd == 0){ element = element.add(field, 0); if (field.initialization == null){ this.lastCheckPoint = field.sourceEnd + 1; } else { this.lastCheckPoint = field.initialization.sourceEnd + 1; } } else { element = element.add(field, 0); this.lastCheckPoint = field.declarationSourceEnd + 1; } continue; } if (node instanceof TypeDeclaration){ TypeDeclaration type = (TypeDeclaration) node; if ((type.modifiers & ClassFileConstants.AccEnum) != 0) { // do not allow enums to be build as recovery types // https://bugs.eclipse.org/bugs/show_bug.cgi?id=340691 continue; } if (type.declarationSourceEnd == 0){ element = element.add(type, 0); this.lastCheckPoint = type.bodyStart; } else { element = element.add(type, 0); this.lastCheckPoint = type.declarationSourceEnd + 1; } continue; } if (node instanceof ImportReference){ ImportReference importRef = (ImportReference) node; element = element.add(importRef, 0); this.lastCheckPoint = importRef.declarationSourceEnd + 1; } if(this.statementRecoveryActivated) { if(node instanceof Block) { Block block = (Block) node; element = element.add(block, 0); this.lastCheckPoint = block.sourceEnd + 1; } else if(node instanceof LocalDeclaration) { LocalDeclaration statement = (LocalDeclaration) node; element = element.add(statement, 0); this.lastCheckPoint = statement.sourceEnd + 1; } else if(node instanceof Expression) { if(node instanceof Assignment || node instanceof PrefixExpression || node instanceof PostfixExpression || node instanceof MessageSend || node instanceof AllocationExpression) { // recover only specific expressions Expression statement = (Expression) node; element = element.add(statement, 0); if(statement.statementEnd != -1) { this.lastCheckPoint = statement.statementEnd + 1; } else { this.lastCheckPoint = statement.sourceEnd + 1; } } } else if(node instanceof Statement) { Statement statement = (Statement) node; element = element.add(statement, 0); this.lastCheckPoint = statement.sourceEnd + 1; } } } if (this.statementRecoveryActivated) { if (this.pendingRecoveredType != null && this.scanner.startPosition - 1 <= this.pendingRecoveredType.declarationSourceEnd) { // Add the pending type to the AST if this type isn't already added in the AST. element = element.add(this.pendingRecoveredType, 0); this.lastCheckPoint = this.pendingRecoveredType.declarationSourceEnd + 1; this.pendingRecoveredType = null; } } return element; } 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 this.astStack. */ if ((this.modifiers & flag) != 0){ // duplicate modifier this.modifiers |= ExtraCompilerModifiers.AccAlternateModifierProblem; } this.modifiers |= flag; if (this.modifiersSourceStart < 0) this.modifiersSourceStart = this.scanner.startPosition; if (this.currentElement != null && this.annotationRecoveryActivated) { this.currentElement.addModifier(flag, this.modifiersSourceStart); } } public void checkComment() { // 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; if (this.modifiersSourceStart >= 0) { // eliminate comments located after modifierSourceStart if positioned while (lastComment >= 0) { int commentSourceStart = this.scanner.commentStarts[lastComment]; if (commentSourceStart < 0) commentSourceStart = -commentSourceStart; if (commentSourceStart <= this.modifiersSourceStart) break; lastComment--; } } if (lastComment >= 0) { // consider all remaining leading comments to be part of current declaration this.modifiersSourceStart = this.scanner.commentStarts[0]; if (this.modifiersSourceStart < 0) this.modifiersSourceStart = -this.modifiersSourceStart; // 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) { int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over, // do not report problem before last parsed comment while recovering code... if (this.javadocParser.shouldReportProblems) { this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd; } else { this.javadocParser.reportProblems = false; } if (this.javadocParser.checkDeprecation(lastComment)) { checkAndSetModifiers(ClassFileConstants.AccDeprecated); } this.javadoc = this.javadocParser.docComment; // null if check javadoc is not activated if (this.currentElement == null) this.lastJavadocEnd = commentEnd; } } } protected void checkNonNLSAfterBodyEnd(int declarationEnd){ if(this.scanner.currentPosition - 1 <= declarationEnd) { this.scanner.eofPosition = declarationEnd < Integer.MAX_VALUE ? declarationEnd + 1 : declarationEnd; try { while(this.scanner.getNextToken() != TokenNameEOF){/*empty*/} } catch (InvalidInputException e) { // Nothing to do } } } protected void classInstanceCreation(boolean isQualified) { // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt // ClassBodyopt produces a null item on the astStak if it produces NO class body // An empty class body produces a 0 on the length stack..... AllocationExpression alloc; int length; if (((length = this.astLengthStack[this.astLengthPtr--]) == 1) && (this.astStack[this.astPtr] == null)) { //NO ClassBody this.astPtr--; if (isQualified) { alloc = new QualifiedAllocationExpression(); } else { 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); checkForDiamond(alloc.type); //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 (anonymousTypeDeclaration.allocation != null) { anonymousTypeDeclaration.allocation.sourceEnd = this.endStatementPosition; checkForDiamond(anonymousTypeDeclaration.allocation.type); } if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) { anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlock; } this.astPtr--; this.astLengthPtr--; } } protected void checkForDiamond(TypeReference allocType) { if (allocType instanceof ParameterizedSingleTypeReference) { ParameterizedSingleTypeReference type = (ParameterizedSingleTypeReference) allocType; if (type.typeArguments == TypeReference.NO_TYPE_ARGUMENTS) { if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { problemReporter().diamondNotBelow17(allocType); } if (this.options.sourceLevel > ClassFileConstants.JDK1_4) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=351965 type.bits |= ASTNode.IsDiamond; } // else don't even bother to recognize this as <> } } else if (allocType instanceof ParameterizedQualifiedTypeReference) { ParameterizedQualifiedTypeReference type = (ParameterizedQualifiedTypeReference) allocType; if (type.typeArguments[type.typeArguments.length - 1] == TypeReference.NO_TYPE_ARGUMENTS) { // Don't care for X<>.Y<> and X<>.Y if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { problemReporter().diamondNotBelow17(allocType, type.typeArguments.length - 1); } if (this.options.sourceLevel > ClassFileConstants.JDK1_4) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=351965 type.bits |= ASTNode.IsDiamond; } // else don't even bother to recognize this as <> } } } 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 concatExpressionLists() { this.expressionLengthStack[--this.expressionLengthPtr]++; } 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 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 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 // ClassBodyopt produces a null item on the astStak if it produces NO class body // An empty class body produces a 0 on the length stack..... if (this.currentElement == null){ return; // should never occur, this consumeRule is only used in recovery mode } if (this.currentToken == TokenNameLBRACE){ // beginning of an anonymous type TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); anonymousType.name = CharOperation.NO_CHAR; anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType); anonymousType.sourceStart = this.intStack[this.intPtr--]; anonymousType.declarationSourceStart = anonymousType.sourceStart; anonymousType.sourceEnd = this.rParenPos; // closing parenthesis QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType); alloc.type = getTypeReference(0); alloc.sourceStart = anonymousType.sourceStart; alloc.sourceEnd = anonymousType.sourceEnd ; this.lastCheckPoint = anonymousType.bodyStart = this.scanner.currentPosition; this.currentElement = this.currentElement.add(anonymousType, 0); this.lastIgnoredToken = -1; this.currentToken = 0; // opening brace already taken into account return; } this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position this.restartRecovery = true; // request to restart from here on } protected void consumeAnnotationAsModifier() { Expression expression = this.expressionStack[this.expressionPtr]; int sourceStart = expression.sourceStart; if (this.modifiersSourceStart < 0) { this.modifiersSourceStart = sourceStart; } } protected void consumeAnnotationName() { if(this.currentElement != null) { int start = this.intStack[this.intPtr]; int end = (int) (this.identifierPositionStack[this.identifierPtr] & 0x00000000FFFFFFFFL); annotationRecoveryCheckPoint(start, end); if (this.annotationRecoveryActivated) { this.currentElement = this.currentElement.addAnnotationName(this.identifierPtr, this.identifierLengthPtr, start, 0); } } this.recordStringLiterals = false; } 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); } TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; //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.ContainsAssertion; } typeDecl.addClinit(); typeDecl.bodyEnd = this.endStatementPosition; if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) { typeDecl.bits |= ASTNode.UndocumentedEmptyBlock; } typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); } protected void consumeAnnotationTypeDeclarationHeader() { TypeDeclaration annotationTypeDeclaration = (TypeDeclaration) this.astStack[this.astPtr]; if (this.currentToken == TokenNameLBRACE) { annotationTypeDeclaration.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 annotation type header this.scanner.commentPtr = -1; } 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.IsMemberType; } } else { // Record that the block has a declaration for local types annotationTypeDeclaration.bits |= ASTNode.IsLocalType; 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--] | ClassFileConstants.AccAnnotation | ClassFileConstants.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; } // Store secondary info if ((annotationTypeDeclaration.bits & ASTNode.IsMemberType) == 0 && (annotationTypeDeclaration.bits & ASTNode.IsLocalType) == 0) { if (this.compilationUnit != null && !CharOperation.equals(annotationTypeDeclaration.name, this.compilationUnit.getMainTypeName())) { annotationTypeDeclaration.bits |= ASTNode.IsSecondaryType; } } // 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(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { problemReporter().invalidUsageOfAnnotationDeclarations(annotationTypeDeclaration); } // recovery if (this.currentElement != null){ this.lastCheckPoint = annotationTypeDeclaration.bodyStart; this.currentElement = this.currentElement.add(annotationTypeDeclaration, 0); this.lastIgnoredToken = -1; } } protected void consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() { // consumeAnnotationTypeDeclarationHeader ::= Modifiers '@' PushModifiers interface Identifier TypeParameters // consumeAnnotationTypeDeclarationHeader ::= '@' PushModifiers interface Identifier TypeParameters TypeDeclaration annotationTypeDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult); // consume type parameters int length = this.genericsLengthStack[this.genericsLengthPtr--]; this.genericsPtr -= length; System.arraycopy(this.genericsStack, this.genericsPtr + 1, annotationTypeDeclaration.typeParameters = new TypeParameter[length], 0, length); problemReporter().invalidUsageOfTypeParametersForAnnotationDeclaration(annotationTypeDeclaration); annotationTypeDeclaration.bodyStart = annotationTypeDeclaration.typeParameters[length-1].declarationSourceEnd + 1; // annotationTypeDeclaration.typeParameters = null; this.listTypeParameterLength = 0; if (this.nestedMethod[this.nestedType] == 0) { if (this.nestedType != 0) { annotationTypeDeclaration.bits |= ASTNode.IsMemberType; } } else { // Record that the block has a declaration for local types annotationTypeDeclaration.bits |= ASTNode.IsLocalType; 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--] | ClassFileConstants.AccAnnotation | ClassFileConstants.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; } // Store secondary info if ((annotationTypeDeclaration.bits & ASTNode.IsMemberType) == 0 && (annotationTypeDeclaration.bits & ASTNode.IsLocalType) == 0) { if (this.compilationUnit != null && !CharOperation.equals(annotationTypeDeclaration.name, this.compilationUnit.getMainTypeName())) { annotationTypeDeclaration.bits |= ASTNode.IsSecondaryType; } } // consume annotations if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { System.arraycopy( this.expressionStack, (this.expressionPtr -= length) + 1, annotationTypeDeclaration.annotations = new Annotation[length], 0, length); } // javadoc annotationTypeDeclaration.javadoc = this.javadoc; this.javadoc = null; pushOnAstStack(annotationTypeDeclaration); if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { 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 |= ExtraCompilerModifiers.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 consumeAnnotationTypeMemberDeclarationsopt() { this.nestedType-- ; } protected void consumeArgumentList() { // ArgumentList ::= ArgumentList ',' Expression concatExpressionLists(); } protected void consumeArguments() { // Arguments ::= '(' ArgumentListopt ')' // nothing to do, the expression stack is already updated pushOnIntStack(this.rParenPos); } protected void consumeArrayAccess(boolean unspecifiedReference) { // ArrayAccess ::= Name '[' Expression ']' ==> true // ArrayAccess ::= PrimaryNoNewArray '[' Expression ']' ==> false //optimize push/pop Expression exp; if (unspecifiedReference) { exp = this.expressionStack[this.expressionPtr] = new ArrayReference( getUnspecifiedReferenceOptimized(), this.expressionStack[this.expressionPtr]); } else { this.expressionPtr--; this.expressionLengthPtr--; exp = this.expressionStack[this.expressionPtr] = new ArrayReference( this.expressionStack[this.expressionPtr], this.expressionStack[this.expressionPtr + 1]); } exp.sourceEnd = this.endStatementPosition; } protected void consumeArrayCreationExpressionWithInitializer() { // ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer int length; ArrayAllocationExpression arrayAllocation = new ArrayAllocationExpression(); this.expressionLengthPtr -- ; arrayAllocation.initializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--]; arrayAllocation.type = getTypeReference(0); arrayAllocation.type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage length = (this.expressionLengthStack[this.expressionLengthPtr--]); this.expressionPtr -= length ; System.arraycopy( this.expressionStack, this.expressionPtr+1, arrayAllocation.dimensions = new Expression[length], 0, length); arrayAllocation.sourceStart = this.intStack[this.intPtr--]; if (arrayAllocation.initializer == null) { arrayAllocation.sourceEnd = this.endStatementPosition; } else { arrayAllocation.sourceEnd = arrayAllocation.initializer.sourceEnd ; } pushOnExpressionStack(arrayAllocation); } protected void consumeArrayCreationExpressionWithoutInitializer() { // ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs int length; ArrayAllocationExpression arrayAllocation = new ArrayAllocationExpression(); arrayAllocation.type = getTypeReference(0); arrayAllocation.type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage length = (this.expressionLengthStack[this.expressionLengthPtr--]); this.expressionPtr -= length ; System.arraycopy( this.expressionStack, this.expressionPtr+1, arrayAllocation.dimensions = new Expression[length], 0, length); arrayAllocation.sourceStart = this.intStack[this.intPtr--]; if (arrayAllocation.initializer == null) { arrayAllocation.sourceEnd = this.endStatementPosition; } else { arrayAllocation.sourceEnd = arrayAllocation.initializer.sourceEnd ; } pushOnExpressionStack(arrayAllocation); } protected void consumeArrayCreationHeader() { // nothing to do } protected void consumeArrayInitializer() { // ArrayInitializer ::= '{' VariableInitializers '}' // ArrayInitializer ::= '{' VariableInitializers , '}' arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]); } protected void consumeArrayTypeWithTypeArgumentsName() { this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] += this.identifierLengthStack[this.identifierLengthPtr]; pushOnGenericsLengthStack(0); // handle type arguments } 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 int op = this.intStack[this.intPtr--] ; //<--the encoded operator this.expressionPtr -- ; this.expressionLengthPtr -- ; Expression expression = this.expressionStack[this.expressionPtr+1]; this.expressionStack[this.expressionPtr] = (op != EQUAL ) ? new CompoundAssignment( this.expressionStack[this.expressionPtr] , expression, op, expression.sourceEnd): new Assignment( this.expressionStack[this.expressionPtr] , expression, expression.sourceEnd); if (this.pendingRecoveredType != null) { // Used only in statements recovery. // This is not a real assignment but a placeholder for an existing anonymous type. // The assignment must be replace by the anonymous type. if (this.pendingRecoveredType.allocation != null && this.scanner.startPosition - 1 <= this.pendingRecoveredType.declarationSourceEnd) { this.expressionStack[this.expressionPtr] = this.pendingRecoveredType.allocation; this.pendingRecoveredType = null; return; } this.pendingRecoveredType = null; } } protected void consumeAssignmentOperator(int pos) { // AssignmentOperator ::= '=' // AssignmentOperator ::= '*=' // AssignmentOperator ::= '/=' // AssignmentOperator ::= '%=' // AssignmentOperator ::= '+=' // AssignmentOperator ::= '-=' // AssignmentOperator ::= '<<=' // AssignmentOperator ::= '>>=' // AssignmentOperator ::= '>>>=' // AssignmentOperator ::= '&=' // AssignmentOperator ::= '^=' // AssignmentOperator ::= '|=' pushOnIntStack(pos); } protected void consumeBinaryExpression(int op) { // MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression // MultiplicativeExpression ::= MultiplicativeExpression '/' UnaryExpression // MultiplicativeExpression ::= MultiplicativeExpression '%' UnaryExpression // AdditiveExpression ::= AdditiveExpression '+' MultiplicativeExpression // AdditiveExpression ::= AdditiveExpression '-' MultiplicativeExpression // ShiftExpression ::= ShiftExpression '<<' AdditiveExpression // ShiftExpression ::= ShiftExpression '>>' AdditiveExpression // ShiftExpression ::= ShiftExpression '>>>' AdditiveExpression // RelationalExpression ::= RelationalExpression '<' ShiftExpression // RelationalExpression ::= RelationalExpression '>' ShiftExpression // RelationalExpression ::= RelationalExpression '<=' ShiftExpression // RelationalExpression ::= RelationalExpression '>=' ShiftExpression // AndExpression ::= AndExpression '&' EqualityExpression // ExclusiveOrExpression ::= ExclusiveOrExpression '^' AndExpression // InclusiveOrExpression ::= InclusiveOrExpression '|' ExclusiveOrExpression // ConditionalAndExpression ::= ConditionalAndExpression '&&' InclusiveOrExpression // ConditionalOrExpression ::= ConditionalOrExpression '||' ConditionalAndExpression //optimize the push/pop this.expressionPtr--; this.expressionLengthPtr--; Expression expr1 = this.expressionStack[this.expressionPtr]; Expression expr2 = this.expressionStack[this.expressionPtr + 1]; 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 (((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { 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 CombinedBinaryExpression) { CombinedBinaryExpression cursor; // left branch is comprised of PLUS BEs // cursor is shifted upwards, while needed BEs are added // on demand; past the arityMax-th // consecutive BE, a CBE is inserted that holds a // full-fledged references table if ((cursor = (CombinedBinaryExpression)expr1).arity < cursor.arityMax) { cursor.left = new BinaryExpression(cursor); cursor.arity++; } else { cursor.left = new CombinedBinaryExpression(cursor); cursor.arity = 0; cursor.tuneArityMax(); } cursor.right = expr2; cursor.sourceEnd = expr2.sourceEnd; this.expressionStack[this.expressionPtr] = cursor; // BE_INSTRUMENTATION: neutralized in the released code // cursor.depthTracker = ((BinaryExpression)cursor.left). // depthTracker + 1; } else if (expr1 instanceof BinaryExpression && // single out the a + b case, which is a BE // instead of a CBE (slightly more than a half of // strings concatenation are one-deep binary // expressions) ((expr1.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) { this.expressionStack[this.expressionPtr] = new CombinedBinaryExpression(expr1, expr2, PLUS, 1); } else { this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS); } } else if (expr1 instanceof StringLiteral) { if (expr2 instanceof StringLiteral && ((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { // string + string this.expressionStack[this.expressionPtr] = ((StringLiteral) expr1).extendsWith((StringLiteral) expr2); } else { // single out the a + b case this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS); } } else if (expr1 instanceof CombinedBinaryExpression) { CombinedBinaryExpression cursor; // shift cursor; create BE/CBE as needed if ((cursor = (CombinedBinaryExpression)expr1).arity < cursor.arityMax) { cursor.left = new BinaryExpression(cursor); // clear the bits on cursor cursor.bits &= ~ASTNode.ParenthesizedMASK; cursor.arity++; } else { cursor.left = new CombinedBinaryExpression(cursor); // clear the bits on cursor cursor.bits &= ~ASTNode.ParenthesizedMASK; cursor.arity = 0; cursor.tuneArityMax(); } cursor.right = expr2; cursor.sourceEnd = expr2.sourceEnd; // BE_INSTRUMENTATION: neutralized in the released code // cursor.depthTracker = ((BinaryExpression)cursor.left). // depthTracker + 1; this.expressionStack[this.expressionPtr] = cursor; } else if (expr1 instanceof BinaryExpression && ((expr1.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) { // single out the a + b case this.expressionStack[this.expressionPtr] = new CombinedBinaryExpression(expr1, expr2, PLUS, 1); } else { this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS); } break; case LESS : case MULTIPLY : this.intPtr--; // star end position or starting position of angle bracket 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]; // Note: we do not attempt to promote BinaryExpression-s to // IndexedBinaryExpression-s here since expr1 always holds a name 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 && ((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { 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 && ((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { // 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 : case MULTIPLY : this.intPtr--; // star end position or starting position of angle bracket this.expressionStack[this.expressionPtr] = new BinaryExpression( expr1, expr2, op); break; default : this.expressionStack[this.expressionPtr] = new BinaryExpression( expr1, expr2, op); } } protected void consumeBlock() { // Block ::= OpenBlock '{' BlockStatementsopt '}' // simpler action for empty blocks int statementsLength = this.astLengthStack[this.astLengthPtr--]; Block block; if (statementsLength == 0) { // empty block block = new Block(0); block.sourceStart = this.intStack[this.intPtr--]; block.sourceEnd = this.endStatementPosition; // check whether this block at least contains some comment in it if (!containsComment(block.sourceStart, block.sourceEnd)) { block.bits |= ASTNode.UndocumentedEmptyBlock; } this.realBlockPtr--; // still need to pop the block variable counter } else { block = new Block(this.realBlockStack[this.realBlockPtr--]); this.astPtr -= statementsLength; System.arraycopy( this.astStack, this.astPtr + 1, block.statements = new Statement[statementsLength], 0, statementsLength); block.sourceStart = this.intStack[this.intPtr--]; block.sourceEnd = this.endStatementPosition; } pushOnAstStack(block); } protected void consumeBlockStatements() { // BlockStatements ::= BlockStatements BlockStatement concatNodeLists(); } protected void consumeCaseLabel() { // SwitchLabel ::= 'case' ConstantExpression ':' this.expressionLengthPtr--; Expression expression = this.expressionStack[this.expressionPtr--]; CaseStatement caseStatement = new CaseStatement(expression, expression.sourceEnd, this.intStack[this.intPtr--]); // Look for $fall-through$ tag in leading comment for case statement if (hasLeadingTagComment(FALL_THROUGH_TAG, caseStatement.sourceStart)) { caseStatement.bits |= ASTNode.DocumentedFallthrough; } pushOnAstStack(caseStatement); } protected void consumeCastExpressionLL1() { //CastExpression ::= '(' Expression ')' InsideCastExpressionLL1 UnaryExpressionNotPlusMinus // Expression is used in order to make the grammar LL1 //optimize push/pop Expression cast; Expression exp; this.expressionPtr--; this.expressionStack[this.expressionPtr] = cast = new CastExpression( exp=this.expressionStack[this.expressionPtr+1] , (TypeReference) this.expressionStack[this.expressionPtr]); this.expressionLengthPtr -- ; updateSourcePosition(cast); cast.sourceEnd=exp.sourceEnd; } protected void consumeCastExpressionWithGenericsArray() { // CastExpression ::= PushLPAREN Name TypeArguments Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus Expression exp; Expression cast; TypeReference 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)); this.intPtr--; castType.sourceEnd = end - 1; castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1; cast.sourceEnd = exp.sourceEnd; } protected void consumeCastExpressionWithNameArray() { // CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus Expression exp; Expression cast; TypeReference castType; int end = this.intStack[this.intPtr--]; // handle type arguments pushOnGenericsLengthStack(0); pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]); 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; Expression cast; TypeReference 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 consumeCastExpressionWithQualifiedGenericsArray() { // CastExpression ::= PushLPAREN Name OnlyTypeArguments '.' ClassOrInterfaceType Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus Expression exp; Expression cast; TypeReference castType; int end = this.intStack[this.intPtr--]; int dim = this.intStack[this.intPtr--]; TypeReference rightSide = getTypeReference(0); ParameterizedQualifiedTypeReference qualifiedParameterizedTypeReference = computeQualifiedGenericsFromRightSide(rightSide, dim); this.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 consumeCatchFormalParameter() { // CatchFormalParameter ::= Modifiersopt CatchType VariableDeclaratorId this.identifierLengthPtr--; char[] identifierName = this.identifierStack[this.identifierPtr]; long namePositions = this.identifierPositionStack[this.identifierPtr--]; int extendedDimensions = this.intStack[this.intPtr--]; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=348369 TypeReference type = (TypeReference) this.astStack[this.astPtr--]; if (extendedDimensions > 0) { type = type.copyDims(type.dimensions() + extendedDimensions); type.sourceEnd = this.endPosition; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391092 if (type instanceof UnionTypeReference) { this.problemReporter().illegalArrayOfUnionType(identifierName, type); } } this.astLengthPtr--; int modifierPositions = this.intStack[this.intPtr--]; this.intPtr--; Argument arg = new Argument( identifierName, namePositions, type, this.intStack[this.intPtr + 1] & ~ClassFileConstants.AccDeprecated); // modifiers arg.bits &= ~ASTNode.IsArgument; 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, this.listLength counter will not have been reset, indicating that some arguments are available on the stack */ this.listLength++; } 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; } protected void consumeCatchType() { // CatchType ::= UnionType int length = this.astLengthStack[this.astLengthPtr--]; if (length != 1) { TypeReference[] typeReferences; System.arraycopy( this.astStack, (this.astPtr -= length) + 1, (typeReferences = new TypeReference[length]), 0, length); UnionTypeReference typeReference = new UnionTypeReference(typeReferences); pushOnAstStack(typeReference); if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { problemReporter().multiCatchNotBelow17(typeReference); } } else { // push back the type reference pushOnAstLengthStack(1); } } protected void consumeClassBodyDeclaration() { // ClassBodyDeclaration ::= Diet NestedMethod CreateInitializer Block //push an Initializer //optimize the push/pop this.nestedMethod[this.nestedType]--; Block block = (Block) this.astStack[this.astPtr--]; this.astLengthPtr--; if (this.diet) block.bits &= ~ASTNode.UndocumentedEmptyBlock; // clear bit since was diet Initializer initializer = (Initializer) this.astStack[this.astPtr]; initializer.declarationSourceStart = initializer.sourceStart = block.sourceStart; initializer.block = block; this.intPtr--; // pop sourcestart left on the stack by consumeNestedMethod. initializer.bodyStart = this.intStack[this.intPtr--]; this.realBlockPtr--; // pop the block variable counter left on the stack by consumeNestedMethod int javadocCommentStart = this.intStack[this.intPtr--]; if (javadocCommentStart != -1) { initializer.declarationSourceStart = javadocCommentStart; initializer.javadoc = this.javadoc; this.javadoc = null; } initializer.bodyEnd = this.endPosition; initializer.sourceEnd = this.endStatementPosition; initializer.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); } protected void consumeClassBodyDeclarations() { // ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration concatNodeLists(); } protected void consumeClassBodyDeclarationsopt() { // ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations this.nestedType-- ; } protected void consumeClassBodyopt() { // ClassBodyopt ::= $empty pushOnAstStack(null); this.endPosition = this.rParenPos; this.shouldDeferRecovery = false; } protected void consumeClassDeclaration() { // ClassDeclaration ::= ClassHeader ClassBody int length; if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { //there are length declarations //dispatch according to the type of the declarations dispatchDeclarationInto(length); } TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; //convert constructor that do not have the type's name into methods boolean hasConstructor = typeDecl.checkConstructors(this); //add the default constructor when needed (interface don't have it) if (!hasConstructor) { switch(TypeDeclaration.kind(typeDecl.modifiers)) { case TypeDeclaration.CLASS_DECL : case TypeDeclaration.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); } } //always add (will be remove at code gen time if empty) if (this.scanner.containsAssertKeyword) { typeDecl.bits |= ASTNode.ContainsAssertion; } typeDecl.addClinit(); typeDecl.bodyEnd = this.endStatementPosition; if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) { typeDecl.bits |= ASTNode.UndocumentedEmptyBlock; } typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); } protected void consumeClassHeader() { // ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt 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 class header this.scanner.commentPtr = -1; } 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]; typeDecl.superclass = superClass; superClass.bits |= ASTNode.IsSuperType; typeDecl.bodyStart = typeDecl.superclass.sourceEnd + 1; // recovery if (this.currentElement != null){ this.lastCheckPoint = typeDecl.bodyStart; } } protected void consumeClassHeaderImplements() { // ClassHeaderImplements ::= 'implements' InterfaceTypeList int length = this.astLengthStack[this.astLengthPtr--]; //super interfaces this.astPtr -= length; // There is a class declaration on the top of stack TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; System.arraycopy( this.astStack, this.astPtr + 1, 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 if (this.currentElement != null) { // is recovering this.lastCheckPoint = typeDecl.bodyStart; } } protected void consumeClassHeaderName1() { // ClassHeaderName1 ::= Modifiersopt 'class' 'Identifier' TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); if (this.nestedMethod[this.nestedType] == 0) { if (this.nestedType != 0) { typeDecl.bits |= ASTNode.IsMemberType; } } else { // Record that the block has a declaration for local types typeDecl.bits |= ASTNode.IsLocalType; markEnclosingMemberWithLocalType(); blockReal(); } //highlight the name of the type long pos = this.identifierPositionStack[this.identifierPtr]; typeDecl.sourceEnd = (int) pos; typeDecl.sourceStart = (int) (pos >>> 32); typeDecl.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. 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--]; if (typeDecl.modifiersSourceStart >= 0) { typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart; } // Store secondary info if ((typeDecl.bits & ASTNode.IsMemberType) == 0 && (typeDecl.bits & ASTNode.IsLocalType) == 0) { if (this.compilationUnit != null && !CharOperation.equals(typeDecl.name, this.compilationUnit.getMainTypeName())) { typeDecl.bits |= ASTNode.IsSecondaryType; } } // 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 // recovery if (this.currentElement != null){ this.lastCheckPoint = typeDecl.bodyStart; this.currentElement = this.currentElement.add(typeDecl, 0); this.lastIgnoredToken = -1; } // javadoc typeDecl.javadoc = this.javadoc; this.javadoc = null; } protected void consumeClassInstanceCreationExpression() { // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt classInstanceCreation(false); } protected void consumeClassInstanceCreationExpressionName() { // ClassInstanceCreationExpressionName ::= Name '.' pushOnExpressionStack(getUnspecifiedReferenceOptimized()); } protected void consumeClassInstanceCreationExpressionQualified() { // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt // ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt classInstanceCreation(true); QualifiedAllocationExpression qae = (QualifiedAllocationExpression) this.expressionStack[this.expressionPtr]; if (qae.anonymousType == null) { this.expressionLengthPtr--; 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); checkForDiamond(alloc.type); length = this.genericsLengthStack[this.genericsLengthPtr--]; this.genericsPtr -= length; System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length); this.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.UndocumentedEmptyBlock; } 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 = this.intStack[this.intPtr--]; checkForDiamond(allocationExpression.type); } } QualifiedAllocationExpression qae = (QualifiedAllocationExpression) this.expressionStack[this.expressionPtr]; if (qae.anonymousType == null) { this.expressionLengthPtr--; this.expressionPtr--; qae.enclosingInstance = this.expressionStack[this.expressionPtr]; 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); checkForDiamond(alloc.type); length = this.genericsLengthStack[this.genericsLengthPtr--]; this.genericsPtr -= length; System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length); this.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.UndocumentedEmptyBlock; } 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 = this.intStack[this.intPtr--]; checkForDiamond(allocationExpression.type); } } } 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, this.listLength counter will not have been reset, indicating that some items are available on the stack */ this.listLength++; } protected void consumeClassTypeList() { // ClassTypeList ::= ClassTypeList ',' ClassTypeElt optimizedConcatNodeLists(); } protected void consumeCompilationUnit() { // 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] = new ConditionalExpression( this.expressionStack[this.expressionPtr], 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 } protected void consumeConstructorBody() { // ConstructorBody ::= NestedMethod '{' BlockStatementsopt '}' // ConstructorBody ::= NestedMethod '{' ExplicitConstructorInvocation '}' this.nestedMethod[this.nestedType] --; } protected void consumeConstructorDeclaration() { // ConstructorDeclaration ::= ConstructorHeader ConstructorBody /* this.astStack : MethodDeclaration statements this.identifierStack : name ==> this.astStack : MethodDeclaration this.identifierStack : */ //must provide a default constructor call when needed int length; // pop the position of the { (body of the method) pushed in block decl this.intPtr--; this.intPtr--; //statements this.realBlockPtr--; ExplicitConstructorCall constructorCall = null; Statement[] statements = null; if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { this.astPtr -= length; if (!this.options.ignoreMethodBodies) { if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) { //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ? System.arraycopy( this.astStack, this.astPtr + 2, statements = new Statement[length - 1], 0, length - 1); constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1]; } else { //need to add explicitly the super(); System.arraycopy( this.astStack, this.astPtr + 1, statements = new Statement[length], 0, length); constructorCall = SuperReference.implicitSuperConstructorCall(); } } } else { boolean insideFieldInitializer = false; if (this.diet) { for (int i = this.nestedType; i > 0; i--){ if (this.variablesCounter[i] > 0) { insideFieldInitializer = true; break; } } } if (!this.diet || insideFieldInitializer){ // add it only in non-diet mode, if diet_bodies, then constructor call will be added elsewhere. constructorCall = SuperReference.implicitSuperConstructorCall(); } } // now we know that the top of stack is a constructorDeclaration ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr]; cd.constructorCall = constructorCall; cd.statements = statements; //highlight of the implicit call on the method name if (constructorCall != null && cd.constructorCall.sourceEnd == 0) { cd.constructorCall.sourceEnd = cd.sourceEnd; cd.constructorCall.sourceStart = cd.sourceStart; } if (!(this.diet && this.dietInt == 0) && statements == null && (constructorCall == null || constructorCall.isImplicitSuper()) && !containsComment(cd.bodyStart, this.endPosition)) { cd.bits |= ASTNode.UndocumentedEmptyBlock; } //watch for } that could be given as a unicode ! ( u007D 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 consumeConstructorHeader() { // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr]; if (this.currentToken == TokenNameLBRACE){ method.bodyStart = this.scanner.currentPosition; } // recovery if (this.currentElement != null){ if (this.currentToken == TokenNameSEMICOLON){ // for invalid constructors method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; method.declarationSourceEnd = this.scanner.currentPosition-1; method.bodyEnd = this.scanner.currentPosition-1; if (this.currentElement.parseTree() == method && this.currentElement.parent != null) { this.currentElement = this.currentElement.parent; } } this.restartRecovery = true; // used to avoid branching back into the regular automaton } } protected void consumeConstructorHeaderName() { /* 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 '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--; //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; //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 consumeCreateInitializer() { pushOnAstStack(new Initializer(null, 0)); } protected void consumeDefaultLabel() { // SwitchLabel ::= 'default' ':' CaseStatement defaultStatement = new CaseStatement(null, this.intStack[this.intPtr--], this.intStack[this.intPtr--]); // Look for $fall-through$ and $CASES-OMITTED$ tags in leading comment for case statement if (hasLeadingTagComment(FALL_THROUGH_TAG, defaultStatement.sourceStart)) { defaultStatement.bits |= ASTNode.DocumentedFallthrough; } if (hasLeadingTagComment(CASES_OMITTED_TAG, defaultStatement.sourceStart)) { defaultStatement.bits |= ASTNode.DocumentedCasesOmitted; } pushOnAstStack(defaultStatement); } protected void consumeDefaultModifiers() { checkComment(); // might update modifiers with AccDeprecated pushOnIntStack(this.modifiers); // modifiers pushOnIntStack( this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition); resetModifiers(); pushOnExpressionStackLengthStack(0); // no annotation } protected void consumeDiet() { // Diet ::= $empty checkComment(); pushOnIntStack(this.modifiersSourceStart); // push the start position of a javadoc comment if there is one resetModifiers(); jumpOverMethodBody(); } protected void consumeDims() { // Dims ::= DimsLoop pushOnIntStack(this.dimensions); this.dimensions = 0; } protected void consumeDimWithOrWithOutExpr() { // DimWithOrWithOutExpr ::= '[' ']' pushOnExpressionStack(null); if(this.currentElement != null && this.currentToken == TokenNameLBRACE) { this.ignoreNextOpeningBrace = true; this.currentElement.bracketBalance++; } } protected void consumeDimWithOrWithOutExprs() { // DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr concatExpressionLists(); } protected void consumeUnionType() { // UnionType ::= UnionType '|' Type pushOnAstStack(getTypeReference(this.intStack[this.intPtr--])); optimizedConcatNodeLists(); } protected void consumeUnionTypeAsClassType() { // UnionType ::= Type pushOnAstStack(getTypeReference(this.intStack[this.intPtr--])); } protected void consumeEmptyAnnotationTypeMemberDeclarationsopt() { // AnnotationTypeMemberDeclarationsopt ::= $empty pushOnAstLengthStack(0); } protected void consumeEmptyArgumentListopt() { // ArgumentListopt ::= $empty pushOnExpressionStackLengthStack(0); } protected void consumeEmptyArguments() { // Argumentsopt ::= $empty final FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr]; pushOnIntStack(fieldDeclaration.sourceEnd); pushOnExpressionStackLengthStack(0); } protected void consumeEmptyArrayInitializer() { // ArrayInitializer ::= '{' ,opt '}' arrayInitializer(0); } protected void consumeEmptyArrayInitializeropt() { // ArrayInitializeropt ::= $empty pushOnExpressionStackLengthStack(0); } protected void consumeEmptyBlockStatementsopt() { // BlockStatementsopt ::= $empty pushOnAstLengthStack(0); } protected void consumeEmptyCatchesopt() { // Catchesopt ::= $empty pushOnAstLengthStack(0); } protected void consumeEmptyClassBodyDeclarationsopt() { // ClassBodyDeclarationsopt ::= $empty pushOnAstLengthStack(0); } protected void consumeEmptyDimsopt() { // Dimsopt ::= $empty pushOnIntStack(0); } protected void consumeEmptyEnumDeclarations() { // EnumBodyDeclarationsopt ::= $empty pushOnAstLengthStack(0); } protected void consumeEmptyExpression() { // Expressionopt ::= $empty pushOnExpressionStackLengthStack(0); } protected void consumeEmptyForInitopt() { // ForInitopt ::= $empty pushOnAstLengthStack(0); } protected void consumeEmptyForUpdateopt() { // ForUpdateopt ::= $empty pushOnExpressionStackLengthStack(0); } protected void consumeEmptyInterfaceMemberDeclarationsopt() { // InterfaceMemberDeclarationsopt ::= $empty pushOnAstLengthStack(0); } protected void consumeEmptyInternalCompilationUnit() { // InternalCompilationUnit ::= $empty // nothing to do by default if (this.compilationUnit.isPackageInfo()) { this.compilationUnit.types = new TypeDeclaration[1]; this.compilationUnit.createPackageInfoType(); } } protected void consumeEmptyMemberValueArrayInitializer() { // MemberValueArrayInitializer ::= '{' ',' '}' // MemberValueArrayInitializer ::= '{' '}' arrayInitializer(0); } protected void consumeEmptyMemberValuePairsopt() { // MemberValuePairsopt ::= $empty pushOnAstLengthStack(0); } 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); } this.recordStringLiterals = true; } protected void consumeEmptyStatement() { // EmptyStatement ::= ';' char[] source = this.scanner.source; if (source[this.endStatementPosition] == ';') { pushOnAstStack(new EmptyStatement(this.endStatementPosition, this.endStatementPosition)); } else { if(source.length > 5) { int c1 = 0, c2 = 0, c3 = 0, c4 = 0; int pos = this.endStatementPosition - 4; while (source[pos] == 'u') { pos--; } if (source[pos] == '\\' && !((c1 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition - 3])) > 15 || c1 < 0 || (c2 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition - 2])) > 15 || c2 < 0 || (c3 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition - 1])) > 15 || c3 < 0 || (c4 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition])) > 15 || c4 < 0) && ((char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4)) == ';'){ // we have a Unicode for the ';' (/u003B) pushOnAstStack(new EmptyStatement(pos, this.endStatementPosition)); return; } } pushOnAstStack(new EmptyStatement(this.endPosition + 1, this.endStatementPosition)); } } protected void consumeEmptySwitchBlock() { // SwitchBlock ::= '{' '}' pushOnAstLengthStack(0); } protected void consumeEmptyTypeDeclaration() { // ClassMemberDeclaration ::= ';' // InterfaceMemberDeclaration ::= ';' // TypeDeclaration ::= ';' pushOnAstLengthStack(0); if(!this.statementRecoveryActivated) problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition); flushCommentsDefinedPriorTo(this.endStatementPosition); } 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.IsUsefulEmptyStatement; foreachStatement.sourceEnd = this.endStatementPosition; } protected void consumeEnhancedForStatementHeader(){ // EnhancedForStatementHeader ::= EnhancedForStatementHeaderInit ':' Expression ')' final ForeachStatement statement = (ForeachStatement) this.astStack[this.astPtr]; //updates are on the expression stack this.expressionLengthPtr--; final Expression collection = this.expressionStack[this.expressionPtr--]; statement.collection = collection; // https://bugs.eclipse.org/393719 - [compiler] inconsistent warnings on iteration variables // let declaration(Source)End include the collection to achieve that @SuppressWarnings affects this part, too: statement.elementVariable.declarationSourceEnd = collection.sourceEnd; statement.elementVariable.declarationEnd = collection.sourceEnd; statement.sourceEnd = this.rParenPos; if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { problemReporter().invalidUsageOfForeachStatements(statement.elementVariable, collection); } } protected void consumeEnhancedForStatementHeaderInit(boolean hasModifiers) { 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; localDeclaration.bits |= ASTNode.IsForeachElementVariable; 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; } 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, this.intStack[this.intPtr--]); pushOnAstStack(iteratorForStatement); iteratorForStatement.sourceEnd = localDeclaration.declarationSourceEnd; } protected void consumeEnterAnonymousClassBody(boolean qualified) { this.shouldDeferRecovery = false; // EnterAnonymousClassBody ::= $empty TypeReference typeReference = getTypeReference(0); TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); anonymousType.name = CharOperation.NO_CHAR; anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType); 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); } if (qualified) { this.expressionLengthPtr--; alloc.enclosingInstance = this.expressionStack[this.expressionPtr--]; } 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 // flush the comments related to the anonymous this.scanner.commentPtr = -1; // recovery if (this.currentElement != null){ this.lastCheckPoint = anonymousType.bodyStart; this.currentElement = this.currentElement.add(anonymousType, 0); if (!(this.currentElement instanceof RecoveredAnnotation)) { this.currentToken = 0; // opening brace already taken into account } else { this.ignoreNextOpeningBrace = true; this.currentElement.bracketBalance++; } this.lastIgnoredToken = -1; } } protected void consumeEnterCompilationUnit() { // EnterCompilationUnit ::= $empty // do nothing by default } protected void consumeEnterMemberValue() { // EnterMemberValue ::= $empty if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) { RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation)this.currentElement; recoveredAnnotation.hasPendingMemberValueName = true; } } protected void consumeEnterMemberValueArrayInitializer() { // EnterMemberValueArrayInitializer ::= $empty if(this.currentElement != null) { this.ignoreNextOpeningBrace = true; this.currentElement.bracketBalance++; } } protected void consumeEnterVariable() { // EnterVariable ::= $empty // do nothing by default char[] identifierName = this.identifierStack[this.identifierPtr]; long namePosition = this.identifierPositionStack[this.identifierPtr]; int extendedDimension = this.intStack[this.intPtr--]; AbstractVariableDeclaration declaration; // create the ast node boolean isLocalDeclaration = this.nestedMethod[this.nestedType] != 0; if (isLocalDeclaration) { // create the local variable declarations declaration = createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition); } else { // create the field declaration declaration = createFieldDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition); } this.identifierPtr--; this.identifierLengthPtr--; TypeReference type; int variableIndex = this.variablesCounter[this.nestedType]; int typeDim = 0; if (variableIndex == 0) { // first variable of the declaration (FieldDeclaration or LocalDeclaration) 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 declaration.declarationSourceStart = type.sourceStart; } pushOnAstStack(type); } else { type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension 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; } this.javadoc = null; } else { type = (TypeReference) this.astStack[this.astPtr - variableIndex]; typeDim = type.dimensions(); AbstractVariableDeclaration previousVariable = (AbstractVariableDeclaration) this.astStack[this.astPtr]; declaration.declarationSourceStart = previousVariable.declarationSourceStart; declaration.modifiers = previousVariable.modifiers; final Annotation[] annotations = previousVariable.annotations; if (annotations != null) { final int annotationsLength = annotations.length; System.arraycopy(annotations, 0, declaration.annotations = new Annotation[annotationsLength], 0, annotationsLength); } } if (extendedDimension == 0) { declaration.type = type; } else { int dimension = typeDim + extendedDimension; declaration.type = copyDims(type, dimension); } this.variablesCounter[this.nestedType]++; pushOnAstStack(declaration); // recovery if (this.currentElement != null) { if (!(this.currentElement instanceof RecoveredType) && (this.currentToken == TokenNameDOT //|| declaration.modifiers != 0 || (Util.getLineNumber(declaration.type.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr) != Util.getLineNumber((int) (namePosition >>> 32), this.scanner.lineEnds, 0, this.scanner.linePtr)))){ this.lastCheckPoint = (int) (namePosition >>> 32); this.restartRecovery = true; return; } if (isLocalDeclaration){ LocalDeclaration localDecl = (LocalDeclaration) this.astStack[this.astPtr]; this.lastCheckPoint = localDecl.sourceEnd + 1; this.currentElement = this.currentElement.add(localDecl, 0); } else { FieldDeclaration fieldDecl = (FieldDeclaration) this.astStack[this.astPtr]; this.lastCheckPoint = fieldDecl.sourceEnd + 1; this.currentElement = this.currentElement.add(fieldDecl, 0); } 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 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 = CharOperation.NO_CHAR; anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType); 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(); consumeNestedType(); this.variablesCounter[this.nestedType]++; 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; } // initialize the starting position of the allocation expression enumConstant.initialization.sourceStart = enumConstant.declarationSourceStart; // 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 = currentRecoveryType(); if(currentType != null) { currentType.insideEnumConstantPart = false; } } this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position this.lastIgnoredToken = -1; this.restartRecovery = true; } } } protected void consumeEnumConstantHeaderName() { if (this.currentElement != null) { if (!(this.currentElement instanceof RecoveredType || (this.currentElement instanceof RecoveredField && ((RecoveredField)this.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.identifierPtr--; 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 consumeEnumConstantNoClassBody() { // set declarationEnd and declarationSourceEnd int endOfEnumConstant = this.intStack[this.intPtr--]; final FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr]; fieldDeclaration.declarationEnd = endOfEnumConstant; fieldDeclaration.declarationSourceEnd = endOfEnumConstant; // initialize the starting position of the allocation expression ASTNode initialization = fieldDeclaration.initialization; if (initialization != null) { initialization.sourceEnd = endOfEnumConstant; } } 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; int declarationSourceEnd = anonymousType.declarationSourceEnd; fieldDeclaration.declarationSourceEnd = declarationSourceEnd; this.intPtr --; // remove end position of the arguments this.variablesCounter[this.nestedType] = 0; this.nestedType--; ASTNode initialization = fieldDeclaration.initialization; if (initialization != null) { initialization.sourceEnd = 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]; //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.ContainsAssertion; } enumDeclaration.addClinit(); enumDeclaration.bodyEnd = this.endStatementPosition; if (length == 0 && !containsComment(enumDeclaration.bodyStart, enumDeclaration.bodyEnd)) { enumDeclaration.bits |= ASTNode.UndocumentedEmptyBlock; } 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.IsMemberType; } } 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--] | ClassFileConstants.AccEnum; if (enumDeclaration.modifiersSourceStart >= 0) { enumDeclaration.declarationSourceStart = enumDeclaration.modifiersSourceStart; } // Store secondary info if ((enumDeclaration.bits & ASTNode.IsMemberType) == 0 && (enumDeclaration.bits & ASTNode.IsLocalType) == 0) { if (this.compilationUnit != null && !CharOperation.equals(enumDeclaration.name, this.compilationUnit.getMainTypeName())) { enumDeclaration.bits |= ASTNode.IsSecondaryType; } } // 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(!this.statementRecoveryActivated && this.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 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 consumeEnumHeaderNameWithTypeParameters() { // EnumHeaderNameWithTypeParameters ::= Modifiersopt 'enum' Identifier TypeParameters TypeDeclaration enumDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult); // consume type parameters int length = this.genericsLengthStack[this.genericsLengthPtr--]; this.genericsPtr -= length; System.arraycopy(this.genericsStack, this.genericsPtr + 1, enumDeclaration.typeParameters = new TypeParameter[length], 0, length); problemReporter().invalidUsageOfTypeParametersForEnumDeclaration(enumDeclaration); enumDeclaration.bodyStart = enumDeclaration.typeParameters[length-1].declarationSourceEnd + 1; // enumDeclaration.typeParameters = null; this.listTypeParameterLength = 0; if (this.nestedMethod[this.nestedType] == 0) { if (this.nestedType != 0) { enumDeclaration.bits |= ASTNode.IsMemberType; } } 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--] | ClassFileConstants.AccEnum; if (enumDeclaration.modifiersSourceStart >= 0) { enumDeclaration.declarationSourceStart = enumDeclaration.modifiersSourceStart; } // Store secondary info if ((enumDeclaration.bits & ASTNode.IsMemberType) == 0 && (enumDeclaration.bits & ASTNode.IsLocalType) == 0) { if (this.compilationUnit != null && !CharOperation.equals(enumDeclaration.name, this.compilationUnit.getMainTypeName())) { enumDeclaration.bits |= ASTNode.IsSecondaryType; } } // consume annotations 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(!this.statementRecoveryActivated && this.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 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 //optimize the push/pop this.expressionPtr--; this.expressionLengthPtr--; this.expressionStack[this.expressionPtr] = new EqualExpression( this.expressionStack[this.expressionPtr], 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 consumeExitMemberValue() { // ExitMemberValue ::= $empty if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) { RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation)this.currentElement; recoveredAnnotation.hasPendingMemberValueName = false; recoveredAnnotation.memberValuPairEqualEnd = -1; } } protected void consumeExitTryBlock() { //ExitTryBlock ::= $empty if(this.currentElement != null) { this.restartRecovery = true; } } protected void consumeExitVariableWithInitialization() { // ExitVariableWithInitialization ::= $empty // do nothing by default this.expressionLengthPtr--; AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr]; variableDecl.initialization = this.expressionStack[this.expressionPtr--]; // we need to update the declarationSourceEnd of the local variable declaration to the // source end position of the initialization expression variableDecl.declarationSourceEnd = variableDecl.initialization.sourceEnd; variableDecl.declarationEnd = variableDecl.initialization.sourceEnd; recoveryExitFromVariable(); } protected void consumeExitVariableWithoutInitialization() { // ExitVariableWithoutInitialization ::= $empty // do nothing by default 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); } } recoveryExitFromVariable(); } protected void consumeExplicitConstructorInvocation(int flag, int recFlag) { /* flag allows to distinguish 3 cases : (0) : ExplicitConstructorInvocation ::= 'this' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= 'super' '(' ArgumentListopt ')' ';' (1) : ExplicitConstructorInvocation ::= Primary '.' 'super' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= Primary '.' 'this' '(' ArgumentListopt ')' ';' (2) : ExplicitConstructorInvocation ::= Name '.' 'super' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= Name '.' '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); } 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.endStatementPosition; } 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[this.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.endStatementPosition; } protected void consumeExpressionStatement() { // ExpressionStatement ::= StatementExpression ';' this.expressionLengthPtr--; Expression expression = this.expressionStack[this.expressionPtr--]; expression.statementEnd = this.endStatementPosition; expression.bits |= ASTNode.InsideExpressionStatement; pushOnAstStack(expression); } protected void consumeFieldAccess(boolean isSuperAccess) { // FieldAccess ::= Primary '.' 'Identifier' // FieldAccess ::= 'super' '.' 'Identifier' FieldReference fr = new FieldReference( this.identifierStack[this.identifierPtr], this.identifierPositionStack[this.identifierPtr--]); this.identifierLengthPtr--; if (isSuperAccess) { //considers the fieldReference beginning at the 'super' .... fr.sourceStart = this.intStack[this.intPtr--]; fr.receiver = new SuperReference(fr.sourceStart, this.endPosition); pushOnExpressionStack(fr); } else { //optimize push/pop fr.receiver = this.expressionStack[this.expressionPtr]; //field reference begins at the receiver fr.sourceStart = fr.receiver.sourceStart; this.expressionStack[this.expressionPtr] = fr; } } protected void consumeFieldDeclaration() { // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';' /* this.astStack : this.expressionStack: Expression Expression ...... Expression this.identifierStack : type identifier identifier ...... identifier this.intStack : typeDim dim dim dim ==> this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration this.expressionStack : this.identifierStack : this.intStack : */ int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr]; for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) { FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr - i]; fieldDeclaration.declarationSourceEnd = this.endStatementPosition; fieldDeclaration.declarationEnd = this.endStatementPosition; // semi-colon included } updateSourceDeclarationParts(variableDeclaratorsCounter); int endPos = flushCommentsDefinedPriorTo(this.endStatementPosition); if (endPos != this.endStatementPosition) { for (int i = 0; i < variableDeclaratorsCounter; i++) { FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr - i]; fieldDeclaration.declarationSourceEnd = endPos; } } // update the this.astStack, this.astPtr and this.astLengthStack int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1; System.arraycopy( this.astStack, startIndex, this.astStack, startIndex - 1, variableDeclaratorsCounter); this.astPtr--; // remove the type reference this.astLengthStack[--this.astLengthPtr] = variableDeclaratorsCounter; // recovery if (this.currentElement != null) { this.lastCheckPoint = endPos + 1; if (this.currentElement.parent != null && this.currentElement instanceof RecoveredField){ if (!(this.currentElement instanceof RecoveredInitializer)) { this.currentElement = this.currentElement.parent; } } this.restartRecovery = true; } this.variablesCounter[this.nestedType] = 0; } protected void consumeForceNoDiet() { // ForceNoDiet ::= $empty this.dietInt++; } protected void consumeForInit() { // ForInit ::= StatementExpressionList pushOnAstLengthStack(-1); } protected void consumeFormalParameter(boolean isVarArgs) { // FormalParameter ::= Type VariableDeclaratorId ==> false // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true /* this.astStack : this.identifierStack : type identifier this.intStack : dim dim ==> this.astStack : Argument this.identifierStack : this.intStack : */ this.identifierLengthPtr--; char[] identifierName = this.identifierStack[this.identifierPtr]; long namePositions = this.identifierPositionStack[this.identifierPtr--]; 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 = copyDims(type, typeDimensions + 1); if (extendedDimensions == 0) { type.sourceEnd = endOfEllipsis; } type.bits |= ASTNode.IsVarArgs; // set isVarArgs } int modifierPositions = this.intStack[this.intPtr--]; this.intPtr--; Argument arg = new Argument( identifierName, namePositions, type, this.intStack[this.intPtr + 1] & ~ClassFileConstants.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); RecoveredType currentRecoveryType = this.currentRecoveryType(); if (currentRecoveryType != null) currentRecoveryType.annotationsConsumed(arg.annotations); } pushOnAstStack(arg); /* 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 (!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { problemReporter().invalidUsageOfVarargs(arg); } else if (!this.statementRecoveryActivated && extendedDimensions > 0) { problemReporter().illegalExtendedDimensions(arg); } } } protected void consumeFormalParameterList() { // FormalParameterList ::= FormalParameterList ',' FormalParameter optimizedConcatNodeLists(); } protected void consumeFormalParameterListopt() { // FormalParameterListopt ::= $empty pushOnAstLengthStack(0); } protected void consumeGenericType() { // GenericType ::= ClassOrInterface TypeArguments // nothing to do // Will be consume by a getTypeReference call } protected void consumeGenericTypeArrayType() { // nothing to do // Will be consume by a getTypeReference call } protected void consumeGenericTypeNameArrayType() { // nothing to do // Will be consume by a getTypeReference call } protected void consumeGenericTypeWithDiamond() { // GenericType ::= ClassOrInterface '<' '>' // zero type arguments == <> pushOnGenericsLengthStack(-1); concatGenericsLists(); this.intPtr--; // pop the null dimension pushed in by consumeReferenceType, as we have no type between <>, getTypeReference won't kick in } 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 = 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 pushOnGenericsLengthStack(0); // handle type arguments pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]); pushOnExpressionStack(getTypeReference(0)); } protected void consumeInsideCastExpressionWithQualifiedGenerics() { // InsideCastExpressionWithQualifiedGenerics ::= $empty } protected void consumeInstanceOfExpression() { // RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType //optimize the push/pop //by construction, no base type may be used in getTypeReference Expression exp; this.expressionStack[this.expressionPtr] = exp = new InstanceOfExpression( this.expressionStack[this.expressionPtr], getTypeReference(this.intStack[this.intPtr--])); if (exp.sourceEnd == 0) { //array on base type.... exp.sourceEnd = this.scanner.startPosition - 1; } //the scanner is on the next token already.... } protected void consumeInstanceOfExpressionWithName() { // 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); 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 int length; if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { //there are length declarations //dispatch.....according to the type of the declarations dispatchDeclarationInto(length); } TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; //convert constructor that do not have the type's name into methods typeDecl.checkConstructors(this); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=212713, // reject initializers that have been tolerated by the grammar. FieldDeclaration [] fields = typeDecl.fields; int fieldCount = fields == null ? 0 : fields.length; for (int i = 0; i < fieldCount; i++) { FieldDeclaration field = fields[i]; if (field instanceof Initializer) { problemReporter().interfaceCannotHaveInitializers(typeDecl.name, field); } } //always add (will be remove at code gen time if empty) if (this.scanner.containsAssertKeyword) { typeDecl.bits |= ASTNode.ContainsAssertion; } typeDecl.addClinit(); typeDecl.bodyEnd = this.endStatementPosition; if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) { typeDecl.bits |= ASTNode.UndocumentedEmptyBlock; } typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); } protected void consumeInterfaceHeader() { // InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt 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 interface header this.scanner.commentPtr = -1; } protected void consumeInterfaceHeaderExtends() { // InterfaceHeaderExtends ::= 'extends' InterfaceTypeList int length = this.astLengthStack[this.astLengthPtr--]; //super interfaces this.astPtr -= length; TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; System.arraycopy( this.astStack, this.astPtr + 1, 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 if (this.currentElement != null) { this.lastCheckPoint = typeDecl.bodyStart; } } protected void consumeInterfaceHeaderName1() { // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier' TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); if (this.nestedMethod[this.nestedType] == 0) { if (this.nestedType != 0) { typeDecl.bits |= ASTNode.IsMemberType; } } else { // Record that the block has a declaration for local types typeDecl.bits |= ASTNode.IsLocalType; markEnclosingMemberWithLocalType(); blockReal(); } //highlight the name of the type long pos = this.identifierPositionStack[this.identifierPtr]; typeDecl.sourceEnd = (int) pos; typeDecl.sourceStart = (int) (pos >>> 32); typeDecl.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. 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--] | ClassFileConstants.AccInterface; if (typeDecl.modifiersSourceStart >= 0) { typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart; } // Store secondary info if ((typeDecl.bits & ASTNode.IsMemberType) == 0 && (typeDecl.bits & ASTNode.IsLocalType) == 0) { if (this.compilationUnit != null && !CharOperation.equals(typeDecl.name, this.compilationUnit.getMainTypeName())) { typeDecl.bits |= ASTNode.IsSecondaryType; } } // 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 // recovery if (this.currentElement != null){ // is recovering this.lastCheckPoint = typeDecl.bodyStart; this.currentElement = this.currentElement.add(typeDecl, 0); this.lastIgnoredToken = -1; } // javadoc typeDecl.javadoc = this.javadoc; this.javadoc = null; } protected void consumeInterfaceMemberDeclarations() { // InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration concatNodeLists(); } protected void consumeInterfaceMemberDeclarationsopt() { // InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations this.nestedType--; } protected void consumeInterfaceType() { // InterfaceType ::= ClassOrInterfaceType pushOnAstStack(getTypeReference(0)); /* if incomplete type header, this.listLength counter will not have been reset, indicating that some interfaces are available on the stack */ this.listLength++; } protected void consumeInterfaceTypeList() { // InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType optimizedConcatNodeLists(); } protected void consumeInternalCompilationUnit() { // InternalCompilationUnit ::= PackageDeclaration // InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports // InternalCompilationUnit ::= ImportDeclarations ReduceImports if (this.compilationUnit.isPackageInfo()) { this.compilationUnit.types = new TypeDeclaration[1]; this.compilationUnit.createPackageInfoType(); } } 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) { if (this.compilationUnit.isPackageInfo()) { this.compilationUnit.types = new TypeDeclaration[length + 1]; this.astPtr -= length; System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types, 1, length); this.compilationUnit.createPackageInfoType(); } else { this.compilationUnit.types = new TypeDeclaration[length]; this.astPtr -= length; System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types, 0, length); } } } protected void consumeInvalidAnnotationTypeDeclaration() { // BlockStatement ::= AnnotationTypeDeclaration TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); // remove the ast node created in interface header this.astPtr--; pushOnAstLengthStack(-1); concatNodeLists(); } 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 |= ExtraCompilerModifiers.AccSemicolonBody; // remember semi-colon body } protected void consumeInvalidConstructorDeclaration(boolean hasBody) { // InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody ==> true // InvalidConstructorDeclaration ::= ConstructorHeader ';' ==> false /* this.astStack : modifiers arguments throws statements this.identifierStack : name ==> this.astStack : MethodDeclaration this.identifierStack : */ if (hasBody) { // pop the position of the { (body of the method) pushed in block decl this.intPtr--; } //statements if (hasBody) { this.realBlockPtr--; } int length; if (hasBody && ((length = this.astLengthStack[this.astLengthPtr--]) != 0)) { this.astPtr -= length; } ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) this.astStack[this.astPtr]; constructorDeclaration.bodyEnd = this.endStatementPosition; constructorDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); if (!hasBody) { constructorDeclaration.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; } } protected void consumeInvalidEnumDeclaration() { // BlockStatement ::= EnumDeclaration TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); // remove the ast node created in interface header this.astPtr--; pushOnAstLengthStack(-1); concatNodeLists(); } protected void consumeInvalidInterfaceDeclaration() { // BlockStatement ::= InvalidInterfaceDeclaration //InterfaceDeclaration ::= Modifiersopt 'interface' 'Identifier' ExtendsInterfacesopt InterfaceHeader InterfaceBody TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); // remove the ast node created in interface header this.astPtr--; pushOnAstLengthStack(-1); concatNodeLists(); } protected void consumeInvalidMethodDeclaration() { // InterfaceMemberDeclaration ::= InvalidMethodDeclaration /* this.astStack : modifiers arguments throws statements this.identifierStack : type name this.intStack : dim dim dim ==> this.astStack : MethodDeclaration this.identifierStack : this.intStack : */ // pop the position of the { (body of the method) pushed in block decl this.intPtr--; // retrieve end position of method declarator //statements this.realBlockPtr--; int length; if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { this.astPtr -= length; } //watch for } that could be given as a unicode ! ( u007D is '}' ) MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr]; md.bodyEnd = this.endPosition; md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); // report the problem and continue the parsing - narrowing the problem onto the method if(!this.statementRecoveryActivated) problemReporter().abstractMethodNeedingNoBody(md); } protected void consumeLabel() { // Do nothing } protected void consumeLeftParen() { // PushLPAREN ::= '(' pushOnIntStack(this.lParenPos); } protected void consumeLocalVariableDeclaration() { // LocalVariableDeclaration ::= Modifiers Type VariableDeclarators ';' /* this.astStack : this.expressionStack: Expression Expression ...... Expression this.identifierStack : type identifier identifier ...... identifier this.intStack : typeDim dim dim dim ==> this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration this.expressionStack : this.identifierStack : this.intStack : */ int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr]; // update the this.astStack, this.astPtr and this.astLengthStack int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1; System.arraycopy( this.astStack, startIndex, this.astStack, startIndex - 1, variableDeclaratorsCounter); this.astPtr--; // remove the type reference this.astLengthStack[--this.astLengthPtr] = variableDeclaratorsCounter; this.variablesCounter[this.nestedType] = 0; } protected void consumeLocalVariableDeclarationStatement() { // LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';' // see blockReal in case of change: duplicated code // increment the amount of declared variables for this block this.realBlockStack[this.realBlockPtr]++; // update source end to include the semi-colon int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr]; for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) { LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr - i]; localDeclaration.declarationSourceEnd = this.endStatementPosition; localDeclaration.declarationEnd = this.endStatementPosition; // semi-colon included } } protected void consumeMarkerAnnotation() { // MarkerAnnotation ::= '@' Name MarkerAnnotation markerAnnotation = null; int oldIndex = this.identifierPtr; TypeReference typeReference = getAnnotationType(); markerAnnotation = new MarkerAnnotation(typeReference, this.intStack[this.intPtr--]); markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd; pushOnExpressionStack(markerAnnotation); if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { problemReporter().invalidUsageOfAnnotation(markerAnnotation); } this.recordStringLiterals = true; if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) { this.currentElement = ((RecoveredAnnotation)this.currentElement).addAnnotation(markerAnnotation, oldIndex); } } 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); if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) { RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation) this.currentElement; recoveredAnnotation.setKind(RecoveredAnnotation.NORMAL); } } protected void consumeMemberValuePairs() { // MemberValuePairs ::= MemberValuePairs ',' MemberValuePair concatNodeLists(); } protected void consumeMemberValues() { // MemberValues ::= MemberValues ',' MemberValue concatExpressionLists(); } protected void consumeMethodBody() { // MethodBody ::= NestedMethod '{' BlockStatementsopt '}' this.nestedMethod[this.nestedType] --; } protected void consumeMethodDeclaration(boolean isNotAbstract) { // MethodDeclaration ::= MethodHeader MethodBody // AbstractMethodDeclaration ::= MethodHeader ';' /* this.astStack : modifiers arguments throws statements this.identifierStack : type name this.intStack : dim dim dim ==> this.astStack : MethodDeclaration this.identifierStack : this.intStack : */ int length; if (isNotAbstract) { // pop the position of the { (body of the method) pushed in block decl this.intPtr--; this.intPtr--; } int explicitDeclarations = 0; Statement[] statements = null; if (isNotAbstract) { //statements explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; if (!this.options.ignoreMethodBodies) { if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { System.arraycopy( this.astStack, (this.astPtr -= length) + 1, statements = new Statement[length], 0, length); } } else { length = this.astLengthStack[this.astLengthPtr--]; this.astPtr -= length; } } // now we know that we have a method declaration at the top of the ast stack MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr]; md.statements = statements; md.explicitDeclarations = explicitDeclarations; // cannot be done in consumeMethodHeader because we have no idea whether or not there // is a body when we reduce the method header if (!isNotAbstract) { //remember the fact that the method has a semicolon body md.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; } else if (!(this.diet && this.dietInt == 0) && statements == null && !containsComment(md.bodyStart, this.endPosition)) { md.bits |= ASTNode.UndocumentedEmptyBlock; } // 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]; if (this.currentToken == TokenNameLBRACE){ method.bodyStart = this.scanner.currentPosition; } // recovery if (this.currentElement != null){ // 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 |= ExtraCompilerModifiers.AccSemicolonBody; method.declarationSourceEnd = this.scanner.currentPosition-1; method.bodyEnd = this.scanner.currentPosition-1; if (this.currentElement.parseTree() == method && this.currentElement.parent != null) { this.currentElement = this.currentElement.parent; } } else if(this.currentToken == TokenNameLBRACE) { if (this.currentElement instanceof RecoveredMethod && ((RecoveredMethod)this.currentElement).methodDeclaration != method) { this.ignoreNextOpeningBrace = true; this.currentElement.bracketBalance++; } } 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) { this.intPtr--; // we get rid of the position of the default keyword this.intPtr--; // we get rid of the position of the default keyword if(md.isAnnotationMethod()) { ((AnnotationMethodDeclaration)md).defaultValue = this.expressionStack[this.expressionPtr]; md.modifiers |= ClassFileConstants.AccAnnotationDefault; } this.expressionPtr--; this.recordStringLiterals = true; } 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; int dims = returnType.dimensions() + extendedDims; md.returnType = copyDims(returnType, dims); if (this.currentToken == TokenNameLBRACE){ md.bodyStart = this.endPosition + 1; } // recovery if (this.currentElement != null){ this.lastCheckPoint = md.bodyStart; } } } protected void consumeMethodHeaderName(boolean isAnnotationMethod) { // MethodHeaderName ::= Modifiersopt Type 'Identifier' '(' // AnnotationMethodHeaderName ::= Modifiersopt Type 'Identifier' '(' // RecoveryMethodHeaderName ::= Modifiersopt Type 'Identifier' '(' MethodDeclaration md = null; if(isAnnotationMethod) { md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult); this.recordStringLiterals = false; } 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 || (Util.getLineNumber(md.returnType.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr) == Util.getLineNumber(md.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr))){ 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); this.recordStringLiterals = false; } 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--]); // 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; //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){ boolean isType; if ((isType = this.currentElement instanceof RecoveredType) //|| md.modifiers != 0 || (Util.getLineNumber(md.returnType.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr) == Util.getLineNumber(md.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr))){ if(isType) { ((RecoveredType) this.currentElement).pendingTypeParameters = null; } this.lastCheckPoint = md.bodyStart; this.currentElement = this.currentElement.add(md, 0); this.lastIgnoredToken = -1; } else { this.lastCheckPoint = md.sourceStart; this.restartRecovery = true; } } } protected void consumeMethodHeaderRightParen() { // MethodHeaderParameters ::= FormalParameterListopt ')' int length = this.astLengthStack[this.astLengthPtr--]; this.astPtr -= length; AbstractMethodDeclaration md = (AbstractMethodDeclaration) this.astStack[this.astPtr]; md.sourceEnd = this.rParenPos; //arguments if (length != 0) { System.arraycopy( this.astStack, this.astPtr + 1, md.arguments = new Argument[length], 0, length); } md.bodyStart = this.rParenPos+1; this.listLength = 0; // reset this.listLength after having read all parameters // recovery if (this.currentElement != null){ this.lastCheckPoint = md.bodyStart; if (this.currentElement.parseTree() == md) return; // might not have been attached yet - in some constructor scenarii if (md.isConstructor()){ if ((length != 0) || (this.currentToken == TokenNameLBRACE) || (this.currentToken == TokenNamethrows)){ this.currentElement = this.currentElement.add(md, 0); this.lastIgnoredToken = -1; } } } } protected void consumeMethodHeaderThrowsClause() { // MethodHeaderThrowsClause ::= 'throws' ClassTypeList int length = this.astLengthStack[this.astLengthPtr--]; this.astPtr -= length; AbstractMethodDeclaration md = (AbstractMethodDeclaration) this.astStack[this.astPtr]; System.arraycopy( this.astStack, this.astPtr + 1, md.thrownExceptions = new TypeReference[length], 0, length); md.sourceEnd = md.thrownExceptions[length-1].sourceEnd; md.bodyStart = md.thrownExceptions[length-1].sourceEnd + 1; 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 ')' // when the name is only an identifier...we have a message send to "this" (implicit) MessageSend m = newMessageSend(); m.sourceEnd = this.rParenPos; m.sourceStart = (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); m.selector = this.identifierStack[this.identifierPtr--]; if (this.identifierLengthStack[this.identifierLengthPtr] == 1) { m.receiver = ThisReference.implicitThis(); this.identifierLengthPtr--; } else { this.identifierLengthStack[this.identifierLengthPtr]--; m.receiver = getUnspecifiedReference(); m.sourceStart = m.receiver.sourceStart; } 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); this.intPtr--; m.receiver = getUnspecifiedReference(); m.sourceStart = m.receiver.sourceStart; pushOnExpressionStack(m); } protected void consumeMethodInvocationPrimary() { //optimize the push/pop //MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')' MessageSend m = newMessageSend(); m.sourceStart = (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); m.selector = this.identifierStack[this.identifierPtr--]; this.identifierLengthPtr--; m.receiver = this.expressionStack[this.expressionPtr]; m.sourceStart = m.receiver.sourceStart; 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); this.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 ')' MessageSend m = newMessageSend(); m.sourceStart = this.intStack[this.intPtr--]; // start position of the super keyword m.sourceEnd = this.rParenPos; m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]; m.selector = this.identifierStack[this.identifierPtr--]; this.identifierLengthPtr--; m.receiver = new SuperReference(m.sourceStart, this.endPosition); pushOnExpressionStack(m); } protected void consumeMethodInvocationSuperWithTypeArguments() { // MethodInvocation ::= 'super' '.' TypeArguments 'Identifier' '(' ArgumentListopt ')' MessageSend m = newMessageSendWithTypeArguments(); this.intPtr--; // start position of the typeArguments 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); m.sourceStart = this.intStack[this.intPtr--]; // start position of the super keyword m.receiver = new SuperReference(m.sourceStart, this.endPosition); pushOnExpressionStack(m); } protected void consumeModifiers() { int savedModifiersSourceStart = this.modifiersSourceStart; checkComment(); // might update modifiers with AccDeprecated pushOnIntStack(this.modifiers); // modifiers if (this.modifiersSourceStart >= savedModifiersSourceStart) { this.modifiersSourceStart = savedModifiersSourceStart; } pushOnIntStack(this.modifiersSourceStart); resetModifiers(); } protected void consumeModifiers2() { this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--]; } protected void consumeMultipleResources() { // Resources ::= Resources ';' Resource concatNodeLists(); } protected void consumeNameArrayType() { pushOnGenericsLengthStack(0); // handle type arguments pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]); } protected void consumeNestedMethod() { // NestedMethod ::= $empty jumpOverMethodBody(); this.nestedMethod[this.nestedType] ++; pushOnIntStack(this.scanner.currentPosition); consumeOpenBlock(); } protected void consumeNestedType() { // NestedType ::= $empty int length = this.nestedMethod.length; if (++this.nestedType >= length) { System.arraycopy( this.nestedMethod, 0, this.nestedMethod = new int[length + 30], 0, length); // increase the size of the variablesCounter as well. It has to be consistent with the size of the nestedMethod collection System.arraycopy( this.variablesCounter, 0, this.variablesCounter = new int[length + 30], 0, length); } this.nestedMethod[this.nestedType] = 0; this.variablesCounter[this.nestedType] = 0; } protected void consumeNormalAnnotation() { // NormalAnnotation ::= '@' Name '(' MemberValuePairsopt ')' NormalAnnotation normalAnnotation = null; int oldIndex = this.identifierPtr; TypeReference typeReference = getAnnotationType(); normalAnnotation = new NormalAnnotation(typeReference, this.intStack[this.intPtr--]); int length; if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { System.arraycopy( this.astStack, (this.astPtr -= length) + 1, normalAnnotation.memberValuePairs = new MemberValuePair[length], 0, length); } normalAnnotation.declarationSourceEnd = this.rParenPos; pushOnExpressionStack(normalAnnotation); if(this.currentElement != null) { annotationRecoveryCheckPoint(normalAnnotation.sourceStart, normalAnnotation.declarationSourceEnd); if (this.currentElement instanceof RecoveredAnnotation) { this.currentElement = ((RecoveredAnnotation)this.currentElement).addAnnotation(normalAnnotation, oldIndex); } } if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { problemReporter().invalidUsageOfAnnotation(normalAnnotation); } this.recordStringLiterals = true; } protected void consumeOneDimLoop() { // OneDimLoop ::= '[' ']' this.dimensions++; } protected void consumeOnlySynchronized() { // OnlySynchronized ::= 'synchronized' pushOnIntStack(this.synchronizedBlockSourceStart); resetModifiers(); this.expressionLengthPtr--; } protected void consumeOnlyTypeArguments() { if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { int length = this.genericsLengthStack[this.genericsLengthPtr]; problemReporter().invalidUsageOfTypeArguments( (TypeReference)this.genericsStack[this.genericsPtr - length + 1], (TypeReference)this.genericsStack[this.genericsPtr]); } } protected void consumeOnlyTypeArgumentsForCastExpression() { // OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments } protected void consumeOpenBlock() { // OpenBlock ::= $empty pushOnIntStack(this.scanner.startPosition); int stackLength = this.realBlockStack.length; if (++this.realBlockPtr >= stackLength) { System.arraycopy( this.realBlockStack, 0, this.realBlockStack = new int[stackLength + StackIncrement], 0, stackLength); } this.realBlockStack[this.realBlockPtr] = 0; } protected void consumePackageComment() { // get possible comment for syntax since 1.5 if(this.options.sourceLevel >= ClassFileConstants.JDK1_5) { checkComment(); resetModifiers(); } } protected void consumePackageDeclaration() { // PackageDeclaration ::= 'package' Name ';' /* build an ImportRef build from the last name stored in the identifier stack. */ ImportReference impt = this.compilationUnit.currentPackage; this.compilationUnit.javadoc = this.javadoc; this.javadoc = null; // flush comments defined prior to import statements impt.declarationEnd = this.endStatementPosition; impt.declarationSourceEnd = flushCommentsDefinedPriorTo(impt.declarationSourceEnd); } protected void consumePackageDeclarationName() { // PackageDeclarationName ::= '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); impt = new ImportReference(tokens, positions, false, ClassFileConstants.AccDefault); this.compilationUnit.currentPackage = impt; 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--]; // get possible comment source start if(this.javadoc != null) { impt.declarationSourceStart = this.javadoc.sourceStart; } // recovery if (this.currentElement != null){ this.lastCheckPoint = impt.declarationSourceEnd+1; this.restartRecovery = true; // used to avoid branching back into the regular automaton } } 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, false, 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; this.intPtr--; // we don't need the position of the 'package keyword } else { impt.declarationSourceStart = this.intStack[this.intPtr--]; // get possible comment source start if (this.javadoc != null) { impt.declarationSourceStart = this.javadoc.sourceStart; } } 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( 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--; // remove the class start position pushOnExpressionStack( 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 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 // PushPosition ::= $empty pushOnIntStack(this.endPosition); } protected void consumePushRealModifiers() { checkComment(); // might update modifiers with AccDeprecated pushOnIntStack(this.modifiers); // modifiers pushOnIntStack(this.modifiersSourceStart); resetModifiers(); } protected void consumeQualifiedName() { // QualifiedName ::= Name '.' SimpleName /*back from the recursive loop of QualifiedName. Updates identifier length into the length stack*/ 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 & ClassFileConstants.AccAnnotation) != 0; } else { RecoveredType recoveredType = this.currentElement.enclosingType(); if(recoveredType != null) { isAnnotationMethod = (recoveredType.typeDeclaration.modifiers & ClassFileConstants.AccAnnotation) != 0; } } 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 & ClassFileConstants.AccAnnotation) != 0; } else { RecoveredType recoveredType = this.currentElement.enclosingType(); if(recoveredType != null) { isAnnotationMethod = (recoveredType.typeDeclaration.modifiers & ClassFileConstants.AccAnnotation) != 0; } } 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() { 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 consumeResourceAsLocalVariableDeclaration() { // Resource ::= Type PushModifiers VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization // Resource ::= Modifiers Type PushRealModifiers VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization consumeLocalVariableDeclaration(); } protected void consumeResourceSpecification() { // ResourceSpecification ::= '(' Resources ')' } protected void consumeResourceOptionalTrailingSemiColon(boolean punctuated) { // TrailingSemiColon ::= ';' LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr]; if (punctuated) { localDeclaration.declarationSourceEnd = this.endStatementPosition; } } protected void consumeRestoreDiet() { // RestoreDiet ::= $empty this.dietInt--; } protected void consumeRightParen() { // PushRPAREN ::= ')' pushOnIntStack(this.rParenPos); } // This method is part of an automatic generation : do NOT edit-modify protected void consumeRule(int act) { switch ( act ) { case 30 : if (DEBUG) { System.out.println("Type ::= PrimitiveType"); } //$NON-NLS-1$ consumePrimitiveType(); break; case 44 : if (DEBUG) { System.out.println("ReferenceType ::= ClassOrInterfaceType"); } //$NON-NLS-1$ consumeReferenceType(); break; case 48 : if (DEBUG) { System.out.println("ClassOrInterface ::= Name"); } //$NON-NLS-1$ consumeClassOrInterfaceName(); break; case 49 : if (DEBUG) { System.out.println("ClassOrInterface ::= GenericType DOT Name"); } //$NON-NLS-1$ consumeClassOrInterface(); break; case 50 : if (DEBUG) { System.out.println("GenericType ::= ClassOrInterface TypeArguments"); } //$NON-NLS-1$ consumeGenericType(); break; case 51 : if (DEBUG) { System.out.println("GenericType ::= ClassOrInterface LESS GREATER"); } //$NON-NLS-1$ consumeGenericTypeWithDiamond(); break; case 52 : if (DEBUG) { System.out.println("ArrayTypeWithTypeArgumentsName ::= GenericType DOT Name"); } //$NON-NLS-1$ consumeArrayTypeWithTypeArgumentsName(); break; case 53 : if (DEBUG) { System.out.println("ArrayType ::= PrimitiveType Dims"); } //$NON-NLS-1$ consumePrimitiveArrayType(); break; case 54 : if (DEBUG) { System.out.println("ArrayType ::= Name Dims"); } //$NON-NLS-1$ consumeNameArrayType(); break; case 55 : if (DEBUG) { System.out.println("ArrayType ::= ArrayTypeWithTypeArgumentsName Dims"); } //$NON-NLS-1$ consumeGenericTypeNameArrayType(); break; case 56 : if (DEBUG) { System.out.println("ArrayType ::= GenericType Dims"); } //$NON-NLS-1$ consumeGenericTypeArrayType(); break; case 61 : if (DEBUG) { System.out.println("QualifiedName ::= Name DOT SimpleName"); } //$NON-NLS-1$ consumeQualifiedName(); break; case 62 : if (DEBUG) { System.out.println("CompilationUnit ::= EnterCompilationUnit..."); } //$NON-NLS-1$ consumeCompilationUnit(); break; case 63 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration"); } //$NON-NLS-1$ consumeInternalCompilationUnit(); break; case 64 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); } //$NON-NLS-1$ consumeInternalCompilationUnit(); break; case 65 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); } //$NON-NLS-1$ consumeInternalCompilationUnitWithTypes(); break; case 66 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); } //$NON-NLS-1$ consumeInternalCompilationUnitWithTypes(); break; case 67 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); } //$NON-NLS-1$ consumeInternalCompilationUnit(); break; case 68 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= TypeDeclarations"); } //$NON-NLS-1$ consumeInternalCompilationUnitWithTypes(); break; case 69 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); } //$NON-NLS-1$ consumeInternalCompilationUnitWithTypes(); break; case 70 : if (DEBUG) { System.out.println("InternalCompilationUnit ::="); } //$NON-NLS-1$ consumeEmptyInternalCompilationUnit(); break; case 71 : if (DEBUG) { System.out.println("ReduceImports ::="); } //$NON-NLS-1$ consumeReduceImports(); break; case 72 : if (DEBUG) { System.out.println("EnterCompilationUnit ::="); } //$NON-NLS-1$ consumeEnterCompilationUnit(); break; case 88 : if (DEBUG) { System.out.println("CatchHeader ::= catch LPAREN CatchFormalParameter RPAREN"); } //$NON-NLS-1$ consumeCatchHeader(); break; case 90 : if (DEBUG) { System.out.println("ImportDeclarations ::= ImportDeclarations..."); } //$NON-NLS-1$ consumeImportDeclarations(); break; case 92 : if (DEBUG) { System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); } //$NON-NLS-1$ consumeTypeDeclarations(); break; case 93 : if (DEBUG) { System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); } //$NON-NLS-1$ consumePackageDeclaration(); break; case 94 : if (DEBUG) { System.out.println("PackageDeclarationName ::= Modifiers package..."); } //$NON-NLS-1$ consumePackageDeclarationNameWithModifiers(); break; case 95 : if (DEBUG) { System.out.println("PackageDeclarationName ::= PackageComment package Name"); } //$NON-NLS-1$ consumePackageDeclarationName(); break; case 96 : if (DEBUG) { System.out.println("PackageComment ::="); } //$NON-NLS-1$ consumePackageComment(); break; case 101 : if (DEBUG) { System.out.println("SingleTypeImportDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; case 102 : if (DEBUG) { System.out.println("SingleTypeImportDeclarationName ::= import Name"); } //$NON-NLS-1$ consumeSingleTypeImportDeclarationName(); break; case 103 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; case 104 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT..."); } //$NON-NLS-1$ consumeTypeImportOnDemandDeclarationName(); break; case 107 : if (DEBUG) { System.out.println("TypeDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyTypeDeclaration(); break; case 111 : if (DEBUG) { System.out.println("Modifiers ::= Modifiers Modifier"); } //$NON-NLS-1$ consumeModifiers2(); break; case 123 : if (DEBUG) { System.out.println("Modifier ::= Annotation"); } //$NON-NLS-1$ consumeAnnotationAsModifier(); break; case 124 : if (DEBUG) { System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); } //$NON-NLS-1$ consumeClassDeclaration(); break; case 125 : if (DEBUG) { System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); } //$NON-NLS-1$ consumeClassHeader(); break; case 126 : if (DEBUG) { System.out.println("ClassHeaderName ::= ClassHeaderName1 TypeParameters"); } //$NON-NLS-1$ consumeTypeHeaderNameWithTypeParameters(); break; case 128 : if (DEBUG) { System.out.println("ClassHeaderName1 ::= Modifiersopt class Identifier"); } //$NON-NLS-1$ consumeClassHeaderName1(); break; case 129 : if (DEBUG) { System.out.println("ClassHeaderExtends ::= extends ClassType"); } //$NON-NLS-1$ consumeClassHeaderExtends(); break; case 130 : if (DEBUG) { System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); } //$NON-NLS-1$ consumeClassHeaderImplements(); break; case 132 : if (DEBUG) { System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA..."); } //$NON-NLS-1$ consumeInterfaceTypeList(); break; case 133 : if (DEBUG) { System.out.println("InterfaceType ::= ClassOrInterfaceType"); } //$NON-NLS-1$ consumeInterfaceType(); break; case 136 : if (DEBUG) { System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations..."); } //$NON-NLS-1$ consumeClassBodyDeclarations(); break; case 140 : if (DEBUG) { System.out.println("ClassBodyDeclaration ::= Diet NestedMethod..."); } //$NON-NLS-1$ consumeClassBodyDeclaration(); break; case 141 : if (DEBUG) { System.out.println("Diet ::="); } //$NON-NLS-1$ consumeDiet(); break; case 142 : if (DEBUG) { System.out.println("Initializer ::= Diet NestedMethod CreateInitializer..."); } //$NON-NLS-1$ consumeClassBodyDeclaration(); break; case 143 : if (DEBUG) { System.out.println("CreateInitializer ::="); } //$NON-NLS-1$ consumeCreateInitializer(); break; case 150 : if (DEBUG) { System.out.println("ClassMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyTypeDeclaration(); break; case 153 : if (DEBUG) { System.out.println("FieldDeclaration ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeFieldDeclaration(); break; case 155 : if (DEBUG) { System.out.println("VariableDeclarators ::= VariableDeclarators COMMA..."); } //$NON-NLS-1$ consumeVariableDeclarators(); break; case 158 : if (DEBUG) { System.out.println("EnterVariable ::="); } //$NON-NLS-1$ consumeEnterVariable(); break; case 159 : if (DEBUG) { System.out.println("ExitVariableWithInitialization ::="); } //$NON-NLS-1$ consumeExitVariableWithInitialization(); break; case 160 : if (DEBUG) { System.out.println("ExitVariableWithoutInitialization ::="); } //$NON-NLS-1$ consumeExitVariableWithoutInitialization(); break; case 161 : if (DEBUG) { System.out.println("ForceNoDiet ::="); } //$NON-NLS-1$ consumeForceNoDiet(); break; case 162 : if (DEBUG) { System.out.println("RestoreDiet ::="); } //$NON-NLS-1$ consumeRestoreDiet(); break; case 167 : 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 168 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); } //$NON-NLS-1$ // set to false to consume a method without body consumeMethodDeclaration(false); break; case 169 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); } //$NON-NLS-1$ consumeMethodHeader(); break; case 170 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt TypeParameters Type..."); } //$NON-NLS-1$ consumeMethodHeaderNameWithTypeParameters(false); break; case 171 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); } //$NON-NLS-1$ consumeMethodHeaderName(false); break; case 172 : if (DEBUG) { System.out.println("MethodHeaderRightParen ::= RPAREN"); } //$NON-NLS-1$ consumeMethodHeaderRightParen(); break; case 173 : if (DEBUG) { System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); } //$NON-NLS-1$ consumeMethodHeaderExtendedDims(); break; case 174 : if (DEBUG) { System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); } //$NON-NLS-1$ consumeMethodHeaderThrowsClause(); break; case 175 : if (DEBUG) { System.out.println("ConstructorHeader ::= ConstructorHeaderName..."); } //$NON-NLS-1$ consumeConstructorHeader(); break; case 176 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt TypeParameters..."); } //$NON-NLS-1$ consumeConstructorHeaderNameWithTypeParameters(); break; case 177 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); } //$NON-NLS-1$ consumeConstructorHeaderName(); break; case 179 : if (DEBUG) { System.out.println("FormalParameterList ::= FormalParameterList COMMA..."); } //$NON-NLS-1$ consumeFormalParameterList(); break; case 180 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeFormalParameter(false); break; case 181 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type ELLIPSIS..."); } //$NON-NLS-1$ consumeFormalParameter(true); break; case 182 : if (DEBUG) { System.out.println("CatchFormalParameter ::= Modifiersopt CatchType..."); } //$NON-NLS-1$ consumeCatchFormalParameter(); break; case 183 : if (DEBUG) { System.out.println("CatchType ::= UnionType"); } //$NON-NLS-1$ consumeCatchType(); break; case 184 : if (DEBUG) { System.out.println("UnionType ::= Type"); } //$NON-NLS-1$ consumeUnionTypeAsClassType(); break; case 185 : if (DEBUG) { System.out.println("UnionType ::= UnionType OR Type"); } //$NON-NLS-1$ consumeUnionType(); break; case 187 : if (DEBUG) { System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); } //$NON-NLS-1$ consumeClassTypeList(); break; case 188 : if (DEBUG) { System.out.println("ClassTypeElt ::= ClassType"); } //$NON-NLS-1$ consumeClassTypeElt(); break; case 189 : if (DEBUG) { System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt..."); } //$NON-NLS-1$ consumeMethodBody(); break; case 190 : if (DEBUG) { System.out.println("NestedMethod ::="); } //$NON-NLS-1$ consumeNestedMethod(); break; case 191 : if (DEBUG) { System.out.println("StaticInitializer ::= StaticOnly Block"); } //$NON-NLS-1$ consumeStaticInitializer(); break; case 192 : if (DEBUG) { System.out.println("StaticOnly ::= static"); } //$NON-NLS-1$ consumeStaticOnly(); break; case 193 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); } //$NON-NLS-1$ consumeConstructorDeclaration() ; break; case 194 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); } //$NON-NLS-1$ consumeInvalidConstructorDeclaration() ; break; case 195 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= this LPAREN..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(0, THIS_CALL); break; case 196 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments this"); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(0,THIS_CALL); break; case 197 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= super LPAREN..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(0,SUPER_CALL); break; case 198 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(0,SUPER_CALL); break; case 199 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT super..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(1, SUPER_CALL); break; case 200 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(1, SUPER_CALL); break; case 201 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN"); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(2, SUPER_CALL); break; case 202 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(2, SUPER_CALL); break; case 203 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT this..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(1, THIS_CALL); break; case 204 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(1, THIS_CALL); break; case 205 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN"); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(2, THIS_CALL); break; case 206 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(2, THIS_CALL); break; case 207 : if (DEBUG) { System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); } //$NON-NLS-1$ consumeInterfaceDeclaration(); break; case 208 : if (DEBUG) { System.out.println("InterfaceHeader ::= InterfaceHeaderName..."); } //$NON-NLS-1$ consumeInterfaceHeader(); break; case 209 : if (DEBUG) { System.out.println("InterfaceHeaderName ::= InterfaceHeaderName1..."); } //$NON-NLS-1$ consumeTypeHeaderNameWithTypeParameters(); break; case 211 : if (DEBUG) { System.out.println("InterfaceHeaderName1 ::= Modifiersopt interface..."); } //$NON-NLS-1$ consumeInterfaceHeaderName1(); break; case 212 : if (DEBUG) { System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); } //$NON-NLS-1$ consumeInterfaceHeaderExtends(); break; case 215 : if (DEBUG) { System.out.println("InterfaceMemberDeclarations ::=..."); } //$NON-NLS-1$ consumeInterfaceMemberDeclarations(); break; case 216 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyTypeDeclaration(); break; case 218 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= MethodHeader MethodBody"); } //$NON-NLS-1$ consumeInvalidMethodDeclaration(); break; case 219 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$ consumeInvalidConstructorDeclaration(true); break; case 220 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$ consumeInvalidConstructorDeclaration(false); break; case 231 : if (DEBUG) { System.out.println("PushLeftBrace ::="); } //$NON-NLS-1$ consumePushLeftBrace(); break; case 232 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace ,opt RBRACE"); } //$NON-NLS-1$ consumeEmptyArrayInitializer(); break; case 233 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$ consumeArrayInitializer(); break; case 234 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$ consumeArrayInitializer(); break; case 236 : if (DEBUG) { System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); } //$NON-NLS-1$ consumeVariableInitializers(); break; case 237 : if (DEBUG) { System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); } //$NON-NLS-1$ consumeBlock(); break; case 238 : if (DEBUG) { System.out.println("OpenBlock ::="); } //$NON-NLS-1$ consumeOpenBlock() ; break; case 240 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatements BlockStatement"); } //$NON-NLS-1$ consumeBlockStatements() ; break; case 244 : if (DEBUG) { System.out.println("BlockStatement ::= InterfaceDeclaration"); } //$NON-NLS-1$ consumeInvalidInterfaceDeclaration(); break; case 245 : if (DEBUG) { System.out.println("BlockStatement ::= AnnotationTypeDeclaration"); } //$NON-NLS-1$ consumeInvalidAnnotationTypeDeclaration(); break; case 246 : if (DEBUG) { System.out.println("BlockStatement ::= EnumDeclaration"); } //$NON-NLS-1$ consumeInvalidEnumDeclaration(); break; case 247 : if (DEBUG) { System.out.println("LocalVariableDeclarationStatement ::=..."); } //$NON-NLS-1$ consumeLocalVariableDeclarationStatement(); break; case 248 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Type PushModifiers..."); } //$NON-NLS-1$ consumeLocalVariableDeclaration(); break; case 249 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Modifiers Type..."); } //$NON-NLS-1$ consumeLocalVariableDeclaration(); break; case 250 : if (DEBUG) { System.out.println("PushModifiers ::="); } //$NON-NLS-1$ consumePushModifiers(); break; case 251 : if (DEBUG) { System.out.println("PushModifiersForHeader ::="); } //$NON-NLS-1$ consumePushModifiersForHeader(); break; case 252 : if (DEBUG) { System.out.println("PushRealModifiers ::="); } //$NON-NLS-1$ consumePushRealModifiers(); break; case 279 : if (DEBUG) { System.out.println("EmptyStatement ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyStatement(); break; case 280 : if (DEBUG) { System.out.println("LabeledStatement ::= Label COLON Statement"); } //$NON-NLS-1$ consumeStatementLabel() ; break; case 281 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Label COLON..."); } //$NON-NLS-1$ consumeStatementLabel() ; break; case 282 : if (DEBUG) { System.out.println("Label ::= Identifier"); } //$NON-NLS-1$ consumeLabel() ; break; case 283 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); } //$NON-NLS-1$ consumeExpressionStatement(); break; case 292 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementIfNoElse(); break; case 293 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementIfWithElse(); break; case 294 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); } //$NON-NLS-1$ consumeStatementIfWithElse(); break; case 295 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementSwitch() ; break; case 296 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); } //$NON-NLS-1$ consumeEmptySwitchBlock() ; break; case 299 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); } //$NON-NLS-1$ consumeSwitchBlock() ; break; case 301 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); } //$NON-NLS-1$ consumeSwitchBlockStatements() ; break; case 302 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); } //$NON-NLS-1$ consumeSwitchBlockStatement() ; break; case 304 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); } //$NON-NLS-1$ consumeSwitchLabels() ; break; case 305 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); } //$NON-NLS-1$ consumeCaseLabel(); break; case 306 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); } //$NON-NLS-1$ consumeDefaultLabel(); break; case 307 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementWhile() ; break; case 308 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); } //$NON-NLS-1$ consumeStatementWhile() ; break; case 309 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); } //$NON-NLS-1$ consumeStatementDo() ; break; case 310 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); } //$NON-NLS-1$ consumeStatementFor() ; break; case 311 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); } //$NON-NLS-1$ consumeStatementFor() ; break; case 312 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); } //$NON-NLS-1$ consumeForInit() ; break; case 316 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); } //$NON-NLS-1$ consumeStatementExpressionList() ; break; case 317 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); } //$NON-NLS-1$ consumeSimpleAssertStatement() ; break; case 318 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); } //$NON-NLS-1$ consumeAssertStatement() ; break; case 319 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); } //$NON-NLS-1$ consumeStatementBreak() ; break; case 320 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); } //$NON-NLS-1$ consumeStatementBreakWithLabel() ; break; case 321 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); } //$NON-NLS-1$ consumeStatementContinue() ; break; case 322 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); } //$NON-NLS-1$ consumeStatementContinueWithLabel() ; break; case 323 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); } //$NON-NLS-1$ consumeStatementReturn() ; break; case 324 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); } //$NON-NLS-1$ consumeStatementThrow(); break; case 325 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); } //$NON-NLS-1$ consumeStatementSynchronized(); break; case 326 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); } //$NON-NLS-1$ consumeOnlySynchronized(); break; case 327 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); } //$NON-NLS-1$ consumeStatementTry(false, false); break; case 328 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); } //$NON-NLS-1$ consumeStatementTry(true, false); break; case 329 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); } //$NON-NLS-1$ consumeStatementTry(false, true); break; case 330 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); } //$NON-NLS-1$ consumeStatementTry(true, true); break; case 331 : if (DEBUG) { System.out.println("ResourceSpecification ::= LPAREN Resources ;opt RPAREN"); } //$NON-NLS-1$ consumeResourceSpecification(); break; case 332 : if (DEBUG) { System.out.println(";opt ::="); } //$NON-NLS-1$ consumeResourceOptionalTrailingSemiColon(false); break; case 333 : if (DEBUG) { System.out.println(";opt ::= SEMICOLON"); } //$NON-NLS-1$ consumeResourceOptionalTrailingSemiColon(true); break; case 334 : if (DEBUG) { System.out.println("Resources ::= Resource"); } //$NON-NLS-1$ consumeSingleResource(); break; case 335 : if (DEBUG) { System.out.println("Resources ::= Resources TrailingSemiColon Resource"); } //$NON-NLS-1$ consumeMultipleResources(); break; case 336 : if (DEBUG) { System.out.println("TrailingSemiColon ::= SEMICOLON"); } //$NON-NLS-1$ consumeResourceOptionalTrailingSemiColon(true); break; case 337 : if (DEBUG) { System.out.println("Resource ::= Type PushModifiers VariableDeclaratorId..."); } //$NON-NLS-1$ consumeResourceAsLocalVariableDeclaration(); break; case 338 : if (DEBUG) { System.out.println("Resource ::= Modifiers Type PushRealModifiers..."); } //$NON-NLS-1$ consumeResourceAsLocalVariableDeclaration(); break; case 340 : if (DEBUG) { System.out.println("ExitTryBlock ::="); } //$NON-NLS-1$ consumeExitTryBlock(); break; case 342 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); } //$NON-NLS-1$ consumeCatches(); break; case 343 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN CatchFormalParameter RPAREN"); } //$NON-NLS-1$ consumeStatementCatch() ; break; case 345 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); } //$NON-NLS-1$ consumeLeftParen(); break; case 346 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); } //$NON-NLS-1$ consumeRightParen(); break; case 351 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); } //$NON-NLS-1$ consumePrimaryNoNewArrayThis(); break; case 352 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); } //$NON-NLS-1$ consumePrimaryNoNewArray(); break; case 353 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); } //$NON-NLS-1$ consumePrimaryNoNewArrayWithName(); break; case 356 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); } //$NON-NLS-1$ consumePrimaryNoNewArrayNameThis(); break; case 357 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT super"); } //$NON-NLS-1$ consumePrimaryNoNewArrayNameSuper(); break; case 358 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayName(); break; case 359 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayArrayType(); break; case 360 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayPrimitiveArrayType(); break; case 361 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayPrimitiveType(); break; case 364 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); } //$NON-NLS-1$ consumeAllocationHeader(); break; case 365 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionWithTypeArguments(); break; case 366 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpression(); break; case 367 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ; break; case 368 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualified() ; break; case 369 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualified() ; break; case 370 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ; break; case 371 : if (DEBUG) { System.out.println("EnterInstanceCreationArgumentList ::="); } //$NON-NLS-1$ consumeEnterInstanceCreationArgumentList(); break; case 372 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT"); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionName() ; break; case 373 : if (DEBUG) { System.out.println("UnqualifiedClassBodyopt ::="); } //$NON-NLS-1$ consumeClassBodyopt(); break; case 375 : if (DEBUG) { System.out.println("UnqualifiedEnterAnonymousClassBody ::="); } //$NON-NLS-1$ consumeEnterAnonymousClassBody(false); break; case 376 : if (DEBUG) { System.out.println("QualifiedClassBodyopt ::="); } //$NON-NLS-1$ consumeClassBodyopt(); break; case 378 : if (DEBUG) { System.out.println("QualifiedEnterAnonymousClassBody ::="); } //$NON-NLS-1$ consumeEnterAnonymousClassBody(true); break; case 380 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); } //$NON-NLS-1$ consumeArgumentList(); break; case 381 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); } //$NON-NLS-1$ consumeArrayCreationHeader(); break; case 382 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); } //$NON-NLS-1$ consumeArrayCreationHeader(); break; case 383 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$ consumeArrayCreationExpressionWithoutInitializer(); break; case 384 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); } //$NON-NLS-1$ consumeArrayCreationExpressionWithInitializer(); break; case 385 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$ consumeArrayCreationExpressionWithoutInitializer(); break; case 386 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); } //$NON-NLS-1$ consumeArrayCreationExpressionWithInitializer(); break; case 388 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); } //$NON-NLS-1$ consumeDimWithOrWithOutExprs(); break; case 390 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET"); } //$NON-NLS-1$ consumeDimWithOrWithOutExpr(); break; case 391 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); } //$NON-NLS-1$ consumeDims(); break; case 394 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); } //$NON-NLS-1$ consumeOneDimLoop(); break; case 395 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); } //$NON-NLS-1$ consumeFieldAccess(false); break; case 396 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); } //$NON-NLS-1$ consumeFieldAccess(true); break; case 397 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$ consumeMethodInvocationName(); break; case 398 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); } //$NON-NLS-1$ consumeMethodInvocationNameWithTypeArguments(); break; case 399 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); } //$NON-NLS-1$ consumeMethodInvocationPrimaryWithTypeArguments(); break; case 400 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); } //$NON-NLS-1$ consumeMethodInvocationPrimary(); break; case 401 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); } //$NON-NLS-1$ consumeMethodInvocationSuperWithTypeArguments(); break; case 402 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); } //$NON-NLS-1$ consumeMethodInvocationSuper(); break; case 403 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); } //$NON-NLS-1$ consumeArrayAccess(true); break; case 404 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); } //$NON-NLS-1$ consumeArrayAccess(false); break; case 405 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); } //$NON-NLS-1$ consumeArrayAccess(false); break; case 407 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); } //$NON-NLS-1$ consumePostfixExpression(); break; case 410 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS,true); break; case 411 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS,true); break; case 412 : if (DEBUG) { System.out.println("PushPosition ::="); } //$NON-NLS-1$ consumePushPosition(); break; case 415 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS); break; case 416 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS); break; case 418 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS,false); break; case 419 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS,false); break; case 421 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.TWIDDLE); break; case 422 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.NOT); break; case 424 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); } //$NON-NLS-1$ consumeCastExpressionWithPrimitiveType(); break; case 425 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$ consumeCastExpressionWithGenericsArray(); break; case 426 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$ consumeCastExpressionWithQualifiedGenericsArray(); break; case 427 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); } //$NON-NLS-1$ consumeCastExpressionLL1(); break; case 428 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN..."); } //$NON-NLS-1$ consumeCastExpressionWithNameArray(); break; case 429 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); } //$NON-NLS-1$ consumeOnlyTypeArgumentsForCastExpression(); break; case 430 : if (DEBUG) { System.out.println("InsideCastExpression ::="); } //$NON-NLS-1$ consumeInsideCastExpression(); break; case 431 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); } //$NON-NLS-1$ consumeInsideCastExpressionLL1(); break; case 432 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); } //$NON-NLS-1$ consumeInsideCastExpressionWithQualifiedGenerics(); break; case 434 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MULTIPLY); break; case 435 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.DIVIDE); break; case 436 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.REMAINDER); break; case 438 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.PLUS); break; case 439 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MINUS); break; case 441 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LEFT_SHIFT); break; case 442 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT); break; case 443 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT); break; case 445 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS); break; case 446 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER); break; case 447 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS_EQUAL); break; case 448 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER_EQUAL); break; case 450 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); } //$NON-NLS-1$ consumeInstanceOfExpression(); break; case 452 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL); break; case 453 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.NOT_EQUAL); break; case 455 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND); break; case 457 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.XOR); break; case 459 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR); break; case 461 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND_AND); break; case 463 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR_OR); break; case 465 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$ consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ; break; case 468 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); } //$NON-NLS-1$ consumeAssignment(); break; case 470 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); } //$NON-NLS-1$ ignoreExpressionAssignment(); break; case 471 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(EQUAL); break; case 472 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(MULTIPLY); break; case 473 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(DIVIDE); break; case 474 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(REMAINDER); break; case 475 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(PLUS); break; case 476 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(MINUS); break; case 477 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(LEFT_SHIFT); break; case 478 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(RIGHT_SHIFT); break; case 479 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT); break; case 480 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(AND); break; case 481 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(XOR); break; case 482 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(OR); break; case 486 : if (DEBUG) { System.out.println("Expressionopt ::="); } //$NON-NLS-1$ consumeEmptyExpression(); break; case 491 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyClassBodyDeclarationsopt(); break; case 492 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ consumeClassBodyDeclarationsopt(); break; case 493 : if (DEBUG) { System.out.println("Modifiersopt ::="); } //$NON-NLS-1$ consumeDefaultModifiers(); break; case 494 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); } //$NON-NLS-1$ consumeModifiers(); break; case 495 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); } //$NON-NLS-1$ consumeEmptyBlockStatementsopt(); break; case 497 : if (DEBUG) { System.out.println("Dimsopt ::="); } //$NON-NLS-1$ consumeEmptyDimsopt(); break; case 499 : if (DEBUG) { System.out.println("ArgumentListopt ::="); } //$NON-NLS-1$ consumeEmptyArgumentListopt(); break; case 503 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); } //$NON-NLS-1$ consumeFormalParameterListopt(); break; case 507 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyInterfaceMemberDeclarationsopt(); break; case 508 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ consumeInterfaceMemberDeclarationsopt(); break; case 509 : if (DEBUG) { System.out.println("NestedType ::="); } //$NON-NLS-1$ consumeNestedType(); break; case 510 : if (DEBUG) { System.out.println("ForInitopt ::="); } //$NON-NLS-1$ consumeEmptyForInitopt(); break; case 512 : if (DEBUG) { System.out.println("ForUpdateopt ::="); } //$NON-NLS-1$ consumeEmptyForUpdateopt(); break; case 516 : if (DEBUG) { System.out.println("Catchesopt ::="); } //$NON-NLS-1$ consumeEmptyCatchesopt(); break; case 518 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); } //$NON-NLS-1$ consumeEnumDeclaration(); break; case 519 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); } //$NON-NLS-1$ consumeEnumHeader(); break; case 520 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); } //$NON-NLS-1$ consumeEnumHeaderName(); break; case 521 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier..."); } //$NON-NLS-1$ consumeEnumHeaderNameWithTypeParameters(); break; case 522 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); } //$NON-NLS-1$ consumeEnumBodyNoConstants(); break; case 523 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); } //$NON-NLS-1$ consumeEnumBodyNoConstants(); break; case 524 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); } //$NON-NLS-1$ consumeEnumBodyWithConstants(); break; case 525 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); } //$NON-NLS-1$ consumeEnumBodyWithConstants(); break; case 527 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); } //$NON-NLS-1$ consumeEnumConstants(); break; case 528 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); } //$NON-NLS-1$ consumeEnumConstantHeaderName(); break; case 529 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); } //$NON-NLS-1$ consumeEnumConstantHeader(); break; case 530 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); } //$NON-NLS-1$ consumeEnumConstantWithClassBody(); break; case 531 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); } //$NON-NLS-1$ consumeEnumConstantNoClassBody(); break; case 532 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$ consumeArguments(); break; case 533 : if (DEBUG) { System.out.println("Argumentsopt ::="); } //$NON-NLS-1$ consumeEmptyArguments(); break; case 535 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); } //$NON-NLS-1$ consumeEnumDeclarations(); break; case 536 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyEnumDeclarations(); break; case 538 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); } //$NON-NLS-1$ consumeEnhancedForStatement(); break; case 539 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); } //$NON-NLS-1$ consumeEnhancedForStatement(); break; case 540 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); } //$NON-NLS-1$ consumeEnhancedForStatementHeaderInit(false); break; case 541 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); } //$NON-NLS-1$ consumeEnhancedForStatementHeaderInit(true); break; case 542 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); } //$NON-NLS-1$ consumeEnhancedForStatementHeader(); break; case 543 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; case 544 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); } //$NON-NLS-1$ consumeSingleStaticImportDeclarationName(); break; case 545 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; case 546 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); } //$NON-NLS-1$ consumeStaticImportOnDemandDeclarationName(); break; case 547 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$ consumeTypeArguments(); break; case 548 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$ consumeOnlyTypeArguments(); break; case 550 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ consumeTypeArgumentList1(); break; case 552 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); } //$NON-NLS-1$ consumeTypeArgumentList(); break; case 553 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); } //$NON-NLS-1$ consumeTypeArgument(); break; case 557 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); } //$NON-NLS-1$ consumeReferenceType1(); break; case 558 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$ consumeTypeArgumentReferenceType1(); break; case 560 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ consumeTypeArgumentList2(); break; case 563 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); } //$NON-NLS-1$ consumeReferenceType2(); break; case 564 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$ consumeTypeArgumentReferenceType2(); break; case 566 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ consumeTypeArgumentList3(); break; case 569 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$ consumeReferenceType3(); break; case 570 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION"); } //$NON-NLS-1$ consumeWildcard(); break; case 571 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION WildcardBounds"); } //$NON-NLS-1$ consumeWildcardWithBounds(); break; case 572 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); } //$NON-NLS-1$ consumeWildcardBoundsExtends(); break; case 573 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); } //$NON-NLS-1$ consumeWildcardBoundsSuper(); break; case 574 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION GREATER"); } //$NON-NLS-1$ consumeWildcard1(); break; case 575 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION WildcardBounds1"); } //$NON-NLS-1$ consumeWildcard1WithBounds(); break; case 576 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); } //$NON-NLS-1$ consumeWildcardBounds1Extends(); break; case 577 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); } //$NON-NLS-1$ consumeWildcardBounds1Super(); break; case 578 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION RIGHT_SHIFT"); } //$NON-NLS-1$ consumeWildcard2(); break; case 579 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION WildcardBounds2"); } //$NON-NLS-1$ consumeWildcard2WithBounds(); break; case 580 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); } //$NON-NLS-1$ consumeWildcardBounds2Extends(); break; case 581 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); } //$NON-NLS-1$ consumeWildcardBounds2Super(); break; case 582 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$ consumeWildcard3(); break; case 583 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION WildcardBounds3"); } //$NON-NLS-1$ consumeWildcard3WithBounds(); break; case 584 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); } //$NON-NLS-1$ consumeWildcardBounds3Extends(); break; case 585 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); } //$NON-NLS-1$ consumeWildcardBounds3Super(); break; case 586 : if (DEBUG) { System.out.println("TypeParameterHeader ::= Identifier"); } //$NON-NLS-1$ consumeTypeParameterHeader(); break; case 587 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); } //$NON-NLS-1$ consumeTypeParameters(); break; case 589 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); } //$NON-NLS-1$ consumeTypeParameterList(); break; case 591 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameterWithExtends(); break; case 592 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameterWithExtendsAndBounds(); break; case 594 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); } //$NON-NLS-1$ consumeAdditionalBoundList(); break; case 595 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); } //$NON-NLS-1$ consumeAdditionalBound(); break; case 597 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); } //$NON-NLS-1$ consumeTypeParameterList1(); break; case 598 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); } //$NON-NLS-1$ consumeTypeParameter1(); break; case 599 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameter1WithExtends(); break; case 600 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameter1WithExtendsAndBounds(); break; case 602 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); } //$NON-NLS-1$ consumeAdditionalBoundList1(); break; case 603 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); } //$NON-NLS-1$ consumeAdditionalBound1(); break; case 609 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS); break; case 610 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS); break; case 613 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.TWIDDLE); break; case 614 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.NOT); break; case 617 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MULTIPLY); break; case 618 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.MULTIPLY); break; case 619 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.DIVIDE); break; case 620 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.DIVIDE); break; case 621 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.REMAINDER); break; case 622 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.REMAINDER); break; case 624 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.PLUS); break; case 625 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.PLUS); break; case 626 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MINUS); break; case 627 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.MINUS); break; case 629 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LEFT_SHIFT); break; case 630 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.LEFT_SHIFT); break; case 631 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT); break; case 632 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.RIGHT_SHIFT); break; case 633 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT); break; case 634 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.UNSIGNED_RIGHT_SHIFT); break; case 636 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS); break; case 637 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.LESS); break; case 638 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER); break; case 639 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.GREATER); break; case 640 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS_EQUAL); break; case 641 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.LESS_EQUAL); break; case 642 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER_EQUAL); break; case 643 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.GREATER_EQUAL); break; case 645 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); } //$NON-NLS-1$ consumeInstanceOfExpressionWithName(); break; case 646 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); } //$NON-NLS-1$ consumeInstanceOfExpression(); break; case 648 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL); break; case 649 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpressionWithName(OperatorIds.EQUAL_EQUAL); break; case 650 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.NOT_EQUAL); break; case 651 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpressionWithName(OperatorIds.NOT_EQUAL); break; case 653 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND); break; case 654 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.AND); break; case 656 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.XOR); break; case 657 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.XOR); break; case 659 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR); break; case 660 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.OR); break; case 662 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND_AND); break; case 663 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.AND_AND); break; case 665 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR_OR); break; case 666 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.OR_OR); break; case 668 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); } //$NON-NLS-1$ consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ; break; case 669 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); } //$NON-NLS-1$ consumeConditionalExpressionWithName(OperatorIds.QUESTIONCOLON) ; break; case 673 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderName() ; break; case 674 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ; break; case 675 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ; break; case 676 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderName() ; break; case 677 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeader() ; break; case 678 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclaration() ; break; case 680 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyAnnotationTypeMemberDeclarationsopt() ; break; case 681 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ consumeAnnotationTypeMemberDeclarationsopt() ; break; case 683 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeMemberDeclarations() ; break; case 684 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); } //$NON-NLS-1$ consumeMethodHeaderNameWithTypeParameters(true); break; case 685 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeMethodHeaderName(true); break; case 686 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); } //$NON-NLS-1$ consumeEmptyMethodHeaderDefaultValue() ; break; case 687 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); } //$NON-NLS-1$ consumeMethodHeaderDefaultValue(); break; case 688 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); } //$NON-NLS-1$ consumeMethodHeader(); break; case 689 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeMemberDeclaration() ; break; case 697 : if (DEBUG) { System.out.println("AnnotationName ::= AT Name"); } //$NON-NLS-1$ consumeAnnotationName() ; break; case 698 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$ consumeNormalAnnotation() ; break; case 699 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); } //$NON-NLS-1$ consumeEmptyMemberValuePairsopt() ; break; case 702 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); } //$NON-NLS-1$ consumeMemberValuePairs() ; break; case 703 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue..."); } //$NON-NLS-1$ consumeMemberValuePair() ; break; case 704 : if (DEBUG) { System.out.println("EnterMemberValue ::="); } //$NON-NLS-1$ consumeEnterMemberValue() ; break; case 705 : if (DEBUG) { System.out.println("ExitMemberValue ::="); } //$NON-NLS-1$ consumeExitMemberValue() ; break; case 707 : if (DEBUG) { System.out.println("MemberValue ::= Name"); } //$NON-NLS-1$ consumeMemberValueAsName() ; break; case 710 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeMemberValueArrayInitializer() ; break; case 711 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeMemberValueArrayInitializer() ; break; case 712 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeEmptyMemberValueArrayInitializer() ; break; case 713 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeEmptyMemberValueArrayInitializer() ; break; case 714 : if (DEBUG) { System.out.println("EnterMemberValueArrayInitializer ::="); } //$NON-NLS-1$ consumeEnterMemberValueArrayInitializer() ; break; case 716 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); } //$NON-NLS-1$ consumeMemberValues() ; break; case 717 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); } //$NON-NLS-1$ consumeMarkerAnnotation() ; break; case 718 : if (DEBUG) { System.out.println("SingleMemberAnnotationMemberValue ::= MemberValue"); } //$NON-NLS-1$ consumeSingleMemberAnnotationMemberValue() ; break; case 719 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$ consumeSingleMemberAnnotation() ; break; case 720 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); } //$NON-NLS-1$ consumeRecoveryMethodHeaderNameWithTypeParameters(); break; case 721 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeRecoveryMethodHeaderName(); break; case 722 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$ consumeMethodHeader(); break; case 723 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$ consumeMethodHeader(); break; } } protected void consumeEnterInstanceCreationArgumentList() { this.shouldDeferRecovery = true; } protected void consumeSimpleAssertStatement() { // AssertStatement ::= 'assert' Expression ';' this.expressionLengthPtr--; pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--])); } protected void consumeSingleMemberAnnotation() { // SingleMemberAnnotation ::= '@' Name '(' MemberValue ')' SingleMemberAnnotation singleMemberAnnotation = null; int oldIndex = this.identifierPtr; TypeReference typeReference = getAnnotationType(); singleMemberAnnotation = new SingleMemberAnnotation(typeReference, this.intStack[this.intPtr--]); singleMemberAnnotation.memberValue = this.expressionStack[this.expressionPtr--]; this.expressionLengthPtr--; singleMemberAnnotation.declarationSourceEnd = this.rParenPos; pushOnExpressionStack(singleMemberAnnotation); if(this.currentElement != null) { annotationRecoveryCheckPoint(singleMemberAnnotation.sourceStart, singleMemberAnnotation.declarationSourceEnd); if (this.currentElement instanceof RecoveredAnnotation) { this.currentElement = ((RecoveredAnnotation)this.currentElement).addAnnotation(singleMemberAnnotation, oldIndex); } } if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { problemReporter().invalidUsageOfAnnotation(singleMemberAnnotation); } this.recordStringLiterals = true; } protected void consumeSingleMemberAnnotationMemberValue() { // this rule is used for syntax recovery only if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) { RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation) this.currentElement; recoveredAnnotation.setKind(RecoveredAnnotation.SINGLE_MEMBER); } } protected void consumeSingleResource() { // Resources ::= Resource } protected void consumeSingleStaticImportDeclarationName() { // SingleTypeImportDeclarationName ::= '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, false, ClassFileConstants.AccStatic)); this.modifiers = ClassFileConstants.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.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference 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 consumeSingleTypeImportDeclarationName() { // SingleTypeImportDeclarationName ::= 'import' 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, false, ClassFileConstants.AccDefault)); 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--]; // 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 consumeStatementBreak() { // BreakStatement ::= 'break' ';' // break pushes a position on this.intStack in case there is no label pushOnAstStack(new BreakStatement(null, this.intStack[this.intPtr--], this.endStatementPosition)); if (this.pendingRecoveredType != null) { // Used only in statements recovery. // This is not a real break statement but a placeholder for an existing local type. // The break statement must be replace by the local type. if (this.pendingRecoveredType.allocation == null && this.endPosition <= this.pendingRecoveredType.declarationSourceEnd) { this.astStack[this.astPtr] = this.pendingRecoveredType; this.pendingRecoveredType = null; return; } this.pendingRecoveredType = null; } } protected void consumeStatementBreakWithLabel() { // BreakStatement ::= 'break' Identifier ';' // break pushs a position on this.intStack in case there is no label pushOnAstStack( new BreakStatement( this.identifierStack[this.identifierPtr--], this.intStack[this.intPtr--], this.endStatementPosition)); this.identifierLengthPtr--; } protected void consumeStatementCatch() { // CatchClause ::= 'catch' '(' FormalParameter ')' Block //catch are stored directly into the Try //has they always comes two by two.... //we remove one entry from the astlengthPtr. //The construction of the try statement must //then fetch the catches using 2*i and 2*i + 1 this.astLengthPtr--; this.listLength = 0; // reset formalParameter counter (incremented for catch variable) } protected void consumeStatementContinue() { // ContinueStatement ::= 'continue' ';' // continue pushs a position on this.intStack in case there is no label pushOnAstStack( new ContinueStatement( null, this.intStack[this.intPtr--], this.endStatementPosition)); } protected void consumeStatementContinueWithLabel() { // ContinueStatement ::= 'continue' Identifier ';' // continue pushs a position on this.intStack in case there is no label pushOnAstStack( new ContinueStatement( this.identifierStack[this.identifierPtr--], this.intStack[this.intPtr--], this.endStatementPosition)); this.identifierLengthPtr--; } protected void consumeStatementDo() { // DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';' //the 'while' pushes a value on this.intStack that we need to remove this.intPtr--; Statement statement = (Statement) this.astStack[this.astPtr]; this.expressionLengthPtr--; this.astStack[this.astPtr] = new DoStatement( this.expressionStack[this.expressionPtr--], statement, this.intStack[this.intPtr--], this.endStatementPosition); } protected void consumeStatementExpressionList() { // StatementExpressionList ::= StatementExpressionList ',' StatementExpression concatExpressionLists(); } protected void consumeStatementFor() { // ForStatement ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' Statement // ForStatementNoShortIf ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' StatementNoShortIf int length; Expression cond = null; Statement[] inits, updates; boolean scope = true; //statements this.astLengthPtr--; Statement statement = (Statement) this.astStack[this.astPtr--]; //updates are on the expresion stack if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) == 0) { updates = null; } else { this.expressionPtr -= length; System.arraycopy( this.expressionStack, this.expressionPtr + 1, updates = new Statement[length], 0, length); } if (this.expressionLengthStack[this.expressionLengthPtr--] != 0) cond = this.expressionStack[this.expressionPtr--]; //inits may be on two different stacks if ((length = this.astLengthStack[this.astLengthPtr--]) == 0) { inits = null; scope = false; } else { if (length == -1) { //on this.expressionStack scope = false; length = this.expressionLengthStack[this.expressionLengthPtr--]; this.expressionPtr -= length; System.arraycopy( this.expressionStack, this.expressionPtr + 1, inits = new Statement[length], 0, length); } else { //on this.astStack this.astPtr -= length; System.arraycopy( this.astStack, this.astPtr + 1, inits = new Statement[length], 0, length); } } pushOnAstStack( new ForStatement( inits, cond, updates, statement, scope, this.intStack[this.intPtr--], this.endStatementPosition)); } protected void consumeStatementIfNoElse() { // IfThenStatement ::= 'if' '(' Expression ')' Statement //optimize the push/pop this.expressionLengthPtr--; Statement thenStatement = (Statement) this.astStack[this.astPtr]; this.astStack[this.astPtr] = new IfStatement( this.expressionStack[this.expressionPtr--], thenStatement, this.intStack[this.intPtr--], this.endStatementPosition); } protected void consumeStatementIfWithElse() { // IfThenElseStatement ::= 'if' '(' Expression ')' StatementNoShortIf 'else' Statement // IfThenElseStatementNoShortIf ::= 'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf this.expressionLengthPtr--; // optimized {..., Then, Else } ==> {..., If } this.astLengthPtr--; //optimize the push/pop this.astStack[--this.astPtr] = new IfStatement( this.expressionStack[this.expressionPtr--], (Statement) this.astStack[this.astPtr], (Statement) this.astStack[this.astPtr + 1], this.intStack[this.intPtr--], this.endStatementPosition); } protected void consumeStatementLabel() { // LabeledStatement ::= 'Identifier' ':' Statement // LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf //optimize push/pop Statement statement = (Statement) this.astStack[this.astPtr]; this.astStack[this.astPtr] = new LabeledStatement( this.identifierStack[this.identifierPtr], statement, this.identifierPositionStack[this.identifierPtr--], this.endStatementPosition); this.identifierLengthPtr--; } protected void consumeStatementReturn() { // ReturnStatement ::= 'return' Expressionopt ';' // return pushs a position on this.intStack in case there is no expression if (this.expressionLengthStack[this.expressionLengthPtr--] != 0) { pushOnAstStack( new ReturnStatement( this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--], this.endStatementPosition) ); } else { pushOnAstStack(new ReturnStatement(null, this.intStack[this.intPtr--], this.endStatementPosition)); } } protected void consumeStatementSwitch() { // SwitchStatement ::= 'switch' OpenBlock '(' Expression ')' SwitchBlock //OpenBlock just makes the semantic action blockStart() //the block is inlined but a scope need to be created //if some declaration occurs. int length; SwitchStatement switchStatement = new SwitchStatement(); this.expressionLengthPtr--; switchStatement.expression = this.expressionStack[this.expressionPtr--]; if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { this.astPtr -= length; System.arraycopy( this.astStack, this.astPtr + 1, switchStatement.statements = new Statement[length], 0, length); } switchStatement.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; pushOnAstStack(switchStatement); switchStatement.blockStart = this.intStack[this.intPtr--]; switchStatement.sourceStart = this.intStack[this.intPtr--]; switchStatement.sourceEnd = this.endStatementPosition; if (length == 0 && !containsComment(switchStatement.blockStart, switchStatement.sourceEnd)) { switchStatement.bits |= ASTNode.UndocumentedEmptyBlock; } } protected void consumeStatementSynchronized() { // SynchronizedStatement ::= OnlySynchronized '(' Expression ')' Block //optimize the push/pop if (this.astLengthStack[this.astLengthPtr] == 0) { this.astLengthStack[this.astLengthPtr] = 1; this.expressionLengthPtr--; this.astStack[++this.astPtr] = new SynchronizedStatement( this.expressionStack[this.expressionPtr--], null, this.intStack[this.intPtr--], this.endStatementPosition); } else { this.expressionLengthPtr--; this.astStack[this.astPtr] = new SynchronizedStatement( this.expressionStack[this.expressionPtr--], (Block) this.astStack[this.astPtr], this.intStack[this.intPtr--], this.endStatementPosition); } this.modifiers = ClassFileConstants.AccDefault; this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int) } protected void consumeStatementThrow() { // ThrowStatement ::= 'throw' Expression ';' this.expressionLengthPtr--; pushOnAstStack(new ThrowStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--], this.endStatementPosition)); } protected void consumeStatementTry(boolean withFinally, boolean hasResources) { // TryStatement ::= 'try' Block Catches // TryStatement ::= 'try' Block Catchesopt Finally // TryStatementWithResources ::= 'try' ResourceSpecification TryBlock Catchesopt // TryStatementWithResources ::= 'try' ResourceSpecification TryBlock Catchesopt Finally int length; TryStatement tryStmt = new TryStatement(); //finally if (withFinally) { this.astLengthPtr--; tryStmt.finallyBlock = (Block) this.astStack[this.astPtr--]; } //catches are handle by two [see statementCatch] if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { if (length == 1) { tryStmt.catchBlocks = new Block[] {(Block) this.astStack[this.astPtr--]}; tryStmt.catchArguments = new Argument[] {(Argument) this.astStack[this.astPtr--]}; } else { Block[] bks = (tryStmt.catchBlocks = new Block[length]); Argument[] args = (tryStmt.catchArguments = new Argument[length]); while (length-- > 0) { bks[length] = (Block) this.astStack[this.astPtr--]; args[length] = (Argument) this.astStack[this.astPtr--]; } } } //try this.astLengthPtr--; tryStmt.tryBlock = (Block) this.astStack[this.astPtr--]; if (hasResources) { // get the resources length = this.astLengthStack[this.astLengthPtr--]; LocalDeclaration[] resources = new LocalDeclaration[length]; System.arraycopy( this.astStack, (this.astPtr -= length) + 1, resources, 0, length); tryStmt.resources = resources; if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { problemReporter().autoManagedResourcesNotBelow17(resources); } } //positions tryStmt.sourceEnd = this.endStatementPosition; tryStmt.sourceStart = this.intStack[this.intPtr--]; pushOnAstStack(tryStmt); } protected void consumeStatementWhile() { // WhileStatement ::= 'while' '(' Expression ')' Statement // WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf this.expressionLengthPtr--; Statement statement = (Statement) this.astStack[this.astPtr]; this.astStack[this.astPtr] = new WhileStatement( this.expressionStack[this.expressionPtr--], statement, 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, ClassFileConstants.AccStatic)); // star end position impt.trailingStarPosition = this.intStack[this.intPtr--]; this.modifiers = ClassFileConstants.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.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference 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 //optimize the push/pop Block block = (Block) this.astStack[this.astPtr]; if (this.diet) block.bits &= ~ASTNode.UndocumentedEmptyBlock; // clear bit set since was diet Initializer initializer = new Initializer(block, ClassFileConstants.AccStatic); this.astStack[this.astPtr] = initializer; initializer.sourceEnd = this.endStatementPosition; initializer.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); this.nestedMethod[this.nestedType] --; initializer.declarationSourceStart = this.intStack[this.intPtr--]; initializer.bodyStart = this.intStack[this.intPtr--]; initializer.bodyEnd = this.endPosition; // doc comment initializer.javadoc = this.javadoc; this.javadoc = null; // recovery if (this.currentElement != null){ this.lastCheckPoint = initializer.declarationSourceEnd; this.currentElement = this.currentElement.add(initializer, 0); this.lastIgnoredToken = -1; } } protected void consumeStaticOnly() { // StaticOnly ::= 'static' int savedModifiersSourceStart = this.modifiersSourceStart; checkComment(); // might update declaration source start if (this.modifiersSourceStart >= savedModifiersSourceStart) { this.modifiersSourceStart = savedModifiersSourceStart; } pushOnIntStack(this.scanner.currentPosition); pushOnIntStack( this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition); jumpOverMethodBody(); this.nestedMethod[this.nestedType]++; resetModifiers(); this.expressionLengthPtr--; // remove the 0 pushed in consumeToken() for the static modifier // recovery if (this.currentElement != null){ this.recoveredStaticInitializerStart = this.intStack[this.intPtr]; // remember start position only for static initializers } } protected void consumeSwitchBlock() { // SwitchBlock ::= '{' SwitchBlockStatements SwitchLabels '}' concatNodeLists(); } protected void consumeSwitchBlockStatement() { // SwitchBlockStatement ::= SwitchLabels BlockStatements concatNodeLists(); } protected void consumeSwitchBlockStatements() { // SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement concatNodeLists(); } protected void consumeSwitchLabels() { // SwitchLabels ::= SwitchLabels SwitchLabel optimizedConcatNodeLists(); } protected void consumeToken(int type) { /* remember the last consumed value */ /* try to minimize the number of build values */ // // clear the commentPtr of the scanner in case we read something different from a modifier // switch(type) { // case TokenNameabstract : // case TokenNamestrictfp : // case TokenNamefinal : // case TokenNamenative : // case TokenNameprivate : // case TokenNameprotected : // case TokenNamepublic : // case TokenNametransient : // case TokenNamevolatile : // case TokenNamestatic : // case TokenNamesynchronized : // break; // default: // this.scanner.commentPtr = -1; // } //System.out.println(this.scanner.toStringAction(type)); switch (type) { case TokenNameIdentifier : pushIdentifier(); if (this.scanner.useAssertAsAnIndentifier && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { long positions = this.identifierPositionStack[this.identifierPtr]; if(!this.statementRecoveryActivated) problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions); } if (this.scanner.useEnumAsAnIndentifier && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { long positions = this.identifierPositionStack[this.identifierPtr]; if(!this.statementRecoveryActivated) problemReporter().useEnumAsAnIdentifier((int) (positions >>> 32), (int) positions); } break; case TokenNameinterface : //'class' is pushing two int (positions) on the stack ==> 'interface' needs to do it too.... pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNameabstract : checkAndSetModifiers(ClassFileConstants.AccAbstract); pushOnExpressionStackLengthStack(0); break; case TokenNamestrictfp : checkAndSetModifiers(ClassFileConstants.AccStrictfp); pushOnExpressionStackLengthStack(0); break; case TokenNamefinal : checkAndSetModifiers(ClassFileConstants.AccFinal); pushOnExpressionStackLengthStack(0); break; case TokenNamenative : checkAndSetModifiers(ClassFileConstants.AccNative); pushOnExpressionStackLengthStack(0); break; case TokenNameprivate : checkAndSetModifiers(ClassFileConstants.AccPrivate); pushOnExpressionStackLengthStack(0); break; case TokenNameprotected : checkAndSetModifiers(ClassFileConstants.AccProtected); pushOnExpressionStackLengthStack(0); break; case TokenNamepublic : checkAndSetModifiers(ClassFileConstants.AccPublic); pushOnExpressionStackLengthStack(0); break; case TokenNametransient : checkAndSetModifiers(ClassFileConstants.AccTransient); pushOnExpressionStackLengthStack(0); break; case TokenNamevolatile : checkAndSetModifiers(ClassFileConstants.AccVolatile); pushOnExpressionStackLengthStack(0); break; case TokenNamestatic : checkAndSetModifiers(ClassFileConstants.AccStatic); pushOnExpressionStackLengthStack(0); break; case TokenNamesynchronized : this.synchronizedBlockSourceStart = this.scanner.startPosition; checkAndSetModifiers(ClassFileConstants.AccSynchronized); pushOnExpressionStackLengthStack(0); break; //============================== case TokenNamevoid : pushIdentifier(-T_void); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); 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 this.intStack case TokenNameboolean : pushIdentifier(-T_boolean); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNamebyte : pushIdentifier(-T_byte); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNamechar : pushIdentifier(-T_char); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNamedouble : pushIdentifier(-T_double); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNamefloat : pushIdentifier(-T_float); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNameint : pushIdentifier(-T_int); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNamelong : pushIdentifier(-T_long); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; case TokenNameshort : pushIdentifier(-T_short); pushOnIntStack(this.scanner.currentPosition - 1); pushOnIntStack(this.scanner.startPosition); break; //============================== case TokenNameIntegerLiteral : pushOnExpressionStack( IntLiteral.buildIntLiteral( this.scanner.getCurrentTokenSource(), this.scanner.startPosition, this.scanner.currentPosition - 1)); break; case TokenNameLongLiteral : pushOnExpressionStack( LongLiteral.buildLongLiteral( this.scanner.getCurrentTokenSource(), this.scanner.startPosition, this.scanner.currentPosition - 1)); break; case TokenNameFloatingPointLiteral : pushOnExpressionStack( new FloatLiteral( this.scanner.getCurrentTokenSource(), this.scanner.startPosition, this.scanner.currentPosition - 1)); break; case TokenNameDoubleLiteral : pushOnExpressionStack( new DoubleLiteral( this.scanner.getCurrentTokenSource(), this.scanner.startPosition, this.scanner.currentPosition - 1)); break; case TokenNameCharacterLiteral : pushOnExpressionStack( new CharLiteral( this.scanner.getCurrentTokenSource(), this.scanner.startPosition, this.scanner.currentPosition - 1)); break; case TokenNameStringLiteral : StringLiteral stringLiteral; if (this.recordStringLiterals && this.checkExternalizeStrings && this.lastPosistion < this.scanner.currentPosition && !this.statementRecoveryActivated) { stringLiteral = createStringLiteral( this.scanner.getCurrentTokenSourceString(), this.scanner.startPosition, this.scanner.currentPosition - 1, Util.getLineNumber(this.scanner.startPosition, this.scanner.lineEnds, 0, this.scanner.linePtr)); this.compilationUnit.recordStringLiteral(stringLiteral, this.currentElement != null); } else { stringLiteral = createStringLiteral( this.scanner.getCurrentTokenSourceString(), this.scanner.startPosition, this.scanner.currentPosition - 1, 0); } pushOnExpressionStack(stringLiteral); break; case TokenNamefalse : pushOnExpressionStack( new FalseLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1)); break; case TokenNametrue : pushOnExpressionStack( new TrueLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1)); break; case TokenNamenull : pushOnExpressionStack( new NullLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1)); break; //============================ case TokenNamesuper : case TokenNamethis : this.endPosition = this.scanner.currentPosition - 1; pushOnIntStack(this.scanner.startPosition); break; case TokenNameassert : case TokenNameimport : case TokenNamepackage : case TokenNamethrow : case TokenNamedo : case TokenNameif : case TokenNamefor : case TokenNameswitch : case TokenNametry : case TokenNamewhile : case TokenNamebreak : case TokenNamecontinue : case TokenNamereturn : case TokenNamecase : pushOnIntStack(this.scanner.startPosition); break; case TokenNamenew : // https://bugs.eclipse.org/bugs/show_bug.cgi?id=40954 resetModifiers(); pushOnIntStack(this.scanner.startPosition); break; case TokenNameclass : 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 TokenNameLBRACE : this.endStatementPosition = this.scanner.currentPosition - 1; //$FALL-THROUGH$ case TokenNamePLUS : case TokenNameMINUS : case TokenNameNOT : case TokenNameTWIDDLE : this.endPosition = this.scanner.startPosition; break; case TokenNamePLUS_PLUS : case TokenNameMINUS_MINUS : this.endPosition = this.scanner.startPosition; this.endStatementPosition = this.scanner.currentPosition - 1; break; case TokenNameRBRACE: case TokenNameSEMICOLON : this.endStatementPosition = this.scanner.currentPosition - 1; this.endPosition = this.scanner.startPosition - 1; //the item is not part of the potential futur expression/statement break; 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 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 TokenNameEQUAL : if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) { RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation) this.currentElement; if (recoveredAnnotation.memberValuPairEqualEnd == -1) { recoveredAnnotation.memberValuPairEqualEnd = this.scanner.currentPosition - 1; } } break; case TokenNameMULTIPLY : // star end position pushOnIntStack(this.scanner.currentPosition - 1); break; // case TokenNameCOMMA : // case TokenNameCOLON : // case TokenNameLBRACKET : // case TokenNameDOT : // case TokenNameERROR : // case TokenNameEOF : // case TokenNamecase : // case TokenNamecatch : // case TokenNameelse : // case TokenNameextends : // case TokenNamefinally : // case TokenNameimplements : // case TokenNamethrows : // case TokenNameinstanceof : // case TokenNameEQUAL_EQUAL : // case TokenNameLESS_EQUAL : // case TokenNameGREATER_EQUAL : // case TokenNameNOT_EQUAL : // case TokenNameLEFT_SHIFT : // case TokenNameRIGHT_SHIFT : // case TokenNameUNSIGNED_RIGHT_SHIFT : // case TokenNamePLUS_EQUAL : // case TokenNameMINUS_EQUAL : // case TokenNameMULTIPLY_EQUAL : // case TokenNameDIVIDE_EQUAL : // case TokenNameAND_EQUAL : // case TokenNameOR_EQUAL : // case TokenNameXOR_EQUAL : // case TokenNameREMAINDER_EQUAL : // case TokenNameLEFT_SHIFT_EQUAL : // case TokenNameRIGHT_SHIFT_EQUAL : // case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : // case TokenNameOR_OR : // case TokenNameAND_AND : // case TokenNameREMAINDER : // case TokenNameXOR : // case TokenNameAND : // case TokenNameMULTIPLY : // case TokenNameOR : // case TokenNameDIVIDE : // case TokenNameGREATER : } } protected void consumeTypeArgument() { pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--])); } protected void consumeTypeArgumentList() { concatGenericsLists(); } protected void consumeTypeArgumentList1() { concatGenericsLists(); } protected void consumeTypeArgumentList2() { concatGenericsLists(); } protected void consumeTypeArgumentList3() { concatGenericsLists(); } protected void consumeTypeArgumentReferenceType1() { concatGenericsLists(); pushOnGenericsStack(getTypeReference(0)); this.intPtr--; } protected void consumeTypeArgumentReferenceType2() { concatGenericsLists(); pushOnGenericsStack(getTypeReference(0)); this.intPtr--; } protected void consumeTypeArguments() { concatGenericsLists(); this.intPtr--; if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5 && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { int length = this.genericsLengthStack[this.genericsLengthPtr]; problemReporter().invalidUsageOfTypeArguments( (TypeReference)this.genericsStack[this.genericsPtr - length + 1], (TypeReference)this.genericsStack[this.genericsPtr]); } } protected void consumeTypeDeclarations() { // TypeDeclarations ::= TypeDeclarations TypeDeclaration concatNodeLists(); } 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 if (this.currentElement instanceof RecoveredType) { RecoveredType recoveredType = (RecoveredType) this.currentElement; recoveredType.pendingTypeParameters = null; this.lastCheckPoint = typeDecl.bodyStart; } else { this.lastCheckPoint = typeDecl.bodyStart; this.currentElement = this.currentElement.add(typeDecl, 0); this.lastIgnoredToken = -1; } } } protected void consumeTypeImportOnDemandDeclarationName() { // TypeImportOnDemandDeclarationName ::= 'import' 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, ClassFileConstants.AccDefault)); // star end position impt.trailingStarPosition = this.intStack[this.intPtr--]; 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--]; // 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 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 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 consumeTypeParameterList() { //TypeParameterList ::= TypeParameterList ',' TypeParameter concatGenericsLists(); } protected void consumeTypeParameterList1() { //TypeParameterList1 ::= TypeParameterList ',' TypeParameter1 concatGenericsLists(); } protected void consumeTypeParameters() { int startPos = this.intStack[this.intPtr--]; if(this.currentElement != null) { if(this.currentElement instanceof RecoveredType) { RecoveredType recoveredType =(RecoveredType) this.currentElement; int length = this.genericsLengthStack[this.genericsLengthPtr]; TypeParameter[] typeParameters = new TypeParameter[length]; System.arraycopy(this.genericsStack, this.genericsPtr - length + 1, typeParameters, 0, length); recoveredType.add(typeParameters, startPos); } } if(!this.statementRecoveryActivated && this.options.sourceLevel < ClassFileConstants.JDK1_5&& this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { int length = this.genericsLengthStack[this.genericsLengthPtr]; problemReporter().invalidUsageOfTypeParameters( (TypeParameter) this.genericsStack[this.genericsPtr - length + 1], (TypeParameter) this.genericsStack[this.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 // UnaryExpressionNotPlusMinus ::= '~' PushPosition UnaryExpression // UnaryExpressionNotPlusMinus ::= '!' PushPosition UnaryExpression //optimize the push/pop //handle manually the -2147483648 while it is not a real //computation of an - and 2147483648 (notice that 2147483648 //is Integer.MAX_VALUE+1.....) //Same for -9223372036854775808L ............ //this.intStack have the position of the operator Expression r, exp = this.expressionStack[this.expressionPtr]; if (op == MINUS) { if (exp instanceof IntLiteral) { IntLiteral intLiteral = (IntLiteral) exp; IntLiteral convertToMinValue = intLiteral.convertToMinValue(); if (convertToMinValue == intLiteral) { // not a min value literal so we convert it to an unary expression r = new UnaryExpression(exp, op); } else { r = convertToMinValue; } } else if (exp instanceof LongLiteral) { LongLiteral longLiteral = (LongLiteral) exp; LongLiteral convertToMinValue = longLiteral.convertToMinValue(); if (convertToMinValue == longLiteral) { // not a min value literal so we convert it to an unary expression r = new UnaryExpression(exp, op); } else { r = convertToMinValue; } } else { r = new UnaryExpression(exp, op); } } else { r = new UnaryExpression(exp, op); } r.sourceStart = this.intStack[this.intPtr--]; r.sourceEnd = exp.sourceEnd; this.expressionStack[this.expressionPtr] = r; } protected void consumeUnaryExpression(int op, boolean post) { // PreIncrementExpression ::= '++' PushPosition UnaryExpression // PreDecrementExpression ::= '--' PushPosition UnaryExpression // ++ and -- operators //optimize the push/pop //this.intStack has the position of the operator when prefix Expression leftHandSide = this.expressionStack[this.expressionPtr]; if (leftHandSide instanceof Reference) { // ++foo()++ is unvalid if (post) { this.expressionStack[this.expressionPtr] = new PostfixExpression( leftHandSide, IntLiteral.One, op, this.endStatementPosition); } else { this.expressionStack[this.expressionPtr] = new PrefixExpression( leftHandSide, IntLiteral.One, op, this.intStack[this.intPtr--]); } } else { //the ++ or the -- is NOT taken into account if code gen proceeds if (!post) { this.intPtr--; } if(!this.statementRecoveryActivated) problemReporter().invalidUnaryExpression(leftHandSide); } } protected void consumeVariableDeclarators() { // VariableDeclarators ::= VariableDeclarators ',' VariableDeclarator optimizedConcatNodeLists(); } 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 * * @param sourceStart int * @param sourceEnd int * @return boolean */ public boolean containsComment(int sourceStart, int sourceEnd) { int iComment = this.scanner.commentPtr; for (; iComment >= 0; iComment--) { int commentStart = this.scanner.commentStarts[iComment]; if (commentStart < 0) commentStart = -commentStart; // ignore comments before start if (commentStart < sourceStart) continue; // ignore comments after end if (commentStart > sourceEnd) continue; return true; } return false; } 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; m.bodyEnd = c.bodyEnd; m.declarationSourceEnd = c.declarationSourceEnd; m.declarationSourceStart = c.declarationSourceStart; 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; m.returnType = null; m.javadoc = c.javadoc; return m; } protected TypeReference copyDims(TypeReference typeRef, int dim) { return typeRef.copyDims(dim); } protected FieldDeclaration createFieldDeclaration(char[] fieldDeclarationName, int sourceStart, int sourceEnd) { return new FieldDeclaration(fieldDeclarationName, sourceStart, sourceEnd); } protected JavadocParser createJavadocParser() { return new JavadocParser(this); } protected LocalDeclaration createLocalDeclaration(char[] localDeclarationName, int sourceStart, int sourceEnd) { return new LocalDeclaration(localDeclarationName, sourceStart, sourceEnd); } protected StringLiteral createStringLiteral(char[] token, int start, int end, int lineNumber) { return new StringLiteral(token, start, end, lineNumber); } 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; boolean old = this.diet; try { this.diet = true; parsedUnit = parse(sourceUnit, compilationResult); } finally { this.diet = old; } return parsedUnit; } protected void dispatchDeclarationInto(int length) { /* 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 */ // Looks for the size of each array . if (length == 0) 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] = 2; size2++; 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) { typeDecl.fields = new FieldDeclaration[size1]; } if (size2 != 0) { typeDecl.methods = new AbstractMethodDeclaration[size2]; if (hasAbstractMethods) typeDecl.bits |= ASTNode.HasAbstractMethods; } if (size3 != 0) { typeDecl.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, typeDecl.fields, size1 - length2, length2); break; case 2 : size2 += (length2 = end - start); System.arraycopy( this.astStack, this.astPtr + start + 1, typeDecl.methods, size2 - length2, length2); break; case 3 : size3 += (length2 = end - start); System.arraycopy( this.astStack, this.astPtr + start + 1, typeDecl.memberTypes, size3 - length2, length2); break; } flagI = flag[start = end]; } } if (typeDecl.memberTypes != null) { for (int i = typeDecl.memberTypes.length - 1; i >= 0; i--) { typeDecl.memberTypes[i].enclosingType = typeDecl; } } } 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; int enumConstantsCounter = 0; 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 (((FieldDeclaration) astNode).getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { enumConstantsCounter++; } } } //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; } } enumDeclaration.enumConstantsCounter = enumConstantsCounter; } protected CompilationUnitDeclaration endParse(int act) { this.lastAct = act; if(this.statementRecoveryActivated) { RecoveredElement recoveredElement = buildInitialRecoveryState(); if (recoveredElement != null) { recoveredElement.topElement().updateParseTree(); } if(this.hasError) resetStacks(); } else if (this.currentElement != null){ if (VERBOSE_RECOVERY){ System.out.print(Messages.parser_syntaxRecovery); System.out.println("--------------------------"); //$NON-NLS-1$ System.out.println(this.compilationUnit); System.out.println("----------------------------------"); //$NON-NLS-1$ } this.currentElement.topElement().updateParseTree(); } else { if (this.diet & VERBOSE_RECOVERY){ System.out.print(Messages.parser_regularParse); System.out.println("--------------------------"); //$NON-NLS-1$ System.out.println(this.compilationUnit); System.out.println("----------------------------------"); //$NON-NLS-1$ } } persistLineSeparatorPositions(); for (int i = 0; i < this.scanner.foundTaskCount; i++){ if(!this.statementRecoveryActivated) problemReporter().task( new String(this.scanner.foundTaskTags[i]), new String(this.scanner.foundTaskMessages[i]), this.scanner.foundTaskPriorities[i] == null ? null : new String(this.scanner.foundTaskPriorities[i]), this.scanner.foundTaskPositions[i][0], this.scanner.foundTaskPositions[i][1]); } this.javadoc = null; return this.compilationUnit; } /* * Flush comments defined prior to a given positions. * * Note: comments are stacked in syntactical order * * Either answer given , or the end position of a comment line * immediately following the (same line) * * e.g. * void foo(){ * } // end of method foo */ public int flushCommentsDefinedPriorTo(int position) { int lastCommentIndex = this.scanner.commentPtr; if (lastCommentIndex < 0) return position; // no comment // compute the index of the first obsolete comment int index = lastCommentIndex; int validCount = 0; while (index >= 0){ int commentEnd = this.scanner.commentStops[index]; if (commentEnd < 0) commentEnd = -commentEnd; // negative end position for non-javadoc comments if (commentEnd <= position){ break; } index--; validCount++; } // if the source at is immediately followed by a line comment, then // flush this comment and shift to the comment end. if (validCount > 0){ int immediateCommentEnd = -this.scanner.commentStops[index+1]; //non-javadoc comment end positions are negative if (immediateCommentEnd > 0){ // only tolerating non-javadoc comments // is there any line break until the end of the immediate comment ? (thus only tolerating line comment) immediateCommentEnd--; // comment end in one char too far if (Util.getLineNumber(position, this.scanner.lineEnds, 0, this.scanner.linePtr) == Util.getLineNumber(immediateCommentEnd, this.scanner.lineEnds, 0, this.scanner.linePtr)){ position = immediateCommentEnd; validCount--; // flush this comment index++; } } } if (index < 0) return position; // no obsolete comment switch (validCount) { case 0: // do nothing break; // move valid comment infos, overriding obsolete comment infos case 2: this.scanner.commentStarts[0] = this.scanner.commentStarts[index+1]; this.scanner.commentStops[0] = this.scanner.commentStops[index+1]; this.scanner.commentTagStarts[0] = this.scanner.commentTagStarts[index+1]; this.scanner.commentStarts[1] = this.scanner.commentStarts[index+2]; this.scanner.commentStops[1] = this.scanner.commentStops[index+2]; this.scanner.commentTagStarts[1] = this.scanner.commentTagStarts[index+2]; break; case 1: this.scanner.commentStarts[0] = this.scanner.commentStarts[index+1]; this.scanner.commentStops[0] = this.scanner.commentStops[index+1]; this.scanner.commentTagStarts[0] = this.scanner.commentTagStarts[index+1]; break; default: System.arraycopy(this.scanner.commentStarts, index + 1, this.scanner.commentStarts, 0, validCount); System.arraycopy(this.scanner.commentStops, index + 1, this.scanner.commentStops, 0, validCount); System.arraycopy(this.scanner.commentTagStarts, index + 1, this.scanner.commentTagStarts, 0, validCount); } this.scanner.commentPtr = validCount - 1; return position; } protected TypeReference getAnnotationType() { int length = this.identifierLengthStack[this.identifierLengthPtr--]; if (length == 1) { return 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); return new QualifiedTypeReference(tokens, positions); } } 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).... // Goal ::= '++' CompilationUnit // Goal ::= '--' MethodBody // Goal ::= '==' ConstructorBody // -- Initializer // Goal ::= '>>' StaticInitializer // Goal ::= '>>' Block // -- error recovery // Goal ::= '>>>' Headers // Goal ::= '*' BlockStatements // Goal ::= '*' MethodPushModifiersHeader // -- JDOM // Goal ::= '&&' FieldDeclaration // Goal ::= '||' ImportDeclaration // Goal ::= '?' PackageDeclaration // Goal ::= '+' TypeDeclaration // Goal ::= '/' GenericMethodDeclaration // Goal ::= '&' ClassBodyDeclaration // -- code snippet // Goal ::= '%' Expression // -- completion parser // Goal ::= '!' ConstructorBlockStatementsopt // Goal ::= '~' BlockStatementsopt return this.firstToken; } /* * Answer back an array of sourceStart/sourceEnd positions of the available JavaDoc comments. * The array is a flattened structure: 2*n entries with consecutives start and end positions. * * If no JavaDoc is available, then null is answered instead of an empty array. * * e.g. { 10, 20, 25, 45 } --> javadoc1 from 10 to 20, javadoc2 from 25 to 45 */ public int[] getJavaDocPositions() { int javadocCount = 0; int max = this.scanner.commentPtr; for (int i = 0; i <= max; i++){ // javadoc only (non javadoc comment have negative start and/or end positions.) if (this.scanner.commentStarts[i] >= 0 && this.scanner.commentStops[i] > 0) { javadocCount++; } } if (javadocCount == 0) return null; int[] positions = new int[2*javadocCount]; int index = 0; for (int i = 0; i <= max; i++){ // javadoc only (non javadoc comment have negative start and/or end positions.) int commentStart = this.scanner.commentStarts[i]; if (commentStart >= 0) { int commentStop = this.scanner.commentStops[i]; if (commentStop > 0){ positions[index++] = commentStart; positions[index++] = commentStop-1; //stop is one over } } } return positions; } public void getMethodBodies(CompilationUnitDeclaration unit) { //fill the methods bodies in order for the code to be generated if (unit == null) return; if (unit.ignoreMethodBodies) { unit.ignoreFurtherInvestigation = true; return; // if initial diet parse did not work, no need to dig into method bodies. } if ((unit.bits & ASTNode.HasAllMethodBodies) != 0) return; //work already done ... // 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; //real parse of the method.... CompilationResult compilationResult = unit.compilationResult; char[] contents = this.readManager != null ? this.readManager.getContents(compilationResult.compilationUnit) : compilationResult.compilationUnit.getContents(); this.scanner.setSource(contents, compilationResult); if (this.javadocParser != null && this.javadocParser.checkDocComment) { this.javadocParser.scanner.setSource(contents); } if (unit.types != null) { for (int i = 0, length = unit.types.length; i < length; i++) unit.types[i].parseMethods(this, unit); } // tag unit has having read bodies unit.bits |= ASTNode.HasAllMethodBodies; // this is done to prevent any side effects on the compilation unit result // line separator positions array. this.scanner.lineEnds = oldLineEnds; this.scanner.linePtr = oldLinePtr; } 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 = ScannerHelper.getHexadecimalValue(comment[index[0]++])) > 15 || c1 < 0) || ((c2 = ScannerHelper.getHexadecimalValue(comment[index[0]++])) > 15 || c2 < 0) || ((c3 = ScannerHelper.getHexadecimalValue(comment[index[0]++])) > 15 || c3 < 0) || ((c4 = ScannerHelper.getHexadecimalValue(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*/ TypeReference ref; 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.sourceEnd = this.intStack[this.intPtr--]; } else { this.intPtr--; ref.sourceEnd = this.endPosition; } } else { 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 = new SingleTypeReference( this.identifierStack[this.identifierPtr], this.identifierPositionStack[this.identifierPtr--]); } else { ref = new ArrayTypeReference( this.identifierStack[this.identifierPtr], dim, this.identifierPositionStack[this.identifierPtr--]); ref.sourceEnd = this.endPosition; } } else { this.genericsLengthPtr--; //Qualified variable reference 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); if (dim == 0) { ref = new QualifiedTypeReference(tokens, positions); } else { ref = new ArrayQualifiedTypeReference(tokens, dim, positions); ref.sourceEnd = this.endPosition; } } } return ref; } protected TypeReference getTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) { if (identifierLength == 1 && numberOfIdentifiers == 1) { int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--]; TypeReference[] typeArguments = null; if (currentTypeArgumentsLength < 0) { typeArguments = TypeReference.NO_TYPE_ARGUMENTS; } else { 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.endStatementPosition; } /* We used to eagerly mark the PSTR as constituting diamond usage if we encountered <>, but that is too eager and complicates error handling by making it hard to distinguish legitimate use cases from ill formed ones. We are more discriminating now and tag a type as being diamond only where <> can legally occur. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=339478#c11 */ 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); } else if (currentTypeArgumentsLength < 0) { // diamond case for qualified type reference (java.util.ArrayList<>) typeArguments[index - 1] = TypeReference.NO_TYPE_ARGUMENTS; } 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--]; } } ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference = new ParameterizedQualifiedTypeReference(tokens, typeArguments, dim, positions); if (dim != 0) { parameterizedQualifiedTypeReference.sourceEnd = this.endStatementPosition; } /* We used to eagerly mark the PQTR as constituting diamond usage if we encountered <>, but that is too eager and complicates error handling by making it hard to distinguish legitimate use cases from ill formed ones. We are more discriminating now and tag a type as being diamond only where <> can legally occur. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=339478#c11 */ return parameterizedQualifiedTypeReference; } } protected NameReference getUnspecifiedReference() { /* build a (unspecified) NameReference which may be qualified*/ int length; NameReference ref; if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) // single variable reference ref = new SingleNameReference( this.identifierStack[this.identifierPtr], this.identifierPositionStack[this.identifierPtr--]); else //Qualified variable reference { char[][] tokens = new char[length][]; this.identifierPtr -= length; System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length); long[] positions = new long[length]; System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length); ref = new QualifiedNameReference(tokens, positions, (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd } return ref; } protected NameReference getUnspecifiedReferenceOptimized() { /* build a (unspecified) NameReference which may be qualified The optimization occurs for qualified reference while we are certain in this case the last item of the qualified name is a field access. This optimization is IMPORTANT while it results that when a NameReference is build, the type checker should always look for that it is not a type reference */ int length; NameReference ref; if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) { // single variable reference ref = new SingleNameReference( this.identifierStack[this.identifierPtr], this.identifierPositionStack[this.identifierPtr--]); ref.bits &= ~ASTNode.RestrictiveFlagMASK; ref.bits |= Binding.LOCAL | Binding.FIELD; return ref; } //Qualified-variable-reference //In fact it is variable-reference DOT field-ref , but it would result in a type //conflict tha can be only reduce by making a superclass (or inetrface ) between //nameReference and FiledReference or putting FieldReference under NameReference //or else..........This optimisation is not really relevant so just leave as it is char[][] tokens = new char[length][]; this.identifierPtr -= length; System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length); long[] positions = new long[length]; System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length); ref = new QualifiedNameReference( tokens, positions, (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd ref.bits &= ~ASTNode.RestrictiveFlagMASK; ref.bits |= Binding.LOCAL | Binding.FIELD; return ref; } public void goForBlockStatementsopt() { //tells the scanner to go for block statements opt parsing this.firstToken = TokenNameTWIDDLE; this.scanner.recordLineSeparator = false; } public void goForBlockStatementsOrCatchHeader() { //tells the scanner to go for block statements or method headers parsing this.firstToken = TokenNameMULTIPLY; this.scanner.recordLineSeparator = false; } public void goForClassBodyDeclarations() { //tells the scanner to go for any body declarations parsing this.firstToken = TokenNameAND; this.scanner.recordLineSeparator = true; } public void goForCompilationUnit(){ //tells the scanner to go for compilation unit parsing this.firstToken = TokenNamePLUS_PLUS ; this.scanner.foundTaskCount = 0; this.scanner.recordLineSeparator = true; } public void goForExpression() { //tells the scanner to go for an expression parsing this.firstToken = TokenNameREMAINDER; this.scanner.recordLineSeparator = true; // recovery goals must record line separators } public void goForFieldDeclaration(){ //tells the scanner to go for field declaration parsing this.firstToken = TokenNameAND_AND ; this.scanner.recordLineSeparator = true; } public void goForGenericMethodDeclaration(){ //tells the scanner to go for generic method declarations parsing this.firstToken = TokenNameDIVIDE; this.scanner.recordLineSeparator = true; } public void goForHeaders(){ //tells the scanner to go for headers only parsing RecoveredType currentType = 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(){ //tells the scanner to go for import declaration parsing this.firstToken = TokenNameOR_OR ; this.scanner.recordLineSeparator = true; } public void goForInitializer(){ //tells the scanner to go for initializer parsing this.firstToken = TokenNameRIGHT_SHIFT ; this.scanner.recordLineSeparator = false; } public void goForMemberValue() { //tells the scanner to go for a member 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 this.firstToken = TokenNameMINUS_MINUS ; this.scanner.recordLineSeparator = false; } public void goForPackageDeclaration() { //tells the scanner to go for package declaration parsing this.firstToken = TokenNameQUESTION; this.scanner.recordLineSeparator = true; } public void goForTypeDeclaration() { //tells the scanner to go for type (interface or class) declaration parsing this.firstToken = TokenNamePLUS; this.scanner.recordLineSeparator = true; } /** * Look for a specific tag comment leading a given source range (comment located after any statement in astStack) * @param rangeEnd int * @return boolean */ public boolean hasLeadingTagComment(char[] commentPrefixTag, int rangeEnd) { int iComment = this.scanner.commentPtr; if (iComment < 0) return false; // no comment available int iStatement = this.astLengthPtr; if (iStatement < 0 || this.astLengthStack[iStatement] <= 1) return false; // no statement available // Fallthrough comment must be located after the previous statement ASTNode lastNode = this.astStack[this.astPtr]; int rangeStart = lastNode.sourceEnd; previousComment: for (; iComment >= 0; iComment--) { int commentStart = this.scanner.commentStarts[iComment]; if (commentStart < 0) commentStart = -commentStart; // line comments have negative start positions // ignore comments before start if (commentStart < rangeStart) return false; // no more comments in range // ignore comments after end if (commentStart > rangeEnd) continue previousComment; // found last comment in range - only check the last comment in range char[] source = this.scanner.source; int charPos = commentStart+2; // skip // or /* // tag can be leaded by optional spaces for (; charPos < rangeEnd; charPos++) { char c = source[charPos]; if (c >= ScannerHelper.MAX_OBVIOUS || (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_JLS_SPACE) == 0) { break; } } for (int iTag = 0, length = commentPrefixTag.length; iTag < length; iTag++, charPos++) { if (charPos >= rangeEnd // comment is too small to host tag || source[charPos] != commentPrefixTag[iTag]) { if (iTag == 0) { return false; // didn't even match leading '$' -> not a tag comment } else { continue previousComment; // accept as tag comment -> skip it and keep searching backwards } } } return true; } return false; } protected void ignoreExpressionAssignment() { // Assignment ::= InvalidArrayInitializerAssignement // encoded operator would be: this.intStack[this.intPtr] this.intPtr--; ArrayInitializer arrayInitializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--]; this.expressionLengthPtr -- ; // report a syntax error and abort parsing if(!this.statementRecoveryActivated) problemReporter().arrayConstantsOnlyInArrayInitializers(arrayInitializer.sourceStart, arrayInitializer.sourceEnd); } public void initialize() { this.initialize(false); } public void initialize(boolean initializeNLS) { //positioning the parser for a new compilation unit //avoiding stack reallocation and all that.... this.javadoc = null; this.astPtr = -1; this.astLengthPtr = -1; this.expressionPtr = -1; this.expressionLengthPtr = -1; this.identifierPtr = -1; this.identifierLengthPtr = -1; this.intPtr = -1; this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse this.variablesCounter[this.nestedType] = 0; this.dimensions = 0 ; this.realBlockPtr = -1; this.compilationUnit = null; this.referenceContext = null; this.endStatementPosition = 0; //remove objects from stack too, while the same parser/compiler couple is //re-used between two compilations .... int astLength = this.astStack.length; if (this.noAstNodes.length < astLength){ this.noAstNodes = new ASTNode[astLength]; //System.out.println("Resized AST stacks : "+ astLength); } System.arraycopy(this.noAstNodes, 0, this.astStack, 0, astLength); int expressionLength = this.expressionStack.length; if (this.noExpressions.length < expressionLength){ this.noExpressions = new Expression[expressionLength]; //System.out.println("Resized EXPR stacks : "+ expressionLength); } System.arraycopy(this.noExpressions, 0, this.expressionStack, 0, expressionLength); // reset this.scanner state this.scanner.commentPtr = -1; this.scanner.foundTaskCount = 0; this.scanner.eofPosition = Integer.MAX_VALUE; this.recordStringLiterals = true; final boolean checkNLS = this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore; this.checkExternalizeStrings = checkNLS; this.scanner.checkNonExternalizedStringLiterals = initializeNLS && checkNLS; this.scanner.lastPosition = -1; resetModifiers(); // recovery this.lastCheckPoint = -1; this.currentElement = null; this.restartRecovery = false; this.hasReportedError = false; this.recoveredStaticInitializerStart = 0; this.lastIgnoredToken = -1; this.lastErrorEndPosition = -1; this.lastErrorEndPositionBeforeRecovery = -1; this.lastJavadocEnd = -1; this.listLength = 0; this.listTypeParameterLength = 0; this.lastPosistion = -1; 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( false /*comment*/, false /*whitespace*/, false, /* will be set in initialize(boolean) */ this.options.sourceLevel /*sourceLevel*/, this.options.complianceLevel /*complianceLevel*/, this.options.taskTags/*taskTags*/, this.options.taskPriorities/*taskPriorities*/, this.options.isTaskCaseSensitive/*taskCaseSensitive*/); } public void jumpOverMethodBody() { //on diet parsing.....do not buffer method statements //the scanner.diet is reinitialized to false //automatically by the scanner once it has jumped over //the statements if (this.diet && (this.dietInt == 0)) this.scanner.diet = true; } private void jumpOverType(){ if (this.recoveredTypes != null && this.nextTypeStart > -1 && this.nextTypeStart < this.scanner.currentPosition) { if (DEBUG_AUTOMATON) { System.out.println("Jump -"); //$NON-NLS-1$ } TypeDeclaration typeDeclaration = this.recoveredTypes[this.recoveredTypePtr]; boolean isAnonymous = typeDeclaration.allocation != null; this.scanner.startPosition = typeDeclaration.declarationSourceEnd + 1; this.scanner.currentPosition = typeDeclaration.declarationSourceEnd + 1; this.scanner.diet = false; // quit jumping over method bodies if(!isAnonymous) { ((RecoveryScanner)this.scanner).setPendingTokens(new int[]{TokenNameSEMICOLON, TokenNamebreak}); } else { ((RecoveryScanner)this.scanner).setPendingTokens(new int[]{TokenNameIdentifier, TokenNameEQUAL, TokenNameIdentifier}); } this.pendingRecoveredType = typeDeclaration; try { this.currentToken = this.scanner.getNextToken(); } catch(InvalidInputException e){ // it's impossible because we added pending tokens before } if(++this.recoveredTypePtr < this.recoveredTypes.length) { TypeDeclaration nextTypeDeclaration = this.recoveredTypes[this.recoveredTypePtr]; this.nextTypeStart = nextTypeDeclaration.allocation == null ? nextTypeDeclaration.declarationSourceStart : nextTypeDeclaration.allocation.sourceStart; } else { this.nextTypeStart = Integer.MAX_VALUE; } } } protected void markEnclosingMemberWithLocalType() { if (this.currentElement != null) return; // this is already done in the recovery code for (int i = this.astPtr; i >= 0; i--) { ASTNode node = this.astStack[i]; if (node instanceof AbstractMethodDeclaration || node instanceof FieldDeclaration || (node instanceof TypeDeclaration // mark type for now: all initializers will be marked when added to this type // and enclosing type must not be closed (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=147485) && ((TypeDeclaration) node).declarationSourceEnd == 0)) { node.bits |= ASTNode.HasLocalType; return; } } // default to reference context (case of parse method body) if (this.referenceContext instanceof AbstractMethodDeclaration || this.referenceContext instanceof TypeDeclaration) { ((ASTNode)this.referenceContext).bits |= ASTNode.HasLocalType; } } /* * Move checkpoint location (current implementation is moving it by one token) * * Answers true if successfully moved checkpoint (in other words, it did not attempt to move it * beyond end of file). */ protected boolean moveRecoveryCheckpoint() { int pos = this.lastCheckPoint; /* 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 /* if about to restart, then no need to shift token */ if (this.restartRecovery){ this.lastIgnoredToken = -1; this.scanner.insideRecovery = true; return true; } /* protect against shifting on an invalid token */ this.lastIgnoredToken = this.nextIgnoredToken; this.nextIgnoredToken = -1; do { try { this.nextIgnoredToken = this.scanner.getNextToken(); if(this.scanner.currentPosition == this.scanner.startPosition){ this.scanner.currentPosition++; // on fake completion identifier this.nextIgnoredToken = -1; } } catch(InvalidInputException e){ pos = this.scanner.currentPosition; } } while (this.nextIgnoredToken < 0); if (this.nextIgnoredToken == TokenNameEOF) { // no more recovery after this point if (this.currentToken == TokenNameEOF) { // already tried one iteration on EOF return false; } } this.lastCheckPoint = this.scanner.currentPosition; /* reset this.scanner again to previous checkpoint location*/ this.scanner.startPosition = pos; this.scanner.currentPosition = pos; this.scanner.commentPtr = -1; this.scanner.foundTaskCount = 0; return true; /* The following implementation moves the checkpoint location by one line: int pos = this.lastCheckPoint; // 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 // if about to restart, then no need to shift token if (this.restartRecovery){ this.lastIgnoredToken = -1; return true; } // protect against shifting on an invalid token this.lastIgnoredToken = this.nextIgnoredToken; this.nextIgnoredToken = -1; boolean wasTokenizingWhiteSpace = this.scanner.tokenizeWhiteSpace; this.scanner.tokenizeWhiteSpace = true; checkpointMove: do { try { this.nextIgnoredToken = this.scanner.getNextToken(); switch(this.nextIgnoredToken){ case Scanner.TokenNameWHITESPACE : if(this.scanner.getLineNumber(this.scanner.startPosition) == this.scanner.getLineNumber(this.scanner.currentPosition)){ this.nextIgnoredToken = -1; } break; case TokenNameSEMICOLON : case TokenNameLBRACE : case TokenNameRBRACE : break; case TokenNameIdentifier : if(this.scanner.currentPosition == this.scanner.startPosition){ this.scanner.currentPosition++; // on fake completion identifier } default: this.nextIgnoredToken = -1; break; case TokenNameEOF : break checkpointMove; } } catch(InvalidInputException e){ pos = this.scanner.currentPosition; } } while (this.nextIgnoredToken < 0); this.scanner.tokenizeWhiteSpace = wasTokenizingWhiteSpace; if (this.nextIgnoredToken == TokenNameEOF) { // no more recovery after this point if (this.currentToken == TokenNameEOF) { // already tried one iteration on EOF return false; } } this.lastCheckPoint = this.scanner.currentPosition; // reset this.scanner again to previous checkpoint location this.scanner.startPosition = pos; this.scanner.currentPosition = pos; this.scanner.commentPtr = -1; return true; */ } protected MessageSend newMessageSend() { // '(' ArgumentListopt ')' // the arguments are on the expression stack 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; } 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; } protected void optimizedConcatNodeLists() { /*back from a recursive loop. Virtualy group the astNode into an array using this.astLengthStack*/ /* * 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 this.astStack. * Look at the InterfaceMemberDeclarations for an example. * This case optimizes the fact that p == 1. */ this.astLengthStack[--this.astLengthPtr]++; } /*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 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$ if (DEBUG_AUTOMATON) { System.out.println("- Start --------------------------------"); //$NON-NLS-1$ } boolean isDietParse = this.diet; int oldFirstToken = getFirstToken(); this.hasError = false; this.hasReportedError = false; int act = START_STATE; this.stateStackTop = -1; this.currentToken = getFirstToken(); ProcessTerminals : for (;;) { int stackLength = this.stack.length; if (++this.stateStackTop >= stackLength) { System.arraycopy( this.stack, 0, this.stack = new int[stackLength + StackIncrement], 0, stackLength); } this.stack[this.stateStackTop] = act; act = tAction(act, this.currentToken); if (act == ERROR_ACTION || (this.restartRecovery && !this.shouldDeferRecovery)) { this.shouldDeferRecovery = false; if (DEBUG_AUTOMATON) { if (this.restartRecovery) { System.out.println("Restart - "); //$NON-NLS-1$ } else { System.out.println("Error - "); //$NON-NLS-1$ } } int errorPos = this.scanner.currentPosition - 1; if (!this.hasReportedError) { this.hasError = true; } int previousToken = this.currentToken; if (resumeOnSyntaxError()) { if (act == ERROR_ACTION && previousToken != 0) this.lastErrorEndPosition = errorPos; act = START_STATE; this.stateStackTop = -1; this.currentToken = getFirstToken(); continue ProcessTerminals; } act = ERROR_ACTION; break ProcessTerminals; } if (act <= NUM_RULES) { this.stateStackTop--; if (DEBUG_AUTOMATON) { System.out.print("Reduce - "); //$NON-NLS-1$ } } else if (act > ERROR_ACTION) { /* shift-reduce */ consumeToken(this.currentToken); if (this.currentElement != null) { boolean oldValue = this.recordStringLiterals; this.recordStringLiterals = false; recoveryTokenCheck(); this.recordStringLiterals = oldValue; } try { this.currentToken = this.scanner.getNextToken(); } catch(InvalidInputException e){ if (!this.hasReportedError){ problemReporter().scannerError(this, e.getMessage()); this.hasReportedError = true; } this.lastCheckPoint = this.scanner.currentPosition; this.currentToken = 0; this.restartRecovery = true; } if(this.statementRecoveryActivated) { jumpOverType(); } act -= ERROR_ACTION; if (DEBUG_AUTOMATON) { System.out.print("Shift/Reduce - (" + name[terminal_index[this.currentToken]]+") "); //$NON-NLS-1$ //$NON-NLS-2$ } } else { if (act < ACCEPT_ACTION) { /* shift */ consumeToken(this.currentToken); if (this.currentElement != null) { boolean oldValue = this.recordStringLiterals; this.recordStringLiterals = false; recoveryTokenCheck(); this.recordStringLiterals = oldValue; } try{ this.currentToken = this.scanner.getNextToken(); } catch(InvalidInputException e){ if (!this.hasReportedError){ problemReporter().scannerError(this, e.getMessage()); this.hasReportedError = true; } this.lastCheckPoint = this.scanner.currentPosition; this.currentToken = 0; this.restartRecovery = true; } if(this.statementRecoveryActivated) { jumpOverType(); } if (DEBUG_AUTOMATON) { System.out.println("Shift - (" + name[terminal_index[this.currentToken]]+")"); //$NON-NLS-1$ //$NON-NLS-2$ } continue ProcessTerminals; } break ProcessTerminals; } // ProcessNonTerminals : do { /* reduce */ if (DEBUG_AUTOMATON) { System.out.println(name[non_terminal_index[lhs[act]]]); } consumeRule(act); this.stateStackTop -= (rhs[act] - 1); act = ntAction(this.stack[this.stateStackTop], lhs[act]); if (DEBUG_AUTOMATON) { if (act <= NUM_RULES) { System.out.print(" - "); //$NON-NLS-1$ } } } while (act <= NUM_RULES); if (DEBUG_AUTOMATON) { System.out.println("----------------------------------------"); //$NON-NLS-1$ } } if (DEBUG_AUTOMATON) { System.out.println("- End ----------------------------------"); //$NON-NLS-1$ } endParse(act); // record all nls tags in the corresponding compilation unit final NLSTag[] tags = this.scanner.getNLSTags(); if (tags != null) { this.compilationUnit.nlsTags = tags; } this.scanner.checkNonExternalizedStringLiterals = false; if (this.reportSyntaxErrorIsRequired && this.hasError && !this.statementRecoveryActivated) { if(!this.options.performStatementsRecovery) { reportSyntaxErrors(isDietParse, oldFirstToken); } else { RecoveryScannerData data = this.referenceContext.compilationResult().recoveryScannerData; if(this.recoveryScanner == null) { this.recoveryScanner = new RecoveryScanner(this.scanner, data); } else { this.recoveryScanner.setData(data); } this.recoveryScanner.setSource(this.scanner.source); this.recoveryScanner.lineEnds = this.scanner.lineEnds; this.recoveryScanner.linePtr = this.scanner.linePtr; reportSyntaxErrors(isDietParse, oldFirstToken); if(data == null) { this.referenceContext.compilationResult().recoveryScannerData = this.recoveryScanner.getData(); } if (this.methodRecoveryActivated && this.options.performStatementsRecovery) { this.methodRecoveryActivated = false; recoverStatements(); this.methodRecoveryActivated = true; this.lastAct = ERROR_ACTION; } } } this.problemReporter.referenceContext = null; // Null this so we won't escalate problems needlessly (bug 393192) if (DEBUG) System.out.println("-- EXIT FROM PARSE METHOD --"); //$NON-NLS-1$ } public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit, boolean recordLineSeparator) { //only parse the method body of cd //fill out its statements //convert bugs into parse error boolean oldMethodRecoveryActivated = this.methodRecoveryActivated; if(this.options.performMethodsFullRecovery) { this.methodRecoveryActivated = true; // we should not relocate bodyStart if there is a block within the statements this.ignoreNextOpeningBrace = true; } initialize(); goForBlockStatementsopt(); if (recordLineSeparator) { this.scanner.recordLineSeparator = true; } this.nestedMethod[this.nestedType]++; pushOnRealBlockStack(0); this.referenceContext = cd; this.compilationUnit = unit; this.scanner.resetTo(cd.bodyStart, cd.bodyEnd); try { parse(); } catch (AbortCompilation ex) { this.lastAct = ERROR_ACTION; } finally { this.nestedMethod[this.nestedType]--; if(this.options.performStatementsRecovery) { this.methodRecoveryActivated = oldMethodRecoveryActivated; } } checkNonNLSAfterBodyEnd(cd.declarationSourceEnd); if (this.lastAct == ERROR_ACTION) { cd.bits |= ASTNode.HasSyntaxErrors; initialize(); return; } //statements cd.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; int length; if (this.astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) { this.astPtr -= length; if (!this.options.ignoreMethodBodies) { if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ? { System.arraycopy( this.astStack, this.astPtr + 2, cd.statements = new Statement[length - 1], 0, length - 1); cd.constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1]; } else { //need to add explicitly the super(); System.arraycopy( this.astStack, this.astPtr + 1, cd.statements = new Statement[length], 0, length); cd.constructorCall = SuperReference.implicitSuperConstructorCall(); } } } else { if (!this.options.ignoreMethodBodies) { cd.constructorCall = SuperReference.implicitSuperConstructorCall(); } if (!containsComment(cd.bodyStart, cd.bodyEnd)) { cd.bits |= ASTNode.UndocumentedEmptyBlock; } } ExplicitConstructorCall explicitConstructorCall = cd.constructorCall; if (explicitConstructorCall != null && explicitConstructorCall.sourceEnd == 0) { explicitConstructorCall.sourceEnd = cd.sourceEnd; explicitConstructorCall.sourceStart = cd.sourceStart; } } // A P I public void parse( FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) { //only parse the initializationSource of the given field //convert bugs into parse error initialize(); goForExpression(); this.nestedMethod[this.nestedType]++; this.referenceContext = type; this.compilationUnit = unit; this.scanner.setSource(initializationSource); this.scanner.resetTo(0, initializationSource.length-1); try { parse(); } catch (AbortCompilation ex) { this.lastAct = ERROR_ACTION; } finally { this.nestedMethod[this.nestedType]--; } if (this.lastAct == ERROR_ACTION) { field.bits |= ASTNode.HasSyntaxErrors; return; } field.initialization = this.expressionStack[this.expressionPtr]; // mark field with local type if one was found during parsing if ((type.bits & ASTNode.HasLocalType) != 0) { field.bits |= ASTNode.HasLocalType; } } // 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(true); goForCompilationUnit(); /* unit creation */ this.referenceContext = this.compilationUnit = new CompilationUnitDeclaration( this.problemReporter, compilationResult, 0); /* scanners initialization */ char[] contents; try { contents = this.readManager != null ? this.readManager.getContents(sourceUnit) : sourceUnit.getContents(); } catch(AbortCompilationUnit abortException) { problemReporter().cannotReadSource(this.compilationUnit, abortException, this.options.verbose); contents = CharOperation.NO_CHAR; // pretend empty from thereon } this.scanner.setSource(contents); this.compilationUnit.sourceEnd = this.scanner.source.length - 1; 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); } } /* 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, CompilationUnitDeclaration unit) { //only parse the method body of md //fill out method statements //convert bugs into parse error boolean oldMethodRecoveryActivated = this.methodRecoveryActivated; if(this.options.performMethodsFullRecovery) { this.methodRecoveryActivated = true; } initialize(); goForBlockStatementsopt(); this.nestedMethod[this.nestedType]++; pushOnRealBlockStack(0); this.referenceContext = type; this.compilationUnit = unit; this.scanner.resetTo(initializer.bodyStart, initializer.bodyEnd); // just on the beginning { try { parse(); } catch (AbortCompilation ex) { this.lastAct = ERROR_ACTION; } finally { this.nestedMethod[this.nestedType]--; if(this.options.performStatementsRecovery) { this.methodRecoveryActivated = oldMethodRecoveryActivated; } } checkNonNLSAfterBodyEnd(initializer.declarationSourceEnd); if (this.lastAct == ERROR_ACTION) { initializer.bits |= ASTNode.HasSyntaxErrors; return; } //refill statements initializer.block.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; int length; if (this.astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) > 0) { System.arraycopy(this.astStack, (this.astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length); } else { // check whether this block at least contains some comment in it if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) { initializer.block.bits |= ASTNode.UndocumentedEmptyBlock; } } // mark initializer with local type if one was found during parsing if ((type.bits & ASTNode.HasLocalType) != 0) { initializer.bits |= ASTNode.HasLocalType; } } // A P I public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) { //only parse the method body of md //fill out method statements //convert bugs into parse error if (md.isAbstract()) return; if (md.isNative()) return; if ((md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) return; boolean oldMethodRecoveryActivated = this.methodRecoveryActivated; if(this.options.performMethodsFullRecovery) { // we should not relocate bodyStart if there is a block within the statements this.ignoreNextOpeningBrace = true; this.methodRecoveryActivated = true; this.rParenPos = md.sourceEnd; } 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]--; if(this.options.performStatementsRecovery) { this.methodRecoveryActivated = oldMethodRecoveryActivated; } } checkNonNLSAfterBodyEnd(md.declarationSourceEnd); if (this.lastAct == ERROR_ACTION) { md.bits |= ASTNode.HasSyntaxErrors; return; } //refill statements md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; int length; if (this.astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) { if (this.options.ignoreMethodBodies) { // ignore statements this.astPtr -= length; } else { 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.UndocumentedEmptyBlock; } } } public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int length, CompilationUnitDeclaration unit) { boolean oldDiet = this.diet; /* automaton initialization */ initialize(); goForClassBodyDeclarations(); /* scanner initialization */ this.scanner.setSource(source); this.scanner.resetTo(offset, offset + length - 1); if (this.javadocParser != null && this.javadocParser.checkDocComment) { this.javadocParser.scanner.setSource(source); this.javadocParser.scanner.resetTo(offset, offset + length - 1); } /* type declaration should be parsed as member type declaration */ this.nestedType = 1; /* unit creation */ TypeDeclaration referenceContextTypeDeclaration = new TypeDeclaration(unit.compilationResult); referenceContextTypeDeclaration.name = Util.EMPTY_STRING.toCharArray(); referenceContextTypeDeclaration.fields = new FieldDeclaration[0]; this.compilationUnit = unit; unit.types = new TypeDeclaration[1]; unit.types[0] = referenceContextTypeDeclaration; this.referenceContext = unit; /* run automaton */ try { this.diet = true; parse(); } catch (AbortCompilation ex) { this.lastAct = ERROR_ACTION; } finally { this.diet = oldDiet; } ASTNode[] result = null; if (this.lastAct == ERROR_ACTION) { if (!this.options.performMethodsFullRecovery && !this.options.performStatementsRecovery) { return null; } // collect all body declaration inside the compilation unit except the default constructor final List bodyDeclarations = new ArrayList(); ASTVisitor visitor = new ASTVisitor() { public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { if (!methodDeclaration.isDefaultConstructor()) { bodyDeclarations.add(methodDeclaration); } return false; } public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { bodyDeclarations.add(fieldDeclaration); return false; } public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) { bodyDeclarations.add(memberTypeDeclaration); return false; } }; unit.ignoreFurtherInvestigation = false; unit.traverse(visitor, unit.scope); unit.ignoreFurtherInvestigation = true; result = (ASTNode[]) bodyDeclarations.toArray(new ASTNode[bodyDeclarations.size()]); } else { int astLength; if (this.astLengthPtr > -1 && (astLength = this.astLengthStack[this.astLengthPtr--]) != 0) { result = new ASTNode[astLength]; this.astPtr -= astLength; System.arraycopy(this.astStack, this.astPtr + 1, result, 0, astLength); } else { // empty class body declaration (like ';' see https://bugs.eclipse.org/bugs/show_bug.cgi?id=280079). result = new ASTNode[0]; } } boolean containsInitializers = false; TypeDeclaration typeDeclaration = null; for (int i = 0, max = result.length; i < max; i++) { // parse each class body declaration ASTNode node = result[i]; if (node instanceof TypeDeclaration) { ((TypeDeclaration) node).parseMethods(this, unit); } else if (node instanceof AbstractMethodDeclaration) { ((AbstractMethodDeclaration) node).parseStatements(this, unit); } else if (node instanceof FieldDeclaration) { FieldDeclaration fieldDeclaration = (FieldDeclaration) node; switch(fieldDeclaration.getKind()) { case AbstractVariableDeclaration.INITIALIZER: containsInitializers = true; if (typeDeclaration == null) { typeDeclaration = referenceContextTypeDeclaration; } if (typeDeclaration.fields == null) { typeDeclaration.fields = new FieldDeclaration[1]; typeDeclaration.fields[0] = fieldDeclaration; } else { int length2 = typeDeclaration.fields.length; FieldDeclaration[] temp = new FieldDeclaration[length2 + 1]; System.arraycopy(typeDeclaration.fields, 0, temp, 0, length2); temp[length2] = fieldDeclaration; typeDeclaration.fields = temp; } break; } } if (((node.bits & ASTNode.HasSyntaxErrors) != 0) && (!this.options.performMethodsFullRecovery && !this.options.performStatementsRecovery)) { return null; } } if (containsInitializers) { FieldDeclaration[] fieldDeclarations = typeDeclaration.fields; for (int i = 0, max = fieldDeclarations.length; i < max; i++) { Initializer initializer = (Initializer) fieldDeclarations[i]; initializer.parseStatements(this, typeDeclaration , unit); if (((initializer.bits & ASTNode.HasSyntaxErrors) != 0) && (!this.options.performMethodsFullRecovery && !this.options.performStatementsRecovery)) { return null; } } } return result; } public Expression parseExpression(char[] source, int offset, int length, CompilationUnitDeclaration unit) { initialize(); goForExpression(); 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 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 parseStatements(ReferenceContext rc, int start, int end, TypeDeclaration[] types, CompilationUnitDeclaration unit) { boolean oldStatementRecoveryEnabled = this.statementRecoveryActivated; this.statementRecoveryActivated = true; initialize(); goForBlockStatementsopt(); this.nestedMethod[this.nestedType]++; pushOnRealBlockStack(0); pushOnAstLengthStack(0); this.referenceContext = rc; this.compilationUnit = unit; this.pendingRecoveredType = null; if(types != null && types.length > 0) { this.recoveredTypes = types; this.recoveredTypePtr = 0; this.nextTypeStart = this.recoveredTypes[0].allocation == null ? this.recoveredTypes[0].declarationSourceStart : this.recoveredTypes[0].allocation.sourceStart; } else { this.recoveredTypes = null; this.recoveredTypePtr = -1; this.nextTypeStart = -1; } this.scanner.resetTo(start, end); // reset the scanner to parser from { down to } this.lastCheckPoint = this.scanner.initialPosition; this.stateStackTop = -1; try { parse(); } catch (AbortCompilation ex) { this.lastAct = ERROR_ACTION; } finally { this.nestedMethod[this.nestedType]--; this.recoveredTypes = null; this.statementRecoveryActivated = oldStatementRecoveryEnabled; } checkNonNLSAfterBodyEnd(end); } public void persistLineSeparatorPositions() { if (this.scanner.recordLineSeparator) { this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds(); } } /* * Prepares the state of the parser to go for BlockStatements. */ protected void prepareForBlockStatements() { this.nestedMethod[this.nestedType = 0] = 1; this.variablesCounter[this.nestedType] = 0; this.realBlockStack[this.realBlockPtr = 1] = 0; } /** * Returns this parser's problem reporter initialized with its reference context. * Also it is assumed that a problem is going to be reported, so initializes * the compilation result's line positions. * * @return ProblemReporter */ public ProblemReporter problemReporter(){ if (this.scanner.recordLineSeparator) { this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds(); } this.problemReporter.referenceContext = this.referenceContext; return this.problemReporter; } protected void pushIdentifier() { /*push the consumeToken on the identifier stack. Increase the total number of identifier in the stack. identifierPtr points on the next top */ int stackLength = this.identifierStack.length; if (++this.identifierPtr >= stackLength) { System.arraycopy( this.identifierStack, 0, this.identifierStack = new char[stackLength + 20][], 0, stackLength); System.arraycopy( this.identifierPositionStack, 0, this.identifierPositionStack = new long[stackLength + 20], 0, stackLength); } this.identifierStack[this.identifierPtr] = this.scanner.getCurrentIdentifierSource(); this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32) + (this.scanner.currentPosition - 1); stackLength = this.identifierLengthStack.length; if (++this.identifierLengthPtr >= stackLength) { System.arraycopy( this.identifierLengthStack, 0, this.identifierLengthStack = new int[stackLength + 10], 0, stackLength); } this.identifierLengthStack[this.identifierLengthPtr] = 1; } protected void pushIdentifier(int flag) { /*push a special flag on the stack : -zero stands for optional Name -negative number for direct ref to base types. identifierLengthPtr points on the top */ int stackLength = this.identifierLengthStack.length; if (++this.identifierLengthPtr >= stackLength) { System.arraycopy( this.identifierLengthStack, 0, this.identifierLengthStack = new int[stackLength + 10], 0, stackLength); } this.identifierLengthStack[this.identifierLengthPtr] = flag; } protected void pushOnAstLengthStack(int pos) { int stackLength = this.astLengthStack.length; if (++this.astLengthPtr >= stackLength) { System.arraycopy( this.astLengthStack, 0, this.astLengthStack = new int[stackLength + StackIncrement], 0, stackLength); } this.astLengthStack[this.astLengthPtr] = pos; } protected void pushOnAstStack(ASTNode node) { /*add a new obj on top of the ast stack astPtr points on the top*/ int stackLength = this.astStack.length; if (++this.astPtr >= stackLength) { System.arraycopy( this.astStack, 0, this.astStack = new ASTNode[stackLength + AstStackIncrement], 0, stackLength); this.astPtr = stackLength; } this.astStack[this.astPtr] = node; stackLength = this.astLengthStack.length; if (++this.astLengthPtr >= stackLength) { System.arraycopy( this.astLengthStack, 0, this.astLengthStack = new int[stackLength + AstStackIncrement], 0, stackLength); } this.astLengthStack[this.astLengthPtr] = 1; } protected void pushOnExpressionStack(Expression expr) { int stackLength = this.expressionStack.length; if (++this.expressionPtr >= stackLength) { System.arraycopy( this.expressionStack, 0, this.expressionStack = new Expression[stackLength + ExpressionStackIncrement], 0, stackLength); } this.expressionStack[this.expressionPtr] = expr; stackLength = this.expressionLengthStack.length; if (++this.expressionLengthPtr >= stackLength) { System.arraycopy( this.expressionLengthStack, 0, this.expressionLengthStack = new int[stackLength + ExpressionStackIncrement], 0, stackLength); } this.expressionLengthStack[this.expressionLengthPtr] = 1; } protected void pushOnExpressionStackLengthStack(int pos) { int stackLength = this.expressionLengthStack.length; if (++this.expressionLengthPtr >= stackLength) { System.arraycopy( this.expressionLengthStack, 0, this.expressionLengthStack = new int[stackLength + StackIncrement], 0, stackLength); } this.expressionLengthStack[this.expressionLengthPtr] = pos; } 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 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 pushOnIntStack(int pos) { int stackLength = this.intStack.length; if (++this.intPtr >= stackLength) { System.arraycopy( this.intStack, 0, this.intStack = new int[stackLength + StackIncrement], 0, stackLength); } this.intStack[this.intPtr] = pos; } protected void pushOnRealBlockStack(int i){ int stackLength = this.realBlockStack.length; if (++this.realBlockPtr >= stackLength) { System.arraycopy( this.realBlockStack, 0, this.realBlockStack = new int[stackLength + StackIncrement], 0, stackLength); } this.realBlockStack[this.realBlockPtr] = i; } protected void recoverStatements() { class MethodVisitor extends ASTVisitor { public ASTVisitor typeVisitor; TypeDeclaration enclosingType; // used only for initializer TypeDeclaration[] types = new TypeDeclaration[0]; int typePtr = -1; public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { endVisitMethod(constructorDeclaration, scope); } public void endVisit(Initializer initializer, MethodScope scope) { if (initializer.block == null) return; TypeDeclaration[] foundTypes = null; int length = 0; if(this.typePtr > -1) { length = this.typePtr + 1; foundTypes = new TypeDeclaration[length]; System.arraycopy(this.types, 0, foundTypes, 0, length); } ReferenceContext oldContext = Parser.this.referenceContext; Parser.this.recoveryScanner.resetTo(initializer.bodyStart, initializer.bodyEnd); Scanner oldScanner = Parser.this.scanner; Parser.this.scanner = Parser.this.recoveryScanner; parseStatements( this.enclosingType, initializer.bodyStart, initializer.bodyEnd, foundTypes, Parser.this.compilationUnit); Parser.this.scanner = oldScanner; Parser.this.referenceContext = oldContext; for (int i = 0; i < length; i++) { foundTypes[i].traverse(this.typeVisitor, scope); } } public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) { endVisitMethod(methodDeclaration, scope); } private void endVisitMethod(AbstractMethodDeclaration methodDeclaration, ClassScope scope) { TypeDeclaration[] foundTypes = null; int length = 0; if(this.typePtr > -1) { length = this.typePtr + 1; foundTypes = new TypeDeclaration[length]; System.arraycopy(this.types, 0, foundTypes, 0, length); } ReferenceContext oldContext = Parser.this.referenceContext; Parser.this.recoveryScanner.resetTo(methodDeclaration.bodyStart, methodDeclaration.bodyEnd); Scanner oldScanner = Parser.this.scanner; Parser.this.scanner = Parser.this.recoveryScanner; parseStatements( methodDeclaration, methodDeclaration.bodyStart, methodDeclaration.bodyEnd, foundTypes, Parser.this.compilationUnit); Parser.this.scanner = oldScanner; Parser.this.referenceContext = oldContext; for (int i = 0; i < length; i++) { foundTypes[i].traverse(this.typeVisitor, scope); } } public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { this.typePtr = -1; return true; } public boolean visit(Initializer initializer, MethodScope scope) { this.typePtr = -1; if (initializer.block == null) return false; return true; } public boolean visit(MethodDeclaration methodDeclaration,ClassScope scope) { this.typePtr = -1; return true; } private boolean visit(TypeDeclaration typeDeclaration) { if(this.types.length <= ++this.typePtr) { int length = this.typePtr; System.arraycopy(this.types, 0, this.types = new TypeDeclaration[length * 2 + 1], 0, length); } this.types[this.typePtr] = typeDeclaration; return false; } public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) { return this.visit(typeDeclaration); } public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) { return this.visit(typeDeclaration); } } class TypeVisitor extends ASTVisitor { public MethodVisitor methodVisitor; TypeDeclaration[] types = new TypeDeclaration[0]; int typePtr = -1; public void endVisit(TypeDeclaration typeDeclaration, BlockScope scope) { endVisitType(); } public void endVisit(TypeDeclaration typeDeclaration, ClassScope scope) { endVisitType(); } private void endVisitType() { this.typePtr--; } public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { if(constructorDeclaration.isDefaultConstructor()) return false; constructorDeclaration.traverse(this.methodVisitor, scope); return false; } public boolean visit(Initializer initializer, MethodScope scope) { if (initializer.block == null) return false; this.methodVisitor.enclosingType = this.types[this.typePtr]; initializer.traverse(this.methodVisitor, scope); return false; } public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { methodDeclaration.traverse(this.methodVisitor, scope); return false; } private boolean visit(TypeDeclaration typeDeclaration) { if(this.types.length <= ++this.typePtr) { int length = this.typePtr; System.arraycopy(this.types, 0, this.types = new TypeDeclaration[length * 2 + 1], 0, length); } this.types[this.typePtr] = typeDeclaration; return true; } public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) { return this.visit(typeDeclaration); } public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) { return this.visit(typeDeclaration); } } MethodVisitor methodVisitor = new MethodVisitor(); TypeVisitor typeVisitor = new TypeVisitor(); methodVisitor.typeVisitor = typeVisitor; typeVisitor.methodVisitor = methodVisitor; if(this.referenceContext instanceof AbstractMethodDeclaration) { ((AbstractMethodDeclaration)this.referenceContext).traverse(methodVisitor, (ClassScope)null); } else if(this.referenceContext instanceof TypeDeclaration) { TypeDeclaration typeContext = (TypeDeclaration)this.referenceContext; int length = typeContext.fields.length; for (int i = 0; i < length; i++) { final FieldDeclaration fieldDeclaration = typeContext.fields[i]; switch(fieldDeclaration.getKind()) { case AbstractVariableDeclaration.INITIALIZER: Initializer initializer = (Initializer) fieldDeclaration; if (initializer.block == null) break; methodVisitor.enclosingType = typeContext; initializer.traverse(methodVisitor, (MethodScope)null); break; } } } } public void recoveryExitFromVariable() { if(this.currentElement != null && this.currentElement.parent != null) { if(this.currentElement instanceof RecoveredLocalVariable) { int end = ((RecoveredLocalVariable)this.currentElement).localDeclaration.sourceEnd; this.currentElement.updateSourceEndIfNecessary(end); this.currentElement = this.currentElement.parent; } else if(this.currentElement instanceof RecoveredField && !(this.currentElement instanceof RecoveredInitializer)) { // Do not move focus to parent if we are still inside an array initializer // https://bugs.eclipse.org/bugs/show_bug.cgi?id=292087 if (this.currentElement.bracketBalance <= 0) { int end = ((RecoveredField)this.currentElement).fieldDeclaration.sourceEnd; this.currentElement.updateSourceEndIfNecessary(end); this.currentElement = this.currentElement.parent; } } } } /* Token check performed on every token shift once having entered * recovery mode. */ public void recoveryTokenCheck() { switch (this.currentToken) { case TokenNameStringLiteral : if (this.recordStringLiterals && this.checkExternalizeStrings && this.lastPosistion < this.scanner.currentPosition && !this.statementRecoveryActivated) { StringLiteral stringLiteral = createStringLiteral( this.scanner.getCurrentTokenSourceString(), this.scanner.startPosition, this.scanner.currentPosition - 1, Util.getLineNumber(this.scanner.startPosition, this.scanner.lineEnds, 0, this.scanner.linePtr)); this.compilationUnit.recordStringLiteral(stringLiteral, this.currentElement != null); } break; case TokenNameLBRACE : RecoveredElement newElement = null; if(!this.ignoreNextOpeningBrace) { newElement = this.currentElement.updateOnOpeningBrace(this.scanner.startPosition - 1, this.scanner.currentPosition - 1); } this.lastCheckPoint = this.scanner.currentPosition; if (newElement != null){ // null means nothing happened this.restartRecovery = true; // opening brace detected this.currentElement = newElement; } break; case TokenNameRBRACE : this.rBraceStart = this.scanner.startPosition - 1; this.rBraceEnd = this.scanner.currentPosition - 1; this.endPosition = flushCommentsDefinedPriorTo(this.rBraceEnd); newElement = this.currentElement.updateOnClosingBrace(this.scanner.startPosition, this.rBraceEnd); 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 = currentRecoveryType(); if(currentType != null) { currentType.insideEnumConstantPart = false; } //$FALL-THROUGH$ default : { if (this.rBraceEnd > this.rBraceSuccessorStart && this.scanner.currentPosition != this.scanner.startPosition){ this.rBraceSuccessorStart = this.scanner.startPosition; } break; } } 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.bits & ASTNode.ErrorInSignature) != 0){ 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 : this.scanner.eofPosition - 1; 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(false); reportSyntaxErrorsForSkippedMethod(types); this.scanner.resetTo(start, end); } else { DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, this.options); diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); } } 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.bits & ASTNode.ErrorInSignature) != 0) { if(method.isAnnotationMethod()) { DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameQUESTION, method.declarationSourceStart, method.declarationSourceEnd, this.options); diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); } else { DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd, this.options); diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); } } } } 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.bits & ASTNode.ErrorInSignature) != 0){ DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd, this.options); diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); } } } } } } } /** * Reset modifiers buffer and comment stack. Should be call only for nodes that claim both. */ protected void resetModifiers() { this.modifiers = ClassFileConstants.AccDefault; this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int) this.scanner.commentPtr = -1; } /* * Reset context so as to resume to regular parse loop */ protected void resetStacks() { this.astPtr = -1; this.astLengthPtr = -1; this.expressionPtr = -1; this.expressionLengthPtr = -1; this.identifierPtr = -1; this.identifierLengthPtr = -1; this.intPtr = -1; this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse this.variablesCounter[this.nestedType] = 0; this.dimensions = 0 ; this.realBlockStack[this.realBlockPtr = 0] = 0; this.recoveredStaticInitializerStart = 0; this.listLength = 0; this.listTypeParameterLength = 0; this.genericsIdentifiersLengthPtr = -1; this.genericsLengthPtr = -1; this.genericsPtr = -1; } /* * Reset context so as to resume to regular parse loop * If unable to reset for resuming, answers false. * * Move checkpoint location, reset internal stacks and * decide which grammar goal is activated. */ protected boolean resumeAfterRecovery() { if(!this.methodRecoveryActivated && !this.statementRecoveryActivated) { // reset internal stacks resetStacks(); resetModifiers(); /* attempt to move checkpoint location */ if (!moveRecoveryCheckpoint()) { return false; } // only look for headers if (this.referenceContext instanceof CompilationUnitDeclaration){ goForHeaders(); this.diet = true; // passed this point, will not consider method bodies return true; } // does not know how to restart return false; } else if(!this.statementRecoveryActivated) { // reset internal stacks resetStacks(); resetModifiers(); /* attempt to move checkpoint location */ if (!moveRecoveryCheckpoint()) { return false; } // only look for headers goForHeaders(); return true; } else { return false; } } protected boolean resumeOnSyntaxError() { /* request recovery initialization */ if (this.currentElement == null){ // Reset javadoc before restart parsing after recovery this.javadoc = null; // do not investigate deeper in statement recovery if (this.statementRecoveryActivated) return false; // build some recovered elements this.currentElement = buildInitialRecoveryState(); } /* do not investigate deeper in recovery when no recovered element */ if (this.currentElement == null) return false; /* manual forced recovery restart - after headers */ if (this.restartRecovery){ this.restartRecovery = false; } /* update recovery state with current error state of the parser */ updateRecoveryState(); if (getFirstToken() == TokenNameAND) { if (this.referenceContext instanceof CompilationUnitDeclaration) { TypeDeclaration typeDeclaration = new TypeDeclaration(this.referenceContext.compilationResult()); typeDeclaration.name = Util.EMPTY_STRING.toCharArray(); this.currentElement = this.currentElement.add(typeDeclaration, 0); } } if (this.lastPosistion < this.scanner.currentPosition) { this.lastPosistion = this.scanner.currentPosition; this.scanner.lastPosition = this.scanner.currentPosition; } /* attempt to reset state in order to resume to parse loop */ return resumeAfterRecovery(); } public void setMethodsFullRecovery(boolean enabled) { this.options.performMethodsFullRecovery = enabled; } public void setStatementsRecovery(boolean enabled) { if(enabled) this.options.performMethodsFullRecovery = true; this.options.performStatementsRecovery = enabled; } public String toString() { 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 + "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["+(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["+(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["+(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; } /* * Update recovery state based on current parser/scanner state */ protected void updateRecoveryState() { /* expose parser state to recovery state */ this.currentElement.updateFromParserState(); /* check and update recovered state based on current token, this action is also performed when shifting token after recovery got activated once. */ recoveryTokenCheck(); } protected void updateSourceDeclarationParts(int variableDeclaratorsCounter) { //fields is a definition of fields that are grouped together like in //public int[] a, b[], c //which results into 3 fields. FieldDeclaration field; int endTypeDeclarationPosition = -1 + this.astStack[this.astPtr - variableDeclaratorsCounter + 1].sourceStart; for (int i = 0; i < variableDeclaratorsCounter - 1; i++) { //last one is special(see below) field = (FieldDeclaration) this.astStack[this.astPtr - i - 1]; field.endPart1Position = endTypeDeclarationPosition; field.endPart2Position = -1 + this.astStack[this.astPtr - i].sourceStart; } //last one (field = (FieldDeclaration) this.astStack[this.astPtr]).endPart1Position = endTypeDeclarationPosition; field.endPart2Position = field.declarationSourceEnd; } protected void updateSourcePosition(Expression exp) { //update the source Position of the expression //this.intStack : int int //--> //this.intStack : exp.sourceEnd = this.intStack[this.intPtr--]; exp.sourceStart = this.intStack[this.intPtr--]; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/parser3.rsc0000644000175000001440000000374212212041344027654 0ustar dokousersÆ9%4Ï®‘G;HHs0‚´00¤£0M´0J&KëYK&&××ÕÕ&ãÛjj›šyA5< 0&KKYK€¶cÅ723êRî &&Džik&&&jhñmôòöõø÷îÄf|/60Ž/W|0Û€k © WË|   O 0&&§nnm&&! $#&%˜'wK-c|Ww-W00‚€®´€¢€€¡´€€€¡0vD; &   «5&&&âäK€"­®&&%äUKKU¡ ¿é'JÝY&&+&€½Ä,€cP' Uç €„Oç&&žžâ&&&&&&&&&&w&&&&&&&&&&&&ÄwUw€ì0€€w€€€ò"&&&&&&&&&&&&&&&&&&w&&&&&&&&&&&&w&&&&&&&&&&&&&&€;cw€õK"w0Jƒ„ƒfÁ~¡ €é~5f¡(~4µ~4DwKD‹;€K€Kå KK倀''iäK@K€iUUU<„ww~& €;à  °å€U€½5@5O'éO€€Q)hhhjjjjòññõô÷ö~}–×;€ì Ñ!0Kò€Ñ€›ò"  #!%$&%$#!  &wdUŸ€ÑùUù0~ƒ„„€~~¯0¢€w¡//¡ED0;;|€€0&0KK'UK­UK€UKKKUKU & ¡Ÿ&   YY뀀h€å´€- €UKKKU&€**D&$.€K€Kòœ~}&&0€R K„„~ À€é0KUUKKUUUU  <„wwMFYKKK Ú€%é-´UUU&**e-#w„Áw0éé ”UåUK  ¡ž%ŸŸY+&&YYÛÚ%U  *€Àé%”&Hå0åU  <ww UÛ   *%%HHå0åžžëYYY *%‹å M‹‹YY‹YOOO7666šÊààti<õõttttiôÊ ˜™š˜™™™™¿ÏÀ¿¿¿¿ÁÁãâããããâzææž U„Dò;óòòòòîîxUùùxxxxy ïUïïïï†X}‹}}XXXXƒD d‹dddd©RF€ª€€€€{{eUÄÅÄÄÄÄôô././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.j0000644000175000001440000000223312212041344032335 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ 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 { int ERROR_SYMBOL = 110, MAX_NAME_LENGTH = 41, NUM_STATES = 1008, NT_OFFSET = 110, SCOPE_UBOUND = 137, SCOPE_SIZE = 138, LA_STATE_OFFSET = 12379, MAX_LA = 1, NUM_RULES = 723, NUM_TERMINALS = 110, NUM_NON_TERMINALS = 324, NUM_SYMBOLS = 434, START_STATE = 1260, EOFT_SYMBOL = 69, EOLT_SYMBOL = 69, ACCEPT_ACTION = 12378, ERROR_ACTION = 12379; } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java0000644000175000001440000004132312212041344031315 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class RecoveredBlock extends RecoveredStatement implements TerminalTokens { public Block blockDeclaration; public RecoveredStatement[] statements; public int statementCount; public boolean preserveContent = false; public RecoveredLocalVariable pendingArgument; int pendingModifiers; int pendingModifersSourceStart = -1; RecoveredAnnotation[] pendingAnnotations; int pendingAnnotationCount; public RecoveredBlock(Block block, RecoveredElement parent, int bracketBalance){ super(block, parent, bracketBalance); this.blockDeclaration = block; this.foundOpeningBrace = true; this.preserveContent = parser().methodRecoveryActivated || parser().statementRecoveryActivated; } public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) { if (this.parent != null && this.parent instanceof RecoveredMethod) { RecoveredMethod enclosingRecoveredMethod = (RecoveredMethod) this.parent; if (enclosingRecoveredMethod.methodBody == this && enclosingRecoveredMethod.parent == null) { resetPendingModifiers(); // the element cannot be added because we are in the body of a top level method return this; // ignore this element } } return super.add(methodDeclaration, bracketBalanceValue); } /* * Record a nested block declaration */ public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { resetPendingModifiers(); /* do not consider a nested block starting passed the block end (if set) it must be belonging to an enclosing block */ if (this.blockDeclaration.sourceEnd != 0 && nestedBlockDeclaration.sourceStart > this.blockDeclaration.sourceEnd){ return this.parent.add(nestedBlockDeclaration, bracketBalanceValue); } RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); // if we have a pending Argument, promote it into the new block if (this.pendingArgument != null){ element.attach(this.pendingArgument); this.pendingArgument = null; } if(parser().statementRecoveryActivated) { addBlockStatement(element); } attach(element); if (nestedBlockDeclaration.sourceEnd == 0) return element; return this; } /* * Record a local declaration */ public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) { return this.add(localDeclaration, bracketBalanceValue, false); } /* * Record a local declaration */ public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue, boolean delegatedByParent) { /* local variables inside method can only be final and non void */ /* char[][] localTypeName; if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final || (localDeclaration.type == null) // initializer || ((localTypeName = localDeclaration.type.getTypeName()).length == 1 // non void && CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){ if (delegatedByParent){ return this; //ignore } else { this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1)); return this.parent.add(localDeclaration, bracketBalance); } } */ /* do not consider a local variable starting passed the block end (if set) it must be belonging to an enclosing block */ if (this.blockDeclaration.sourceEnd != 0 && localDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){ resetPendingModifiers(); if (delegatedByParent) return this; //ignore return this.parent.add(localDeclaration, bracketBalanceValue); } RecoveredLocalVariable element = new RecoveredLocalVariable(localDeclaration, this, bracketBalanceValue); if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); if (localDeclaration instanceof Argument){ this.pendingArgument = element; return this; } attach(element); if (localDeclaration.declarationSourceEnd == 0) return element; return this; } /* * Record a statement declaration */ public RecoveredElement add(Statement stmt, int bracketBalanceValue) { return this.add(stmt, bracketBalanceValue, false); } /* * Record a statement declaration */ public RecoveredElement add(Statement stmt, int bracketBalanceValue, boolean delegatedByParent) { resetPendingModifiers(); /* do not consider a nested block starting passed the block end (if set) it must be belonging to an enclosing block */ if (this.blockDeclaration.sourceEnd != 0 && stmt.sourceStart > this.blockDeclaration.sourceEnd){ if (delegatedByParent) return this; //ignore return this.parent.add(stmt, bracketBalanceValue); } RecoveredStatement element = new RecoveredStatement(stmt, this, bracketBalanceValue); attach(element); if (stmt.sourceEnd == 0) return element; return this; } /* * Addition of a type to an initializer (act like inside method body) */ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { return this.add(typeDeclaration, bracketBalanceValue, false); } /* * Addition of a type to an initializer (act like inside method body) */ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue, boolean delegatedByParent) { /* do not consider a type starting passed the block end (if set) it must be belonging to an enclosing block */ if (this.blockDeclaration.sourceEnd != 0 && typeDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){ resetPendingModifiers(); if (delegatedByParent) return this; //ignore return this.parent.add(typeDeclaration, bracketBalanceValue); } RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); if(this.pendingAnnotationCount > 0) { element.attach( this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers, this.pendingModifersSourceStart); } resetPendingModifiers(); attach(element); if (typeDeclaration.declarationSourceEnd == 0) return element; return this; } public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) { if (this.pendingAnnotations == null) { this.pendingAnnotations = new RecoveredAnnotation[5]; this.pendingAnnotationCount = 0; } else { if (this.pendingAnnotationCount == this.pendingAnnotations.length) { System.arraycopy( this.pendingAnnotations, 0, (this.pendingAnnotations = new RecoveredAnnotation[2 * this.pendingAnnotationCount]), 0, this.pendingAnnotationCount); } } RecoveredAnnotation element = new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue); this.pendingAnnotations[this.pendingAnnotationCount++] = element; return element; } public void addModifier(int flag, int modifiersSourceStart) { this.pendingModifiers |= flag; if (this.pendingModifersSourceStart < 0) { this.pendingModifersSourceStart = modifiersSourceStart; } } /* * Attach a recovered statement */ void attach(RecoveredStatement recoveredStatement) { if (this.statements == null) { this.statements = new RecoveredStatement[5]; this.statementCount = 0; } else { if (this.statementCount == this.statements.length) { System.arraycopy( this.statements, 0, (this.statements = new RecoveredStatement[2 * this.statementCount]), 0, this.statementCount); } } this.statements[this.statementCount++] = recoveredStatement; } void attachPendingModifiers(RecoveredAnnotation[] pendingAnnots, int pendingAnnotCount, int pendingMods, int pendingModsSourceStart) { this.pendingAnnotations = pendingAnnots; this.pendingAnnotationCount = pendingAnnotCount; this.pendingModifiers = pendingMods; this.pendingModifersSourceStart = pendingModsSourceStart; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.blockDeclaration; } public void resetPendingModifiers() { this.pendingAnnotations = null; this.pendingAnnotationCount = 0; this.pendingModifiers = 0; this.pendingModifersSourceStart = -1; } public String toString(int tab) { StringBuffer result = new StringBuffer(tabString(tab)); result.append("Recovered block:\n"); //$NON-NLS-1$ this.blockDeclaration.print(tab + 1, result); if (this.statements != null) { for (int i = 0; i < this.statementCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.statements[i].toString(tab + 1)); } } return result.toString(); } /* * Rebuild a block from the nested structure which is in scope */ public Block updatedBlock(int depth, Set knownTypes){ // if block was not marked to be preserved or empty, then ignore it if (!this.preserveContent || this.statementCount == 0) return null; Statement[] updatedStatements = new Statement[this.statementCount]; int updatedCount = 0; // may need to update the end of the last statement RecoveredStatement lastStatement = this.statements[this.statementCount - 1]; RecoveredMethod enclosingMethod = enclosingMethod(); RecoveredInitializer enclosingIntializer = enclosingInitializer(); int bodyEndValue = 0; if(enclosingMethod != null) { bodyEndValue = enclosingMethod.methodDeclaration.bodyEnd; if(enclosingIntializer != null && enclosingMethod.methodDeclaration.sourceStart < enclosingIntializer.fieldDeclaration.sourceStart) { bodyEndValue = enclosingIntializer.fieldDeclaration.declarationSourceEnd; } } else if(enclosingIntializer != null) { bodyEndValue = enclosingIntializer.fieldDeclaration.declarationSourceEnd; } else { bodyEndValue = this.blockDeclaration.sourceEnd - 1; } if(lastStatement instanceof RecoveredLocalVariable) { RecoveredLocalVariable lastLocalVariable = (RecoveredLocalVariable) lastStatement; if(lastLocalVariable.localDeclaration.declarationSourceEnd == 0) { lastLocalVariable.localDeclaration.declarationSourceEnd = bodyEndValue; lastLocalVariable.localDeclaration.declarationEnd = bodyEndValue; } } else if(lastStatement instanceof RecoveredBlock) { RecoveredBlock lastBlock = (RecoveredBlock) lastStatement; if(lastBlock.blockDeclaration.sourceEnd == 0) { lastBlock.blockDeclaration.sourceEnd = bodyEndValue; } } else if(!(lastStatement instanceof RecoveredType)){ if(lastStatement.statement.sourceEnd == 0) { lastStatement.statement.sourceEnd = bodyEndValue; } } int lastEnd = this.blockDeclaration.sourceStart; // only collect the non-null updated statements for (int i = 0; i < this.statementCount; i++){ Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes); if (updatedStatement != null){ updatedStatements[updatedCount++] = updatedStatement; if (updatedStatement instanceof LocalDeclaration) { LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement; if(localDeclaration.declarationSourceEnd > lastEnd) { lastEnd = localDeclaration.declarationSourceEnd; } } else if (updatedStatement instanceof TypeDeclaration) { TypeDeclaration typeDeclaration = (TypeDeclaration) updatedStatement; if(typeDeclaration.declarationSourceEnd > lastEnd) { lastEnd = typeDeclaration.declarationSourceEnd; } } else { if (updatedStatement.sourceEnd > lastEnd) { lastEnd = updatedStatement.sourceEnd; } } } } if (updatedCount == 0) return null; // not interesting block // resize statement collection if necessary if (updatedCount != this.statementCount){ this.blockDeclaration.statements = new Statement[updatedCount]; System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount); } else { this.blockDeclaration.statements = updatedStatements; } if (this.blockDeclaration.sourceEnd == 0) { if(lastEnd < bodyEndValue) { this.blockDeclaration.sourceEnd = bodyEndValue; } else { this.blockDeclaration.sourceEnd = lastEnd; } } return this.blockDeclaration; } /* * Rebuild a statement from the nested structure which is in scope */ public Statement updatedStatement(int depth, Set knownTypes){ return updatedBlock(depth, knownTypes); } /* * A closing brace got consumed, might have closed the current element, * in which case both the currentElement is exited */ public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ if ((--this.bracketBalance <= 0) && (this.parent != null)){ this.updateSourceEndIfNecessary(braceStart, braceEnd); /* if the block is the method body, then it closes the method too */ RecoveredMethod method = enclosingMethod(); if (method != null && method.methodBody == this){ return this.parent.updateOnClosingBrace(braceStart, braceEnd); } RecoveredInitializer initializer = enclosingInitializer(); if (initializer != null && initializer.initializerBody == this){ return this.parent.updateOnClosingBrace(braceStart, braceEnd); } return this.parent; } return this; } /* * An opening brace got consumed, might be the expected opening one of the current element, * in which case the bodyStart is updated. */ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ // create a nested block Block block = new Block(0); block.sourceStart = parser().scanner.startPosition; return this.add(block, 1); } /* * Final update the corresponding parse node */ public void updateParseTree(){ updatedBlock(0, new HashSet()); } /* * Rebuild a flattened block from the nested structure which is in scope */ public Statement updateStatement(int depth, Set knownTypes){ // if block was closed or empty, then ignore it if (this.blockDeclaration.sourceEnd != 0 || this.statementCount == 0) return null; Statement[] updatedStatements = new Statement[this.statementCount]; int updatedCount = 0; // only collect the non-null updated statements for (int i = 0; i < this.statementCount; i++){ Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes); if (updatedStatement != null){ updatedStatements[updatedCount++] = updatedStatement; } } if (updatedCount == 0) return null; // not interesting block // resize statement collection if necessary if (updatedCount != this.statementCount){ this.blockDeclaration.statements = new Statement[updatedCount]; System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount); } else { this.blockDeclaration.statements = updatedStatements; } return this.blockDeclaration; } /* * Record a field declaration */ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { resetPendingModifiers(); /* local variables inside method can only be final and non void */ char[][] fieldTypeName; if ((fieldDeclaration.modifiers & ~ClassFileConstants.AccFinal) != 0 // local var can only be final || (fieldDeclaration.type == null) // initializer || ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 // non void && CharOperation.equals(fieldTypeName[0], TypeBinding.VOID.sourceName()))){ this.updateSourceEndIfNecessary(previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1)); return this.parent.add(fieldDeclaration, bracketBalanceValue); } /* do not consider a local variable starting passed the block end (if set) it must be belonging to an enclosing block */ if (this.blockDeclaration.sourceEnd != 0 && fieldDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){ return this.parent.add(fieldDeclaration, bracketBalanceValue); } // ignore the added field, since indicates a local variable behind recovery point // which thus got parsed as a field reference. This can happen if restarting after // having reduced an assistNode to get the following context (see 1GEK7SG) return this; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/0000755000175000001440000000000012212041344025573 5ustar dokousers././@LongLink0000644000000000000000000000015412251602427011643 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBindi0000644000175000001440000003250112212041344032422 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ 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(final ParameterizedTypeBinding parameterizedDeclaringClass, MethodBinding originalMethod) { super( originalMethod.modifiers, originalMethod.selector, originalMethod.returnType, originalMethod.parameters, originalMethod.thrownExceptions, parameterizedDeclaringClass); this.originalMethod = originalMethod; /* missing type bit cannot be copied as is it might come from the return type or a parameter type that * is substituted by a raw type. */ this.tagBits = originalMethod.tagBits & ~TagBits.HasMissingType; this.parameterNonNullness = originalMethod.parameterNonNullness; final TypeVariableBinding[] originalVariables = originalMethod.typeVariables; Substitution substitution = null; final int length = originalVariables.length; final boolean isStatic = originalMethod.isStatic(); if (length == 0) { this.typeVariables = Binding.NO_TYPE_VARIABLES; if (!isStatic) substitution = parameterizedDeclaringClass; } else { // at least fix up the declaringElement binding + bound substitution if non static final TypeVariableBinding[] substitutedVariables = new TypeVariableBinding[length]; for (int i = 0; i < length; i++) { // copy original type variable to relocate TypeVariableBinding originalVariable = originalVariables[i]; substitutedVariables[i] = new TypeVariableBinding(originalVariable.sourceName, this, originalVariable.rank, parameterizedDeclaringClass.environment); } this.typeVariables = substitutedVariables; // need to substitute old var refs with new ones (double substitution: declaringClass + new type variables) substitution = new Substitution() { public LookupEnvironment environment() { return parameterizedDeclaringClass.environment; } public boolean isRawSubstitution() { return !isStatic && parameterizedDeclaringClass.isRawSubstitution(); } public TypeBinding substitute(TypeVariableBinding typeVariable) { // check this variable can be substituted given copied variables if (typeVariable.rank < length && originalVariables[typeVariable.rank] == typeVariable) { return substitutedVariables[typeVariable.rank]; } if (!isStatic) return parameterizedDeclaringClass.substitute(typeVariable); return typeVariable; } }; // initialize new variable bounds for (int i = 0; i < length; i++) { TypeVariableBinding originalVariable = originalVariables[i]; TypeVariableBinding substitutedVariable = substitutedVariables[i]; TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass); ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces); if (originalVariable.firstBound != null) { substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass ? substitutedSuperclass // could be array type or interface : substitutedInterfaces[0]; } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); substitutedVariable.superInterfaces = substitutedInterfaces; break; default: if (substitutedSuperclass.isInterface()) { substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); int interfaceCount = substitutedInterfaces.length; System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount); substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass; substitutedVariable.superInterfaces = substitutedInterfaces; } else { substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface substitutedVariable.superInterfaces = substitutedInterfaces; } } } } if (substitution != null) { this.returnType = Scope.substitute(substitution, this.returnType); this.parameters = Scope.substitute(substitution, this.parameters); this.thrownExceptions = Scope.substitute(substitution, this.thrownExceptions); // error case where exception type variable would have been substituted by a non-reference type (207573) if (this.thrownExceptions == null) this.thrownExceptions = Binding.NO_EXCEPTIONS; } checkMissingType: { if ((this.tagBits & TagBits.HasMissingType) != 0) break checkMissingType; if ((this.returnType.tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } for (int i = 0, max = this.parameters.length; i < max; i++) { if ((this.parameters[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } for (int i = 0, max = this.thrownExceptions.length; i < max; i++) { if ((this.thrownExceptions[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } } } /** * Create method of parameterized type, substituting original parameters/exception/return type with type arguments. * This is a CODE ASSIST method ONLY. */ public ParameterizedMethodBinding(final ReferenceBinding declaringClass, MethodBinding originalMethod, char[][] alternateParamaterNames, final LookupEnvironment environment) { super( originalMethod.modifiers, originalMethod.selector, originalMethod.returnType, originalMethod.parameters, originalMethod.thrownExceptions, declaringClass); this.originalMethod = originalMethod; /* missing type bit cannot be copied as is it might come from the return type or a parameter type that * is substituted by a raw type. */ this.tagBits = originalMethod.tagBits & ~TagBits.HasMissingType; this.parameterNonNullness = originalMethod.parameterNonNullness; final TypeVariableBinding[] originalVariables = originalMethod.typeVariables; Substitution substitution = null; final int length = originalVariables.length; if (length == 0) { this.typeVariables = Binding.NO_TYPE_VARIABLES; } else { // at least fix up the declaringElement binding + bound substitution if non static final TypeVariableBinding[] substitutedVariables = new TypeVariableBinding[length]; for (int i = 0; i < length; i++) { // copy original type variable to relocate TypeVariableBinding originalVariable = originalVariables[i]; substitutedVariables[i] = new TypeVariableBinding( alternateParamaterNames == null ? originalVariable.sourceName : alternateParamaterNames[i], this, originalVariable.rank, environment); } this.typeVariables = substitutedVariables; // need to substitute old var refs with new ones (double substitution: declaringClass + new type variables) substitution = new Substitution() { public LookupEnvironment environment() { return environment; } public boolean isRawSubstitution() { return false; } public TypeBinding substitute(TypeVariableBinding typeVariable) { // check this variable can be substituted given copied variables if (typeVariable.rank < length && originalVariables[typeVariable.rank] == typeVariable) { return substitutedVariables[typeVariable.rank]; } return typeVariable; } }; // initialize new variable bounds for (int i = 0; i < length; i++) { TypeVariableBinding originalVariable = originalVariables[i]; TypeVariableBinding substitutedVariable = substitutedVariables[i]; TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass); ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces); if (originalVariable.firstBound != null) { substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass ? substitutedSuperclass // could be array type or interface : substitutedInterfaces[0]; } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); substitutedVariable.superInterfaces = substitutedInterfaces; break; default: if (substitutedSuperclass.isInterface()) { substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); int interfaceCount = substitutedInterfaces.length; System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount); substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass; substitutedVariable.superInterfaces = substitutedInterfaces; } else { substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface substitutedVariable.superInterfaces = substitutedInterfaces; } } } } if (substitution != null) { this.returnType = Scope.substitute(substitution, this.returnType); this.parameters = Scope.substitute(substitution, this.parameters); this.thrownExceptions = Scope.substitute(substitution, this.thrownExceptions); // error case where exception type variable would have been substituted by a non-reference type (207573) if (this.thrownExceptions == null) this.thrownExceptions = Binding.NO_EXCEPTIONS; } checkMissingType: { if ((this.tagBits & TagBits.HasMissingType) != 0) break checkMissingType; if ((this.returnType.tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } for (int i = 0, max = this.parameters.length; i < max; i++) { if ((this.parameters[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } for (int i = 0, max = this.thrownExceptions.length; i < max; i++) { if ((this.thrownExceptions[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } } } public ParameterizedMethodBinding() { // no init } /** * The type of x.getClass() is substituted from 'Class' into: 'Class */ 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 = Binding.NO_TYPE_VARIABLES; method.originalMethod = originalMethod; method.parameters = originalMethod.parameters; method.thrownExceptions = originalMethod.thrownExceptions; method.tagBits = originalMethod.tagBits; ReferenceBinding genericClassType = scope.getJavaLangClass(); LookupEnvironment environment = scope.environment(); TypeBinding rawType = environment.convertToRawType(receiverType.erasure(), false /*do not force conversion of enclosing types*/); method.returnType = environment.createParameterizedType( genericClassType, new TypeBinding[] { environment.createWildcard(genericClassType, 0, rawType, null /*no extra bound*/, Wildcard.EXTENDS) }, null); if ((method.returnType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } return method; } /** * Returns true if some parameters got substituted. */ public boolean hasSubstitutedParameters() { return this.parameters != this.originalMethod.parameters; } /** * Returns true if the return type got substituted. */ public boolean hasSubstitutedReturnType() { return this.returnType != this.originalMethod.returnType; } /** * Returns the original method (as opposed to parameterized instances) */ public MethodBinding original() { return this.originalMethod.original(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java0000644000175000001440000005106612212041344030660 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 374605 - Unreasonable warning for enum-based switch statements *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; 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.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; /** * Specific block scope used for methods, constructors or clinits, representing * its outermost blockscope. Note also that such a scope will be provided to enclose * field initializers subscopes as well. */ public class MethodScope extends BlockScope { public ReferenceContext referenceContext; public boolean isStatic; // method modifier or initializer one //fields used during name resolution public boolean isConstructorCall = false; public FieldBinding initializedField; // the field being initialized public int lastVisibleFieldID = -1; // the ID of the last field which got declared // note that #initializedField can be null AND lastVisibleFieldID >= 0, when processing instance field initializers. // flow analysis public int analysisIndex; // for setting flow-analysis id public boolean isPropagatingInnerClassEmulation; // for local variables table attributes public int lastIndex = 0; public long[] definiteInits = new long[4]; public long[][] extraDefiniteInits = new long[4][]; // annotation support public boolean insideTypeAnnotation = false; // inner-emulation public SyntheticArgumentBinding[] extraSyntheticArguments; // remember suppressed warning re missing 'default:' to give hints on possibly related flow problems public boolean hasMissingSwitchDefault; // TODO(stephan): combine flags to a bitset? public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) { super(METHOD_SCOPE, parent); this.locals = new LocalVariableBinding[5]; this.referenceContext = context; this.isStatic = isStatic; this.startIndex = 0; } String basicToString(int tab) { String newLine = "\n"; //$NON-NLS-1$ for (int i = tab; --i >= 0;) newLine += "\t"; //$NON-NLS-1$ String s = newLine + "--- Method Scope ---"; //$NON-NLS-1$ newLine += "\t"; //$NON-NLS-1$ s += newLine + "locals:"; //$NON-NLS-1$ for (int i = 0; i < this.localIndex; i++) s += newLine + "\t" + this.locals[i].toString(); //$NON-NLS-1$ s += newLine + "startIndex = " + this.startIndex; //$NON-NLS-1$ s += newLine + "isConstructorCall = " + this.isConstructorCall; //$NON-NLS-1$ s += newLine + "initializedField = " + this.initializedField; //$NON-NLS-1$ s += newLine + "lastVisibleFieldID = " + this.lastVisibleFieldID; //$NON-NLS-1$ s += newLine + "referenceContext = " + this.referenceContext; //$NON-NLS-1$ return s; } /** * Spec : 8.4.3 & 9.4 */ private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) { int modifiers = methodBinding.modifiers; final ReferenceBinding declaringClass = methodBinding.declaringClass; if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) this.referenceContext); if ((((ConstructorDeclaration) this.referenceContext).bits & ASTNode.IsDefaultConstructor) != 0) { // certain flags are propagated from declaring class onto constructor final int DECLARING_FLAGS = ClassFileConstants.AccEnum|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected; final int VISIBILITY_FLAGS = ClassFileConstants.AccPrivate|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected; int flags; if ((flags = declaringClass.modifiers & DECLARING_FLAGS) != 0) { if ((flags & ClassFileConstants.AccEnum) != 0) { modifiers &= ~VISIBILITY_FLAGS; modifiers |= ClassFileConstants.AccPrivate; // default constructor is implicitly private in enum } else { modifiers &= ~VISIBILITY_FLAGS; modifiers |= flags; // propagate public/protected } } } // after this point, tests on the 16 bits reserved. int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; // check for abnormal modifiers final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStrictfp); if (declaringClass.isEnum() && (((ConstructorDeclaration) this.referenceContext).bits & ASTNode.IsDefaultConstructor) == 0) { final int UNEXPECTED_ENUM_CONSTR_MODIFIERS = ~(ClassFileConstants.AccPrivate | ClassFileConstants.AccStrictfp); if ((realModifiers & UNEXPECTED_ENUM_CONSTR_MODIFIERS) != 0) { problemReporter().illegalModifierForEnumConstructor((AbstractMethodDeclaration) this.referenceContext); modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_ENUM_CONSTR_MODIFIERS; } else if ((((AbstractMethodDeclaration) this.referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) { // must check the parse node explicitly problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) this.referenceContext); } modifiers |= ClassFileConstants.AccPrivate; // enum constructor is implicitly private } else if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) this.referenceContext); modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS; } else if ((((AbstractMethodDeclaration) this.referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) { // must check the parse node explicitly problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) this.referenceContext); } // check for incompatible modifiers in the visibility bits, isolate the visibility bits int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); if ((accessorBits & (accessorBits - 1)) != 0) { problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) this.referenceContext); // need to keep the less restrictive so disable Protected/Private as necessary if ((accessorBits & ClassFileConstants.AccPublic) != 0) { if ((accessorBits & ClassFileConstants.AccProtected) != 0) modifiers &= ~ClassFileConstants.AccProtected; if ((accessorBits & ClassFileConstants.AccPrivate) != 0) modifiers &= ~ClassFileConstants.AccPrivate; } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { modifiers &= ~ClassFileConstants.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 (declaringClass.isPrivate() && (modifiers & ClassFileConstants.AccPrivate) != 0) // modifiers &= ~ClassFileConstants.AccPrivate; methodBinding.modifiers = modifiers; } /** * Spec : 8.4.3 & 9.4 */ private void checkAndSetModifiersForMethod(MethodBinding methodBinding) { int modifiers = methodBinding.modifiers; final ReferenceBinding declaringClass = methodBinding.declaringClass; if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) this.referenceContext); // after this point, tests on the 16 bits reserved. int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; // set the requested modifiers for a method in an interface/annotation if (declaringClass.isInterface()) { if ((realModifiers & ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract)) != 0) { if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0) problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) this.referenceContext); else problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) this.referenceContext); } return; } // check for abnormal modifiers final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) this.referenceContext); modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS; } // check for incompatible modifiers in the visibility bits, isolate the visibility bits int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); if ((accessorBits & (accessorBits - 1)) != 0) { problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) this.referenceContext); // need to keep the less restrictive so disable Protected/Private as necessary if ((accessorBits & ClassFileConstants.AccPublic) != 0) { if ((accessorBits & ClassFileConstants.AccProtected) != 0) modifiers &= ~ClassFileConstants.AccProtected; if ((accessorBits & ClassFileConstants.AccPrivate) != 0) modifiers &= ~ClassFileConstants.AccPrivate; } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { modifiers &= ~ClassFileConstants.AccPrivate; } } // check for modifiers incompatible with abstract modifier if ((modifiers & ClassFileConstants.AccAbstract) != 0) { int incompatibleWithAbstract = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp; if ((modifiers & incompatibleWithAbstract) != 0) problemReporter().illegalAbstractModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) this.referenceContext); if (!methodBinding.declaringClass.isAbstract()) problemReporter().abstractMethodInAbstractClass((SourceTypeBinding) declaringClass, (AbstractMethodDeclaration) this.referenceContext); } /* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final) // methods from a final class are final : 8.4.3.3 if (methodBinding.declaringClass.isFinal()) modifiers |= AccFinal; */ // native methods cannot also be tagged as strictfp if ((modifiers & ClassFileConstants.AccNative) != 0 && (modifiers & ClassFileConstants.AccStrictfp) != 0) problemReporter().nativeMethodsCannotBeStrictfp(declaringClass, (AbstractMethodDeclaration) this.referenceContext); // static members are only authorized in a static member or top level type if (((realModifiers & ClassFileConstants.AccStatic) != 0) && declaringClass.isNestedType() && !declaringClass.isStatic()) problemReporter().unexpectedStaticModifierForMethod(declaringClass, (AbstractMethodDeclaration) this.referenceContext); methodBinding.modifiers = modifiers; } public void checkUnusedParameters(MethodBinding method) { if (method.isAbstract() || (method.isImplementing() && !compilerOptions().reportUnusedParameterWhenImplementingAbstract) || (method.isOverriding() && !method.isImplementing() && !compilerOptions().reportUnusedParameterWhenOverridingConcrete) || method.isMain()) { // do not want to check return; } for (int i = 0, maxLocals = this.localIndex; i < maxLocals; i++) { LocalVariableBinding local = this.locals[i]; if (local == null || ((local.tagBits & TagBits.IsArgument) == 0)) { break; // done with arguments } if (local.useFlag == LocalVariableBinding.UNUSED && // do not report fake used variable ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable problemReporter().unusedArgument(local.declaration); } } } /** * Compute variable positions in scopes given an initial position offset * ignoring unused local variables. * * Deal with arguments here, locals and subscopes are processed in BlockScope method */ public void computeLocalVariablePositions(int initOffset, CodeStream codeStream) { this.offset = initOffset; this.maxOffset = initOffset; // manage arguments int ilocal = 0, maxLocals = this.localIndex; while (ilocal < maxLocals) { LocalVariableBinding local = this.locals[ilocal]; if (local == null || ((local.tagBits & TagBits.IsArgument) == 0)) break; // done with arguments // record user-defined argument for attribute generation codeStream.record(local); // assign variable position local.resolvedPosition = this.offset; if ((local.type == TypeBinding.LONG) || (local.type == TypeBinding.DOUBLE)) { this.offset += 2; } else { this.offset++; } // check for too many arguments/local variables if (this.offset > 0xFF) { // no more than 255 words of arguments problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration); } ilocal++; } // sneak in extra argument before other local variables if (this.extraSyntheticArguments != null) { for (int iarg = 0, maxArguments = this.extraSyntheticArguments.length; iarg < maxArguments; iarg++){ SyntheticArgumentBinding argument = this.extraSyntheticArguments[iarg]; argument.resolvedPosition = this.offset; if ((argument.type == TypeBinding.LONG) || (argument.type == TypeBinding.DOUBLE)){ this.offset += 2; } else { this.offset++; } if (this.offset > 0xFF) { // no more than 255 words of arguments problemReporter().noMoreAvailableSpaceForArgument(argument, (ASTNode)this.referenceContext); } } } this.computeLocalVariablePositions(ilocal, this.offset, codeStream); } /** * Error management: * keep null for all the errors that prevent the method to be created * otherwise return a correct method binding (but without the element * that caused the problem) : i.e. Incorrect thrown exception */ MethodBinding createMethod(AbstractMethodDeclaration method) { // is necessary to ensure error reporting this.referenceContext = method; method.scope = this; SourceTypeBinding declaringClass = referenceType().binding; int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved; if (method.isConstructor()) { if (method.isDefaultConstructor()) modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor; method.binding = new MethodBinding(modifiers, null, null, declaringClass); checkAndSetModifiersForConstructor(method.binding); } else { if (declaringClass.isInterface()) // interface or annotation type modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.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 && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { if (argTypes[--argLength].isVarArgs()) method.binding.modifiers |= ClassFileConstants.AccVarargs; while (--argLength >= 0) { if (argTypes[argLength].isVarArgs()) problemReporter().illegalVararg(argTypes[argLength], method); } } TypeParameter[] typeParameters = method.typeParameters(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, If they exist at all, process type parameters irrespective of source level. if (typeParameters == null || typeParameters.length == 0) { method.binding.typeVariables = Binding.NO_TYPE_VARIABLES; } else { method.binding.typeVariables = createTypeVariables(typeParameters, method.binding); method.binding.modifiers |= ExtraCompilerModifiers.AccGenericSignature; } return method.binding; } /** * Overridden to detect the error case inside an explicit constructor call: class X { int i; X myX; X(X x) { this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors } } */ public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) { FieldBinding field = super.findField(receiverType, fieldName, invocationSite, needResolve); if (field == null) return null; if (!field.isValidBinding()) return field; // answer the error field if (field.isStatic()) return field; // static fields are always accessible if (!this.isConstructorCall || receiverType != enclosingSourceType()) return field; if (invocationSite instanceof SingleNameReference) return new ProblemFieldBinding( field, // closest match field.declaringClass, fieldName, ProblemReasons.NonStaticReferenceInConstructorInvocation); if (invocationSite instanceof QualifiedNameReference) { // look to see if the field is the first binding QualifiedNameReference name = (QualifiedNameReference) invocationSite; if (name.binding == null) // only true when the field is the fieldbinding at the beginning of name's tokens return new ProblemFieldBinding( field, // closest match field.declaringClass, fieldName, ProblemReasons.NonStaticReferenceInConstructorInvocation); } return field; } public boolean isInsideConstructor() { return (this.referenceContext instanceof ConstructorDeclaration); } public boolean isInsideInitializer() { return (this.referenceContext instanceof TypeDeclaration); } public boolean isInsideInitializerOrConstructor() { return (this.referenceContext instanceof TypeDeclaration) || (this.referenceContext instanceof ConstructorDeclaration); } /** * Answer the problem reporter to use for raising new problems. * * Note that as a side-effect, this updates the current reference context * (unit, type or method) in case the problem handler decides it is necessary * to abort. */ public ProblemReporter problemReporter() { ProblemReporter problemReporter = referenceCompilationUnit().problemReporter; problemReporter.referenceContext = this.referenceContext; return problemReporter; } public final int recordInitializationStates(FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return -1; UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInitsWithoutSideEffect(); long[] extraInits = unconditionalFlowInfo.extra == null ? null : unconditionalFlowInfo.extra[0]; long inits = unconditionalFlowInfo.definiteInits; checkNextEntry : for (int i = this.lastIndex; --i >= 0;) { if (this.definiteInits[i] == inits) { long[] otherInits = this.extraDefiniteInits[i]; if ((extraInits != null) && (otherInits != null)) { if (extraInits.length == otherInits.length) { int j, max; for (j = 0, max = extraInits.length; j < max; j++) { if (extraInits[j] != otherInits[j]) { continue checkNextEntry; } } return i; } } else { if ((extraInits == null) && (otherInits == null)) { return i; } } } } // add a new entry if (this.definiteInits.length == this.lastIndex) { // need a resize System.arraycopy( this.definiteInits, 0, (this.definiteInits = new long[this.lastIndex + 20]), 0, this.lastIndex); System.arraycopy( this.extraDefiniteInits, 0, (this.extraDefiniteInits = new long[this.lastIndex + 20][]), 0, this.lastIndex); } this.definiteInits[this.lastIndex] = inits; if (extraInits != null) { this.extraDefiniteInits[this.lastIndex] = new long[extraInits.length]; System.arraycopy( extraInits, 0, this.extraDefiniteInits[this.lastIndex], 0, extraInits.length); } return this.lastIndex++; } /** * Answer the reference method of this scope, or null if initialization scope. */ public AbstractMethodDeclaration referenceMethod() { if (this.referenceContext instanceof AbstractMethodDeclaration) return (AbstractMethodDeclaration) this.referenceContext; return null; } /** * Answer the reference type of this scope. * It is the nearest enclosing type of this scope. */ public TypeDeclaration referenceType() { return ((ClassScope) this.parent).referenceContext; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java0000644000175000001440000007176412212041344031501 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource * bug 358903 - Filter practically unimportant resource leak warnings *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.List; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; /* * 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 { public ReferenceBinding genericType; public int rank; public TypeBinding bound; // when unbound denotes the corresponding type variable (so as to retrieve its bound lazily) public TypeBinding[] otherBounds; // only positionned by lub computations (if so, #bound is also set) and associated to EXTENDS mode char[] genericSignature; public int boundKind; 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, TypeBinding[] otherBounds, int boundKind, LookupEnvironment environment) { this.rank = rank; this.boundKind = boundKind; this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat wildcard as public this.environment = environment; initialize(genericType, bound, otherBounds); // if (!genericType.isGenericType() && !(genericType instanceof UnresolvedReferenceBinding)) { // RuntimeException e = new RuntimeException("WILDCARD with NON GENERIC"); // e.printStackTrace(); // throw e; // } if (genericType instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) genericType).addWrapper(this, environment); if (bound instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) bound).addWrapper(this, environment); this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve() this.typeBits = TypeIds.BitUninitialized; } public int kind() { return this.otherBounds == null ? Binding.WILDCARD_TYPE : Binding.INTERSECTION_TYPE; } /** * Returns true if the argument type satisfies the wildcard bound(s) */ public boolean boundCheck(TypeBinding argumentType) { switch (this.boundKind) { case Wildcard.UNBOUND : return true; case Wildcard.EXTENDS : if (!argumentType.isCompatibleWith(this.bound)) return false; // check other bounds (lub scenario) for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length; i < length; i++) { if (!argumentType.isCompatibleWith(this.otherBounds[i])) return false; } return true; default: // SUPER // ? super Exception ok for: IOException, since it would be ok for (Exception)ioException return argumentType.isCompatibleWith(this.bound); } } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated() */ public boolean canBeInstantiated() { // cannot be asked per construction return false; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List) */ public List collectMissingTypes(List missingTypes) { if ((this.tagBits & TagBits.HasMissingType) != 0) { missingTypes = this.bound.collectMissingTypes(missingTypes); } return missingTypes; } /** * Collect the substitutes into a map for certain type variables inside the receiver type * e.g. Collection.collectSubstitutes(Collection>, Map), will populate Map with: T --> List * Constraints: * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1)) * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0)) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2)) */ public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { if ((this.tagBits & TagBits.HasTypeVariable) == 0) return; if (actualType == TypeBinding.NULL) return; if (actualType.isCapture()) { CaptureBinding capture = (CaptureBinding) actualType; actualType = capture.wildcard; } switch (constraint) { case TypeConstants.CONSTRAINT_EXTENDS : // A << F switch (this.boundKind) { case Wildcard.UNBOUND: // F={?} // switch (actualType.kind()) { // case Binding.WILDCARD_TYPE : // WildcardBinding actualWildcard = (WildcardBinding) actualType; // switch(actualWildcard.kind) { // case Wildcard.UNBOUND: // A={?} << F={?} --> 0 // break; // case Wildcard.EXTENDS: // A={? extends V} << F={?} ---> 0 // break; // case Wildcard.SUPER: // A={? super V} << F={?} ---> 0 // break; // } // break; // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} << F={?} ---> 0 // break; // default :// A=V << F={?} ---> 0 // break; // } break; case Wildcard.EXTENDS: // F={? extends U} switch(actualType.kind()) { case Binding.WILDCARD_TYPE : WildcardBinding actualWildcard = (WildcardBinding) actualType; switch(actualWildcard.boundKind) { case Wildcard.UNBOUND: // A={?} << F={? extends U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); break; case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0 break; } break; case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} << F={? extends U} ---> V1 << U, ..., Vn << U WildcardBinding actualIntersection = (WildcardBinding) actualType; this.bound.collectSubstitutes(scope, actualIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); for (int i = 0, length = actualIntersection.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actualIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); } break; default : // A=V << F={? extends U} ---> V << U this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); break; } break; case Wildcard.SUPER: // F={? super U} switch (actualType.kind()) { case Binding.WILDCARD_TYPE : WildcardBinding actualWildcard = (WildcardBinding) actualType; switch(actualWildcard.boundKind) { case Wildcard.UNBOUND: // A={?} << F={? super U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0 break; case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; } break; case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} << F={? super U} ---> 0 break; default :// A=V << F={? super U} ---> V >> U this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_SUPER); break; } break; } break; case TypeConstants.CONSTRAINT_EQUAL : // A == F switch (this.boundKind) { case Wildcard.UNBOUND: // F={?} // switch (actualType.kind()) { // case Binding.WILDCARD_TYPE : // WildcardBinding actualWildcard = (WildcardBinding) actualType; // switch(actualWildcard.kind) { // case Wildcard.UNBOUND: // A={?} == F={?} --> 0 // break; // case Wildcard.EXTENDS: // A={? extends V} == F={?} ---> 0 // break; // case Wildcard.SUPER: // A={? super V} == F={?} ---> 0 // break; // } // break; // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} == F={?} ---> 0 // break; // default :// A=V == F={?} ---> 0 // break; // } break; case Wildcard.EXTENDS: // F={? extends U} switch (actualType.kind()) { case Binding.WILDCARD_TYPE : WildcardBinding actualWildcard = (WildcardBinding) actualType; switch(actualWildcard.boundKind) { case Wildcard.UNBOUND: // A={?} == F={? extends U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); } break; case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0 break; } break; case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} == F={? extends U} ---> V1 == U, ..., Vn == U WildcardBinding actuaIntersection = (WildcardBinding) actualType; this.bound.collectSubstitutes(scope, actuaIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); for (int i = 0, length = actuaIntersection.otherBounds == null ? 0 : actuaIntersection.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actuaIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); } break; default : // A=V == F={? extends U} ---> 0 break; } break; case Wildcard.SUPER: // F={? super U} switch (actualType.kind()) { case Binding.WILDCARD_TYPE : WildcardBinding actualWildcard = (WildcardBinding) actualType; switch(actualWildcard.boundKind) { case Wildcard.UNBOUND: // A={?} == F={? super U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0 break; case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); } break; } break; case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} == F={? super U} ---> 0 break; default : // A=V == F={? super U} ---> 0 break; } break; } break; case TypeConstants.CONSTRAINT_SUPER : // A >> F switch (this.boundKind) { case Wildcard.UNBOUND: // F={?} // switch (actualType.kind()) { // case Binding.WILDCARD_TYPE : // WildcardBinding actualWildcard = (WildcardBinding) actualType; // switch(actualWildcard.kind) { // case Wildcard.UNBOUND: // A={?} >> F={?} --> 0 // break; // case Wildcard.EXTENDS: // A={? extends V} >> F={?} ---> 0 // break; // case Wildcard.SUPER: // A={? super V} >> F={?} ---> 0 // break; // } // break; // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} >> F={?} ---> 0 // break; // default :// A=V >> F={?} ---> 0 // break; // } break; case Wildcard.EXTENDS: // F={? extends U} switch (actualType.kind()) { case Binding.WILDCARD_TYPE : WildcardBinding actualWildcard = (WildcardBinding) actualType; switch(actualWildcard.boundKind) { case Wildcard.UNBOUND: // A={?} >> F={? extends U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0 break; } break; case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} >> F={? extends U} ---> V1 >> U, ..., Vn >> U WildcardBinding actualIntersection = (WildcardBinding) actualType; this.bound.collectSubstitutes(scope, actualIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); for (int i = 0, length = actualIntersection.otherBounds == null ? 0 : actualIntersection.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actualIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; default : // A=V == F={? extends U} ---> 0 break; } break; case Wildcard.SUPER: // F={? super U} switch (actualType.kind()) { case Binding.WILDCARD_TYPE : WildcardBinding actualWildcard = (WildcardBinding) actualType; switch(actualWildcard.boundKind) { case Wildcard.UNBOUND: // A={?} >> F={? super U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0 break; case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; } break; case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} >> F={? super U} ---> 0 break; default : // A=V >> F={? super U} ---> 0 break; } break; } break; } } /* * genericTypeKey {rank}*|+|- [boundKey] * p.X { X ... } --> Lp/X;{0}* */ public char[] computeUniqueKey(boolean isLeaf) { char[] genericTypeKey = this.genericType.computeUniqueKey(false/*not a leaf*/); char[] wildCardKey; // We now encode the rank also in the binding key - https://bugs.eclipse.org/bugs/show_bug.cgi?id=234609 char[] rankComponent = ('{' + String.valueOf(this.rank) + '}').toCharArray(); switch (this.boundKind) { case Wildcard.UNBOUND : wildCardKey = TypeConstants.WILDCARD_STAR; break; case Wildcard.EXTENDS : wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.computeUniqueKey(false/*not a leaf*/)); break; default: // SUPER wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.computeUniqueKey(false/*not a leaf*/)); break; } return CharOperation.concat(genericTypeKey, rankComponent, wildCardKey); } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName() */ public char[] constantPoolName() { return erasure().constantPoolName(); } /** * @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.otherBounds == null) { if (this.boundKind == Wildcard.EXTENDS) return this.bound.erasure(); TypeVariableBinding var = typeVariable(); if (var != null) return var.erasure(); return this.genericType; // if typeVariable() == null, then its inconsistent & return this.genericType to avoid NPE case } // intersection type return this.bound.id == TypeIds.T_JavaLangObject ? this.otherBounds[0].erasure() // use first explicit bound to improve stackmap : this.bound.erasure(); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature() */ public char[] genericTypeSignature() { if (this.genericSignature == null) { switch (this.boundKind) { case Wildcard.UNBOUND : this.genericSignature = TypeConstants.WILDCARD_STAR; break; case Wildcard.EXTENDS : this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.genericTypeSignature()); break; default: // SUPER this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.genericTypeSignature()); } } return this.genericSignature; } public int hashCode() { return this.genericType.hashCode(); } public boolean hasTypeBit(int bit) { if (this.typeBits == TypeIds.BitUninitialized) { // initialize from upper bounds this.typeBits = 0; if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized)) this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); if (this.superInterfaces != null) for (int i = 0, l = this.superInterfaces.length; i < l; i++) if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized)) this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); } return (this.typeBits & bit) != 0; } void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) { this.genericType = someGenericType; this.bound = someBound; this.otherBounds = someOtherBounds; if (someGenericType != null) { this.fPackage = someGenericType.getPackage(); } if (someBound != null) { this.tagBits |= someBound.tagBits & (TagBits.HasTypeVariable | TagBits.HasMissingType | TagBits.ContainsNestedTypeReferences); } if (someOtherBounds != null) { for (int i = 0, max = someOtherBounds.length; i < max; i++) { TypeBinding someOtherBound = someOtherBounds[i]; this.tagBits |= someOtherBound.tagBits & TagBits.ContainsNestedTypeReferences; } } } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#isSuperclassOf(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding) */ public boolean isSuperclassOf(ReferenceBinding otherType) { if (this.boundKind == Wildcard.SUPER) { if (this.bound instanceof ReferenceBinding) { return ((ReferenceBinding) this.bound).isSuperclassOf(otherType); } else { // array bound return otherType.id == TypeIds.T_JavaLangObject; } } return false; } /** * Returns true if the current type denotes an intersection type: Number & Comparable */ public boolean isIntersectionType() { return this.otherBounds != null; } public boolean isHierarchyConnected() { return this.superclass != null && this.superInterfaces != null; } /** * Returns true if the type is a wildcard */ public boolean isUnboundWildcard() { return this.boundKind == 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.boundKind) { case Wildcard.UNBOUND : return TypeConstants.WILDCARD_NAME; case Wildcard.EXTENDS : if (this.otherBounds == null) return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.readableName()); StringBuffer buffer = new StringBuffer(10); buffer.append(this.bound.readableName()); for (int i = 0, length = this.otherBounds.length; i < length; i++) { buffer.append('&').append(this.otherBounds[i].readableName()); } int length; char[] result = new char[length = buffer.length()]; buffer.getChars(0, length, result, 0); return result; default: // SUPER return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.readableName()); } } ReferenceBinding resolve() { if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0) return this; this.tagBits &= ~TagBits.HasUnresolvedTypeVariables; BinaryTypeBinding.resolveType(this.genericType, this.environment, false /* no raw conversion */); switch(this.boundKind) { case Wildcard.EXTENDS : TypeBinding resolveType = BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */); this.bound = resolveType; this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences; for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length; i < length; i++) { resolveType = BinaryTypeBinding.resolveType(this.otherBounds[i], this.environment, true /* raw conversion */); this.otherBounds[i]= resolveType; this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences; } break; case Wildcard.SUPER : resolveType = BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */); this.bound = resolveType; this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences; break; case Wildcard.UNBOUND : } return this; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName() */ public char[] shortReadableName() { switch (this.boundKind) { case Wildcard.UNBOUND : return TypeConstants.WILDCARD_NAME; case Wildcard.EXTENDS : if (this.otherBounds == null) return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.shortReadableName()); StringBuffer buffer = new StringBuffer(10); buffer.append(this.bound.shortReadableName()); for (int i = 0, length = this.otherBounds.length; i < length; i++) { buffer.append('&').append(this.otherBounds[i].shortReadableName()); } int length; char[] result = new char[length = buffer.length()]; buffer.getChars(0, length, result, 0); return result; default: // SUPER return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.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.boundKind) { case Wildcard.EXTENDS : return this.bound.signature(); default: // SUPER | UNBOUND return typeVariable().signature(); } } return this.signature; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#sourceName() */ public char[] sourceName() { switch (this.boundKind) { case Wildcard.UNBOUND : return TypeConstants.WILDCARD_NAME; case Wildcard.EXTENDS : return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.sourceName()); default: // SUPER return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.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 = null; if (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface()) { superType = this.bound; } else { TypeVariableBinding variable = typeVariable(); if (variable != null) superType = variable.firstBound; } this.superclass = superType instanceof ReferenceBinding && !superType.isInterface() ? (ReferenceBinding) superType : this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); } return this.superclass; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces() */ public ReferenceBinding[] superInterfaces() { if (this.superInterfaces == null) { if (typeVariable() != null) { this.superInterfaces = this.typeVariable.superInterfaces(); } else { this.superInterfaces = Binding.NO_SUPERINTERFACES; } if (this.boundKind == 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 } if (this.otherBounds != null) { // augment super interfaces with the wildcard otherBounds (interfaces per construction) int length = this.superInterfaces.length; int otherLength = this.otherBounds.length; System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+otherLength], 0, length); for (int i = 0; i < otherLength; i++) { this.superInterfaces[length+i] = (ReferenceBinding) this.otherBounds[i]; } } } } 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; } if (this.bound == unresolvedType) { this.bound = env.convertUnresolvedBinaryToRawType(resolvedType); affected = true; } if (this.otherBounds != null) { for (int i = 0, length = this.otherBounds.length; i < length; i++) { if (this.otherBounds[i] == unresolvedType) { this.otherBounds[i] = env.convertUnresolvedBinaryToRawType(resolvedType); affected = true; } } } if (affected) initialize(this.genericType, this.bound, this.otherBounds); } /** * @see java.lang.Object#toString() */ public String toString() { switch (this.boundKind) { case Wildcard.UNBOUND : return new String(TypeConstants.WILDCARD_NAME); case Wildcard.EXTENDS : if (this.otherBounds == null) return new String(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.debugName().toCharArray())); StringBuffer buffer = new StringBuffer(this.bound.debugName()); for (int i = 0, length = this.otherBounds.length; i < length; i++) { buffer.append('&').append(this.otherBounds[i].debugName()); } return buffer.toString(); default: // SUPER return new String(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.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; } } ././@LongLink0000644000000000000000000000015312251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBindin0000644000175000001440000000442412212041344032406 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 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.modifiers & ClassFileConstants.AccEnum) != 0 ? parameterizedDeclaringClass // enum constant get paramType as its type : (originalField.modifiers & ClassFileConstants.AccStatic) != 0 ? originalField.type // no subst for static field : Scope.substitute(parameterizedDeclaringClass, originalField.type), originalField.modifiers, parameterizedDeclaringClass, null); this.originalField = originalField; this.tagBits = originalField.tagBits; this.id = originalField.id; } /** * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#constant() */ public Constant constant() { return this.originalField.constant(); } /** * @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); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java0000644000175000001440000000337312212041344031337 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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 ProblemBinding extends Binding { public char[] name; public ReferenceBinding searchType; private int problemId; // NOTE: must only answer the subset of the name related to the problem public ProblemBinding(char[][] compoundName, int problemId) { this(CharOperation.concatWith(compoundName, '.'), problemId); } // NOTE: must only answer the subset of the name related to the problem public ProblemBinding(char[][] compoundName, ReferenceBinding searchType, int problemId) { this(CharOperation.concatWith(compoundName, '.'), searchType, problemId); } ProblemBinding(char[] name, int problemId) { this.name = name; this.problemId = problemId; } ProblemBinding(char[] name, ReferenceBinding searchType, int problemId) { this(name, problemId); this.searchType = searchType; } /* API * Answer the receiver's binding type from Binding.BindingID. */ public final int kind() { return VARIABLE | TYPE; } /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. */ public final int problemId() { return this.problemId; } public char[] readableName() { return this.name; } } ././@LongLink0000644000000000000000000000016312251602427011643 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMeth0000644000175000001440000007006312212041344032433 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; 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 private MethodBinding tiebreakMethod; /** * 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(); InferenceContext inferenceContext = null; TypeBinding[] uncheckedArguments = null; computeSubstitutes: { if (substitutes != null) { // explicit type arguments got supplied if (substitutes.length != typeVariables.length) { // incompatible due to wrong arity return new ProblemMethodBinding(originalMethod, originalMethod.selector, substitutes, ProblemReasons.TypeParameterArityMismatch); } methodSubstitute = scope.environment().createParameterizedGenericMethod(originalMethod, substitutes); break computeSubstitutes; } // perform type argument inference (15.12.2.7) // initializes the map of substitutes (var --> type[][]{ equal, extends, super} TypeBinding[] parameters = originalMethod.parameters; inferenceContext = new InferenceContext(originalMethod); methodSubstitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, inferenceContext); if (methodSubstitute == null) return null; // substitutes may hold null to denote unresolved vars, but null arguments got replaced with respective original variable in param method // 15.12.2.8 - inferring unresolved type arguments if (inferenceContext.hasUnresolvedTypeArgument()) { if (inferenceContext.isUnchecked) { // only remember unchecked status post 15.12.2.7 int length = inferenceContext.substitutes.length; System.arraycopy(inferenceContext.substitutes, 0, uncheckedArguments = new TypeBinding[length], 0, length); } if (methodSubstitute.returnType != TypeBinding.VOID) { TypeBinding expectedType = invocationSite.expectedType(); if (expectedType != null) { // record it was explicit from context, as opposed to assumed by default (see below) inferenceContext.hasExplicitExpectedType = true; } else { expectedType = scope.getJavaLangObject(); // assume Object by default } inferenceContext.expectedType = expectedType; } methodSubstitute = methodSubstitute.inferFromExpectedType(scope, inferenceContext); if (methodSubstitute == null) return null; } } /* bounds check: https://bugs.eclipse.org/bugs/show_bug.cgi?id=242159, Inferred types may contain self reference in formal bounds. If "T extends I" is a original type variable and T was inferred to be I due possibly to under constraints and resultant glb application per 15.12.2.8, using this.typeArguments to drive the bounds check against itself is doomed to fail. For, the variable T would after substitution be I> and would fail bounds check against I. Use the inferred types from the context directly - see that there is one round of extra substitution that has taken place to properly substitute a remaining unresolved variable which also appears in a formal bound (So we really have a bounds mismatch between I> and I>>, in the absence of a fix.) */ Substitution substitution = null; if (inferenceContext != null) { substitution = new LingeringTypeVariableEliminator(typeVariables, inferenceContext.substitutes, scope); } else { substitution = methodSubstitute; } for (int i = 0, length = typeVariables.length; i < length; i++) { TypeVariableBinding typeVariable = typeVariables[i]; TypeBinding substitute = methodSubstitute.typeArguments[i]; // retain for diagnostics /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=375394, To avoid spurious bounds check failures due to circularity in formal bounds, we should eliminate only the lingering embedded type variable references after substitution, not alien type variable references that constitute the inference per se. */ TypeBinding substituteForChecks; if (substitute instanceof TypeVariableBinding) { substituteForChecks = substitute; } else { substituteForChecks = Scope.substitute(new LingeringTypeVariableEliminator(typeVariables, null, scope), substitute); // while using this for bounds check } if (uncheckedArguments != null && uncheckedArguments[i] == null) continue; // only bound check if inferred through 15.12.2.6 switch (typeVariable.boundCheck(substitution, substituteForChecks, scope)) { case TypeConstants.MISMATCH : // incompatible due to bound check int argLength = arguments.length; TypeBinding[] augmentedArguments = new TypeBinding[argLength + 2]; // append offending substitute and typeVariable System.arraycopy(arguments, 0, augmentedArguments, 0, argLength); augmentedArguments[argLength] = substitute; augmentedArguments[argLength+1] = typeVariable; return new ProblemMethodBinding(methodSubstitute, originalMethod.selector, augmentedArguments, ProblemReasons.ParameterBoundMismatch); case TypeConstants.UNCHECKED : // tolerate unchecked bounds methodSubstitute.tagBits |= TagBits.HasUncheckedTypeArgumentForBoundCheck; break; } } // check presence of unchecked argument conversion a posteriori (15.12.2.6) return methodSubstitute; } /** * Collect argument type mapping, handling varargs */ private static ParameterizedGenericMethodBinding inferFromArgumentTypes(Scope scope, MethodBinding originalMethod, TypeBinding[] arguments, TypeBinding[] parameters, InferenceContext inferenceContext) { 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(scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } // process optional arguments if (minArgLength < argLength) { TypeBinding varargType = parameters[minArgLength]; // last arg type - as is ? TypeBinding lastArgument = arguments[minArgLength]; checkVarargDimension: { if (paramLength == argLength) { if (lastArgument == TypeBinding.NULL) break checkVarargDimension; switch (lastArgument.dimensions()) { case 0 : break; // will remove one dim case 1 : if (!lastArgument.leafComponentType().isBaseType()) break checkVarargDimension; break; // will remove one dim default : break checkVarargDimension; } } // eliminate one array dimension varargType = ((ArrayBinding)varargType).elementsType(); } for (int i = minArgLength; i < argLength; i++) { varargType.collectSubstitutes(scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } } } else { int paramLength = parameters.length; for (int i = 0; i < paramLength; i++) { parameters[i].collectSubstitutes(scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } } TypeVariableBinding[] originalVariables = originalMethod.typeVariables; if (!resolveSubstituteConstraints(scope, originalVariables , inferenceContext, false/*ignore Ti<:Uk*/)) return null; // impossible substitution // apply inferred variable substitutions - replacing unresolved variable with original ones in param method TypeBinding[] inferredSustitutes = inferenceContext.substitutes; TypeBinding[] actualSubstitutes = inferredSustitutes; for (int i = 0, varLength = originalVariables.length; i < varLength; i++) { if (inferredSustitutes[i] == null) { if (actualSubstitutes == inferredSustitutes) { System.arraycopy(inferredSustitutes, 0, actualSubstitutes = new TypeBinding[varLength], 0, i); // clone to replace null with original variable in param method } actualSubstitutes[i] = originalVariables[i]; } else if (actualSubstitutes != inferredSustitutes) { actualSubstitutes[i] = inferredSustitutes[i]; } } ParameterizedGenericMethodBinding paramMethod = scope.environment().createParameterizedGenericMethod(originalMethod, actualSubstitutes); return paramMethod; } private static boolean resolveSubstituteConstraints(Scope scope, TypeVariableBinding[] typeVariables, InferenceContext inferenceContext, boolean considerEXTENDSConstraints) { TypeBinding[] substitutes = inferenceContext.substitutes; int varLength = typeVariables.length; // check Tj=U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding [] equalSubstitutes = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EQUAL); if (equalSubstitutes != null) { nextConstraint: for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) { TypeBinding equalSubstitute = equalSubstitutes[j]; if (equalSubstitute == null) continue nextConstraint; if (equalSubstitute == current) { // try to find a better different match if any in subsequent equal candidates for (int k = j+1; k < equalLength; k++) { equalSubstitute = equalSubstitutes[k]; if (equalSubstitute != current && equalSubstitute != null) { substitutes[i] = equalSubstitute; continue nextTypeParameter; } } substitutes[i] = current; continue nextTypeParameter; } // if (equalSubstitute.isTypeVariable()) { // TypeVariableBinding variable = (TypeVariableBinding) equalSubstitute; // // substituted by a variable of the same method, ignore // if (variable.rank < varLength && typeVariables[variable.rank] == variable) { // // TODO (philippe) rewrite all other constraints to use current instead. // continue nextConstraint; // } // } substitutes[i] = equalSubstitute; continue nextTypeParameter; // pick first match, applicability check will rule out invalid scenario where others were present } } } if (inferenceContext.hasUnresolvedTypeArgument()) { // check Tj>:U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding [] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_SUPER); if (bounds == null) continue nextTypeParameter; TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(bounds); if (mostSpecificSubstitute == null) { return false; // incompatible } if (mostSpecificSubstitute != TypeBinding.VOID) { substitutes[i] = mostSpecificSubstitute; } } } if (considerEXTENDSConstraints && inferenceContext.hasUnresolvedTypeArgument()) { // check Tj<:U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding [] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EXTENDS); if (bounds == null) continue nextTypeParameter; TypeBinding[] glb = Scope.greaterLowerBound(bounds, scope); TypeBinding mostSpecificSubstitute = null; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=341795 - Per 15.12.2.8, we should fully apply glb if (glb != null) { if (glb.length == 1) { mostSpecificSubstitute = glb[0]; } else { TypeBinding [] otherBounds = new TypeBinding[glb.length - 1]; System.arraycopy(glb, 1, otherBounds, 0, glb.length - 1); mostSpecificSubstitute = scope.environment().createWildcard(null, 0, glb[0], otherBounds, Wildcard.EXTENDS); } } if (mostSpecificSubstitute != null) { substitutes[i] = mostSpecificSubstitute; } } } return true; } /** * 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] = environment.convertToRawType(originalVariables[i].erasure(), false /*do not force conversion of enclosing types*/); } this.isRaw = true; this.tagBits = originalMethod.tagBits; this.environment = environment; this.modifiers = originalMethod.modifiers; this.selector = originalMethod.selector; this.declaringClass = rawType == null ? originalMethod.declaringClass : rawType; this.typeVariables = Binding.NO_TYPE_VARIABLES; 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)); // error case where exception type variable would have been substituted by a non-reference type (207573) if (this.thrownExceptions == null) this.thrownExceptions = Binding.NO_EXCEPTIONS; this.returnType = Scope.substitute(this, ignoreRawTypeSubstitution ? originalMethod.returnType // no substitution if original was static : Scope.substitute(rawType, originalMethod.returnType)); this.wasInferred = false; // not resulting from method invocation inferrence this.parameterNonNullness = originalMethod.parameterNonNullness; } /** * 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 = Binding.NO_TYPE_VARIABLES; this.typeArguments = typeArguments; this.isRaw = false; this.tagBits = originalMethod.tagBits; this.originalMethod = originalMethod; this.parameters = Scope.substitute(this, originalMethod.parameters); // error case where exception type variable would have been substituted by a non-reference type (207573) this.returnType = Scope.substitute(this, originalMethod.returnType); this.thrownExceptions = Scope.substitute(this, originalMethod.thrownExceptions); if (this.thrownExceptions == null) this.thrownExceptions = Binding.NO_EXCEPTIONS; checkMissingType: { if ((this.tagBits & TagBits.HasMissingType) != 0) break checkMissingType; if ((this.returnType.tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } for (int i = 0, max = this.parameters.length; i < max; i++) { if ((this.parameters[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } for (int i = 0, max = this.thrownExceptions.length; i < max; i++) { if ((this.thrownExceptions[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } } this.wasInferred = true;// resulting from method invocation inferrence this.parameterNonNullness = originalMethod.parameterNonNullness; } /* * parameterizedDeclaringUniqueKey dot selector originalMethodGenericSignature percent typeArguments * p.X { void bar(T t, U u) { new X().bar(this, "") } } --> Lp/X;.bar(TT;Ljava/lang/String;)V% */ public char[] computeUniqueKey(boolean isLeaf) { StringBuffer buffer = new StringBuffer(); buffer.append(this.originalMethod.computeUniqueKey(false/*not a leaf*/)); buffer.append('%'); buffer.append('<'); if (!this.isRaw) { int length = this.typeArguments.length; for (int i = 0; i < length; i++) { TypeBinding typeArgument = this.typeArguments[i]; buffer.append(typeArgument.computeUniqueKey(false/*not a leaf*/)); } } buffer.append('>'); int resultLength = buffer.length(); char[] result = new char[resultLength]; buffer.getChars(0, resultLength, result, 0); return result; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#environment() */ public LookupEnvironment environment() { return this.environment; } /** * 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.inferredReturnType) return this.originalMethod.hasSubstitutedReturnType(); return super.hasSubstitutedReturnType(); } /** * Given some type expectation, and type variable bounds, perform some inference. * Returns true if still had unresolved type variable at the end of the operation */ private ParameterizedGenericMethodBinding inferFromExpectedType(Scope scope, InferenceContext inferenceContext) { TypeVariableBinding[] originalVariables = this.originalMethod.typeVariables; // immediate parent (could be a parameterized method) int varLength = originalVariables.length; // infer from expected return type if (inferenceContext.expectedType != null) { this.returnType.collectSubstitutes(scope, inferenceContext.expectedType, inferenceContext, TypeConstants.CONSTRAINT_SUPER); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } // infer from bounds of type parameters for (int i = 0; i < varLength; i++) { TypeVariableBinding originalVariable = originalVariables[i]; TypeBinding argument = this.typeArguments[i]; boolean argAlreadyInferred = argument != originalVariable; if (originalVariable.firstBound == originalVariable.superclass) { TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superclass); argument.collectSubstitutes(scope, substitutedBound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution // JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference // e.g. given: > S test1(S param) // invocation: test1(new Vector()) will infer: S=Vector and with code below: E=String if (argAlreadyInferred) { substitutedBound.collectSubstitutes(scope, argument, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } } for (int j = 0, max = originalVariable.superInterfaces.length; j < max; j++) { TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superInterfaces[j]); argument.collectSubstitutes(scope, substitutedBound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution // JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference if (argAlreadyInferred) { substitutedBound.collectSubstitutes(scope, argument, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } } } if (!resolveSubstituteConstraints(scope, originalVariables, inferenceContext, true/*consider Ti<:Uk*/)) return null; // incompatible // this.typeArguments = substitutes; - no op since side effects got performed during #resolveSubstituteConstraints for (int i = 0; i < varLength; i++) { TypeBinding substitute = inferenceContext.substitutes[i]; if (substitute != null) { this.typeArguments[i] = substitute; } else { // remaining unresolved variable are considered to be Object (or their bound actually) this.typeArguments[i] = inferenceContext.substitutes[i] = originalVariables[i].upperBound(); } } /* May still need an extra substitution at the end (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=121369) to properly substitute a remaining unresolved variable which also appear in a formal bound. See also http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5021635. It is questionable though whether this extra substitution should take place when the invocation site offers no guidance whatsoever and the type variables are inferred to be the glb of the published bounds - as there can recursion in the formal bounds, the inferred bounds would no longer be glb. */ this.typeArguments = Scope.substitute(this, this.typeArguments); // adjust method types to reflect latest inference TypeBinding oldReturnType = this.returnType; this.returnType = Scope.substitute(this, this.returnType); this.inferredReturnType = inferenceContext.hasExplicitExpectedType && this.returnType != oldReturnType; this.parameters = Scope.substitute(this, this.parameters); this.thrownExceptions = Scope.substitute(this, this.thrownExceptions); // error case where exception type variable would have been substituted by a non-reference type (207573) if (this.thrownExceptions == null) this.thrownExceptions = Binding.NO_EXCEPTIONS; checkMissingType: { if ((this.tagBits & TagBits.HasMissingType) != 0) break checkMissingType; if ((this.returnType.tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } for (int i = 0, max = this.parameters.length; i < max; i++) { if ((this.parameters[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } for (int i = 0, max = this.thrownExceptions.length; i < max; i++) { if ((this.thrownExceptions[i].tagBits & TagBits.HasMissingType) != 0) { this.tagBits |= TagBits.HasMissingType; break checkMissingType; } } } return this; } /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=347600 && https://bugs.eclipse.org/bugs/show_bug.cgi?id=242159 Sometimes due to recursion/circularity in formal bounds, even *published bounds* fail bound check. We need to break the circularity/self reference in order not to be overly strict during type equivalence checks. See also http://bugs.sun.com/view_bug.do?bug_id=6932571 */ private static class LingeringTypeVariableEliminator implements Substitution { final private TypeVariableBinding [] variables; final private TypeBinding [] substitutes; // when null, substitute type variables by unbounded wildcard final private Scope scope; /** * @param variables * @param substitutes when null, substitute type variable by unbounded wildcard * @param scope */ public LingeringTypeVariableEliminator(TypeVariableBinding [] variables, TypeBinding [] substitutes, Scope scope) { this.variables = variables; this.substitutes = substitutes; this.scope = scope; } // With T mapping to I, answer of I, when given T, having eliminated the circularity/self reference. public TypeBinding substitute(TypeVariableBinding typeVariable) { if (typeVariable.rank >= this.variables.length || this.variables[typeVariable.rank] != typeVariable) { // not kosher, don't touch. return typeVariable; } if (this.substitutes != null) { return Scope.substitute(new LingeringTypeVariableEliminator(this.variables, null, this.scope), this.substitutes[typeVariable.rank]); } ReferenceBinding genericType = (ReferenceBinding) (typeVariable.declaringElement instanceof ReferenceBinding ? typeVariable.declaringElement : null); return this.scope.environment().createWildcard(genericType, typeVariable.rank, null, null, Wildcard.UNBOUND); } public LookupEnvironment environment() { return this.scope.environment(); } public boolean isRawSubstitution() { return false; } } /** * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#isRawSubstitution() */ public boolean isRawSubstitution() { return this.isRaw; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#substitute(org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding) */ public TypeBinding substitute(TypeVariableBinding originalVariable) { 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]; } return originalVariable; } /** * @see org.eclipse.jdt.internal.compiler.lookup.MethodBinding#tiebreakMethod() */ public MethodBinding tiebreakMethod() { if (this.tiebreakMethod == null) this.tiebreakMethod = this.originalMethod.asRawMethod(this.environment); return this.tiebreakMethod; } }ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java0000644000175000001440000001412712212041344031452 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public final class BaseTypeBinding extends TypeBinding { public static final int[] CONVERSIONS; public static final int IDENTITY = 1; public static final int WIDENING = 2; public static final int NARROWING = 4; public static final int MAX_CONVERSIONS = 16*16; // well-known x well-known static { CONVERSIONS = initializeConversions(); } public static final int[] initializeConversions(){ // fromType destType --> conversion // 0000 0000 0000 int[] table = new int[MAX_CONVERSIONS]; table[TypeIds.Boolean2Boolean] = IDENTITY; table[TypeIds.Byte2Byte] = IDENTITY; table[TypeIds.Byte2Short] = WIDENING; table[TypeIds.Byte2Char] = NARROWING; table[TypeIds.Byte2Int] = WIDENING; table[TypeIds.Byte2Long] = WIDENING; table[TypeIds.Byte2Float] = WIDENING; table[TypeIds.Byte2Double] = WIDENING; table[TypeIds.Short2Byte] = NARROWING; table[TypeIds.Short2Short] = IDENTITY; table[TypeIds.Short2Char] = NARROWING; table[TypeIds.Short2Int] = WIDENING; table[TypeIds.Short2Long] = WIDENING; table[TypeIds.Short2Float] = WIDENING; table[TypeIds.Short2Double] = WIDENING; table[TypeIds.Char2Byte] = NARROWING; table[TypeIds.Char2Short] = NARROWING; table[TypeIds.Char2Char] = IDENTITY; table[TypeIds.Char2Int] = WIDENING; table[TypeIds.Char2Long] = WIDENING; table[TypeIds.Char2Float] = WIDENING; table[TypeIds.Char2Double] = WIDENING; table[TypeIds.Int2Byte] = NARROWING; table[TypeIds.Int2Short] = NARROWING; table[TypeIds.Int2Char] = NARROWING; table[TypeIds.Int2Int] = IDENTITY; table[TypeIds.Int2Long] = WIDENING; table[TypeIds.Int2Float] = WIDENING; table[TypeIds.Int2Double] = WIDENING; table[TypeIds.Long2Byte] = NARROWING; table[TypeIds.Long2Short] = NARROWING; table[TypeIds.Long2Char] = NARROWING; table[TypeIds.Long2Int] = NARROWING; table[TypeIds.Long2Long] = IDENTITY; table[TypeIds.Long2Float] = WIDENING; table[TypeIds.Long2Double] = WIDENING; table[TypeIds.Float2Byte] = NARROWING; table[TypeIds.Float2Short] = NARROWING; table[TypeIds.Float2Char] = NARROWING; table[TypeIds.Float2Int] = NARROWING; table[TypeIds.Float2Long] = NARROWING; table[TypeIds.Float2Float] = IDENTITY; table[TypeIds.Float2Double] = WIDENING; table[TypeIds.Double2Byte] = NARROWING; table[TypeIds.Double2Short] = NARROWING; table[TypeIds.Double2Char] = NARROWING; table[TypeIds.Double2Int] = NARROWING; table[TypeIds.Double2Long] = NARROWING; table[TypeIds.Double2Float] = NARROWING; table[TypeIds.Double2Double]= IDENTITY; return table; } /** * Predicate telling whether "left" can store a "right" using some narrowing conversion *(is left smaller than right) * @param left - the target type to convert to * @param right - the actual type * @return true if legal narrowing conversion */ public static final boolean isNarrowing(int left, int right) { int right2left = right + (left<<4); return right2left >= 0 && right2left < MAX_CONVERSIONS && (CONVERSIONS[right2left] & (IDENTITY|NARROWING)) != 0; } /** * Predicate telling whether "left" can store a "right" using some widening conversion *(is left bigger than right) * @param left - the target type to convert to * @param right - the actual type * @return true if legal widening conversion */ public static final boolean isWidening(int left, int right) { int right2left = right + (left<<4); return right2left >= 0 && right2left < MAX_CONVERSIONS && (CONVERSIONS[right2left] & (IDENTITY|WIDENING)) != 0; } public char[] simpleName; private char[] constantPoolName; BaseTypeBinding(int id, char[] name, char[] constantPoolName) { this.tagBits |= TagBits.IsBaseType; this.id = id; this.simpleName = name; this.constantPoolName = constantPoolName; } /** * int -> I */ public char[] computeUniqueKey(boolean isLeaf) { return constantPoolName(); } /* Answer the receiver's constant pool name. */ public char[] constantPoolName() { return this.constantPoolName; } public PackageBinding getPackage() { return null; } /* Answer true if the receiver type can be assigned to the argument type (right) */ public final boolean isCompatibleWith(TypeBinding left, Scope captureScope) { if (this == left) return true; int right2left = this.id + (left.id<<4); if (right2left >= 0 && right2left < MAX_CONVERSIONS && (CONVERSIONS[right2left] & (IDENTITY|WIDENING)) != 0) return true; return this == TypeBinding.NULL && !left.isBaseType(); } /** * T_null is acting as an unchecked exception * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isUncheckedException(boolean) */ public boolean isUncheckedException(boolean includeSupertype) { return this == TypeBinding.NULL; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#kind() */ public int kind() { return Binding.BASE_TYPE; } public char[] qualifiedSourceName() { return this.simpleName; } public char[] readableName() { return this.simpleName; } public char[] shortReadableName() { return this.simpleName; } public char[] sourceName() { return this.simpleName; } public String toString() { return new String(this.constantPoolName) + " (id=" + this.id + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.ja0000644000175000001440000000216412212041344032261 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; public class ProblemPackageBinding extends PackageBinding { private int problemId; // NOTE: must only answer the subset of the name related to the problem ProblemPackageBinding(char[][] compoundName, int problemId) { this.compoundName = compoundName; this.problemId = problemId; } ProblemPackageBinding(char[] name, int problemId) { this(new char[][] {name}, problemId); } /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. */ public final int problemId() { return this.problemId; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/Binding.java0000644000175000001440000001206512212041344030014 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.ASTNode; public abstract class Binding { // 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 BASE_TYPE = TYPE | ASTNode.Bit8; public static final int PARAMETERIZED_TYPE = TYPE | ASTNode.Bit9; public static final int WILDCARD_TYPE = TYPE | ASTNode.Bit10; public static final int RAW_TYPE = TYPE | ASTNode.Bit11; public static final int GENERIC_TYPE = TYPE | ASTNode.Bit12; public static final int TYPE_PARAMETER = TYPE | ASTNode.Bit13; public static final int INTERSECTION_TYPE = TYPE | ASTNode.Bit14; // Shared binding collections public static final TypeBinding[] NO_TYPES = new TypeBinding[0]; public static final TypeBinding[] NO_PARAMETERS = new TypeBinding[0]; public static final ReferenceBinding[] NO_EXCEPTIONS = new ReferenceBinding[0]; public static final ReferenceBinding[] ANY_EXCEPTION = new ReferenceBinding[] { null }; // special handler for all exceptions public static final FieldBinding[] NO_FIELDS = new FieldBinding[0]; public static final MethodBinding[] NO_METHODS = new MethodBinding[0]; public static final ReferenceBinding[] NO_SUPERINTERFACES = new ReferenceBinding[0]; public static final ReferenceBinding[] NO_MEMBER_TYPES = new ReferenceBinding[0]; public static final TypeVariableBinding[] NO_TYPE_VARIABLES = new TypeVariableBinding[0]; public static final AnnotationBinding[] NO_ANNOTATIONS = new AnnotationBinding[0]; public static final ElementValuePair[] NO_ELEMENT_VALUE_PAIRS = new ElementValuePair[0]; public static final FieldBinding[] UNINITIALIZED_FIELDS = new FieldBinding[0]; public static final MethodBinding[] UNINITIALIZED_METHODS = new MethodBinding[0]; public static final ReferenceBinding[] UNINITIALIZED_REFERENCE_TYPES = new ReferenceBinding[0]; // Nullness defaults: public static final int NO_NULL_DEFAULT = 0; public static final int NULL_UNSPECIFIED_BY_DEFAULT = 1; public static final int NONNULL_BY_DEFAULT = 2; /* * Answer the receiver's binding type from Binding.BindingID. */ 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 computeUniqueKey(true/*leaf*/); } /* * Computes a key that uniquely identifies this binding. Optionally include access flags. * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding or a PackageBinding. */ public char[] computeUniqueKey(boolean isLeaf) { return null; } /** * Compute the tagbits for standard annotations. For source types, these could require * lazily resolving corresponding annotation nodes, in case of forward references. * @see org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding#getAnnotationTagBits() */ public long getAnnotationTagBits() { return 0; } /** * Compute the tag bits for @Deprecated annotations, avoiding resolving * entire annotation if not necessary. * @see org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding#initializeDeprecatedAnnotationTagBits() */ public void initializeDeprecatedAnnotationTagBits() { // empty block } /* API * Answer true if the receiver is not a problem binding */ public final boolean isValidBinding() { return problemId() == ProblemReasons.NoError; } public boolean isVolatile() { return false; } public boolean isParameter() { return false; } /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. * Note: a parameterized type or an array type are always valid, but may be formed of invalid pieces. */ // TODO (philippe) should rename into problemReason() public int problemId() { return ProblemReasons.NoError; } /* Answer a printable representation of the receiver. */ public abstract char[] readableName(); /* Shorter printable representation of the receiver (no qualified type) */ public char[] shortReadableName(){ return readableName(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java0000644000175000001440000014717512212041344031537 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 388795 - [compiler] detection of name clash depends on order of super interfaces * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * bug 395681 - [compiler] Improve simulation of javac6 behavior from bug 317719 after fixing bug 388795 * bug 409473 - [compiler] JDT cannot compile against JRE 1.8 * Bug 410325 - [1.7][compiler] Generified method override different between javac and eclipse compiler *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; 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.CompilerOptions; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; import org.eclipse.jdt.internal.compiler.util.SimpleSet; class MethodVerifier15 extends MethodVerifier { MethodVerifier15(LookupEnvironment environment) { super(environment); } boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { // use the original methods to test compatibility, but do not check visibility, etc one = one.original(); two = one.findOriginalInheritedMethod(two); if (two == null) return false; // method's declaringClass does not inherit from inheritedMethod's return isParameterSubsignature(one, two); } boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) { if (one.returnType == two.returnType) return true; if (this.type.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { return areReturnTypesCompatible0(one, two); } else { return areTypesEqual(one.returnType.erasure(), two.returnType.erasure()); } } // Given `overridingMethod' which overrides `inheritedMethod' answer whether some subclass method that // differs in erasure from overridingMethod could override `inheritedMethod' protected boolean canOverridingMethodDifferInErasure(MethodBinding overridingMethod, MethodBinding inheritedMethod) { if (overridingMethod.areParameterErasuresEqual(inheritedMethod)) return false; // no further change in signature is possible due to parameterization. if (overridingMethod.declaringClass.isRawType()) return false; // no parameterization is happening anyways. return true; } boolean canSkipInheritedMethods() { if (this.type.superclass() != null) if (this.type.superclass().isAbstract() || this.type.superclass().isParameterizedType()) return false; return this.type.superInterfaces() == Binding.NO_SUPERINTERFACES; } boolean canSkipInheritedMethods(MethodBinding one, MethodBinding two) { return two == null // already know one is not null || (one.declaringClass == two.declaringClass && !one.declaringClass.isParameterizedType()); } void checkConcreteInheritedMethod(MethodBinding concreteMethod, MethodBinding[] abstractMethods) { super.checkConcreteInheritedMethod(concreteMethod, abstractMethods); boolean analyseNullAnnotations = this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled; // TODO (stephan): unclear if this srcMethod is actually needed AbstractMethodDeclaration srcMethod = null; if (analyseNullAnnotations && this.type.equals(concreteMethod.declaringClass)) // is currentMethod from the current type? srcMethod = concreteMethod.sourceMethod(); boolean hasNonNullDefault = concreteMethod.hasNonNullDefault(); for (int i = 0, l = abstractMethods.length; i < l; i++) { MethodBinding abstractMethod = abstractMethods[i]; if (concreteMethod.isVarargs() != abstractMethod.isVarargs()) problemReporter().varargsConflict(concreteMethod, abstractMethod, this.type); // so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod MethodBinding originalInherited = abstractMethod.original(); if (originalInherited.returnType != concreteMethod.returnType) if (!isAcceptableReturnTypeOverride(concreteMethod, abstractMethod)) problemReporter().unsafeReturnTypeOverride(concreteMethod, originalInherited, this.type); // check whether bridge method is already defined above for interface methods // skip generation of bridge method for current class & method if an equivalent // bridge will be/would have been generated in the context of the super class since // the bridge itself will be inherited. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=298362 if (originalInherited.declaringClass.isInterface()) { if ((concreteMethod.declaringClass == this.type.superclass && this.type.superclass.isParameterizedType() && !areMethodsCompatible(concreteMethod, originalInherited)) || this.type.superclass.erasure().findSuperTypeOriginatingFrom(originalInherited.declaringClass) == null) this.type.addSyntheticBridgeMethod(originalInherited, concreteMethod.original()); } if (analyseNullAnnotations && !concreteMethod.isStatic() && !abstractMethod.isStatic()) { checkNullSpecInheritance(concreteMethod, srcMethod, hasNonNullDefault, true, abstractMethod, this.type.scope, null); } } } void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) { if (currentMethod.isVarargs() != inheritedMethod.isVarargs()) problemReporter(currentMethod).varargsConflict(currentMethod, inheritedMethod, this.type); // so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod MethodBinding originalInherited = inheritedMethod.original(); if (originalInherited.returnType != currentMethod.returnType) if (!isAcceptableReturnTypeOverride(currentMethod, inheritedMethod)) problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, this.type); MethodBinding bridge = this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original()); if (bridge != null) { for (int i = 0, l = allInheritedMethods == null ? 0 : allInheritedMethods.length; i < l; i++) { if (allInheritedMethods[i] != null && detectInheritedNameClash(originalInherited, allInheritedMethods[i].original())) return; } // See if the new bridge clashes with any of the user methods of the class. For this check // we should check for "method descriptor clash" and not just "method signature clash". Really // what we are checking is whether there is a contention for the method dispatch table slot. // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=293615. MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(bridge.selector); for (int i = current.length - 1; i >= 0; --i) { final MethodBinding thisMethod = current[i]; if (thisMethod.areParameterErasuresEqual(bridge) && thisMethod.returnType.erasure() == bridge.returnType.erasure()) { // use inherited method for problem reporting. problemReporter(thisMethod).methodNameClash(thisMethod, inheritedMethod.declaringClass.isRawType() ? inheritedMethod : inheritedMethod.original(), ProblemSeverities.Error); return; } } } } void checkForNameClash(MethodBinding currentMethod, MethodBinding inheritedMethod) { // sent from checkMethods() to compare a current method and an inherited method that are not 'equal' // error cases: // abstract class AA { abstract void test(E element); } // class A extends AA { public void test(Integer i) {} } // public class B extends A { public void test(Comparable i) {} } // interface I { void test(E element); } // class A implements I { public void test(Integer i) {} } // public class B extends A { public void test(Comparable i) {} } // abstract class Y implements EqualityComparable, Equivalent { // public boolean equalTo(Integer other) { return true; } // } // interface Equivalent { boolean equalTo(T other); } // interface EqualityComparable { boolean equalTo(T other); } // class Y implements EqualityComparable, Equivalent{ // public boolean equalTo(String other) { return true; } // public boolean equalTo(Object other) { return true; } // } // interface Equivalent { boolean equalTo(T other); } // interface EqualityComparable { boolean equalTo(Object other); } // class A { void m(T t) {} } // class B extends A { void m(S t) {}} // class D extends B { void m(Number t) {} void m(Integer t) {} } // inheritedMethods does not include I.test since A has a valid implementation // interface I> { void test(E element); } // class A implements I { public void test(Integer i) {} } // class B extends A { public void test(Comparable i) {} } if (inheritedMethod.isStatic() || currentMethod.isStatic()) { MethodBinding original = inheritedMethod.original(); // can be the same as inherited if (this.type.scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_7 && currentMethod.areParameterErasuresEqual(original)) { problemReporter(currentMethod).methodNameClashHidden(currentMethod, inheritedMethod.declaringClass.isRawType() ? inheritedMethod : original); } return; // no chance of bridge method's clashing } if (!detectNameClash(currentMethod, inheritedMethod, false)) { // check up the hierarchy for skipped inherited methods TypeBinding[] currentParams = currentMethod.parameters; TypeBinding[] inheritedParams = inheritedMethod.parameters; int length = currentParams.length; if (length != inheritedParams.length) return; // no match for (int i = 0; i < length; i++) if (currentParams[i] != inheritedParams[i]) if (currentParams[i].isBaseType() != inheritedParams[i].isBaseType() || !inheritedParams[i].isCompatibleWith(currentParams[i])) return; // no chance that another inherited method's bridge method can collide ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; ReferenceBinding superType = inheritedMethod.declaringClass; ReferenceBinding[] itsInterfaces = superType.superInterfaces(); if (itsInterfaces != Binding.NO_SUPERINTERFACES) { nextPosition = itsInterfaces.length; interfacesToVisit = itsInterfaces; } superType = superType.superclass(); // now start with its superclass while (superType != null && superType.isValidBinding()) { MethodBinding[] methods = superType.getMethods(currentMethod.selector); for (int m = 0, n = methods.length; m < n; m++) { MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute, true)) return; } if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } superType = superType.superclass(); } for (int i = 0; i < nextPosition; i++) { superType = interfacesToVisit[i]; if (superType.isValidBinding()) { MethodBinding[] methods = superType.getMethods(currentMethod.selector); for (int m = 0, n = methods.length; m < n; m++){ MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute, true)) return; } if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } } } void checkInheritedMethods(MethodBinding inheritedMethod, MethodBinding otherInheritedMethod) { // the 2 inherited methods clash because of a parameterized type overrides a raw type // interface I { void foo(A a); } // class Y { void foo(A a) {} } // abstract class X extends Y implements I { } // class A {} // in this case the 2 inherited methods clash because of type variables // interface I { void foo(T t); } // class Y { void foo(T t) {} } // abstract class X extends Y implements I {} if (inheritedMethod.isStatic()) return; if (this.environment.globalOptions.complianceLevel < ClassFileConstants.JDK1_7 && inheritedMethod.declaringClass.isInterface()) return; // JDK7 checks for name clashes in interface inheritance, while JDK6 and below don't. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=354229 detectInheritedNameClash(inheritedMethod.original(), otherInheritedMethod.original()); } // 8.4.8.4 void checkInheritedMethods(MethodBinding[] methods, int length, boolean[] isOverridden) { boolean continueInvestigation = true; MethodBinding concreteMethod = null; for (int i = 0; i < length; i++) { // when unexpectedly seeing a non-abstract interface method regard it as abstract, too, for this check: boolean isAbstract = methods[i].isAbstract() || methods[i].declaringClass.isInterface(); if (!isAbstract) { if (concreteMethod != null) { // https://bugs.eclipse.org/195802 with https://bugs.eclipse.org/410325 // If a replace method (from findReplacedMethod()) is the rawified version of another // don't count this as duplicates: // (Not asking ParameterizedGenericMethodBinding.isRawMethod(), // because that is true only for methods of a RawTypeBinding, // but here we look for rawness regarding the method's type variables). if (concreteMethod.declaringClass == methods[i].declaringClass && concreteMethod.typeVariables.length != methods[i].typeVariables.length) { if (concreteMethod.typeVariables == Binding.NO_TYPE_VARIABLES && concreteMethod.original() == methods[i]) continue; if (methods[i].typeVariables == Binding.NO_TYPE_VARIABLES && methods[i].original() == concreteMethod) continue; } problemReporter().duplicateInheritedMethods(this.type, concreteMethod, methods[i]); continueInvestigation = false; } concreteMethod = methods[i]; } } if (continueInvestigation) { super.checkInheritedMethods(methods, length, isOverridden); } } boolean checkInheritedReturnTypes(MethodBinding method, MethodBinding otherMethod) { if (areReturnTypesCompatible(method, otherMethod)) return true; /* We used to have some checks here to see if we would have already blamed the super type and if so avoid blaming the current type again. I have gotten rid of them as they in fact short circuit error reporting in cases where they should not. This means that occasionally we would report the error twice - the diagnostics is valid however, albeit arguably redundant. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=334313. For an example of a test where we do this extra reporting see org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test159() */ // check to see if this is just a warning, if so report it & skip to next method if (isUnsafeReturnTypeOverride(method, otherMethod)) { if (!method.declaringClass.implementsInterface(otherMethod.declaringClass, false)) problemReporter(method).unsafeReturnTypeOverride(method, otherMethod, this.type); return true; } return false; } void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length, MethodBinding[] allInheritedMethods) { super.checkAgainstInheritedMethods(currentMethod, methods, length, allInheritedMethods); CompilerOptions options = this.environment.globalOptions; if (options.isAnnotationBasedNullAnalysisEnabled && (currentMethod.tagBits & TagBits.IsNullnessKnown) == 0) { // if annotations are inherited these have been checked during STB.resolveTypesFor() (for methods explicit in this.type) AbstractMethodDeclaration srcMethod = null; if (this.type.equals(currentMethod.declaringClass)) // is currentMethod from the current type? srcMethod = currentMethod.sourceMethod(); boolean hasNonNullDefault = currentMethod.hasNonNullDefault(); for (int i = length; --i >= 0;) if (!currentMethod.isStatic() && !methods[i].isStatic()) checkNullSpecInheritance(currentMethod, srcMethod, hasNonNullDefault, true, methods[i], this.type.scope, null); } } void checkNullSpecInheritance(MethodBinding currentMethod, AbstractMethodDeclaration srcMethod, boolean hasNonNullDefault, boolean complain, MethodBinding inheritedMethod, Scope scope, InheritedNonNullnessInfo[] inheritedNonNullnessInfos) { complain &= !currentMethod.isConstructor(); if (!hasNonNullDefault && !complain && !this.environment.globalOptions.inheritNullAnnotations) { // nothing to be done, take the shortcut currentMethod.tagBits |= TagBits.IsNullnessKnown; return; } // in this context currentMethod can be inherited, too. Recurse if needed. if (currentMethod.declaringClass != this.type && (currentMethod.tagBits & TagBits.IsNullnessKnown) == 0) { this.buddyImplicitNullAnnotationsVerifier.checkImplicitNullAnnotations(currentMethod, srcMethod, complain, this.type.scope); } super.checkNullSpecInheritance(currentMethod, srcMethod, hasNonNullDefault, complain, inheritedMethod, scope, inheritedNonNullnessInfos); } void reportRawReferences() { CompilerOptions compilerOptions = this.type.scope.compilerOptions(); if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_5 // shouldn't whine at all || compilerOptions.reportUnavoidableGenericTypeProblems) { // must have already whined return; } /* Code below is only for a method that does not override/implement a super type method. If it were to, it would have been handled in checkAgainstInheritedMethods. */ Object [] methodArray = this.currentMethods.valueTable; for (int s = methodArray.length; --s >= 0;) { if (methodArray[s] == null) continue; MethodBinding[] current = (MethodBinding[]) methodArray[s]; for (int i = 0, length = current.length; i < length; i++) { MethodBinding currentMethod = current[i]; if ((currentMethod.modifiers & (ExtraCompilerModifiers.AccImplementing | ExtraCompilerModifiers.AccOverriding)) == 0) { AbstractMethodDeclaration methodDecl = currentMethod.sourceMethod(); if (methodDecl == null) return; TypeBinding [] parameterTypes = currentMethod.parameters; Argument[] arguments = methodDecl.arguments; for (int j = 0, size = currentMethod.parameters.length; j < size; j++) { TypeBinding parameterType = parameterTypes[j]; Argument arg = arguments[j]; if (parameterType.leafComponentType().isRawType() && compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore && (arg.type.bits & ASTNode.IgnoreRawTypeCheck) == 0) { methodDecl.scope.problemReporter().rawTypeReference(arg.type, parameterType); } } if (!methodDecl.isConstructor() && methodDecl instanceof MethodDeclaration) { TypeReference returnType = ((MethodDeclaration) methodDecl).returnType; TypeBinding methodType = currentMethod.returnType; if (returnType != null) { if (methodType.leafComponentType().isRawType() && compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore && (returnType.bits & ASTNode.IgnoreRawTypeCheck) == 0) { methodDecl.scope.problemReporter().rawTypeReference(returnType, methodType); } } } } } } } public void reportRawReferences(MethodBinding currentMethod, MethodBinding inheritedMethod) { CompilerOptions compilerOptions = this.type.scope.compilerOptions(); if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_5 // shouldn't whine at all || compilerOptions.reportUnavoidableGenericTypeProblems) { // must have already whined return; } AbstractMethodDeclaration methodDecl = currentMethod.sourceMethod(); if (methodDecl == null) return; TypeBinding [] parameterTypes = currentMethod.parameters; TypeBinding [] inheritedParameterTypes = inheritedMethod.parameters; Argument[] arguments = methodDecl.arguments; for (int j = 0, size = currentMethod.parameters.length; j < size; j++) { TypeBinding parameterType = parameterTypes[j]; TypeBinding inheritedParameterType = inheritedParameterTypes[j]; Argument arg = arguments[j]; if (parameterType.leafComponentType().isRawType()) { if (inheritedParameterType.leafComponentType().isRawType()) { arg.binding.tagBits |= TagBits.ForcedToBeRawType; } else { if (compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore && (arg.type.bits & ASTNode.IgnoreRawTypeCheck) == 0) { methodDecl.scope.problemReporter().rawTypeReference(arg.type, parameterType); } } } } TypeReference returnType = null; if (!methodDecl.isConstructor() && methodDecl instanceof MethodDeclaration && (returnType = ((MethodDeclaration) methodDecl).returnType) != null) { final TypeBinding inheritedMethodType = inheritedMethod.returnType; final TypeBinding methodType = currentMethod.returnType; if (methodType.leafComponentType().isRawType()) { if (inheritedMethodType.leafComponentType().isRawType()) { // } else { if ((returnType.bits & ASTNode.IgnoreRawTypeCheck) == 0 && compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) { methodDecl.scope.problemReporter().rawTypeReference(returnType, methodType); } } } } } void checkMethods() { boolean mustImplementAbstractMethods = mustImplementAbstractMethods(); boolean skipInheritedMethods = mustImplementAbstractMethods && canSkipInheritedMethods(); // have a single concrete superclass so only check overridden methods boolean isOrEnclosedByPrivateType = this.type.isOrEnclosedByPrivateType(); char[][] methodSelectors = this.inheritedMethods.keyTable; nextSelector : for (int s = methodSelectors.length; --s >= 0;) { if (methodSelectors[s] == null) continue nextSelector; MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]); MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s]; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed, // inherited methods of super classes are too. current != null case handled below. if (current == null && !isOrEnclosedByPrivateType) { int length = inherited.length; for (int i = 0; i < length; i++){ inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } if (current == null && this.type.isPublic()) { int length = inherited.length; for (int i = 0; i < length; i++) { MethodBinding inheritedMethod = inherited[i]; if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic()) this.type.addSyntheticBridgeMethod(inheritedMethod.original()); } } if (current == null && skipInheritedMethods) continue nextSelector; if (inherited.length == 1 && current == null) { // handle the common case if (mustImplementAbstractMethods && inherited[0].isAbstract()) checkAbstractMethod(inherited[0]); continue nextSelector; } int index = -1; int inheritedLength = inherited.length; MethodBinding[] matchingInherited = new MethodBinding[inheritedLength]; MethodBinding[] foundMatch = new MethodBinding[inheritedLength]; // null is no match, otherwise value is matching currentMethod // skip tracks inherited methods which can be safely ignored for one of these reasons: // - methods that have matched other inherited methods // either because they match the same currentMethod or match each other // - methods that are overridden by a current method boolean[] skip = new boolean[inheritedLength]; boolean[] isOverridden = new boolean[inheritedLength]; if (current != null) { for (int i = 0, length1 = current.length; i < length1; i++) { MethodBinding currentMethod = current[i]; MethodBinding[] nonMatchingInherited = null; for (int j = 0; j < inheritedLength; j++) { MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod); if (inheritedMethod != null) { if (foundMatch[j] == null && isSubstituteParameterSubsignature(currentMethod, inheritedMethod)) { // already checked compatibility, do visibility etc. also indicate overriding? If so ignore inheritedMethod further downstream isOverridden[j] = skip[j] = couldMethodOverride(currentMethod, inheritedMethod); matchingInherited[++index] = inheritedMethod; foundMatch[j] = currentMethod; } else { // best place to check each currentMethod against each non-matching inheritedMethod checkForNameClash(currentMethod, inheritedMethod); if (inheritedLength > 1) { if (nonMatchingInherited == null) nonMatchingInherited = new MethodBinding[inheritedLength]; nonMatchingInherited[j] = inheritedMethod; } } } } if (index >= 0) { // see addtional comments in https://bugs.eclipse.org/bugs/show_bug.cgi?id=122881 // if (index > 0 && currentMethod.declaringClass.isInterface()) // only check when inherited methods are from interfaces // checkInheritedReturnTypes(matchingInherited, index + 1); checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1, nonMatchingInherited); // pass in the length of matching while (index >= 0) matchingInherited[index--] = null; // clear the contents of the matching methods } } } // first round: collect information into skip and isOverridden by comparing all pairs: // (and perform some side effects : bridge methods & use flags) for (int i = 0; i < inheritedLength; i++) { MethodBinding matchMethod = foundMatch[i]; if (matchMethod == null && current != null && this.type.isPublic()) { // current == null case handled already. MethodBinding inheritedMethod = inherited[i]; if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic()) { this.type.addSyntheticBridgeMethod(inheritedMethod.original()); } } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed, // inherited methods of super classes are too. current == null case handled already. if (!isOrEnclosedByPrivateType && matchMethod == null && current != null) { inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } MethodBinding inheritedMethod = inherited[i]; for (int j = i + 1; j < inheritedLength; j++) { MethodBinding otherInheritedMethod = inherited[j]; if (matchMethod == foundMatch[j] && matchMethod != null) continue; // both inherited methods matched the same currentMethod if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) continue; // Skip the otherInheritedMethod if it is completely replaced by inheritedMethod // This elimination used to happen rather eagerly in computeInheritedMethods step // itself earlier. (https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358) if (inheritedMethod.declaringClass != otherInheritedMethod.declaringClass) { // these method calls produce their effect as side-effects into skip and isOverridden: if (isSkippableOrOverridden(inheritedMethod, otherInheritedMethod, skip, isOverridden, j)) continue; if (isSkippableOrOverridden(otherInheritedMethod, inheritedMethod, skip, isOverridden, i)) continue; } } } // second round: collect and check matchingInherited, directly check methods with no replacing etc. for (int i = 0; i < inheritedLength; i++) { MethodBinding matchMethod = foundMatch[i]; if (skip[i]) continue; MethodBinding inheritedMethod = inherited[i]; if (matchMethod == null) matchingInherited[++index] = inheritedMethod; for (int j = i + 1; j < inheritedLength; j++) { if (foundMatch[j] == null) { MethodBinding otherInheritedMethod = inherited[j]; if (matchMethod == foundMatch[j] && matchMethod != null) continue; // both inherited methods matched the same currentMethod if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) continue; MethodBinding replaceMatch; if ((replaceMatch = findReplacedMethod(inheritedMethod, otherInheritedMethod)) != null) { matchingInherited[++index] = replaceMatch; skip[j] = true; } else if ((replaceMatch = findReplacedMethod(otherInheritedMethod, inheritedMethod)) != null) { matchingInherited[++index] = replaceMatch; skip[j] = true; } else if (matchMethod == null) { // none replaced by the other, check these methods against each other now: checkInheritedMethods(inheritedMethod, otherInheritedMethod); } } } if (index == -1) continue; if (index > 0) checkInheritedMethods(matchingInherited, index + 1, isOverridden); // pass in the length of matching else if (mustImplementAbstractMethods && matchingInherited[0].isAbstract() && matchMethod == null) checkAbstractMethod(matchingInherited[0]); while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods } } } /* mark as skippable * - any interface method implemented by a class method * - an x method (x in {class, interface}), for which another x method with a subsignature was found * mark as isOverridden * - any skippable method as defined above iff it is actually overridden by the specific method (disregarding visibility etc.) * Note, that 'idx' corresponds to the position of 'general' in the arrays 'skip' and 'isOverridden' * TODO(stephan) currently (as of Bug 410325), the boarder between skip and isOverridden is blurred, * should reassess after more experience with this patch. */ boolean isSkippableOrOverridden(MethodBinding specific, MethodBinding general, boolean[] skip, boolean[] isOverridden, int idx) { boolean specificIsInterface = specific.declaringClass.isInterface(); boolean generalIsInterface = general.declaringClass.isInterface(); if (!specificIsInterface && generalIsInterface) { if (isInterfaceMethodImplemented(general, specific, general.declaringClass)) { skip[idx] = true; isOverridden[idx] = true; return true; } } else if (specificIsInterface == generalIsInterface) { if (specific.declaringClass.isCompatibleWith(general.declaringClass) && isMethodSubsignature(specific, general)) { skip[idx] = true; isOverridden[idx] = true; return true; } } return false; } /* 'general' is considered as replaced by 'specific' if * - 'specific' is "at least as concrete as" 'general' * - 'specific' has a signature that is a subsignature of the substituted signature of 'general' (as seen from specific's declaring class) */ MethodBinding findReplacedMethod(MethodBinding specific, MethodBinding general) { MethodBinding generalSubstitute = computeSubstituteMethod(general, specific); if (generalSubstitute != null && (!specific.isAbstract() || general.isAbstract()) // if (abstract(specific) => abstract(general)) check if 'specific' overrides 'general' && isSubstituteParameterSubsignature(specific, generalSubstitute)) { return generalSubstitute; } return null; } void checkTypeVariableMethods(TypeParameter typeParameter) { char[][] methodSelectors = this.inheritedMethods.keyTable; nextSelector : for (int s = methodSelectors.length; --s >= 0;) { if (methodSelectors[s] == null) continue nextSelector; MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s]; if (inherited.length == 1) continue nextSelector; int index = -1; MethodBinding[] matchingInherited = new MethodBinding[inherited.length]; for (int i = 0, length = inherited.length; i < length; i++) { while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods MethodBinding inheritedMethod = inherited[i]; if (inheritedMethod != null) { matchingInherited[++index] = inheritedMethod; for (int j = i + 1; j < length; j++) { MethodBinding otherInheritedMethod = inherited[j]; if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) continue; otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); if (otherInheritedMethod != null && isSubstituteParameterSubsignature(inheritedMethod, otherInheritedMethod)) { matchingInherited[++index] = otherInheritedMethod; inherited[j] = null; // do not want to find it again } } } if (index > 0) { MethodBinding first = matchingInherited[0]; int count = index + 1; while (--count > 0) { MethodBinding match = matchingInherited[count]; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=314556 MethodBinding interfaceMethod = null, implementation = null; if (first.declaringClass.isInterface()) { interfaceMethod = first; } else if (first.declaringClass.isClass()) { implementation = first; } if (match.declaringClass.isInterface()) { interfaceMethod = match; } else if (match.declaringClass.isClass()) { implementation = match; } if (interfaceMethod != null && implementation != null && !isAsVisible(implementation, interfaceMethod)) problemReporter().inheritedMethodReducesVisibility(typeParameter, implementation, new MethodBinding [] {interfaceMethod}); if (areReturnTypesCompatible(first, match)) continue; // unrelated interfaces - check to see if return types are compatible if (first.declaringClass.isInterface() && match.declaringClass.isInterface() && areReturnTypesCompatible(match, first)) continue; break; } if (count > 0) { // All inherited methods do NOT have the same vmSignature problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(typeParameter, matchingInherited, index + 1); continue nextSelector; } } } } } MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { if (inheritedMethod == null) return null; if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match // due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved if (currentMethod.declaringClass instanceof BinaryTypeBinding) ((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod); if (inheritedMethod.declaringClass instanceof BinaryTypeBinding) ((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod); TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables; int inheritedLength = inheritedTypeVariables.length; if (inheritedLength == 0) return inheritedMethod; // no substitution needed TypeVariableBinding[] typeVariables = currentMethod.typeVariables; int length = typeVariables.length; if (length == 0) return inheritedMethod.asRawMethod(this.environment); if (length != inheritedLength) return inheritedMethod; // no match JLS 8.4.2 // interface I { void foo(T t); } // class X implements I { public void foo(T t) {} } // for the above case, we do not want to answer the substitute method since its not a match TypeBinding[] arguments = new TypeBinding[length]; System.arraycopy(typeVariables, 0, arguments, 0, length); ParameterizedGenericMethodBinding substitute = this.environment.createParameterizedGenericMethod(inheritedMethod, arguments); for (int i = 0; i < inheritedLength; i++) { TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables[i]; TypeBinding argument = arguments[i]; if (argument instanceof TypeVariableBinding) { TypeVariableBinding typeVariable = (TypeVariableBinding) argument; if (typeVariable.firstBound == inheritedTypeVariable.firstBound) { if (typeVariable.firstBound == null) continue; // both are null } else if (typeVariable.firstBound != null && inheritedTypeVariable.firstBound != null) { if (typeVariable.firstBound.isClass() != inheritedTypeVariable.firstBound.isClass()) return inheritedMethod; // not a match } if (Scope.substitute(substitute, inheritedTypeVariable.superclass) != typeVariable.superclass) return inheritedMethod; // not a match int interfaceLength = inheritedTypeVariable.superInterfaces.length; ReferenceBinding[] interfaces = typeVariable.superInterfaces; if (interfaceLength != interfaces.length) return inheritedMethod; // not a match next : for (int j = 0; j < interfaceLength; j++) { TypeBinding superType = Scope.substitute(substitute, inheritedTypeVariable.superInterfaces[j]); for (int k = 0; k < interfaceLength; k++) if (superType == interfaces[k]) continue next; return inheritedMethod; // not a match } } else if (inheritedTypeVariable.boundCheck(substitute, argument, this.type.scope) != TypeConstants.OK) { return inheritedMethod; } } return substitute; } boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) { if (!inherited.areParameterErasuresEqual(otherInherited)) return false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=322001 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=323693 // When reporting a name clash between two inherited methods, we should not look for a // signature clash, but instead should be looking for method descriptor clash. if (inherited.returnType.erasure() != otherInherited.returnType.erasure()) return false; // skip it if otherInherited is defined by a subtype of inherited's declaringClass or vice versa. // avoid being order sensitive and check with the roles reversed also. if (inherited.declaringClass.erasure() != otherInherited.declaringClass.erasure()) { if (inherited.declaringClass.findSuperTypeOriginatingFrom(otherInherited.declaringClass) != null) return false; if (otherInherited.declaringClass.findSuperTypeOriginatingFrom(inherited.declaringClass) != null) return false; } problemReporter().inheritedMethodsHaveNameClash(this.type, inherited, otherInherited); return true; } boolean detectNameClash(MethodBinding current, MethodBinding inherited, boolean treatAsSynthetic) { MethodBinding methodToCheck = inherited; MethodBinding original = methodToCheck.original(); // can be the same as inherited if (!current.areParameterErasuresEqual(original)) return false; int severity = ProblemSeverities.Error; if (this.environment.globalOptions.complianceLevel == ClassFileConstants.JDK1_6) { // for 1.6 return types also need to be checked // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317719 if (current.returnType.erasure() != original.returnType.erasure()) severity = ProblemSeverities.Warning; } if (!treatAsSynthetic) { // For a user method, see if current class overrides the inherited method. If it does, // then any grievance we may have ought to be against the current class's method and // NOT against any super implementations. https://bugs.eclipse.org/bugs/show_bug.cgi?id=293615 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=315978 : we now defer this rather expensive // check to just before reporting (the incorrect) name clash. In the event there is no name // clash to report to begin with (the common case), no penalty needs to be paid. MethodBinding[] currentNamesakes = (MethodBinding[]) this.currentMethods.get(inherited.selector); if (currentNamesakes.length > 1) { // we know it ought to at least one and that current is NOT the override for (int i = 0, length = currentNamesakes.length; i < length; i++) { MethodBinding currentMethod = currentNamesakes[i]; if (currentMethod != current && doesMethodOverride(currentMethod, inherited)) { methodToCheck = currentMethod; break; } } } } original = methodToCheck.original(); // can be the same as inherited if (!current.areParameterErasuresEqual(original)) return false; original = inherited.original(); // For error reporting use, inherited.original() problemReporter(current).methodNameClash(current, inherited.declaringClass.isRawType() ? inherited : original, severity); if (severity == ProblemSeverities.Warning) return false; return true; } public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod); } boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) { // one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod() return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding); } SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; ReferenceBinding[] itsInterfaces = superInterfaces; if (itsInterfaces != Binding.NO_SUPERINTERFACES) { nextPosition = itsInterfaces.length; interfacesToVisit = itsInterfaces; } boolean isInconsistent = this.type.isHierarchyInconsistent(); ReferenceBinding superType = superclass; while (superType != null && superType.isValidBinding()) { isInconsistent |= superType.isHierarchyInconsistent(); if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } superType = superType.superclass(); } for (int i = 0; i < nextPosition; i++) { superType = interfacesToVisit[i]; if (superType.isValidBinding()) { isInconsistent |= superType.isHierarchyInconsistent(); if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } if (!isInconsistent) return null; // hierarchy is consistent so no collisions are possible SimpleSet copy = null; for (int i = 0; i < nextPosition; i++) { ReferenceBinding current = interfacesToVisit[i]; if (current.isValidBinding()) { TypeBinding erasure = current.erasure(); for (int j = i + 1; j < nextPosition; j++) { ReferenceBinding next = interfacesToVisit[j]; if (next.isValidBinding() && next.erasure() == erasure) { if (copy == null) copy = new SimpleSet(nextPosition); copy.add(interfacesToVisit[i]); copy.add(interfacesToVisit[j]); } } } } return copy; } boolean hasGenericParameter(MethodBinding method) { if (method.genericSignature() == null) return false; // may be only the return type that is generic, need to check parameters TypeBinding[] params = method.parameters; for (int i = 0, l = params.length; i < l; i++) { TypeBinding param = params[i].leafComponentType(); if (param instanceof ReferenceBinding) { int modifiers = ((ReferenceBinding) param).modifiers; if ((modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) return true; } } return false; } boolean isAcceptableReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { // called when currentMethod's return type is compatible with inheritedMethod's return type if (inheritedMethod.declaringClass.isRawType()) return true; // since the inheritedMethod comes from a raw type, the return type is always acceptable MethodBinding originalInherited = inheritedMethod.original(); TypeBinding originalInheritedReturnType = originalInherited.returnType.leafComponentType(); if (originalInheritedReturnType.isParameterizedTypeWithActualArguments()) return !currentMethod.returnType.leafComponentType().isRawType(); // raw types issue a warning if inherited is parameterized TypeBinding currentReturnType = currentMethod.returnType.leafComponentType(); switch (currentReturnType.kind()) { case Binding.TYPE_PARAMETER : if (currentReturnType == inheritedMethod.returnType.leafComponentType()) return true; //$FALL-THROUGH$ default : if (originalInheritedReturnType.isTypeVariable()) if (((TypeVariableBinding) originalInheritedReturnType).declaringElement == originalInherited) return false; return true; } } // caveat: returns false if a method is implemented that needs a bridge method boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) { if (inheritedMethod.original() != inheritedMethod && existingMethod.declaringClass.isInterface()) return false; // must hold onto ParameterizedMethod to see if a bridge method is necessary inheritedMethod = computeSubstituteMethod(inheritedMethod, existingMethod); return inheritedMethod != null && inheritedMethod.returnType == existingMethod.returnType // keep around to produce bridge methods && doesMethodOverride(existingMethod, inheritedMethod); } public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) { if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)) return false; // need to switch back to the original if the method is from a ParameterizedType if (method.declaringClass.isParameterizedType()) method = method.original(); MethodBinding inheritedOriginal = method.findOriginalInheritedMethod(inheritedMethod); return isParameterSubsignature(method, inheritedOriginal == null ? inheritedMethod : inheritedOriginal); } boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method); return substitute != null && isSubstituteParameterSubsignature(method, substitute); } // if method "overrides" substituteMethod then we can skip over substituteMethod while resolving a message send // if it does not then a name clash error is likely boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod) { if (!areParametersEqual(method, substituteMethod)) { // method can still override substituteMethod in cases like : // void c(U u) {} // @Override void c(Number n) {} // but method cannot have a "generic-enabled" parameter type if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod)) return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=279836 if (method.declaringClass.isRawType() && substituteMethod.declaringClass.isRawType()) if (method.hasSubstitutedParameters() && substituteMethod.hasSubstitutedParameters()) return areMethodsCompatible(method, substituteMethod); return false; } if (substituteMethod instanceof ParameterizedGenericMethodBinding) { if (method.typeVariables != Binding.NO_TYPE_VARIABLES) return !((ParameterizedGenericMethodBinding) substituteMethod).isRaw; // since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does return !hasGenericParameter(method); } // if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod() return method.typeVariables == Binding.NO_TYPE_VARIABLES; } boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { // called when currentMethod's return type is NOT compatible with inheritedMethod's return type // JLS 3 �8.4.5: more are accepted, with an unchecked conversion if (currentMethod.returnType == inheritedMethod.returnType.erasure()) { TypeBinding[] currentParams = currentMethod.parameters; TypeBinding[] inheritedParams = inheritedMethod.parameters; for (int i = 0, l = currentParams.length; i < l; i++) if (!areTypesEqual(currentParams[i], inheritedParams[i])) return true; } if (currentMethod.typeVariables == Binding.NO_TYPE_VARIABLES && inheritedMethod.original().typeVariables != Binding.NO_TYPE_VARIABLES && currentMethod.returnType.erasure().findSuperTypeOriginatingFrom(inheritedMethod.returnType.erasure()) != null) { return true; } return false; } boolean reportIncompatibleReturnTypeError(MethodBinding currentMethod, MethodBinding inheritedMethod) { if (isUnsafeReturnTypeOverride(currentMethod, inheritedMethod)) { problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, inheritedMethod, this.type); return false; } return super.reportIncompatibleReturnTypeError(currentMethod, inheritedMethod); } void verify() { if (this.type.isAnnotationType()) this.type.detectAnnotationCycle(); super.verify(); reportRawReferences(); for (int i = this.type.typeVariables.length; --i >= 0;) { TypeVariableBinding var = this.type.typeVariables[i]; // must verify bounds if the variable has more than 1 if (var.superInterfaces == Binding.NO_SUPERINTERFACES) continue; if (var.superInterfaces.length == 1 && var.superclass.id == TypeIds.T_JavaLangObject) continue; this.currentMethods = new HashtableOfObject(0); ReferenceBinding superclass = var.superclass(); if (superclass.kind() == Binding.TYPE_PARAMETER) superclass = (ReferenceBinding) superclass.erasure(); ReferenceBinding[] itsInterfaces = var.superInterfaces(); ReferenceBinding[] superInterfaces = new ReferenceBinding[itsInterfaces.length]; for (int j = itsInterfaces.length; --j >= 0;) { superInterfaces[j] = itsInterfaces[j].kind() == Binding.TYPE_PARAMETER ? (ReferenceBinding) itsInterfaces[j].erasure() : itsInterfaces[j]; } computeInheritedMethods(superclass, superInterfaces); checkTypeVariableMethods(this.type.scope.referenceContext.typeParameters[i]); } } } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/CatchParameterBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/CatchParameterBinding.ja0000644000175000001440000000267312212041344032275 0ustar dokousers/******************************************************************************* * Copyright (c) 2003, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; public class CatchParameterBinding extends LocalVariableBinding { TypeBinding [] preciseTypes = Binding.NO_EXCEPTIONS; // the catch block can be entered with the parameters set to these types. public CatchParameterBinding(LocalDeclaration declaration, TypeBinding type, int modifiers, boolean isArgument) { super(declaration, type, modifiers, isArgument); } public TypeBinding [] getPreciseTypes() { return this.preciseTypes; } public void setPreciseType(TypeBinding raisedException) { int length = this.preciseTypes.length; for (int i = 0; i < length; ++i) { if (this.preciseTypes[i] == raisedException) return; } System.arraycopy(this.preciseTypes, 0, this.preciseTypes = new TypeBinding [length + 1], 0, length); this.preciseTypes[length] = raisedException; return; } }ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/InferenceContext.java0000644000175000001440000001225112212041344031702 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; /** * Context used during type inference for a generic method invocation */ public class InferenceContext { private TypeBinding[][][] collectedSubstitutes; MethodBinding genericMethod; int depth; int status; TypeBinding expectedType; boolean hasExplicitExpectedType; // indicates whether the expectedType (if set) was explicit in code, or set by default public boolean isUnchecked; TypeBinding[] substitutes; final static int FAILED = 1; public InferenceContext(MethodBinding genericMethod) { this.genericMethod = genericMethod; TypeVariableBinding[] typeVariables = genericMethod.typeVariables; int varLength = typeVariables.length; this.collectedSubstitutes = new TypeBinding[varLength][3][]; this.substitutes = new TypeBinding[varLength]; } public TypeBinding[] getSubstitutes(TypeVariableBinding typeVariable, int constraint) { return this.collectedSubstitutes[typeVariable.rank][constraint]; } /** * Returns true if any unresolved variable is detected, i.e. any variable is substituted with itself */ public boolean hasUnresolvedTypeArgument() { for (int i = 0, varLength = this.substitutes.length; i :"); //$NON-NLS-1$ break; } if (constraintCollected[k] != null) { buffer.append(constraintCollected[k].shortReadableName()); } } } } } buffer.append("}]");//$NON-NLS-1$ buffer.append("\n\t[inferred=");//$NON-NLS-1$ int count = 0; for (int i = 0, length = this.substitutes == null ? 0 : this.substitutes.length; i < length; i++) { if (this.substitutes[i] == null) continue; count++; buffer.append('{').append(this.genericMethod.typeVariables[i].sourceName); buffer.append("=").append(this.substitutes[i].shortReadableName()).append('}'); //$NON-NLS-1$ } if (count == 0) buffer.append("{}"); //$NON-NLS-1$ buffer.append(']'); return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemFieldBinding.java0000644000175000001440000000246212212041344032301 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; public class ProblemFieldBinding extends FieldBinding { private int problemId; public FieldBinding closestMatch; // NOTE: must only answer the subset of the name related to the problem public ProblemFieldBinding(ReferenceBinding declaringClass, char[] name, int problemId) { this(null, declaringClass, name, problemId); } public ProblemFieldBinding(FieldBinding closestMatch, ReferenceBinding declaringClass, char[] name, int problemId) { this.closestMatch = closestMatch; this.declaringClass = declaringClass; this.name = name; this.problemId = problemId; } /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. */ public final int problemId() { return this.problemId; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java0000644000175000001440000017001212212041344030476 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * Bug 328281 - visibility leaks not detected when analyzing unused field in private class * Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries * Bug 354536 - compiling package-info.java still depends on the order of compilation units * Bug 349326 - [1.7] new warning for missing try-with-resources * Bug 358903 - Filter practically unimportant resource leak warnings * Bug 395977 - [compiler][resource] Resource leak warning behavior possibly incorrect for anonymous inner class * Bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.HashMap; import java.util.Iterator; import java.util.Map; 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.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; 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.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; public TypeReference superTypeReference; java.util.ArrayList deferredBoundChecks; public ClassScope(Scope parent, TypeDeclaration context) { super(Scope.CLASS_SCOPE, parent); this.referenceContext = context; this.deferredBoundChecks = null; // initialized if required } void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) { LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage); anonymousType.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; // tag all anonymous types as used locally int inheritedBits = supertype.typeBits; // for anonymous class assume same properties as its super (as a closeable) ... // ... unless it overrides close(): if ((inheritedBits & TypeIds.BitWrapperCloseable) != 0) { AbstractMethodDeclaration[] methods = this.referenceContext.methods; if (methods != null) { for (int i=0; i= ClassFileConstants.JDK1_5) { checkParameterizedTypeBounds(); checkParameterizedSuperTypeCollisions(); } buildFieldsAndMethods(); localType.faultInTypesForFieldsAndMethods(); this.referenceContext.binding.verifyMethods(environment().methodVerifier()); } private void buildMemberTypes(AccessRestriction accessRestriction) { SourceTypeBinding sourceType = this.referenceContext.binding; ReferenceBinding[] memberTypeBindings = Binding.NO_MEMBER_TYPES; if (this.referenceContext.memberTypes != null) { int length = this.referenceContext.memberTypes.length; memberTypeBindings = new ReferenceBinding[length]; int count = 0; nextMember : for (int i = 0; i < length; i++) { TypeDeclaration memberContext = this.referenceContext.memberTypes[i]; switch(TypeDeclaration.kind(memberContext.modifiers)) { case TypeDeclaration.INTERFACE_DECL : case TypeDeclaration.ANNOTATION_TYPE_DECL : if (sourceType.isNestedType() && sourceType.isClass() // no need to check for enum, since implicitly static && !sourceType.isStatic()) { problemReporter().illegalLocalTypeDeclaration(memberContext); continue nextMember; } break; } ReferenceBinding type = sourceType; // check that the member does not conflict with an enclosing type do { if (CharOperation.equals(type.sourceName, memberContext.name)) { problemReporter().typeCollidesWithEnclosingType(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(this.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; } void buildMethods() { SourceTypeBinding sourceType = this.referenceContext.binding; if (sourceType.areMethodsInitialized()) return; boolean isEnum = TypeDeclaration.kind(this.referenceContext.modifiers) == TypeDeclaration.ENUM_DECL; if (this.referenceContext.methods == null && !isEnum) { this.referenceContext.binding.setMethods(Binding.NO_METHODS); return; } // iterate the method declarations to create the bindings AbstractMethodDeclaration[] methods = this.referenceContext.methods; int size = methods == null ? 0 : methods.length; // look for method int clinitIndex = -1; for (int i = 0; i < size; i++) { if (methods[i].isClinit()) { clinitIndex = i; break; } } 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) { methodBindings[0] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUES); // add [] values() methodBindings[1] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUEOF); // add valueOf() } // create bindings for source methods boolean hasNativeMethods = false; if (sourceType.isAbstract()) { for (int i = 0; i < size; i++) { if (i != clinitIndex) { MethodScope scope = new MethodScope(this, methods[i], false); MethodBinding methodBinding = scope.createMethod(methods[i]); if (methodBinding != null) { // is null if binding could not be created methodBindings[count++] = methodBinding; hasNativeMethods = hasNativeMethods || methodBinding.isNative(); } } } } else { boolean hasAbstractMethods = false; for (int i = 0; i < size; i++) { if (i != clinitIndex) { MethodScope scope = new MethodScope(this, methods[i], false); MethodBinding methodBinding = scope.createMethod(methods[i]); if (methodBinding != null) { // is null if binding could not be created methodBindings[count++] = methodBinding; hasAbstractMethods = hasAbstractMethods || methodBinding.isAbstract(); hasNativeMethods = hasNativeMethods || methodBinding.isNative(); } } } if (hasAbstractMethods) problemReporter().abstractMethodInConcreteClass(sourceType); } if (count != methodBindings.length) System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count); sourceType.tagBits &= ~(TagBits.AreMethodsSorted|TagBits.AreMethodsComplete); // in case some static imports reached already into this type sourceType.setMethods(methodBindings); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=243917, conservatively tag all methods and fields as // being in use if there is a native method in the class. if (hasNativeMethods) { for (int i = 0; i < methodBindings.length; i++) { methodBindings[i].modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } FieldBinding[] fields = sourceType.unResolvedFields(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=301683 for (int i = 0; i < fields.length; i++) { fields[i].modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding, AccessRestriction accessRestriction) { // provide the typeDeclaration with needed scopes this.referenceContext.scope = this; this.referenceContext.staticInitializerScope = new MethodScope(this, this.referenceContext, true); this.referenceContext.initializerScope = new MethodScope(this, this.referenceContext, false); if (enclosingType == null) { char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, this.referenceContext.name); this.referenceContext.binding = new SourceTypeBinding(className, packageBinding, this); } else { char[][] className = CharOperation.deepCopy(enclosingType.compoundName); className[className.length - 1] = CharOperation.concat(className[className.length - 1], this.referenceContext.name, '$'); ReferenceBinding existingType = packageBinding.getType0(className[className.length - 1]); if (existingType != null) { if (existingType instanceof UnresolvedReferenceBinding) { // its possible that a BinaryType referenced the member type before its enclosing source type was built // so just replace the unresolved type with a new member type } else { // report the error against the parent - its still safe to answer the member type this.parent.problemReporter().duplicateNestedType(this.referenceContext); } } this.referenceContext.binding = new MemberTypeBinding(className, this, enclosingType); } SourceTypeBinding sourceType = this.referenceContext.binding; environment().setAccessRestriction(sourceType, accessRestriction); sourceType.fPackage.addType(sourceType); checkAndSetModifiers(); buildTypeVariables(); buildMemberTypes(accessRestriction); return sourceType; } private void buildTypeVariables() { SourceTypeBinding sourceType = this.referenceContext.binding; TypeParameter[] typeParameters = this.referenceContext.typeParameters; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, If they exist at all, process type parameters irrespective of source level. if (typeParameters == null || typeParameters.length == 0) { sourceType.typeVariables = Binding.NO_TYPE_VARIABLES; return; } sourceType.typeVariables = Binding.NO_TYPE_VARIABLES; // safety if (sourceType.id == TypeIds.T_JavaLangObject) { // handle the case of redefining java.lang.Object up front problemReporter().objectCannotBeGeneric(this.referenceContext); return; } sourceType.typeVariables = createTypeVariables(typeParameters, sourceType); sourceType.modifiers |= ExtraCompilerModifiers.AccGenericSignature; } private void checkAndSetModifiers() { SourceTypeBinding sourceType = this.referenceContext.binding; int modifiers = sourceType.modifiers; if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) problemReporter().duplicateModifierForType(sourceType); ReferenceBinding enclosingType = sourceType.enclosingType(); boolean isMemberType = sourceType.isMemberType(); if (isMemberType) { modifiers |= (enclosingType.modifiers & (ExtraCompilerModifiers.AccGenericSignature|ClassFileConstants.AccStrictfp)); // checks for member types before local types to catch local members if (enclosingType.isInterface()) modifiers |= ClassFileConstants.AccPublic; if (sourceType.isEnum()) { if (!enclosingType.isStatic()) problemReporter().nonStaticContextForEnumMemberType(sourceType); else modifiers |= ClassFileConstants.AccStatic; } } else if (sourceType.isLocalType()) { if (sourceType.isEnum()) { problemReporter().illegalLocalTypeDeclaration(this.referenceContext); sourceType.modifiers = 0; return; } if (sourceType.isAnonymousType()) { modifiers |= ClassFileConstants.AccFinal; // set AccEnum flag for anonymous body of enum constants if (this.referenceContext.allocation.type == null) modifiers |= ClassFileConstants.AccEnum; } Scope scope = this; do { switch (scope.kind) { case METHOD_SCOPE : MethodScope methodScope = (MethodScope) scope; if (methodScope.isInsideInitializer()) { SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding; // inside field declaration ? check field modifier to see if deprecated if (methodScope.initializedField != null) { // currently inside this field initialization if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()) modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; } else { if (type.isStrictfp()) modifiers |= ClassFileConstants.AccStrictfp; if (type.isViewedAsDeprecated() && !sourceType.isDeprecated()) modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; } } else { MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding; if (method != null) { if (method.isStrictfp()) modifiers |= ClassFileConstants.AccStrictfp; if (method.isViewedAsDeprecated() && !sourceType.isDeprecated()) modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; } } break; case CLASS_SCOPE : // local member if (enclosingType.isStrictfp()) modifiers |= ClassFileConstants.AccStrictfp; if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated()) modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; break; } scope = scope.parent; } while (scope != null); } // after this point, tests on the 16 bits reserved. int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; if ((realModifiers & ClassFileConstants.AccInterface) != 0) { // interface and annotation type // detect abnormal cases for interfaces if (isMemberType) { final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccStrictfp | ClassFileConstants.AccAnnotation); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { if ((realModifiers & ClassFileConstants.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); if ((realModifiers & unexpectedModifiers) != 0) problemReporter().illegalModifierForLocalInterface(sourceType); */ } else { final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccStrictfp | ClassFileConstants.AccAnnotation); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { if ((realModifiers & ClassFileConstants.AccAnnotation) != 0) problemReporter().illegalModifierForAnnotationType(sourceType); else problemReporter().illegalModifierForInterface(sourceType); } } /* * AccSynthetic must be set if the target is greater than 1.5. 1.5 VM don't support AccSynthetics flag. */ if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME && compilerOptions().targetJDK > ClassFileConstants.JDK1_5) { modifiers |= ClassFileConstants.AccSynthetic; } modifiers |= ClassFileConstants.AccAbstract; } else if ((realModifiers & ClassFileConstants.AccEnum) != 0) { // detect abnormal cases for enums if (isMemberType) { // includes member types defined inside local types final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStatic | ClassFileConstants.AccStrictfp | ClassFileConstants.AccEnum); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { problemReporter().illegalModifierForMemberEnum(sourceType); modifiers &= ~ClassFileConstants.AccAbstract; // avoid leaking abstract modifier realModifiers &= ~ClassFileConstants.AccAbstract; // modifiers &= ~(realModifiers & UNEXPECTED_MODIFIERS); // realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; } } else if (sourceType.isLocalType()) { // each enum constant is an anonymous local type and its modifiers were already checked as an enum constant field } else { final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccStrictfp | ClassFileConstants.AccEnum); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) problemReporter().illegalModifierForEnum(sourceType); } if (!sourceType.isAnonymousType()) { checkAbstractEnum: { // does define abstract methods ? if ((this.referenceContext.bits & ASTNode.HasAbstractMethods) != 0) { modifiers |= ClassFileConstants.AccAbstract; break checkAbstractEnum; } // body of enum constant must implement any inherited abstract methods // enum type needs to implement abstract methods if one of its constants does not supply a body TypeDeclaration typeDeclaration = this.referenceContext; FieldDeclaration[] fields = typeDeclaration.fields; int fieldsLength = fields == null ? 0 : fields.length; if (fieldsLength == 0) break checkAbstractEnum; // has no constants so must implement the method itself AbstractMethodDeclaration[] methods = typeDeclaration.methods; int methodsLength = methods == null ? 0 : methods.length; // TODO (kent) cannot tell that the superinterfaces are empty or that their methods are implemented boolean definesAbstractMethod = typeDeclaration.superInterfaces != null; for (int i = 0; i < methodsLength && !definesAbstractMethod; i++) definesAbstractMethod = methods[i].isAbstract(); if (!definesAbstractMethod) break checkAbstractEnum; // all methods have bodies boolean needAbstractBit = false; for (int i = 0; i < fieldsLength; i++) { FieldDeclaration fieldDecl = fields[i]; if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { if (fieldDecl.initialization instanceof QualifiedAllocationExpression) { needAbstractBit = true; } else { break checkAbstractEnum; } } } // tag this enum as abstract since an abstract method must be implemented AND all enum constants define an anonymous body // as a result, each of its anonymous constants will see it as abstract and must implement each inherited abstract method if (needAbstractBit) { modifiers |= ClassFileConstants.AccAbstract; } } // final if no enum constant with anonymous body checkFinalEnum: { TypeDeclaration typeDeclaration = this.referenceContext; FieldDeclaration[] fields = typeDeclaration.fields; if (fields != null) { for (int i = 0, fieldsLength = fields.length; i < fieldsLength; i++) { FieldDeclaration fieldDecl = fields[i]; if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { if (fieldDecl.initialization instanceof QualifiedAllocationExpression) { break checkFinalEnum; } } } } modifiers |= ClassFileConstants.AccFinal; } } } else { // detect abnormal cases for classes if (isMemberType) { // includes member types defined inside local types final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract | ClassFileConstants.AccFinal | ClassFileConstants.AccStrictfp); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) problemReporter().illegalModifierForMemberClass(sourceType); } else if (sourceType.isLocalType()) { final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccFinal | ClassFileConstants.AccStrictfp); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) problemReporter().illegalModifierForLocalClass(sourceType); } else { final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ClassFileConstants.AccFinal | ClassFileConstants.AccStrictfp); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) problemReporter().illegalModifierForClass(sourceType); } // check that Final and Abstract are not set together if ((realModifiers & (ClassFileConstants.AccFinal | ClassFileConstants.AccAbstract)) == (ClassFileConstants.AccFinal | ClassFileConstants.AccAbstract)) problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType); } if (isMemberType) { // test visibility modifiers inconsistency, isolate the accessors bits if (enclosingType.isInterface()) { if ((realModifiers & (ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate)) != 0) { problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType); // need to keep the less restrictive if ((realModifiers & ClassFileConstants.AccProtected) != 0) modifiers &= ~ClassFileConstants.AccProtected; if ((realModifiers & ClassFileConstants.AccPrivate) != 0) modifiers &= ~ClassFileConstants.AccPrivate; } } else { int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); if ((accessorBits & (accessorBits - 1)) > 1) { problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType); // need to keep the less restrictive so disable Protected/Private as necessary if ((accessorBits & ClassFileConstants.AccPublic) != 0) { if ((accessorBits & ClassFileConstants.AccProtected) != 0) modifiers &= ~ClassFileConstants.AccProtected; if ((accessorBits & ClassFileConstants.AccPrivate) != 0) modifiers &= ~ClassFileConstants.AccPrivate; } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { modifiers &= ~ClassFileConstants.AccPrivate; } } } // static modifier test if ((realModifiers & ClassFileConstants.AccStatic) == 0) { if (enclosingType.isInterface()) modifiers |= ClassFileConstants.AccStatic; } else if (!enclosingType.isStatic()) { // error the enclosing type of a static field must be static or a top-level type problemReporter().illegalStaticModifierForMemberType(sourceType); } } sourceType.modifiers = modifiers; } /* This method checks the modifiers of a field. * * 9.3 & 8.3 * Need to integrate the check for the final modifiers for nested types * * Note : A scope is accessible by : fieldBinding.declaringClass.scope */ private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) { int modifiers = fieldBinding.modifiers; final ReferenceBinding declaringClass = fieldBinding.declaringClass; if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) problemReporter().duplicateModifierForField(declaringClass, fieldDecl); if (declaringClass.isInterface()) { final int IMPLICIT_MODIFIERS = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal; // set the modifiers modifiers |= IMPLICIT_MODIFIERS; // and then check that they are the only ones if ((modifiers & ExtraCompilerModifiers.AccJustFlag) != IMPLICIT_MODIFIERS) { if ((declaringClass.modifiers & ClassFileConstants.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 & ExtraCompilerModifiers.AccJustFlag) != 0) problemReporter().illegalModifierForEnumConstant(declaringClass, fieldDecl); // set the modifiers // https://bugs.eclipse.org/bugs/show_bug.cgi?id=267670. Force all enumerators to be marked // as used locally. We are unable to track the usage of these reliably as they could be used // in non obvious ways via the synthesized methods values() and valueOf(String) or by using // Enum.valueOf(Class, String). final int IMPLICIT_MODIFIERS = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccEnum | ExtraCompilerModifiers.AccLocallyUsed; fieldBinding.modifiers|= IMPLICIT_MODIFIERS; return; } // after this point, tests on the 16 bits reserved. int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccFinal | ClassFileConstants.AccStatic | ClassFileConstants.AccTransient | ClassFileConstants.AccVolatile); if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { problemReporter().illegalModifierForField(declaringClass, fieldDecl); modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS; } int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); if ((accessorBits & (accessorBits - 1)) > 1) { problemReporter().illegalVisibilityModifierCombinationForField(declaringClass, fieldDecl); // need to keep the less restrictive so disable Protected/Private as necessary if ((accessorBits & ClassFileConstants.AccPublic) != 0) { if ((accessorBits & ClassFileConstants.AccProtected) != 0) modifiers &= ~ClassFileConstants.AccProtected; if ((accessorBits & ClassFileConstants.AccPrivate) != 0) modifiers &= ~ClassFileConstants.AccPrivate; } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { modifiers &= ~ClassFileConstants.AccPrivate; } } if ((realModifiers & (ClassFileConstants.AccFinal | ClassFileConstants.AccVolatile)) == (ClassFileConstants.AccFinal | ClassFileConstants.AccVolatile)) problemReporter().illegalModifierCombinationFinalVolatileForField(declaringClass, fieldDecl); if (fieldDecl.initialization == null && (modifiers & ClassFileConstants.AccFinal) != 0) modifiers |= ExtraCompilerModifiers.AccBlankFinal; fieldBinding.modifiers = modifiers; } public void checkParameterizedSuperTypeCollisions() { // check for parameterized interface collisions (when different parameterizations occur) SourceTypeBinding sourceType = this.referenceContext.binding; ReferenceBinding[] interfaces = sourceType.superInterfaces; Map invocations = new HashMap(2); ReferenceBinding itsSuperclass = sourceType.isInterface() ? null : sourceType.superclass; nextInterface: for (int i = 0, length = interfaces.length; i < length; i++) { ReferenceBinding one = interfaces[i]; if (one == null) continue nextInterface; if (itsSuperclass != null && hasErasedCandidatesCollisions(itsSuperclass, one, invocations, sourceType, this.referenceContext)) continue nextInterface; nextOtherInterface: for (int j = 0; j < i; j++) { ReferenceBinding two = interfaces[j]; if (two == null) continue nextOtherInterface; if (hasErasedCandidatesCollisions(one, two, invocations, sourceType, this.referenceContext)) continue nextInterface; } } TypeParameter[] typeParameters = this.referenceContext.typeParameters; nextVariable : for (int i = 0, paramLength = typeParameters == null ? 0 : typeParameters.length; i < paramLength; i++) { TypeParameter typeParameter = typeParameters[i]; TypeVariableBinding typeVariable = typeParameter.binding; if (typeVariable == null || !typeVariable.isValidBinding()) continue nextVariable; TypeReference[] boundRefs = typeParameter.bounds; if (boundRefs != null) { boolean checkSuperclass = typeVariable.firstBound == typeVariable.superclass; for (int j = 0, boundLength = boundRefs.length; j < boundLength; j++) { TypeReference typeRef = boundRefs[j]; TypeBinding superType = typeRef.resolvedType; if (superType == null || !superType.isValidBinding()) continue; // check against superclass if (checkSuperclass) if (hasErasedCandidatesCollisions(superType, typeVariable.superclass, invocations, typeVariable, typeRef)) continue nextVariable; // check against superinterfaces for (int index = typeVariable.superInterfaces.length; --index >= 0;) if (hasErasedCandidatesCollisions(superType, typeVariable.superInterfaces[index], invocations, typeVariable, typeRef)) continue nextVariable; } } } ReferenceBinding[] memberTypes = this.referenceContext.binding.memberTypes; if (memberTypes != null && memberTypes != Binding.NO_MEMBER_TYPES) for (int i = 0, size = memberTypes.length; i < size; i++) ((SourceTypeBinding) memberTypes[i]).scope.checkParameterizedSuperTypeCollisions(); } 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 nextPosition = 0; do { if (currentType.hasMemberTypes()) // avoid resolving member types eagerly return; ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); // in code assist cases when source types are added late, may not be finished connecting hierarchy if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & TagBits.HasNoMemberTypes) == 0); if (interfacesToVisit != null) { // 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 < nextPosition; i++) { ReferenceBinding anInterface = interfacesToVisit[i]; if ((anInterface.tagBits & 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 != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } if (needToTag) { for (int i = 0; i < nextPosition; i++) interfacesToVisit[i].tagBits |= TagBits.HasNoMemberTypes; } } // tag the sourceType and all of its superclasses, unless they have already been tagged currentType = sourceType; do { currentType.tagBits |= TagBits.HasNoMemberTypes; } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & TagBits.HasNoMemberTypes) == 0); } // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected) public void checkParameterizedTypeBounds() { for (int i = 0, l = this.deferredBoundChecks == null ? 0 : this.deferredBoundChecks.size(); i < l; i++) ((TypeReference) this.deferredBoundChecks.get(i)).checkBounds(this); this.deferredBoundChecks = null; ReferenceBinding[] memberTypes = this.referenceContext.binding.memberTypes; if (memberTypes != null && memberTypes != Binding.NO_MEMBER_TYPES) for (int i = 0, size = memberTypes.length; i < size; i++) ((SourceTypeBinding) memberTypes[i]).scope.checkParameterizedTypeBounds(); } private void connectMemberTypes() { SourceTypeBinding sourceType = this.referenceContext.binding; ReferenceBinding[] memberTypes = sourceType.memberTypes; if (memberTypes != null && memberTypes != Binding.NO_MEMBER_TYPES) { for (int i = 0, size = memberTypes.length; i < size; i++) ((SourceTypeBinding) memberTypes[i]).scope.connectTypeHierarchy(); } } /* Our current belief based on available JCK tests is: inherited member types are visible as a potential superclass. inherited interfaces are not visible when defining a superinterface. Error recovery story: ensure the superclass is set to java.lang.Object if a problem is detected resolving the superclass. Answer false if an error was reported against the sourceType. */ private boolean connectSuperclass() { SourceTypeBinding sourceType = this.referenceContext.binding; if (sourceType.id == TypeIds.T_JavaLangObject) { // handle the case of redefining java.lang.Object up front sourceType.superclass = null; sourceType.superInterfaces = Binding.NO_SUPERINTERFACES; if (!sourceType.isClass()) problemReporter().objectMustBeClass(sourceType); if (this.referenceContext.superclass != null || (this.referenceContext.superInterfaces != null && this.referenceContext.superInterfaces.length > 0)) problemReporter().objectCannotHaveSuperTypes(sourceType); return true; // do not propagate Object's hierarchy problems down to every subtype } if (this.referenceContext.superclass == null) { if (sourceType.isEnum() && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error return connectEnumSuperclass(); sourceType.superclass = getJavaLangObject(); return !detectHierarchyCycle(sourceType, sourceType.superclass, null); } TypeReference superclassRef = this.referenceContext.superclass; ReferenceBinding superclass = findSupertype(superclassRef); if (superclass != null) { // is null if a cycle was detected cycle or a problem if (!superclass.isClass() && (superclass.tagBits & TagBits.HasMissingType) == 0) { problemReporter().superclassMustBeAClass(sourceType, superclassRef, superclass); } else if (superclass.isFinal()) { problemReporter().classExtendFinalClass(sourceType, superclassRef, superclass); } else if ((superclass.tagBits & TagBits.HasDirectWildcard) != 0) { problemReporter().superTypeCannotUseWildcard(sourceType, superclassRef, superclass); } else if (superclass.erasure().id == TypeIds.T_JavaLangEnum) { problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass); } else if ((superclass.tagBits & TagBits.HierarchyHasProblems) != 0 || !superclassRef.resolvedType.isValidBinding()) { sourceType.superclass = superclass; sourceType.tagBits |= TagBits.HierarchyHasProblems; // propagate if missing supertype return superclassRef.resolvedType.isValidBinding(); // reported some error against the source type ? } else { // only want to reach here when no errors are reported sourceType.superclass = superclass; sourceType.typeBits |= (superclass.typeBits & TypeIds.InheritableBits); // further analysis against white lists for the unlikely case we are compiling java.io.*: if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) sourceType.typeBits |= sourceType.applyCloseableWhitelists(); return true; } } sourceType.tagBits |= TagBits.HierarchyHasProblems; sourceType.superclass = getJavaLangObject(); if ((sourceType.superclass.tagBits & TagBits.BeginHierarchyCheck) == 0) detectHierarchyCycle(sourceType, sourceType.superclass, null); return false; // reported some error against the source type } /** * enum X (implicitly) extends Enum */ private boolean connectEnumSuperclass() { SourceTypeBinding sourceType = this.referenceContext.binding; ReferenceBinding rootEnumType = getJavaLangEnum(); if ((rootEnumType.tagBits & TagBits.HasMissingType) != 0) { sourceType.tagBits |= TagBits.HierarchyHasProblems; // mark missing supertpye sourceType.superclass = rootEnumType; return false; } boolean foundCycle = detectHierarchyCycle(sourceType, rootEnumType, null); // arity check for well-known Enum TypeVariableBinding[] refTypeVariables = rootEnumType.typeVariables(); if (refTypeVariables == Binding.NO_TYPE_VARIABLES) { // check generic problemReporter().nonGenericTypeCannotBeParameterized(0, 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 = environment().createParameterizedType( rootEnumType, new TypeBinding[]{ environment().convertToRawType(sourceType, false /*do not force conversion of enclosing types*/), } , null); sourceType.tagBits |= (superType.tagBits & TagBits.HierarchyHasProblems); // propagate if missing supertpye sourceType.superclass = superType; // bound check (in case of bogus definition of Enum type) if (refTypeVariables[0].boundCheck(superType, sourceType, this) != TypeConstants.OK) { 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. inherited interfaces are visible when defining a superinterface. Error recovery story: ensure the superinterfaces contain only valid visible interfaces. Answer false if an error was reported against the sourceType. */ private boolean connectSuperInterfaces() { SourceTypeBinding sourceType = this.referenceContext.binding; sourceType.superInterfaces = Binding.NO_SUPERINTERFACES; if (this.referenceContext.superInterfaces == null) { if (sourceType.isAnnotationType() && compilerOptions().sourceLevel >= ClassFileConstants.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 == TypeIds.T_JavaLangObject) // already handled the case of redefining java.lang.Object return true; boolean noProblems = true; int length = this.referenceContext.superInterfaces.length; ReferenceBinding[] interfaceBindings = new ReferenceBinding[length]; int count = 0; nextInterface : for (int i = 0; i < length; i++) { TypeReference superInterfaceRef = this.referenceContext.superInterfaces[i]; ReferenceBinding superInterface = findSupertype(superInterfaceRef); if (superInterface == null) { // detected cycle sourceType.tagBits |= TagBits.HierarchyHasProblems; noProblems = false; continue nextInterface; } // check for simple interface collisions // Check for a duplicate interface once the name is resolved, otherwise we may be confused (i.e. a.b.I and c.d.I) for (int j = 0; j < i; j++) { if (interfaceBindings[j] == superInterface) { problemReporter().duplicateSuperinterface(sourceType, superInterfaceRef, superInterface); sourceType.tagBits |= TagBits.HierarchyHasProblems; noProblems = false; continue nextInterface; } } if (!superInterface.isInterface() && (superInterface.tagBits & TagBits.HasMissingType) == 0) { problemReporter().superinterfaceMustBeAnInterface(sourceType, superInterfaceRef, superInterface); sourceType.tagBits |= TagBits.HierarchyHasProblems; noProblems = false; continue nextInterface; } else if (superInterface.isAnnotationType()){ problemReporter().annotationTypeUsedAsSuperinterface(sourceType, superInterfaceRef, superInterface); } if ((superInterface.tagBits & TagBits.HasDirectWildcard) != 0) { problemReporter().superTypeCannotUseWildcard(sourceType, superInterfaceRef, superInterface); sourceType.tagBits |= TagBits.HierarchyHasProblems; noProblems = false; continue nextInterface; } if ((superInterface.tagBits & TagBits.HierarchyHasProblems) != 0 || !superInterfaceRef.resolvedType.isValidBinding()) { sourceType.tagBits |= TagBits.HierarchyHasProblems; // propagate if missing supertype noProblems &= superInterfaceRef.resolvedType.isValidBinding(); } // only want to reach here when no errors are reported sourceType.typeBits |= (superInterface.typeBits & TypeIds.InheritableBits); interfaceBindings[count++] = superInterface; } // hold onto all correctly resolved superinterfaces if (count > 0) { if (count != length) System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count); sourceType.superInterfaces = interfaceBindings; } return noProblems; } void connectTypeHierarchy() { SourceTypeBinding sourceType = this.referenceContext.binding; if ((sourceType.tagBits & TagBits.BeginHierarchyCheck) == 0) { sourceType.tagBits |= TagBits.BeginHierarchyCheck; environment().typesBeingConnected.add(sourceType); boolean noProblems = connectSuperclass(); noProblems &= connectSuperInterfaces(); environment().typesBeingConnected.remove(sourceType); sourceType.tagBits |= TagBits.EndHierarchyCheck; noProblems &= connectTypeVariables(this.referenceContext.typeParameters, false); sourceType.tagBits |= TagBits.TypeVariablesAreConnected; if (noProblems && sourceType.isHierarchyInconsistent()) problemReporter().hierarchyHasProblems(sourceType); } connectMemberTypes(); LookupEnvironment env = environment(); try { env.missingClassFileLocation = this.referenceContext; checkForInheritedMemberTypes(sourceType); } catch (AbortCompilation e) { e.updateContext(this.referenceContext, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } } private void connectTypeHierarchyWithoutMembers() { // must ensure the imports are resolved if (this.parent instanceof CompilationUnitScope) { if (((CompilationUnitScope) this.parent).imports == null) ((CompilationUnitScope) this.parent).checkAndSetImports(); } else if (this.parent instanceof ClassScope) { // ensure that the enclosing type has already been checked ((ClassScope) this.parent).connectTypeHierarchyWithoutMembers(); } // double check that the hierarchy search has not already begun... SourceTypeBinding sourceType = this.referenceContext.binding; if ((sourceType.tagBits & TagBits.BeginHierarchyCheck) != 0) return; sourceType.tagBits |= TagBits.BeginHierarchyCheck; environment().typesBeingConnected.add(sourceType); boolean noProblems = connectSuperclass(); noProblems &= connectSuperInterfaces(); environment().typesBeingConnected.remove(sourceType); sourceType.tagBits |= TagBits.EndHierarchyCheck; noProblems &= connectTypeVariables(this.referenceContext.typeParameters, false); sourceType.tagBits |= TagBits.TypeVariablesAreConnected; if (noProblems && sourceType.isHierarchyInconsistent()) problemReporter().hierarchyHasProblems(sourceType); } public boolean detectHierarchyCycle(TypeBinding superType, TypeReference reference) { if (!(superType instanceof ReferenceBinding)) return false; 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).genericType(); compilationUnitScope().recordSuperTypeReference(superType); // to record supertypes return detectHierarchyCycle(this.referenceContext.binding, (ReferenceBinding) superType, reference); } // Reinstate the code deleted by the fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=205235 // For details, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=294057. if ((superType.tagBits & 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 detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) { if (superType.isRawType()) superType = ((RawTypeBinding) superType).genericType(); // by this point the superType must be a binary or source type if (sourceType == superType) { problemReporter().hierarchyCircularity(sourceType, superType, reference); sourceType.tagBits |= TagBits.HierarchyHasProblems; return true; } if (superType.isMemberType()) { ReferenceBinding current = superType.enclosingType(); do { if (current.isHierarchyBeingActivelyConnected() && current == sourceType) { problemReporter().hierarchyCircularity(sourceType, current, reference); sourceType.tagBits |= TagBits.HierarchyHasProblems; current.tagBits |= 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 // - another source type... this case is reported against the other source type boolean hasCycle = false; ReferenceBinding parentType = superType.superclass(); if (parentType != null) { if (sourceType == parentType) { problemReporter().hierarchyCircularity(sourceType, superType, reference); sourceType.tagBits |= TagBits.HierarchyHasProblems; superType.tagBits |= TagBits.HierarchyHasProblems; return true; } if (parentType.isParameterizedType()) parentType = ((ParameterizedTypeBinding) parentType).genericType(); hasCycle |= detectHierarchyCycle(sourceType, parentType, reference); if ((parentType.tagBits & TagBits.HierarchyHasProblems) != 0) { sourceType.tagBits |= TagBits.HierarchyHasProblems; parentType.tagBits |= TagBits.HierarchyHasProblems; // propagate down the hierarchy } } ReferenceBinding[] itsInterfaces = superType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { for (int i = 0, length = itsInterfaces.length; i < length; i++) { ReferenceBinding anInterface = itsInterfaces[i]; if (sourceType == anInterface) { problemReporter().hierarchyCircularity(sourceType, superType, reference); sourceType.tagBits |= TagBits.HierarchyHasProblems; superType.tagBits |= TagBits.HierarchyHasProblems; return true; } if (anInterface.isParameterizedType()) anInterface = ((ParameterizedTypeBinding) anInterface).genericType(); hasCycle |= detectHierarchyCycle(sourceType, anInterface, reference); if ((anInterface.tagBits & TagBits.HierarchyHasProblems) != 0) { sourceType.tagBits |= TagBits.HierarchyHasProblems; superType.tagBits |= TagBits.HierarchyHasProblems; } } } return hasCycle; } if (superType.isHierarchyBeingActivelyConnected()) { org.eclipse.jdt.internal.compiler.ast.TypeReference ref = ((SourceTypeBinding) superType).scope.superTypeReference; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=133071 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=121734 if (ref != null && ref.resolvedType != null && ((ReferenceBinding) ref.resolvedType).isHierarchyBeingActivelyConnected()) { problemReporter().hierarchyCircularity(sourceType, superType, reference); sourceType.tagBits |= TagBits.HierarchyHasProblems; superType.tagBits |= TagBits.HierarchyHasProblems; return true; } if (ref != null && ref.resolvedType == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=319885 Don't cry foul prematurely. // Check the edges traversed to see if there really is a cycle. char [] referredName = ref.getLastToken(); for (Iterator iter = environment().typesBeingConnected.iterator(); iter.hasNext();) { SourceTypeBinding type = (SourceTypeBinding) iter.next(); if (CharOperation.equals(referredName, type.sourceName())) { problemReporter().hierarchyCircularity(sourceType, superType, reference); sourceType.tagBits |= TagBits.HierarchyHasProblems; superType.tagBits |= TagBits.HierarchyHasProblems; return true; } } } } if ((superType.tagBits & TagBits.BeginHierarchyCheck) == 0) // ensure if this is a source superclass that it has already been checked ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers(); if ((superType.tagBits & TagBits.HierarchyHasProblems) != 0) sourceType.tagBits |= TagBits.HierarchyHasProblems; return false; } private ReferenceBinding findSupertype(TypeReference typeReference) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; try { env.missingClassFileLocation = typeReference; typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes unitScope.recordQualifiedReference(typeReference.getTypeName()); this.superTypeReference = typeReference; ReferenceBinding superType = (ReferenceBinding) typeReference.resolveSuperType(this); return superType; } catch (AbortCompilation e) { SourceTypeBinding sourceType = this.referenceContext.binding; if (sourceType.superInterfaces == null) sourceType.superInterfaces = Binding.NO_SUPERINTERFACES; // be more resilient for hierarchies (144976) e.updateContext(typeReference, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; this.superTypeReference = null; } } /* Answer the problem reporter to use for raising new problems. * * Note that as a side-effect, this updates the current reference context * (unit, type or method) in case the problem handler decides it is necessary * to abort. */ public ProblemReporter problemReporter() { MethodScope outerMethodScope; if ((outerMethodScope = outerMostMethodScope()) == null) { ProblemReporter problemReporter = referenceCompilationUnit().problemReporter; problemReporter.referenceContext = this.referenceContext; return problemReporter; } return outerMethodScope.problemReporter(); } /* Answer the reference type of this scope. * It is the nearest enclosing type of this scope. */ public TypeDeclaration referenceType() { return this.referenceContext; } public String toString() { if (this.referenceContext != null) return "--- Class Scope ---\n\n" //$NON-NLS-1$ + this.referenceContext.binding.toString(); return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$ } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/MissingTypeBinding.java0000644000175000001440000000533712212041344032214 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.ArrayList; import java.util.List; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; public class MissingTypeBinding extends BinaryTypeBinding { /** * Special constructor for constructing proxies of missing types (114349) * @param packageBinding * @param compoundName * @param environment */ public MissingTypeBinding(PackageBinding packageBinding, char[][] compoundName, LookupEnvironment environment) { this.compoundName = compoundName; computeId(); this.tagBits |= TagBits.IsBinaryBinding | TagBits.HierarchyHasProblems | TagBits.HasMissingType; this.environment = environment; this.fPackage = packageBinding; this.fileName = CharOperation.concatWith(compoundName, '/'); this.sourceName = compoundName[compoundName.length - 1]; // [java][util][Map$Entry] this.modifiers = ClassFileConstants.AccPublic; this.superclass = null; // will be fixed up using #setMissingSuperclass(...) this.superInterfaces = Binding.NO_SUPERINTERFACES; this.typeVariables = Binding.NO_TYPE_VARIABLES; this.memberTypes = Binding.NO_MEMBER_TYPES; this.fields = Binding.NO_FIELDS; this.methods = Binding.NO_METHODS; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List) */ public List collectMissingTypes(List missingTypes) { if (missingTypes == null) { missingTypes = new ArrayList(5); } else if (missingTypes.contains(this)) { return missingTypes; } missingTypes.add(this); return missingTypes; } /** * Missing binary type will answer false to #isValidBinding() * @see org.eclipse.jdt.internal.compiler.lookup.Binding#problemId() */ public int problemId() { return ProblemReasons.NotFound; } /** * Only used to fixup the superclass hierarchy of proxy binary types * @param missingSuperclass * @see LookupEnvironment#createMissingType(PackageBinding, char[][]) */ void setMissingSuperclass(ReferenceBinding missingSuperclass) { this.superclass = missingSuperclass; } public String toString() { return "[MISSING:" + new String(CharOperation.concatWith(this.compoundName, '.')) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/TagBits.java0000644000175000001440000001601512212041344027776 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 388281 - [compiler][null] inheritance of null annotations as an option *******************************************************************************/ 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 long IsArrayType = ASTNode.Bit1; long IsBaseType = ASTNode.Bit2; long IsNestedType = ASTNode.Bit3; long IsMemberType = ASTNode.Bit4; long ContainsNestedTypeReferences = ASTNode.Bit12; // method/parameterized type binding long MemberTypeMask = IsNestedType | IsMemberType | ContainsNestedTypeReferences; long IsLocalType = ASTNode.Bit5; long LocalTypeMask = IsNestedType | IsLocalType | ContainsNestedTypeReferences; long IsAnonymousType = ASTNode.Bit6; long AnonymousTypeMask = LocalTypeMask | IsAnonymousType | ContainsNestedTypeReferences; long IsBinaryBinding = ASTNode.Bit7; // set for all bindings either representing a missing type (type), or directly referencing a missing type (field/method/variable) long HasMissingType = ASTNode.Bit8; // for method long HasUncheckedTypeArgumentForBoundCheck = ASTNode.Bit9; // local variable long NotInitialized = ASTNode.Bit9; // local variable long ForcedToBeRawType = ASTNode.Bit10; // set when method has argument(s) that couldn't be resolved long HasUnresolvedArguments = ASTNode.Bit10; // for the type cycle hierarchy check used by ClassScope long BeginHierarchyCheck = ASTNode.Bit9; // type long EndHierarchyCheck = ASTNode.Bit10; // type long PauseHierarchyCheck = ASTNode.Bit20; // type long HasParameterAnnotations = ASTNode.Bit11; // method/constructor // test bit to see if default abstract methods were computed long KnowsDefaultAbstractMethods = ASTNode.Bit11; // type long IsArgument = ASTNode.Bit11; // local long ClearPrivateModifier = ASTNode.Bit10; // constructor binding // for java 7 long IsEffectivelyFinal = ASTNode.Bit12; // local long MultiCatchParameter = ASTNode.Bit13; // local long IsResource = ASTNode.Bit14; // local // have implicit null annotations been collected (inherited(?) & default)? long IsNullnessKnown = ASTNode.Bit13; // method // test bits to see if parts of binary types are faulted long AreFieldsSorted = ASTNode.Bit13; long AreFieldsComplete = ASTNode.Bit14; // sorted and all resolved long AreMethodsSorted = ASTNode.Bit15; long AreMethodsComplete = ASTNode.Bit16; // sorted and all resolved // test bit to avoid asking a type for a member type (includes inherited member types) long HasNoMemberTypes = ASTNode.Bit17; // test bit to identify if the type's hierarchy is inconsistent long HierarchyHasProblems = ASTNode.Bit18; // test bit to identify if the type's type variables have been connected long TypeVariablesAreConnected = ASTNode.Bit19; // set for parameterized type with successful bound check long PassedBoundCheck = ASTNode.Bit23; // 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 DeprecatedAnnotationResolved = ASTNode.Bit35L; long AnnotationTarget = ASTNode.Bit36L; // @Target({}) only sets this bit long AnnotationForType = ASTNode.Bit37L; long AnnotationForField = ASTNode.Bit38L; long AnnotationForMethod = ASTNode.Bit39L; long AnnotationForParameter = ASTNode.Bit40L; long AnnotationForConstructor = ASTNode.Bit41L; long AnnotationForLocalVariable = ASTNode.Bit42L; long AnnotationForAnnotationType = ASTNode.Bit43L; long AnnotationForPackage = ASTNode.Bit44L; long AnnotationTargetMASK = AnnotationTarget | AnnotationForType | AnnotationForField | AnnotationForMethod | AnnotationForParameter | AnnotationForConstructor | AnnotationForLocalVariable | AnnotationForAnnotationType | AnnotationForPackage; // 2-bits for retention (should check (tagBits & RetentionMask) == RuntimeRetention long AnnotationSourceRetention = ASTNode.Bit45L; long AnnotationClassRetention = ASTNode.Bit46L; long AnnotationRuntimeRetention = AnnotationSourceRetention | AnnotationClassRetention; long AnnotationRetentionMASK = AnnotationSourceRetention | AnnotationClassRetention | AnnotationRuntimeRetention; // marker annotations long AnnotationDeprecated = ASTNode.Bit47L; long AnnotationDocumented = ASTNode.Bit48L; long AnnotationInherited = ASTNode.Bit49L; long AnnotationOverride = ASTNode.Bit50L; long AnnotationSuppressWarnings = ASTNode.Bit51L; /** @since 3.7 - java 7 safe vargs invocation */ long AnnotationSafeVarargs = ASTNode.Bit52L; /** @since 3.7 - java 7 MethodHandle.invokeExact(..)/invokeGeneric(..)*/ long AnnotationPolymorphicSignature = ASTNode.Bit53L; /** @since 3.8 null annotation for MethodBinding or LocalVariableBinding (argument): */ long AnnotationNullable = ASTNode.Bit56L; /** @since 3.8 null annotation for MethodBinding or LocalVariableBinding (argument): */ long AnnotationNonNull = ASTNode.Bit57L; /** @since 3.8 null-default annotation for PackageBinding or TypeBinding or MethodBinding: */ long AnnotationNonNullByDefault = ASTNode.Bit58L; /** @since 3.8 canceling null-default annotation for PackageBinding or TypeBinding or MethodBinding: */ long AnnotationNullUnspecifiedByDefault = ASTNode.Bit59L; long AllStandardAnnotationsMask = AnnotationTargetMASK | AnnotationRetentionMASK | AnnotationDeprecated | AnnotationDocumented | AnnotationInherited | AnnotationOverride | AnnotationSuppressWarnings | AnnotationSafeVarargs | AnnotationPolymorphicSignature | AnnotationNullable | AnnotationNonNull | AnnotationNonNullByDefault | AnnotationNullUnspecifiedByDefault; long DefaultValueResolved = ASTNode.Bit60L; // set when type contains non-private constructor(s) long HasNonPrivateConstructor = ASTNode.Bit61L; } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java0000644000175000001440000000323012212041344031201 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.ImportReference; public class ImportBinding extends Binding { public char[][] compoundName; public boolean onDemand; public ImportReference reference; public Binding resolvedImport; // must ensure the import is resolved public ImportBinding(char[][] compoundName, boolean isOnDemand, Binding binding, ImportReference reference) { this.compoundName = compoundName; this.onDemand = isOnDemand; this.resolvedImport = binding; this.reference = reference; } /* API * Answer the receiver's binding type from Binding.BindingID. */ public final int kind() { return IMPORT; } public boolean isStatic() { return this.reference != null && this.reference.isStatic(); } public char[] readableName() { if (this.onDemand) return CharOperation.concat(CharOperation.concatWith(this.compoundName, '.'), ".*".toCharArray()); //$NON-NLS-1$ else return CharOperation.concatWith(this.compoundName, '.'); } public String toString() { return "import : " + new String(readableName()); //$NON-NLS-1$ } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.jav0000644000175000001440000000355412212041344032340 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; public class ProblemMethodBinding extends MethodBinding { 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) ? Binding.NO_PARAMETERS : args; this.problemReason = problemReason; this.thrownExceptions = Binding.NO_EXCEPTIONS; } public ProblemMethodBinding(char[] selector, TypeBinding[] args, ReferenceBinding declaringClass, int problemReason) { this.selector = selector; this.parameters = (args == null || args.length == 0) ? Binding.NO_PARAMETERS : args; this.declaringClass = declaringClass; this.problemReason = problemReason; this.thrownExceptions = Binding.NO_EXCEPTIONS; } public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBinding[] args, int problemReason) { this(selector, args, problemReason); this.closestMatch = closestMatch; if (closestMatch != null && problemReason != ProblemReasons.Ambiguous) this.declaringClass = closestMatch.declaringClass; } /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. */ public final int problemId() { return this.problemReason; } } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ImportConflictBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ImportConflictBinding.ja0000644000175000001440000000242712212041344032343 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.ImportReference; public class ImportConflictBinding extends ImportBinding { public ReferenceBinding conflictingTypeBinding; // must ensure the import is resolved public ImportConflictBinding(char[][] compoundName, Binding methodBinding, ReferenceBinding conflictingTypeBinding, ImportReference reference) { super(compoundName, false, methodBinding, reference); this.conflictingTypeBinding = conflictingTypeBinding; } public char[] readableName() { return CharOperation.concatWith(this.compoundName, '.'); } public String toString() { return "method import : " + new String(readableName()); //$NON-NLS-1$ } } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.j0000644000175000001440000000530312212041344032367 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; // TODO (philippe) these should be moved to tagbits public interface ExtraCompilerModifiers { // modifier constant // those constants are depending upon ClassFileConstants (relying that classfiles only use the 16 lower bits) final int AccJustFlag = 0xFFFF;// 16 lower bits // bit17 - free // bit18 - use by ClassFileConstants.AccAnnotationDefault final int AccRestrictedAccess = ASTNode.Bit19; final int AccFromClassFile = ASTNode.Bit20; final int AccDefaultAbstract = ASTNode.Bit20; // bit21 - use by ClassFileConstants.AccDeprecated 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 AccBlankFinal = ASTNode.Bit27; // for blank final variables final int AccIsDefaultConstructor = ASTNode.Bit27; // for default constructor final int AccLocallyUsed = ASTNode.Bit28; // used to diagnose unused (a) private/local members or (b) members of private classes // generally set when actual usage has been detected // or, (b) when member of a private class is exposed via a non-private subclass // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=328281 final int AccVisibilityMASK = ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate; 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) } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java0000644000175000001440000012105712212041344030660 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephen Herrmann - Contributions for * bug 317046 - Exception during debugging when hover mouse over a field * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.List; 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. * Some are initialized only when needed. * * Accessors have been provided for some public fields so all TypeBindings have the same API... * but access public fields directly whenever possible. * Non-public fields have accessors which should be used everywhere you expect the field to be initialized. * * null is NOT a valid value for a non-public field... it just means the field is not initialized. */ abstract public class TypeBinding extends Binding { public int id = TypeIds.NoId; public long tagBits = 0; // See values in the interface TagBits below /** Base type definitions */ public final static BaseTypeBinding INT = new BaseTypeBinding( TypeIds.T_int, TypeConstants.INT, new char[] { 'I' }); public final static BaseTypeBinding BYTE = new BaseTypeBinding( TypeIds.T_byte, TypeConstants.BYTE, new char[] { 'B' }); public final static BaseTypeBinding SHORT = new BaseTypeBinding( TypeIds.T_short, TypeConstants.SHORT, new char[] { 'S' }); public final static BaseTypeBinding CHAR = new BaseTypeBinding( TypeIds.T_char, TypeConstants.CHAR, new char[] { 'C' }); public final static BaseTypeBinding LONG = new BaseTypeBinding( TypeIds.T_long, TypeConstants.LONG, new char[] { 'J' }); public final static BaseTypeBinding FLOAT = new BaseTypeBinding( TypeIds.T_float, TypeConstants.FLOAT, new char[] { 'F' }); public final static BaseTypeBinding DOUBLE = new BaseTypeBinding( TypeIds.T_double, TypeConstants.DOUBLE, new char[] { 'D' }); public final static BaseTypeBinding BOOLEAN = new BaseTypeBinding( TypeIds.T_boolean, TypeConstants.BOOLEAN, new char[] { 'Z' }); public final static BaseTypeBinding NULL = new BaseTypeBinding( TypeIds.T_null, TypeConstants.NULL, new char[] { 'N' }); //N stands for null even if it is never internally used public final static BaseTypeBinding VOID = new BaseTypeBinding( TypeIds.T_void, TypeConstants.VOID, new char[] { 'V' }); /** * Match a well-known type id to its binding */ public static final TypeBinding wellKnownType(Scope scope, int id) { switch (id) { case TypeIds.T_boolean: return TypeBinding.BOOLEAN; case TypeIds.T_byte: return TypeBinding.BYTE; case TypeIds.T_char: return TypeBinding.CHAR; case TypeIds.T_short: return TypeBinding.SHORT; case TypeIds.T_double: return TypeBinding.DOUBLE; case TypeIds.T_float: return TypeBinding.FLOAT; case TypeIds.T_int: return TypeBinding.INT; case TypeIds.T_long: return TypeBinding.LONG; case TypeIds.T_JavaLangObject: return scope.getJavaLangObject(); case TypeIds.T_JavaLangString: return scope.getJavaLangString(); default: return null; } } /* Answer true if the receiver can be instantiated */ public boolean canBeInstantiated() { return !isBaseType(); } /** * Perform capture conversion on a given type (only effective on parameterized type with wildcards) */ public TypeBinding capture(Scope scope, int position) { return this; } /** * In case of problems, returns the closest match found. It may not be perfect match, but the * result of a best effort to improve fault-tolerance. */ public TypeBinding closestMatch() { return this; // by default no better type } /** * Iterate through the type components to collect instances of leaf missing types * @param missingTypes * @return missing types */ public List collectMissingTypes(List missingTypes) { return missingTypes; } /** * Collect the substitutes into a map for certain type variables inside the receiver type * e.g. Collection.findSubstitute(T, Collection>): T --> List * Constraints: * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1)) * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0)) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2)) */ public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { // no substitute by default } /** * 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(); public String debugName() { return new String(readableName()); } /* * Answer the receiver's dimensions - 0 for non-array types */ 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; } /** * Find supertype which originates from 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. * @see TypeIds */ public ReferenceBinding findSuperTypeOriginatingFrom(int wellKnownOriginalID, boolean originalIsClass) { if (!(this instanceof ReferenceBinding)) return null; ReferenceBinding reference = (ReferenceBinding) this; // do not allow type variables to match with erasures for free if (reference.id == wellKnownOriginalID || (original().id == wellKnownOriginalID)) return reference; ReferenceBinding currentType = reference; // iterate superclass to avoid recording interfaces if searched supertype is class if (originalIsClass) { while ((currentType = currentType.superclass()) != null) { if (currentType.id == wellKnownOriginalID) return currentType; if (currentType.original().id == wellKnownOriginalID) return currentType; } return null; } ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; do { ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } while ((currentType = currentType.superclass()) != null); for (int i = 0; i < nextPosition; i++) { currentType = interfacesToVisit[i]; if (currentType.id == wellKnownOriginalID) return currentType; if (currentType.original().id == wellKnownOriginalID) return currentType; ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } return null; } /** * Find supertype which originates from a given type, or null if not found */ public TypeBinding findSuperTypeOriginatingFrom(TypeBinding otherType) { if (this == otherType) return this; if (otherType == null) return null; switch(kind()) { case Binding.ARRAY_TYPE : ArrayBinding arrayType = (ArrayBinding) this; int otherDim = otherType.dimensions(); if (arrayType.dimensions != otherDim) { switch(otherType.id) { case TypeIds.T_JavaLangObject : case TypeIds.T_JavaIoSerializable : case TypeIds.T_JavaLangCloneable : return otherType; } if (otherDim < arrayType.dimensions && otherType.leafComponentType().id == TypeIds.T_JavaLangObject) { return otherType; // X[][] has Object[] as an implicit supertype } return null; } if (!(arrayType.leafComponentType instanceof ReferenceBinding)) return null; TypeBinding leafSuperType = arrayType.leafComponentType.findSuperTypeOriginatingFrom(otherType.leafComponentType()); if (leafSuperType == null) return null; return arrayType.environment().createArrayType(leafSuperType, arrayType.dimensions); case Binding.TYPE_PARAMETER : if (isCapture()) { CaptureBinding capture = (CaptureBinding) this; TypeBinding captureBound = capture.firstBound; if (captureBound instanceof ArrayBinding) { TypeBinding match = captureBound.findSuperTypeOriginatingFrom(otherType); if (match != null) return match; } } //$FALL-THROUGH$ case Binding.TYPE : case Binding.PARAMETERIZED_TYPE : case Binding.GENERIC_TYPE : case Binding.RAW_TYPE : case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE: // do not allow type variables/intersection types to match with erasures for free otherType = otherType.original(); if (this == otherType) return this; if (original() == otherType) return this; ReferenceBinding currentType = (ReferenceBinding)this; if (!otherType.isInterface()) { while ((currentType = currentType.superclass()) != null) { if (currentType == otherType) return currentType; if (currentType.original() == otherType) return currentType; } return null; } ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; do { ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } while ((currentType = currentType.superclass()) != null); for (int i = 0; i < nextPosition; i++) { currentType = interfacesToVisit[i]; if (currentType == otherType) return currentType; if (currentType.original() == otherType) return currentType; ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } return null; } /** * Returns the type to use for generic cast, or null if none required */ public TypeBinding genericCast(TypeBinding targetType) { if (this == targetType) return null; TypeBinding targetErasure = targetType.erasure(); // type var get replaced by upper bound if (erasure().findSuperTypeOriginatingFrom(targetErasure) != null) return null; return targetErasure; } /** * 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(); } /** * Return the supertype which would erase as a subtype of a given declaring class. * If the receiver is already erasure compatible, then it will returned. If not, then will return the alternate lowest * upper bound compatible with declaring class. * NOTE: the declaringClass is already know to be compatible with the receiver * @param declaringClass to look for * @return the lowest erasure compatible type (considering alternate bounds) */ public TypeBinding getErasureCompatibleType(TypeBinding declaringClass) { switch(kind()) { case Binding.TYPE_PARAMETER : TypeVariableBinding variable = (TypeVariableBinding) this; if (variable.erasure().findSuperTypeOriginatingFrom(declaringClass) != null) { return this; // no need for alternate receiver type } if (variable.superclass != null && variable.superclass.findSuperTypeOriginatingFrom(declaringClass) != null) { return variable.superclass.getErasureCompatibleType(declaringClass); } for (int i = 0, otherLength = variable.superInterfaces.length; i < otherLength; i++) { ReferenceBinding superInterface = variable.superInterfaces[i]; if (superInterface.findSuperTypeOriginatingFrom(declaringClass) != null) { return superInterface.getErasureCompatibleType(declaringClass); } } return this; // only occur if passed null declaringClass for arraylength case Binding.INTERSECTION_TYPE : WildcardBinding intersection = (WildcardBinding) this; if (intersection.erasure().findSuperTypeOriginatingFrom(declaringClass) != null) { return this; // no need for alternate receiver type } if (intersection.superclass != null && intersection.superclass.findSuperTypeOriginatingFrom(declaringClass) != null) { return intersection.superclass.getErasureCompatibleType(declaringClass); } for (int i = 0, otherLength = intersection.superInterfaces.length; i < otherLength; i++) { ReferenceBinding superInterface = intersection.superInterfaces[i]; if (superInterface.findSuperTypeOriginatingFrom(declaringClass) != null) { return superInterface.getErasureCompatibleType(declaringClass); } } return this; // only occur if passed null declaringClass for arraylength default : return this; } } public abstract PackageBinding getPackage(); void initializeForStaticImports() { // only applicable to source types } public boolean isAnnotationType() { return false; } public final boolean isAnonymousType() { return (this.tagBits & TagBits.IsAnonymousType) != 0; } /* Answer true if the receiver is an array */ public final boolean isArrayType() { return (this.tagBits & TagBits.IsArrayType) != 0; } /* Answer true if the receiver is a base type */ public final boolean isBaseType() { return (this.tagBits & TagBits.IsBaseType) != 0; } /** * Returns true if parameterized type AND not of the form List */ public boolean isBoundParameterizedType() { return (this.tagBits & TagBits.IsBoundParameterizedType) != 0; } /** * Returns true if the type is the capture of some wildcard */ public boolean isCapture() { return false; } public boolean isClass() { return false; } /* Answer true if the receiver type can be assigned to the argument type (right) */ public boolean isCompatibleWith(TypeBinding right) { return isCompatibleWith(right, null); // delegate from the old signature to the new implementation: } // version that allows to capture a type bound using 'scope': public abstract boolean isCompatibleWith(TypeBinding right, /*@Nullable*/ Scope scope); 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; switch (otherType.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : 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 (this.tagBits & TagBits.HierarchyHasProblems) != 0; } public boolean isInterface() { return false; } /** * Returns true if the current type denotes an intersection type: Number & Comparable */ public boolean isIntersectionType() { return false; } public final boolean isLocalType() { return (this.tagBits & TagBits.IsLocalType) != 0; } public final boolean isMemberType() { return (this.tagBits & TagBits.IsMemberType) != 0; } public final boolean isNestedType() { return (this.tagBits & TagBits.IsNestedType) != 0; } public final boolean isNumericType() { switch (this.id) { case TypeIds.T_int: case TypeIds.T_float: case TypeIds.T_double: case TypeIds.T_short: case TypeIds.T_byte: case TypeIds.T_long: case TypeIds.T_char: return true; default: return false; } } /** * Returns true if the type is parameterized, e.g. List. * Note that some instances of ParameterizedTypeBinding have no arguments, like for non-generic members * of a parameterized type. Use {@link #isParameterizedTypeWithActualArguments()} instead to find out. */ public final boolean isParameterizedType() { return kind() == Binding.PARAMETERIZED_TYPE; } /** * Returns true if the type is parameterized, e.g. List * Note that some instances of ParameterizedTypeBinding do answer false to {@link #isParameterizedType()} * in case they have no arguments, like for non-generic members of a parameterized type. * i.e. {@link #isParameterizedType()} is not equivalent to testing type.kind() == Binding.PARAMETERIZED_TYPE */ public final boolean isParameterizedTypeWithActualArguments() { return (kind() == Binding.PARAMETERIZED_TYPE) && ((ParameterizedTypeBinding) this).arguments != null; } /** * Returns true if the type is parameterized using its own type variables as arguments */ public boolean isParameterizedWithOwnVariables() { if (kind() != Binding.PARAMETERIZED_TYPE) return false; ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) this; if (paramType.arguments == null) return false; TypeVariableBinding[] variables = erasure().typeVariables(); for (int i = 0, length = variables.length; i < length; i++) { if (variables[i] != paramType.arguments[i]) return false; } ReferenceBinding enclosing = paramType.enclosingType(); if (enclosing != null && enclosing.erasure().isGenericType() && !enclosing.isParameterizedWithOwnVariables()) { return false; } return true; } private boolean isProvableDistinctSubType(TypeBinding otherType) { if (otherType.isInterface()) { if (isInterface()) return false; if (isArrayType() || ((this instanceof ReferenceBinding) && ((ReferenceBinding) this).isFinal()) || (isTypeVariable() && ((TypeVariableBinding)this).superclass().isFinal())) { return !isCompatibleWith(otherType); } return false; } else { if (isInterface()) { if (otherType.isArrayType() || ((otherType instanceof ReferenceBinding) && ((ReferenceBinding) otherType).isFinal()) || (otherType.isTypeVariable() && ((TypeVariableBinding)otherType).superclass().isFinal())) { return !isCompatibleWith(otherType); } } else { if (!isTypeVariable() && !otherType.isTypeVariable()) { return !isCompatibleWith(otherType); } } } return false; } /** * Returns true if a type is provably distinct from another one, */ public boolean isProvablyDistinct(TypeBinding otherType) { /* With the hybrid 1.4/1.5+ projects modes, while establishing type equivalence, we need to be prepared for a type such as Map appearing in one of three forms: As (a) a ParameterizedTypeBinding e.g Map, (b) as RawTypeBinding Map#RAW and finally (c) as a BinaryTypeBinding When the usage of a type lacks type parameters, whether we land up with the raw form or not depends on whether the underlying type was "seen to be" a generic type in the particular build environment or not. See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=186565 https://bugs.eclipse.org/bugs/show_bug.cgi?id=328827 https://bugs.eclipse.org/bugs/show_bug.cgi?id=329588 */ if (this == otherType) return false; if (otherType == null) return true; switch (kind()) { case Binding.PARAMETERIZED_TYPE : ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) this; switch(otherType.kind()) { case Binding.PARAMETERIZED_TYPE : ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType; if (paramType.genericType() != otherParamType.genericType()) return true; if (!paramType.isStatic()) { // static member types do not compare their enclosing ReferenceBinding enclosing = enclosingType(); if (enclosing != null) { ReferenceBinding otherEnclosing = otherParamType.enclosingType(); if (otherEnclosing == null) return true; if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) { if (enclosing.isProvablyDistinct(otherEnclosing)) return true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=302919 } else { if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return true; } } } int length = paramType.arguments == null ? 0 : paramType.arguments.length; TypeBinding[] otherArguments = otherParamType.arguments; int otherLength = otherArguments == null ? 0 : otherArguments.length; if (otherLength != length) return true; for (int i = 0; i < length; i++) { if (paramType.arguments[i].isProvablyDistinctTypeArgument(otherArguments[i], paramType, i)) return true; } return false; case Binding.GENERIC_TYPE : if (paramType.genericType() != otherType) return true; if (!paramType.isStatic()) { // static member types do not compare their enclosing ReferenceBinding enclosing = enclosingType(); if (enclosing != null) { ReferenceBinding otherEnclosing = otherType.enclosingType(); if (otherEnclosing == null) return true; if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) { if (enclosing != otherEnclosing) return true; } else { if (!enclosing.isEquivalentTo(otherType.enclosingType())) return true; } } } length = paramType.arguments == null ? 0 : paramType.arguments.length; otherArguments = otherType.typeVariables(); otherLength = otherArguments == null ? 0 : otherArguments.length; if (otherLength != length) return true; for (int i = 0; i < length; i++) { if (paramType.arguments[i].isProvablyDistinctTypeArgument(otherArguments[i], paramType, i)) return true; } return false; case Binding.RAW_TYPE : return erasure() != otherType.erasure(); case Binding.TYPE: // https://bugs.eclipse.org/bugs/show_bug.cgi?id=329588 return erasure() != otherType; } return true; case Binding.RAW_TYPE : // dead code ?? switch(otherType.kind()) { case Binding.GENERIC_TYPE : case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : case Binding.TYPE: // https://bugs.eclipse.org/bugs/show_bug.cgi?id=329588 return erasure() != otherType.erasure(); } return true; case Binding.TYPE: // https://bugs.eclipse.org/bugs/show_bug.cgi?id=329588 switch(otherType.kind()) { case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : return this != otherType.erasure(); } break; default : break; } return true; } /** * Returns false if two given types could not intersect as argument types: * List & List --> false * List & List --> true * List & List --> false */ private boolean isProvablyDistinctTypeArgument(TypeBinding otherArgument, final ParameterizedTypeBinding paramType, final int rank) { if (this == otherArgument) return false; TypeBinding upperBound1 = null; TypeBinding lowerBound1 = null; ReferenceBinding genericType = paramType.genericType(); switch (kind()) { case Binding.WILDCARD_TYPE : WildcardBinding wildcard = (WildcardBinding) this; switch (wildcard.boundKind) { case Wildcard.EXTENDS: upperBound1 = wildcard.bound; break; case Wildcard.SUPER: lowerBound1 = wildcard.bound; break; case Wildcard.UNBOUND: return false; } break; case Binding.INTERSECTION_TYPE : break; case Binding.TYPE_PARAMETER : final TypeVariableBinding variable = (TypeVariableBinding) this; if (variable.isCapture()) { CaptureBinding capture = (CaptureBinding) variable; switch (capture.wildcard.boundKind) { case Wildcard.EXTENDS: upperBound1 = capture.wildcard.bound; break; case Wildcard.SUPER: lowerBound1 = capture.wildcard.bound; break; case Wildcard.UNBOUND: return false; } break; } if (variable.firstBound == null) // unbound variable return false; TypeBinding eliminatedType = Scope.convertEliminatingTypeVariables(variable, genericType, rank, null); switch (eliminatedType.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : wildcard = (WildcardBinding) eliminatedType; switch (wildcard.boundKind) { case Wildcard.EXTENDS: upperBound1 = wildcard.bound; break; case Wildcard.SUPER: lowerBound1 = wildcard.bound; break; case Wildcard.UNBOUND: return false; } break; } break; } TypeBinding upperBound2 = null; TypeBinding lowerBound2 = null; switch (otherArgument.kind()) { case Binding.WILDCARD_TYPE : WildcardBinding otherWildcard = (WildcardBinding) otherArgument; switch (otherWildcard.boundKind) { case Wildcard.EXTENDS: upperBound2 = otherWildcard.bound; break; case Wildcard.SUPER: lowerBound2 = otherWildcard.bound; break; case Wildcard.UNBOUND: return false; } break; case Binding.INTERSECTION_TYPE : break; case Binding.TYPE_PARAMETER : TypeVariableBinding otherVariable = (TypeVariableBinding) otherArgument; if (otherVariable.isCapture()) { CaptureBinding otherCapture = (CaptureBinding) otherVariable; switch (otherCapture.wildcard.boundKind) { case Wildcard.EXTENDS: upperBound2 = otherCapture.wildcard.bound; break; case Wildcard.SUPER: lowerBound2 = otherCapture.wildcard.bound; break; case Wildcard.UNBOUND: return false; } break; } if (otherVariable.firstBound == null) // unbound variable return false; TypeBinding otherEliminatedType = Scope.convertEliminatingTypeVariables(otherVariable, genericType, rank, null); switch (otherEliminatedType.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : otherWildcard = (WildcardBinding) otherEliminatedType; switch (otherWildcard.boundKind) { case Wildcard.EXTENDS: upperBound2 = otherWildcard.bound; break; case Wildcard.SUPER: lowerBound2 = otherWildcard.bound; break; case Wildcard.UNBOUND: return false; } break; } break; } if (lowerBound1 != null) { if (lowerBound2 != null) { return false; // Object could always be a candidate } else if (upperBound2 != null) { if (lowerBound1.isTypeVariable() || upperBound2.isTypeVariable()) { return false; } return !lowerBound1.isCompatibleWith(upperBound2); } else { if (lowerBound1.isTypeVariable() || otherArgument.isTypeVariable()) { return false; } return !lowerBound1.isCompatibleWith(otherArgument); } } else if (upperBound1 != null) { if (lowerBound2 != null) { return !lowerBound2.isCompatibleWith(upperBound1); } else if (upperBound2 != null) { return upperBound1.isProvableDistinctSubType(upperBound2) && upperBound2.isProvableDistinctSubType(upperBound1); } else { return otherArgument.isProvableDistinctSubType(upperBound1); } } else { if (lowerBound2 != null) { if (lowerBound2.isTypeVariable() || isTypeVariable()) { return false; } return !lowerBound2.isCompatibleWith(this); } else if (upperBound2 != null) { return isProvableDistinctSubType(upperBound2); } else { return true; // ground types should have been the same } } } public final boolean isRawType() { return kind() == Binding.RAW_TYPE; } /** * JLS(3) 4.7. * Note: Foo.Bar is also reifiable */ 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.INTERSECTION_TYPE: case Binding.GENERIC_TYPE: return false; case Binding.PARAMETERIZED_TYPE: if (current.isBoundParameterizedType()) return false; break; case Binding.RAW_TYPE: return true; } if (current.isStatic()) { return true; } if (current.isLocalType()) { LocalTypeBinding localTypeBinding = (LocalTypeBinding) current.erasure(); MethodBinding enclosingMethod = localTypeBinding.enclosingMethod; if (enclosingMethod != null && enclosingMethod.isStatic()) { return true; } } } while ((current = current.enclosingType()) != null); return true; } /** * Returns true if a given type may be thrown */ public boolean isThrowable() { return false; } // JLS3: 4.5.1.1 public boolean isTypeArgumentContainedBy(TypeBinding otherType) { if (this == otherType) return true; switch (otherType.kind()) { // handle captured wildcards. case Binding.TYPE_PARAMETER: { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=347426 if (!isParameterizedType() || !otherType.isCapture()) { return false; } CaptureBinding capture = (CaptureBinding) otherType; WildcardBinding wildcard = capture.wildcard; TypeBinding upperBound = null; TypeBinding [] otherBounds = null; switch (wildcard.boundKind) { case Wildcard.SUPER: return false; // T super syntax isn't allowed, impossible capture. case Wildcard.UNBOUND: TypeVariableBinding variable = wildcard.genericType.typeVariables()[wildcard.rank]; upperBound = variable.upperBound(); otherBounds = variable.boundsCount() > 1 ? variable.otherUpperBounds() : null; break; case Wildcard.EXTENDS: upperBound = wildcard.bound; otherBounds = wildcard.otherBounds; break; } // Given class A>, A cannot be the universe of all parameterizations of A if (upperBound.id == TypeIds.T_JavaLangObject && otherBounds == null) { return false; // but given class A, A stays an unbounded wildcard, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=348956 } otherType = capture.environment.createWildcard(null, 0, upperBound, otherBounds, Wildcard.EXTENDS); return isTypeArgumentContainedBy(otherType); } // allow wildcard containment case Binding.WILDCARD_TYPE: case Binding.INTERSECTION_TYPE: TypeBinding lowerBound = this; TypeBinding upperBound = this; switch (kind()) { case Binding.WILDCARD_TYPE: case Binding.INTERSECTION_TYPE: WildcardBinding wildcard = (WildcardBinding) this; switch (wildcard.boundKind) { case Wildcard.EXTENDS: if (wildcard.otherBounds != null) // intersection type break; upperBound = wildcard.bound; lowerBound = null; break; case Wildcard.SUPER: upperBound = wildcard; lowerBound = wildcard.bound; break; case Wildcard.UNBOUND: upperBound = wildcard; lowerBound = null; } break; case Binding.TYPE_PARAMETER: if (isCapture()) { CaptureBinding capture = (CaptureBinding) this; if (capture.lowerBound != null) lowerBound = capture.lowerBound; } } WildcardBinding otherWildcard = (WildcardBinding) otherType; if (otherWildcard.otherBounds != null) return false; // not a true wildcard (intersection type) TypeBinding otherBound = otherWildcard.bound; switch (otherWildcard.boundKind) { case Wildcard.EXTENDS: if (otherBound == this) return true; // ? extends T <= ? extends ? extends T if (upperBound == null) return false; TypeBinding match = upperBound.findSuperTypeOriginatingFrom(otherBound); if (match != null && (match = match.leafComponentType()).isRawType()) { return match == otherBound.leafComponentType(); // forbide: Collection <= ? extends Collection // forbide: Collection[] <= ? extends Collection[] } return upperBound.isCompatibleWith(otherBound); case Wildcard.SUPER: if (otherBound == this) return true; // ? super T <= ? super ? super T if (lowerBound == null) return false; match = otherBound.findSuperTypeOriginatingFrom(lowerBound); if (match != null && (match = match.leafComponentType()).isRawType()) { return match == lowerBound.leafComponentType(); // forbide: Collection <= ? super Collection // forbide: Collection[] <= ? super Collection[] } return otherBound.isCompatibleWith(lowerBound); case Wildcard.UNBOUND: default: return true; } // allow List to match List (and reciprocally) case Binding.PARAMETERIZED_TYPE: if (!isParameterizedType()) return false; ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) this; ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType; if (paramType.actualType() != otherParamType.actualType()) return false; if (!paramType.isStatic()) { // static member types do not compare their enclosing ReferenceBinding enclosing = enclosingType(); if (enclosing != null) { ReferenceBinding otherEnclosing = otherParamType .enclosingType(); if (otherEnclosing == null) return false; if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) { if (enclosing != otherEnclosing) return false; } else { if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false; } } } int length = paramType.arguments == null ? 0 : paramType.arguments.length; TypeBinding[] otherArguments = otherParamType.arguments; int otherLength = otherArguments == null ? 0 : otherArguments.length; if (otherLength != length) return false; nextArgument: for (int i = 0; i < length; i++) { TypeBinding argument = paramType.arguments[i]; TypeBinding otherArgument = otherArguments[i]; if (argument == otherArgument) continue nextArgument; int kind = argument.kind(); if (otherArgument.kind() != kind) return false; switch (kind) { case Binding.PARAMETERIZED_TYPE: if (argument.isTypeArgumentContainedBy(otherArgument)) // recurse continue nextArgument; break; case Binding.WILDCARD_TYPE: case Binding.INTERSECTION_TYPE: WildcardBinding wildcard = (WildcardBinding) argument; otherWildcard = (WildcardBinding) otherArgument; switch (wildcard.boundKind) { case Wildcard.EXTENDS: // match "? extends " with "?" if (otherWildcard.boundKind == Wildcard.UNBOUND && wildcard.bound == wildcard.typeVariable().upperBound()) continue nextArgument; break; case Wildcard.SUPER: break; case Wildcard.UNBOUND: // match "?" with "? extends " if (otherWildcard.boundKind == Wildcard.EXTENDS && otherWildcard.bound == otherWildcard.typeVariable().upperBound()) continue nextArgument; break; } break; } return false; } return true; } // (? super Object) <= Object if (otherType.id == TypeIds.T_JavaLangObject) { switch (kind()) { case Binding.WILDCARD_TYPE: WildcardBinding wildcard = (WildcardBinding) this; if (wildcard.boundKind == Wildcard.SUPER && wildcard.bound.id == TypeIds.T_JavaLangObject) { return true; } break; } } 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 subclass of java.lang.Error or java.lang.RuntimeException */ public boolean isUncheckedException(boolean includeSupertype) { return false; } /** * Returns true if the type is a wildcard */ public boolean isWildcard() { return false; } /* API * Answer the receiver's binding type from Binding.BindingID. */ public int kind() { return Binding.TYPE; } public TypeBinding leafComponentType() { return this; } /** * Meant to be invoked on compatible types, to figure if unchecked conversion is necessary */ public boolean needsUncheckedConversion(TypeBinding targetType) { if (this == targetType) return false; targetType = targetType.leafComponentType(); if (!(targetType instanceof ReferenceBinding)) return false; TypeBinding currentType = leafComponentType(); TypeBinding match = currentType.findSuperTypeOriginatingFrom(targetType); if (!(match instanceof ReferenceBinding)) return false; ReferenceBinding compatible = (ReferenceBinding) match; while (compatible.isRawType()) { if (targetType.isBoundParameterizedType()) return true; if (compatible.isStatic()) break; if ((compatible = compatible.enclosingType()) == null) break; if ((targetType = targetType.enclosingType()) == null) break; } return false; } /** * Returns the orignal generic type instantiated by the receiver type, or itself if not. * This is similar to erasure process, except it doesn't erase type variable, wildcard, intersection types etc... */ public TypeBinding original() { switch(kind()) { case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : case Binding.ARRAY_TYPE : return erasure(); default : return this; } } /** * Answer the qualified name of the receiver's package separated by periods * or an empty string if its the default package. * * For example, {java.util}. */ public char[] qualifiedPackageName() { PackageBinding packageBinding = getPackage(); return packageBinding == null || packageBinding.compoundName == CharOperation.NO_CHAR_CHAR ? CharOperation.NO_CHAR : packageBinding.readableName(); } /** * Answer the source name for the type. * In the case of member types, as the qualified name from its top level type. * For example, for a member type N defined inside M & A: "A.M.N". */ public abstract char[] qualifiedSourceName(); /** * 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(); public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment environment) { // subclasses must override if they wrap another type binding } public TypeVariableBinding[] typeVariables() { return Binding.NO_TYPE_VARIABLES; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java0000644000175000001440000000266512212041344031402 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; public interface ProblemReasons { final int NoError = 0; final int NotFound = 1; final int NotVisible = 2; final int Ambiguous = 3; final int InternalNameProvided = 4; // used if an internal name is used in source final int InheritedNameHidesEnclosingName = 5; 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; final int InvalidTypeForAutoManagedResource = 15; final int VarargsElementTypeNotVisible = 16; } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/Scope.java0000644000175000001440000057764412212041344027536 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 387612 - Unreachable catch block...exception is never thrown from the try * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * bug 401456 - Code compiles from javac/intellij, but fails from eclipse * bug 401271 - StackOverflowError when searching for a methods references * bug 405706 - Eclipse compiler fails to give compiler error when return type is a inferred generic * Jesper S Moller - Contributions for * Bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.*; 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.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; import org.eclipse.jdt.internal.compiler.util.ObjectVector; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.SimpleSet; public abstract class Scope { /* Scope kinds */ public final static int BLOCK_SCOPE = 1; public final static int CLASS_SCOPE = 3; public final static int COMPILATION_UNIT_SCOPE = 4; public final static int METHOD_SCOPE = 2; /* Argument Compatibilities */ 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; /* Type Compatibilities */ public static final int EQUAL_OR_MORE_SPECIFIC = -1; public static final int NOT_RELATED = 0; public static final int MORE_GENERIC = 1; public int kind; public Scope parent; protected Scope(int kind, Scope parent) { this.kind = kind; this.parent = parent; } /* Answer an int describing the relationship between the given types. * * NOT_RELATED * EQUAL_OR_MORE_SPECIFIC : left is compatible with right * MORE_GENERIC : right is compatible with left */ public static int compareTypes(TypeBinding left, TypeBinding right) { if (left.isCompatibleWith(right)) return Scope.EQUAL_OR_MORE_SPECIFIC; if (right.isCompatibleWith(left)) return Scope.MORE_GENERIC; return Scope.NOT_RELATED; } /** * Returns a type where either all variables or specific ones got discarded. * e.g. List (discarding ) will return: List> */ public static TypeBinding convertEliminatingTypeVariables(TypeBinding originalType, ReferenceBinding genericType, int rank, Set eliminatedVariables) { if ((originalType.tagBits & TagBits.HasTypeVariable) != 0) { switch (originalType.kind()) { case Binding.ARRAY_TYPE : ArrayBinding originalArrayType = (ArrayBinding) originalType; TypeBinding originalLeafComponentType = originalArrayType.leafComponentType; TypeBinding substitute = convertEliminatingTypeVariables(originalLeafComponentType, genericType, rank, eliminatedVariables); // substitute could itself be array type if (substitute != originalLeafComponentType) { return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalArrayType.dimensions()); } break; case Binding.PARAMETERIZED_TYPE : ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType; ReferenceBinding originalEnclosing = paramType.enclosingType(); ReferenceBinding substitutedEnclosing = originalEnclosing; if (originalEnclosing != null) { substitutedEnclosing = (ReferenceBinding) convertEliminatingTypeVariables(originalEnclosing, genericType, rank, eliminatedVariables); } TypeBinding[] originalArguments = paramType.arguments; TypeBinding[] substitutedArguments = originalArguments; for (int i = 0, length = originalArguments == null ? 0 : originalArguments.length; i < length; i++) { TypeBinding originalArgument = originalArguments[i]; TypeBinding substitutedArgument = convertEliminatingTypeVariables(originalArgument, paramType.genericType(), i, eliminatedVariables); if (substitutedArgument != originalArgument) { if (substitutedArguments == originalArguments) { System.arraycopy(originalArguments, 0, substitutedArguments = new TypeBinding[length], 0, i); } substitutedArguments[i] = substitutedArgument; } else if (substitutedArguments != originalArguments) { substitutedArguments[i] = originalArgument; } } if (originalEnclosing != substitutedEnclosing || originalArguments != substitutedArguments) { return paramType.environment.createParameterizedType(paramType.genericType(), substitutedArguments, substitutedEnclosing); } break; case Binding.TYPE_PARAMETER : if (genericType == null) { break; } TypeVariableBinding originalVariable = (TypeVariableBinding) originalType; if (eliminatedVariables != null && eliminatedVariables.contains(originalType)) { return originalVariable.environment.createWildcard(genericType, rank, null, null, Wildcard.UNBOUND); } TypeBinding originalUpperBound = originalVariable.upperBound(); if (eliminatedVariables == null) { eliminatedVariables = new HashSet(2); } eliminatedVariables.add(originalVariable); TypeBinding substitutedUpperBound = convertEliminatingTypeVariables(originalUpperBound, genericType, rank, eliminatedVariables); eliminatedVariables.remove(originalVariable); return originalVariable.environment.createWildcard(genericType, rank, substitutedUpperBound, null, Wildcard.EXTENDS); case Binding.RAW_TYPE : break; case Binding.GENERIC_TYPE : ReferenceBinding currentType = (ReferenceBinding) originalType; originalEnclosing = currentType.enclosingType(); substitutedEnclosing = originalEnclosing; if (originalEnclosing != null) { substitutedEnclosing = (ReferenceBinding) convertEliminatingTypeVariables(originalEnclosing, genericType, rank, eliminatedVariables); } originalArguments = currentType.typeVariables(); substitutedArguments = originalArguments; for (int i = 0, length = originalArguments == null ? 0 : originalArguments.length; i < length; i++) { TypeBinding originalArgument = originalArguments[i]; TypeBinding substitutedArgument = convertEliminatingTypeVariables(originalArgument, currentType, i, eliminatedVariables); if (substitutedArgument != originalArgument) { if (substitutedArguments == originalArguments) { System.arraycopy(originalArguments, 0, substitutedArguments = new TypeBinding[length], 0, i); } substitutedArguments[i] = substitutedArgument; } else if (substitutedArguments != originalArguments) { substitutedArguments[i] = originalArgument; } } if (originalEnclosing != substitutedEnclosing || originalArguments != substitutedArguments) { return ((TypeVariableBinding)originalArguments[0]).environment.createParameterizedType(genericType, substitutedArguments, substitutedEnclosing); } break; case Binding.WILDCARD_TYPE : WildcardBinding wildcard = (WildcardBinding) originalType; TypeBinding originalBound = wildcard.bound; TypeBinding substitutedBound = originalBound; if (originalBound != null) { substitutedBound = convertEliminatingTypeVariables(originalBound, genericType, rank, eliminatedVariables); if (substitutedBound != originalBound) { return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, null, wildcard.boundKind); } } break; case Binding.INTERSECTION_TYPE : WildcardBinding intersection = (WildcardBinding) originalType; originalBound = intersection.bound; substitutedBound = originalBound; if (originalBound != null) { substitutedBound = convertEliminatingTypeVariables(originalBound, genericType, rank, eliminatedVariables); } TypeBinding[] originalOtherBounds = intersection.otherBounds; TypeBinding[] substitutedOtherBounds = originalOtherBounds; for (int i = 0, length = originalOtherBounds == null ? 0 : originalOtherBounds.length; i < length; i++) { TypeBinding originalOtherBound = originalOtherBounds[i]; TypeBinding substitutedOtherBound = convertEliminatingTypeVariables(originalOtherBound, genericType, rank, eliminatedVariables); if (substitutedOtherBound != originalOtherBound) { if (substitutedOtherBounds == originalOtherBounds) { System.arraycopy(originalOtherBounds, 0, substitutedOtherBounds = new TypeBinding[length], 0, i); } substitutedOtherBounds[i] = substitutedOtherBound; } else if (substitutedOtherBounds != originalOtherBounds) { substitutedOtherBounds[i] = originalOtherBound; } } if (substitutedBound != originalBound || substitutedOtherBounds != originalOtherBounds) { return intersection.environment.createWildcard(intersection.genericType, intersection.rank, substitutedBound, substitutedOtherBounds, intersection.boundKind); } break; } } return originalType; } public static TypeBinding getBaseType(char[] name) { // list should be optimized (with most often used first) int length = name.length; if (length > 2 && length < 8) { switch (name[0]) { case 'i' : if (length == 3 && name[1] == 'n' && name[2] == 't') return TypeBinding.INT; break; case 'v' : if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd') return TypeBinding.VOID; break; case 'b' : if (length == 7 && name[1] == 'o' && name[2] == 'o' && name[3] == 'l' && name[4] == 'e' && name[5] == 'a' && name[6] == 'n') return TypeBinding.BOOLEAN; if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e') return TypeBinding.BYTE; break; case 'c' : if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r') return TypeBinding.CHAR; break; case 'd' : if (length == 6 && name[1] == 'o' && name[2] == 'u' && name[3] == 'b' && name[4] == 'l' && name[5] == 'e') return TypeBinding.DOUBLE; break; case 'f' : if (length == 5 && name[1] == 'l' && name[2] == 'o' && name[3] == 'a' && name[4] == 't') return TypeBinding.FLOAT; break; case 'l' : if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') return TypeBinding.LONG; break; case 's' : if (length == 5 && name[1] == 'h' && name[2] == 'o' && name[3] == 'r' && name[4] == 't') return TypeBinding.SHORT; } } return null; } // 5.1.10 public static ReferenceBinding[] greaterLowerBound(ReferenceBinding[] types) { if (types == null) return null; int length = types.length; if (length == 0) return null; ReferenceBinding[] result = types; int removed = 0; for (int i = 0; i < length; i++) { ReferenceBinding iType = result[i]; if (iType == null) continue; for (int j = 0; j < length; j++) { if (i == j) continue; ReferenceBinding 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 ReferenceBinding[length], 0, length); } result[j] = null; removed ++; } } } if (removed == 0) return result; if (length == removed) return null; ReferenceBinding[] trimmedResult = new ReferenceBinding[length - removed]; for (int i = 0, index = 0; i < length; i++) { ReferenceBinding iType = result[i]; if (iType != null) { trimmedResult[index++] = iType; } } return trimmedResult; } // 5.1.10 public static TypeBinding[] greaterLowerBound(TypeBinding[] types, /*@Nullable*/ Scope scope) { if (types == null) return null; int length = types.length; if (length == 0) return null; TypeBinding[] result = types; int removed = 0; for (int i = 0; i < length; i++) { TypeBinding iType = result[i]; if (iType == null) continue; for (int j = 0; j < length; j++) { if (i == j) continue; TypeBinding jType = result[j]; if (jType == null) continue; if (iType.isCompatibleWith(jType, scope)) { // 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 ++; } else if (!jType.isCompatibleWith(iType, scope)) { // avoid creating unsatisfiable intersection types (see https://bugs.eclipse.org/405706): if (iType.isParameterizedType() && jType.isParameterizedType()) { if (iType.original().isCompatibleWith(jType.original(), scope) || jType.original().isCompatibleWith(iType.original(), scope)) { // parameterized types are incompatible due to incompatible type arguments => unsatisfiable return null; } } } } } if (removed == 0) return result; if (length == removed) return null; // how is this possible ??? 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; } /** * 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) { if (originalTypes == null) return null; ReferenceBinding[] substitutedTypes = originalTypes; for (int i = 0, length = originalTypes.length; i < length; i++) { ReferenceBinding originalType = originalTypes[i]; TypeBinding substitutedType = substitute(substitution, originalType); if (!(substitutedType instanceof ReferenceBinding)) { return null; // impossible substitution } if (substitutedType != originalType) { if (substitutedTypes == originalTypes) { System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i); } substitutedTypes[i] = (ReferenceBinding)substitutedType; } else if (substitutedTypes != originalTypes) { substitutedTypes[i] = originalType; } } return substitutedTypes; } /** * Returns a type, where original type was substituted using the receiver * parameterized type. * In raw mode (see {@link Substitution#isRawSubstitution()}), * all parameterized types are converted to raw types. * Cf. 4.8: "The type of a constructor (8.8), instance method (8.4, 9.4), * or non-static field (8.3) M of a raw type C that is not inherited from its * superclasses or superinterfaces is the raw type that corresponds to the erasure * of its type in the generic declaration corresponding to C." */ public static TypeBinding substitute(Substitution substitution, TypeBinding originalType) { if (originalType == null) return null; switch (originalType.kind()) { case Binding.TYPE_PARAMETER: return substitution.substitute((TypeVariableBinding) originalType); case Binding.PARAMETERIZED_TYPE: ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType; ReferenceBinding originalEnclosing = originalType.enclosingType(); ReferenceBinding substitutedEnclosing = originalEnclosing; if (originalEnclosing != null) { substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing); if (isMemberTypeOfRaw(originalType, substitutedEnclosing)) return originalParameterizedType.environment.createRawType( originalParameterizedType.genericType(), substitutedEnclosing); } TypeBinding[] originalArguments = originalParameterizedType.arguments; TypeBinding[] substitutedArguments = originalArguments; if (originalArguments != null) { if (substitution.isRawSubstitution()) { return originalParameterizedType.environment.createRawType(originalParameterizedType.genericType(), substitutedEnclosing); } substitutedArguments = substitute(substitution, originalArguments); } if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) { return originalParameterizedType.environment.createParameterizedType( originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing); } break; case Binding.ARRAY_TYPE: ArrayBinding originalArrayType = (ArrayBinding) originalType; TypeBinding originalLeafComponentType = originalArrayType.leafComponentType; TypeBinding substitute = substitute(substitution, originalLeafComponentType); // substitute could itself be array type if (substitute != originalLeafComponentType) { return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions()); } break; case Binding.WILDCARD_TYPE: case Binding.INTERSECTION_TYPE: WildcardBinding wildcard = (WildcardBinding) originalType; if (wildcard.boundKind != Wildcard.UNBOUND) { TypeBinding originalBound = wildcard.bound; TypeBinding substitutedBound = substitute(substitution, originalBound); TypeBinding[] originalOtherBounds = wildcard.otherBounds; TypeBinding[] substitutedOtherBounds = substitute(substitution, originalOtherBounds); if (substitutedBound != originalBound || originalOtherBounds != substitutedOtherBounds) { if (originalOtherBounds != null) { /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=347145: the constituent intersecting types have changed in the last round of substitution. Reevaluate the composite intersection type, as there is a possibility of the intersection collapsing into one of the constituents, the other being fully subsumed. */ TypeBinding [] bounds = new TypeBinding[1 + substitutedOtherBounds.length]; bounds[0] = substitutedBound; System.arraycopy(substitutedOtherBounds, 0, bounds, 1, substitutedOtherBounds.length); TypeBinding[] glb = Scope.greaterLowerBound(bounds, null); // re-evaluate if (glb != null && glb != bounds) { substitutedBound = glb[0]; if (glb.length == 1) { substitutedOtherBounds = null; } else { System.arraycopy(glb, 1, substitutedOtherBounds = new TypeBinding[glb.length - 1], 0, glb.length - 1); } } } return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, substitutedOtherBounds, wildcard.boundKind); } } break; case Binding.TYPE: if (!originalType.isMemberType()) break; ReferenceBinding originalReferenceType = (ReferenceBinding) originalType; originalEnclosing = originalType.enclosingType(); substitutedEnclosing = originalEnclosing; if (originalEnclosing != null) { substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing); if (isMemberTypeOfRaw(originalType, substitutedEnclosing)) return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing); } // treat as if parameterized with its type variables (non generic type gets 'null' arguments) if (substitutedEnclosing != originalEnclosing) { return substitution.isRawSubstitution() ? substitution.environment().createRawType(originalReferenceType, substitutedEnclosing) : substitution.environment().createParameterizedType(originalReferenceType, null, substitutedEnclosing); } break; case Binding.GENERIC_TYPE: originalReferenceType = (ReferenceBinding) originalType; originalEnclosing = originalType.enclosingType(); substitutedEnclosing = originalEnclosing; if (originalEnclosing != null) { substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing); if (isMemberTypeOfRaw(originalType, substitutedEnclosing)) return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing); } if (substitution.isRawSubstitution()) { return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing); } // treat as if parameterized with its type variables (non generic type gets 'null' arguments) originalArguments = originalReferenceType.typeVariables(); substitutedArguments = substitute(substitution, originalArguments); return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing); } return originalType; } private static boolean isMemberTypeOfRaw(TypeBinding originalType, ReferenceBinding substitutedEnclosing) { // 4.8: // "a raw type is defined to be one of: // ... // * A non-static member type of a raw type R that is not // inherited from a superclass or superinterface of R." // Due to staticness, e.g., Map.Entry is *not* considered as a raw type return (substitutedEnclosing != null && substitutedEnclosing.isRawType()) && ((originalType instanceof ReferenceBinding) && !((ReferenceBinding)originalType).isStatic()); } /** * 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) { if (originalTypes == null) return null; TypeBinding[] substitutedTypes = originalTypes; for (int i = 0, length = originalTypes.length; i < length; i++) { TypeBinding originalType = originalTypes[i]; TypeBinding substitutedParameter = substitute(substitution, 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; } /* * Boxing primitive */ public TypeBinding boxing(TypeBinding type) { if (type.isBaseType()) return environment().computeBoxingType(type); return type; } public final ClassScope classScope() { Scope scope = this; do { if (scope instanceof ClassScope) return (ClassScope) scope; scope = scope.parent; } while (scope != null); return null; } public final CompilationUnitScope compilationUnitScope() { Scope lastScope = null; Scope scope = this; do { lastScope = scope; scope = scope.parent; } while (scope != null); return (CompilationUnitScope) lastScope; } /** * Finds the most specific compiler options */ public final CompilerOptions compilerOptions() { return compilationUnitScope().environment.globalOptions; } /** * Internal use only * Given a method, returns null if arguments cannot be converted to parameters. * Will answer a substituted 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) { return computeCompatibleMethod(method, arguments, invocationSite, false); } /** * Internal use only * Given a method, returns null if arguments cannot be converted to parameters. * Will answer a substituted 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, boolean tiebreakingVarargsMethods) { TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments(); TypeBinding[] parameters = method.parameters; TypeVariableBinding[] typeVariables = method.typeVariables; if (parameters == arguments && (method.returnType.tagBits & TagBits.HasTypeVariable) == 0 && genericTypeArguments == null && typeVariables == Binding.NO_TYPE_VARIABLES) 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 CompilerOptions compilerOptions = this.compilerOptions(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=330435, inference should kick in only at source 1.5+ if (typeVariables != Binding.NO_TYPE_VARIABLES && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) { // generic method TypeBinding[] newArgs = null; for (int i = 0; i < argLength; i++) { TypeBinding param = i < paramLength ? parameters[i] : parameters[paramLength - 1]; if (arguments[i].isBaseType() != param.isBaseType()) { if (newArgs == null) { newArgs = new TypeBinding[argLength]; System.arraycopy(arguments, 0, newArgs, 0, argLength); } newArgs[i] = environment().computeBoxingType(arguments[i]); } } if (newArgs != null) arguments = newArgs; method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite); if (method == null) return null; // incompatible if (!method.isValidBinding()) return method; // bound check issue is taking precedence } else if (genericTypeArguments != null && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) { 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, ProblemReasons.TypeArgumentsForRawGenericMethod); } else if (!method.isOverriding() || !isOverriddenMethodGeneric(method)) { return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.TypeParameterArityMismatch); } } int compatibilityLevel; if (tiebreakingVarargsMethods) { if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) tiebreakingVarargsMethods = false; } if ((compatibilityLevel = parameterCompatibilityLevel(method, arguments, tiebreakingVarargsMethods)) > NOT_COMPATIBLE) { if (compatibilityLevel == VARARGS_COMPATIBLE) { TypeBinding varargsElementType = method.parameters[method.parameters.length - 1].leafComponentType(); if (varargsElementType instanceof ReferenceBinding) { if (!((ReferenceBinding) varargsElementType).canBeSeenBy(this)) { return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.VarargsElementTypeNotVisible); } } } if ((method.tagBits & TagBits.AnnotationPolymorphicSignature) != 0) { // generate polymorphic method return this.environment().createPolymorphicMethod(method, arguments); } return method; } // if method is generic and type arguments have been supplied, only then answer a problem // of ParameterizedMethodTypeMismatch, else a non-generic method was invoked using type arguments // in which case this problem category will be bogus if (genericTypeArguments != null && typeVariables != Binding.NO_TYPE_VARIABLES) return new ProblemMethodBinding(method, method.selector, arguments, ProblemReasons.ParameterizedMethodTypeMismatch); return null; // incompatible } /** * Connect type variable supertypes, and returns true if no problem was detected * @param typeParameters * @param checkForErasedCandidateCollisions */ protected boolean connectTypeVariables(TypeParameter[] typeParameters, boolean checkForErasedCandidateCollisions) { /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 - We used to not bother with connecting type variables if source level is < 1.5. This creates problems in the reconciler if a 1.4 project references the generified API of a 1.5 project. The "current" project's source level cannot decide this question for some other project. Now, if we see type parameters at all, we assume that the concerned java element has some legitimate business with them. */ if (typeParameters == null || typeParameters.length == 0) return true; Map invocations = new HashMap(2); boolean noProblems = true; // preinitializing each type variable 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 = Binding.NO_SUPERINTERFACES; // set firstBound to the binding of the first explicit bound in parameter declaration typeVariable.firstBound = null; // first bound used to compute erasure } nextVariable: for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) { TypeParameter typeParameter = typeParameters[i]; TypeVariableBinding typeVariable = typeParameter.binding; TypeReference typeRef = typeParameter.type; if (typeRef == null) continue nextVariable; boolean isFirstBoundTypeVariable = false; TypeBinding superType = this.kind == METHOD_SCOPE ? typeRef.resolveType((BlockScope)this, false/*no bound check*/) : typeRef.resolveType((ClassScope)this); if (superType == null) { typeVariable.tagBits |= TagBits.HierarchyHasProblems; } else { typeRef.resolvedType = superType; // hold onto the problem type firstBound: { switch (superType.kind()) { case Binding.ARRAY_TYPE : problemReporter().boundCannotBeArray(typeRef, superType); typeVariable.tagBits |= TagBits.HierarchyHasProblems; break firstBound; // do not keep first bound case Binding.TYPE_PARAMETER : isFirstBoundTypeVariable = true; TypeVariableBinding varSuperType = (TypeVariableBinding) superType; if (varSuperType.rank >= typeVariable.rank && varSuperType.declaringElement == typeVariable.declaringElement) { if (compilerOptions().complianceLevel <= ClassFileConstants.JDK1_6) { problemReporter().forwardTypeVariableReference(typeParameter, varSuperType); typeVariable.tagBits |= TagBits.HierarchyHasProblems; break firstBound; // do not keep first bound } } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=335751 if (compilerOptions().complianceLevel > ClassFileConstants.JDK1_6) { if (typeVariable.rank >= varSuperType.rank && varSuperType.declaringElement == typeVariable.declaringElement) { SimpleSet set = new SimpleSet(typeParameters.length); set.add(typeVariable); ReferenceBinding superBinding = varSuperType; while (superBinding instanceof TypeVariableBinding) { if (set.includes(superBinding)) { problemReporter().hierarchyCircularity(typeVariable, varSuperType, typeRef); typeVariable.tagBits |= TagBits.HierarchyHasProblems; break firstBound; // do not keep first bound } else { set.add(superBinding); superBinding = ((TypeVariableBinding)superBinding).superclass; } } } } break; default : if (((ReferenceBinding) superType).isFinal()) { problemReporter().finalVariableBound(typeVariable, typeRef); } break; } ReferenceBinding superRefType = (ReferenceBinding) superType; if (!superType.isInterface()) { typeVariable.superclass = superRefType; } else { typeVariable.superInterfaces = new ReferenceBinding[] {superRefType}; } typeVariable.tagBits |= superType.tagBits & TagBits.ContainsNestedTypeReferences; typeVariable.firstBound = superRefType; // first bound used to compute erasure } } TypeReference[] boundRefs = typeParameter.bounds; if (boundRefs != null) { nextBound: for (int j = 0, boundLength = boundRefs.length; j < boundLength; j++) { typeRef = boundRefs[j]; superType = this.kind == METHOD_SCOPE ? typeRef.resolveType((BlockScope)this, false) : typeRef.resolveType((ClassScope)this); if (superType == null) { typeVariable.tagBits |= TagBits.HierarchyHasProblems; continue nextBound; } else { typeVariable.tagBits |= superType.tagBits & TagBits.ContainsNestedTypeReferences; boolean didAlreadyComplain = !typeRef.resolvedType.isValidBinding(); if (isFirstBoundTypeVariable && j == 0) { problemReporter().noAdditionalBoundAfterTypeVariable(typeRef); typeVariable.tagBits |= TagBits.HierarchyHasProblems; didAlreadyComplain = true; //continue nextBound; - keep these bounds to minimize secondary errors } else if (superType.isArrayType()) { if (!didAlreadyComplain) { problemReporter().boundCannotBeArray(typeRef, superType); typeVariable.tagBits |= TagBits.HierarchyHasProblems; } continue nextBound; } else { if (!superType.isInterface()) { if (!didAlreadyComplain) { problemReporter().boundMustBeAnInterface(typeRef, superType); typeVariable.tagBits |= TagBits.HierarchyHasProblems; } continue nextBound; } } // check against superclass if (checkForErasedCandidateCollisions && typeVariable.firstBound == typeVariable.superclass) { if (hasErasedCandidatesCollisions(superType, typeVariable.superclass, invocations, typeVariable, typeRef)) { continue nextBound; } } // check against superinterfaces ReferenceBinding superRefType = (ReferenceBinding) superType; for (int index = typeVariable.superInterfaces.length; --index >= 0;) { ReferenceBinding previousInterface = typeVariable.superInterfaces[index]; if (previousInterface == superRefType) { problemReporter().duplicateBounds(typeRef, superType); typeVariable.tagBits |= TagBits.HierarchyHasProblems; continue nextBound; } if (checkForErasedCandidateCollisions) { if (hasErasedCandidatesCollisions(superType, previousInterface, invocations, typeVariable, typeRef)) { continue nextBound; } } } int size = typeVariable.superInterfaces.length; System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.superInterfaces = new ReferenceBinding[size + 1], 0, size); typeVariable.superInterfaces[size] = superRefType; } } } noProblems &= (typeVariable.tagBits & TagBits.HierarchyHasProblems) == 0; } return noProblems; } 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 TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, If they exist at all, process type parameters irrespective of source level. if (typeParameters == null || typeParameters.length == 0) return Binding.NO_TYPE_VARIABLES; PackageBinding unitPackage = compilationUnitScope().fPackage; int length = typeParameters.length; TypeVariableBinding[] typeVariableBindings = new TypeVariableBinding[length]; int count = 0; for (int i = 0; i < length; i++) { TypeParameter typeParameter = typeParameters[i]; TypeVariableBinding parameterBinding = new TypeVariableBinding(typeParameter.name, declaringElement, i, environment()); parameterBinding.fPackage = unitPackage; typeParameter.binding = parameterBinding; // detect duplicates, but keep each variable to reduce secondary errors with instantiating this generic type (assume number of variables is correct) for (int j = 0; j < count; j++) { TypeVariableBinding knownVar = typeVariableBindings[j]; if (CharOperation.equals(knownVar.sourceName, typeParameter.name)) problemReporter().duplicateTypeParameterInType(typeParameter); } 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; } return null; // may answer null if no type around } public final MethodScope enclosingMethodScope() { Scope scope = this; while ((scope = scope.parent) != null) { if (scope instanceof MethodScope) return (MethodScope) scope; } return null; // may answer null if no method around } /* Answer the scope receiver type (could be parameterized) */ public final ReferenceBinding enclosingReceiverType() { Scope scope = this; do { if (scope instanceof ClassScope) { return environment().convertToParameterizedType(((ClassScope) scope).referenceContext.binding); } scope = scope.parent; } while (scope != null); return null; } /** * Returns the immediately enclosing reference context, starting from current scope parent. * If starting on a class, it will skip current class. If starting on unitScope, returns null. */ public ReferenceContext enclosingReferenceContext() { Scope current = this; while ((current = current.parent) != null) { switch(current.kind) { case METHOD_SCOPE : return ((MethodScope) current).referenceContext; case CLASS_SCOPE : return ((ClassScope) current).referenceContext; case COMPILATION_UNIT_SCOPE : return ((CompilationUnitScope) current).referenceContext; } } return null; } /* Answer the scope enclosing source type (could be generic) */ public final SourceTypeBinding enclosingSourceType() { Scope scope = this; do { if (scope instanceof ClassScope) return ((ClassScope) scope).referenceContext.binding; scope = scope.parent; } while (scope != null); return null; } public final LookupEnvironment environment() { Scope scope, unitScope = this; while ((scope = unitScope.parent) != null) unitScope = scope; return ((CompilationUnitScope) unitScope).environment; } // abstract method lookup lookup (since maybe missing default abstract methods) protected MethodBinding findDefaultAbstractMethod( ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite, ReferenceBinding classHierarchyStart, ObjectVector found, MethodBinding concreteMatch) { int startFoundSize = found.size; ReferenceBinding currentType = classHierarchyStart; while (currentType != null) { findMethodInSuperInterfaces(currentType, selector, found, invocationSite); currentType = currentType.superclass(); } MethodBinding[] candidates = null; int candidatesCount = 0; MethodBinding problemMethod = null; int foundSize = found.size; if (foundSize > startFoundSize) { // argument type compatibility check for (int i = startFoundSize; i < foundSize; i++) { MethodBinding methodBinding = (MethodBinding) found.elementAt(i); MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) { if (concreteMatch != null && environment().methodVerifier().areMethodsCompatible(concreteMatch, compatibleMethod)) continue; // can skip this method since concreteMatch overrides it if (candidatesCount == 0) { candidates = new MethodBinding[foundSize - startFoundSize + 1]; if (concreteMatch != null) candidates[candidatesCount++] = concreteMatch; } candidates[candidatesCount++] = compatibleMethod; } else if (problemMethod == null) { problemMethod = compatibleMethod; } } } } if (candidatesCount < 2) { if (concreteMatch == null) { if (candidatesCount == 0) return problemMethod; // can be null concreteMatch = candidates[0]; } compilationUnitScope().recordTypeReferences(concreteMatch.thrownExceptions); return concreteMatch; } // no need to check for visibility - interface methods are public if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite, receiverType); return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite); } // Internal use only public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) { if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0) return null; // know it has no member types (nor inherited member types) ReferenceBinding enclosingReceiverType = enclosingReceiverType(); CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordReference(enclosingType, typeName); ReferenceBinding memberType = enclosingType.getMemberType(typeName); if (memberType != null) { unitScope.recordTypeReference(memberType); if (enclosingReceiverType == null) { if (memberType.canBeSeenBy(getCurrentPackage())) { return memberType; } // maybe some type in the compilation unit is extending some class in some package // and the selection is for some protected inner class of that superclass // https://bugs.eclipse.org/bugs/show_bug.cgi?id=235658 if (this instanceof CompilationUnitScope) { TypeDeclaration[] types = ((CompilationUnitScope)this).referenceContext.types; if (types != null) { for (int i = 0, max = types.length; i < max; i++) { if (memberType.canBeSeenBy(enclosingType, types[i].binding)) { return memberType; } } } } } else if (memberType.canBeSeenBy(enclosingType, enclosingReceiverType)) { return memberType; } return new ProblemReferenceBinding(new char[][]{typeName}, memberType, ProblemReasons.NotVisible); } return null; } // Internal use only public MethodBinding findExactMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordTypeReferences(argumentTypes); MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope); if (exactMethod != null && exactMethod.typeVariables == Binding.NO_TYPE_VARIABLES && !exactMethod.isBridge()) { // in >= 1.5 mode, ensure the exactMatch did not match raw types if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) for (int i = argumentTypes.length; --i >= 0;) if (isPossibleSubtypeOfRawType(argumentTypes[i])) return null; // must find both methods for this case: void foo() {} and N foo() { return null; } // or find an inherited method when the exact match is to a bridge method unitScope.recordTypeReferences(exactMethod.thrownExceptions); if (exactMethod.isAbstract() && exactMethod.thrownExceptions != Binding.NO_EXCEPTIONS) return null; // may need to merge exceptions with interface method // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) { if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, TypeConstants.GETCLASS) && exactMethod.returnType.isParameterizedType()/*1.5*/) { return environment().createGetClassMethod(receiverType, exactMethod, this); } // targeting a generic method could find an exact match with variable return type if (invocationSite.genericTypeArguments() != null) { // computeCompatibleMethod(..) will return a PolymorphicMethodBinding if needed exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite); } else if ((exactMethod.tagBits & TagBits.AnnotationPolymorphicSignature) != 0) { // generate polymorphic method return this.environment().createPolymorphicMethod(exactMethod, argumentTypes); } return exactMethod; } } return null; } // Internal use only /* Answer the field binding that corresponds to fieldName. Start the lookup at the receiverType. InvocationSite implements isSuperAccess(); this is used to determine if the discovered field is visible. Only fields defined by the receiverType or its supertypes are answered; a field of an enclosing type will not be found using this API. If no visible field is discovered, null is answered. */ public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) { return findField(receiverType, fieldName, invocationSite, needResolve, false); } // Internal use only /* Answer the field binding that corresponds to fieldName. Start the lookup at the receiverType. InvocationSite implements isSuperAccess(); this is used to determine if the discovered field is visible. Only fields defined by the receiverType or its supertypes are answered; a field of an enclosing type will not be found using this API. If the parameter invisibleFieldsOk is true, visibility checks have not been run on any returned fields. The caller needs to apply these checks as needed. Otherwise, If no visible field is discovered, null is answered. */ public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve, boolean invisibleFieldsOk) { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordTypeReference(receiverType); checkArrayField: { TypeBinding leafType; switch (receiverType.kind()) { case Binding.BASE_TYPE : return null; case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE: case Binding.TYPE_PARAMETER : // capture TypeBinding receiverErasure = receiverType.erasure(); if (!receiverErasure.isArrayType()) break checkArrayField; leafType = receiverErasure.leafComponentType(); break; case Binding.ARRAY_TYPE : leafType = receiverType.leafComponentType(); break; default: break checkArrayField; } if (leafType instanceof ReferenceBinding) if (!((ReferenceBinding) leafType).canBeSeenBy(this)) return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ProblemReasons.ReceiverTypeNotVisible); if (CharOperation.equals(fieldName, TypeConstants.LENGTH)) { if ((leafType.tagBits & TagBits.HasMissingType) != 0) { return new ProblemFieldBinding(ArrayBinding.ArrayLength, null, fieldName, ProblemReasons.NotFound); } return ArrayBinding.ArrayLength; } return null; } ReferenceBinding currentType = (ReferenceBinding) receiverType; if (!currentType.canBeSeenBy(this)) return new ProblemFieldBinding(currentType, fieldName, ProblemReasons.ReceiverTypeNotVisible); currentType.initializeForStaticImports(); FieldBinding field = currentType.getField(fieldName, needResolve); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=316456 boolean insideTypeAnnotations = this instanceof MethodScope && ((MethodScope) this).insideTypeAnnotation; if (field != null) { if (invisibleFieldsOk) { return field; } if (invocationSite == null || insideTypeAnnotations ? field.canBeSeenBy(getCurrentPackage()) : field.canBeSeenBy(currentType, invocationSite, this)) return field; return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, ProblemReasons.NotVisible); } // collect all superinterfaces of receiverType until the field is found in a supertype ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; FieldBinding visibleField = null; boolean keepLooking = true; FieldBinding notVisibleField = null; // we could hold onto the not visible field for extra error reporting while (keepLooking) { ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } if ((currentType = currentType.superclass()) == null) break; unitScope.recordTypeReference(currentType); currentType.initializeForStaticImports(); currentType = (ReferenceBinding) currentType.capture(this, invocationSite == null ? 0 : invocationSite.sourceEnd()); if ((field = currentType.getField(fieldName, needResolve)) != null) { if (invisibleFieldsOk) { return field; } keepLooking = false; if (field.canBeSeenBy(receiverType, invocationSite, this)) { if (visibleField == null) visibleField = field; else return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous); } else { if (notVisibleField == null) notVisibleField = field; } } } // walk all visible interfaces to find ambiguous references if (interfacesToVisit != null) { ProblemFieldBinding ambiguous = null; done : for (int i = 0; i < nextPosition; i++) { ReferenceBinding anInterface = interfacesToVisit[i]; unitScope.recordTypeReference(anInterface); // no need to capture rcv interface, since member field is going to be static anyway if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) { if (invisibleFieldsOk) { return field; } if (visibleField == null) { visibleField = field; } else { ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous); break done; } } else { ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } if (ambiguous != null) return ambiguous; } if (visibleField != null) return visibleField; if (notVisibleField != null) { return new ProblemFieldBinding(notVisibleField, currentType, fieldName, ProblemReasons.NotVisible); } return null; } // Internal use only public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) { if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0) return null; // know it has no member types (nor inherited member types) ReferenceBinding enclosingSourceType = enclosingSourceType(); PackageBinding currentPackage = getCurrentPackage(); CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordReference(enclosingType, typeName); ReferenceBinding memberType = enclosingType.getMemberType(typeName); if (memberType != null) { unitScope.recordTypeReference(memberType); if (enclosingSourceType == null || (this.parent == unitScope && (enclosingSourceType.tagBits & TagBits.TypeVariablesAreConnected) == 0) ? memberType.canBeSeenBy(currentPackage) : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) return memberType; return new ProblemReferenceBinding(new char[][]{typeName}, memberType, ProblemReasons.NotVisible); } // collect all superinterfaces of receiverType until the memberType is found in a supertype ReferenceBinding currentType = enclosingType; ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; ReferenceBinding visibleMemberType = null; boolean keepLooking = true; ReferenceBinding notVisible = null; // 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 ReferenceBinding sourceType = currentType.isParameterizedType() ? ((ParameterizedTypeBinding) currentType).genericType() : currentType; if (sourceType.isHierarchyBeingConnected()) return null; // looking for an undefined member type in its own superclass ref ((SourceTypeBinding) sourceType).scope.connectTypeHierarchy(); itsInterfaces = currentType.superInterfaces(); } if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } if ((currentType = currentType.superclass()) == null) break; unitScope.recordReference(currentType, typeName); if ((memberType = currentType.getMemberType(typeName)) != null) { unitScope.recordTypeReference(memberType); keepLooking = false; if (enclosingSourceType == null ? memberType.canBeSeenBy(currentPackage) : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) { if (visibleMemberType == null) visibleMemberType = memberType; else return new ProblemReferenceBinding(new char[][]{typeName}, visibleMemberType, ProblemReasons.Ambiguous); } else { notVisible = memberType; } } } // walk all visible interfaces to find ambiguous references if (interfacesToVisit != null) { ProblemReferenceBinding ambiguous = null; done : for (int i = 0; i < nextPosition; i++) { ReferenceBinding anInterface = interfacesToVisit[i]; unitScope.recordReference(anInterface, typeName); if ((memberType = anInterface.getMemberType(typeName)) != null) { unitScope.recordTypeReference(memberType); if (visibleMemberType == null) { visibleMemberType = memberType; } else { ambiguous = new ProblemReferenceBinding(new char[][]{typeName}, visibleMemberType, ProblemReasons.Ambiguous); break done; } } else { ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } if (ambiguous != null) return ambiguous; } if (visibleMemberType != null) return visibleMemberType; if (notVisible != null) return new ProblemReferenceBinding(new char[][]{typeName}, notVisible, ProblemReasons.NotVisible); return null; } // Internal use only - use findMethod() public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { return findMethod(receiverType, selector, argumentTypes, invocationSite, false); } // Internal use only - use findMethod() public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite, boolean inStaticContext) { ReferenceBinding currentType = receiverType; boolean receiverTypeIsInterface = receiverType.isInterface(); ObjectVector found = new ObjectVector(3); CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordTypeReferences(argumentTypes); if (receiverTypeIsInterface) { unitScope.recordTypeReference(receiverType); MethodBinding[] receiverMethods = receiverType.getMethods(selector, argumentTypes.length); if (receiverMethods.length > 0) found.addAll(receiverMethods); findMethodInSuperInterfaces(receiverType, selector, found, invocationSite); currentType = getJavaLangObject(); } // superclass lookup long complianceLevel = compilerOptions().complianceLevel; boolean isCompliant14 = complianceLevel >= ClassFileConstants.JDK1_4; boolean isCompliant15 = complianceLevel >= ClassFileConstants.JDK1_5; ReferenceBinding classHierarchyStart = currentType; MethodVerifier verifier = environment().methodVerifier(); while (currentType != null) { unitScope.recordTypeReference(currentType); currentType = (ReferenceBinding) currentType.capture(this, invocationSite == null ? 0 : invocationSite.sourceEnd()); MethodBinding[] currentMethods = currentType.getMethods(selector, argumentTypes.length); int currentLength = currentMethods.length; if (currentLength > 0) { if (isCompliant14 && (receiverTypeIsInterface || found.size > 0)) { nextMethod: for (int i = 0, l = currentLength; i < l; i++) { // currentLength can be modified inside the loop MethodBinding currentMethod = currentMethods[i]; if (currentMethod == null) continue nextMethod; if (receiverTypeIsInterface && !currentMethod.isPublic()) { // only public methods from Object are visible to interface receiverTypes currentLength--; currentMethods[i] = null; continue nextMethod; } // 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; // BUT we can also ignore any overridden method since we already know the better match (fixes 80028) for (int j = 0, max = found.size; j < max; j++) { MethodBinding matchingMethod = (MethodBinding) found.elementAt(j); MethodBinding matchingOriginal = matchingMethod.original(); MethodBinding currentOriginal = matchingOriginal.findOriginalInheritedMethod(currentMethod); if (currentOriginal != null && verifier.isParameterSubsignature(matchingOriginal, currentOriginal)) { if (isCompliant15) { if (matchingMethod.isBridge() && !currentMethod.isBridge()) continue nextMethod; // keep inherited methods to find concrete method over a bridge method } currentLength--; currentMethods[i] = null; continue nextMethod; } } } } if (currentLength > 0) { // append currentMethods, filtering out null entries if (currentMethods.length == currentLength) { found.addAll(currentMethods); } else { for (int i = 0, max = currentMethods.length; i < max; i++) { MethodBinding currentMethod = currentMethods[i]; if (currentMethod != null) found.add(currentMethod); } } } } currentType = currentType.superclass(); } // if found several candidates, then eliminate those not matching argument types int foundSize = found.size; MethodBinding[] candidates = null; int candidatesCount = 0; MethodBinding problemMethod = null; boolean searchForDefaultAbstractMethod = isCompliant14 && ! receiverTypeIsInterface && (receiverType.isAbstract() || receiverType.isTypeVariable()); if (foundSize > 0) { // argument type compatibility check for (int i = 0; i < foundSize; i++) { MethodBinding methodBinding = (MethodBinding) found.elementAt(i); MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) { if (foundSize == 1 && compatibleMethod.canBeSeenBy(receiverType, invocationSite, this)) { // return the single visible match now if (searchForDefaultAbstractMethod) return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, compatibleMethod); unitScope.recordTypeReferences(compatibleMethod.thrownExceptions); return compatibleMethod; } if (candidatesCount == 0) candidates = new MethodBinding[foundSize]; candidates[candidatesCount++] = compatibleMethod; } else if (problemMethod == null) { problemMethod = compatibleMethod; } } } } // no match was found if (candidatesCount == 0) { if (problemMethod != null) { switch (problemMethod.problemId()) { case ProblemReasons.TypeArgumentsForRawGenericMethod : case ProblemReasons.TypeParameterArityMismatch : return problemMethod; } } // abstract classes may get a match in interfaces; for non abstract // classes, reduces secondary errors since missing interface method // error is already reported MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); if (interfaceMethod != null) return interfaceMethod; if (found.size == 0) return null; if (problemMethod != null) return problemMethod; // still no match; try to find a close match when the parameter // order is wrong or missing some parameters // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=69471 // bad guesses are foo(), when argument types have been supplied // and foo(X, Y), when the argument types are (int, float, Y) // so answer the method with the most argType matches and least parameter type mismatches int bestArgMatches = -1; MethodBinding bestGuess = (MethodBinding) found.elementAt(0); // if no good match so just use the first one found int argLength = argumentTypes.length; foundSize = found.size; nextMethod : for (int i = 0; i < foundSize; i++) { MethodBinding methodBinding = (MethodBinding) found.elementAt(i); TypeBinding[] params = methodBinding.parameters; int paramLength = params.length; int argMatches = 0; next: for (int a = 0; a < argLength; a++) { TypeBinding arg = argumentTypes[a]; for (int p = a == 0 ? 0 : a - 1; p < paramLength && p < a + 1; p++) { // look one slot before & after to see if the type matches if (params[p] == arg) { argMatches++; continue next; } } } if (argMatches < bestArgMatches) continue nextMethod; if (argMatches == bestArgMatches) { int diff1 = paramLength < argLength ? 2 * (argLength - paramLength) : paramLength - argLength; int bestLength = bestGuess.parameters.length; int diff2 = bestLength < argLength ? 2 * (argLength - bestLength) : bestLength - argLength; if (diff1 >= diff2) continue nextMethod; } bestArgMatches = argMatches; bestGuess = methodBinding; } return new ProblemMethodBinding(bestGuess, bestGuess.selector, argumentTypes, ProblemReasons.NotFound); } // tiebreak using visibility check int visiblesCount = 0; if (receiverTypeIsInterface) { if (candidatesCount == 1) { unitScope.recordTypeReferences(candidates[0].thrownExceptions); return candidates[0]; } visiblesCount = candidatesCount; } else { for (int i = 0; i < candidatesCount; i++) { MethodBinding methodBinding = candidates[i]; if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) { if (visiblesCount != i) { candidates[i] = null; candidates[visiblesCount] = methodBinding; } visiblesCount++; } } switch (visiblesCount) { case 0 : MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); if (interfaceMethod != null) return interfaceMethod; return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, ProblemReasons.NotVisible); case 1 : if (searchForDefaultAbstractMethod) return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, candidates[0]); unitScope.recordTypeReferences(candidates[0].thrownExceptions); return candidates[0]; default : break; } } if (complianceLevel <= ClassFileConstants.JDK1_3) { ReferenceBinding declaringClass = candidates[0].declaringClass; return !declaringClass.isInterface() ? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite) : mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite); } // check for duplicate parameterized methods if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { for (int i = 0; i < visiblesCount; i++) { MethodBinding candidate = candidates[i]; if (candidate instanceof ParameterizedGenericMethodBinding) candidate = ((ParameterizedGenericMethodBinding) candidate).originalMethod; if (candidate.hasSubstitutedParameters()) { for (int j = i + 1; j < visiblesCount; j++) { MethodBinding otherCandidate = candidates[j]; if (otherCandidate.hasSubstitutedParameters()) { if (otherCandidate == candidate || (candidate.declaringClass == otherCandidate.declaringClass && candidate.areParametersEqual(otherCandidate))) { return new ProblemMethodBinding(candidates[i], candidates[i].selector, candidates[i].parameters, ProblemReasons.Ambiguous); } } } } } } if (inStaticContext) { MethodBinding[] staticCandidates = new MethodBinding[visiblesCount]; int staticCount = 0; for (int i = 0; i < visiblesCount; i++) if (candidates[i].isStatic()) staticCandidates[staticCount++] = candidates[i]; if (staticCount == 1) return staticCandidates[0]; if (staticCount > 1) return mostSpecificMethodBinding(staticCandidates, staticCount, argumentTypes, invocationSite, receiverType); } MethodBinding mostSpecificMethod = mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite, receiverType); if (searchForDefaultAbstractMethod) { // search interfaces for a better match if (mostSpecificMethod.isValidBinding()) // see if there is a better match in the interfaces - see AutoBoxingTest 99, LookupTest#81 return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, mostSpecificMethod); // see if there is a match in the interfaces - see LookupTest#84 MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); if (interfaceMethod != null && interfaceMethod.isValidBinding() /* else return the same error as before */) return interfaceMethod; } return mostSpecificMethod; } // Internal use only public MethodBinding findMethodForArray( ArrayBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { TypeBinding leafType = receiverType.leafComponentType(); if (leafType instanceof ReferenceBinding) { if (!((ReferenceBinding) leafType).canBeSeenBy(this)) return new ProblemMethodBinding(selector, Binding.NO_PARAMETERS, (ReferenceBinding)leafType, ProblemReasons.ReceiverTypeNotVisible); } ReferenceBinding object = getJavaLangObject(); MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes, null); if (methodBinding != null) { // handle the method clone() specially... cannot be protected or throw exceptions if (argumentTypes == Binding.NO_PARAMETERS) { switch (selector[0]) { case 'c': if (CharOperation.equals(selector, TypeConstants.CLONE)) { return environment().computeArrayClone(methodBinding); } break; case 'g': if (CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return environment().createGetClassMethod(receiverType, methodBinding, this); } break; } } if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) return methodBinding; } methodBinding = findMethod(object, selector, argumentTypes, invocationSite); if (methodBinding == null) return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); return methodBinding; } protected void findMethodInSuperInterfaces(ReferenceBinding currentType, char[] selector, ObjectVector found, InvocationSite invocationSite) { ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { ReferenceBinding[] interfacesToVisit = itsInterfaces; int nextPosition = interfacesToVisit.length; for (int i = 0; i < nextPosition; i++) { currentType = interfacesToVisit[i]; compilationUnitScope().recordTypeReference(currentType); currentType = (ReferenceBinding) currentType.capture(this, invocationSite == null ? 0 : invocationSite.sourceEnd()); MethodBinding[] currentMethods = currentType.getMethods(selector); if (currentMethods.length > 0) { int foundSize = found.size; if (foundSize > 0) { // its possible to walk the same superinterface from different classes in the hierarchy next : for (int c = 0, l = currentMethods.length; c < l; c++) { MethodBinding current = currentMethods[c]; for (int f = 0; f < foundSize; f++) if (current == found.elementAt(f)) continue next; found.add(current); } } else { found.addAll(currentMethods); } } if ((itsInterfaces = currentType.superInterfaces()) != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } } // Internal use only public ReferenceBinding findType( char[] typeName, PackageBinding declarationPackage, PackageBinding invocationPackage) { compilationUnitScope().recordReference(declarationPackage.compoundName, typeName); ReferenceBinding typeBinding = declarationPackage.getType(typeName); if (typeBinding == null) return null; if (typeBinding.isValidBinding()) { if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage)) return new ProblemReferenceBinding(new char[][]{typeName}, typeBinding, ProblemReasons.NotVisible); } return typeBinding; } public LocalVariableBinding findVariable(char[] variable) { return null; } /* 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. * * For example, getBinding("foo", VARIABLE, site) will answer * the binding for the field or local named "foo" (or an error binding if none exists). * If a type named "foo" exists, it will not be detected (and an error binding will be answered) * * The VARIABLE mask has precedence over the TYPE mask. * * If the VARIABLE mask is not set, neither fields nor locals will be looked for. * * InvocationSite implements: * isSuperAccess(); this is used to determine if the discovered field is visible. * * Limitations: cannot request FIELD independently of LOCAL, or vice versa */ public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; try { env.missingClassFileLocation = invocationSite; Binding binding = null; FieldBinding problemField = null; if ((mask & Binding.VARIABLE) != 0) { boolean insideStaticContext = false; boolean insideConstructorCall = false; boolean insideTypeAnnotation = false; FieldBinding foundField = null; // can be a problem field which is answered if a valid field is not found ProblemFieldBinding foundInsideProblem = null; // inside Constructor call or inside static context Scope scope = this; MethodScope methodScope = null; int depth = 0; int foundDepth = 0; ReferenceBinding foundActualReceiverType = null; done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found switch (scope.kind) { case METHOD_SCOPE : methodScope = (MethodScope) scope; insideStaticContext |= methodScope.isStatic; insideConstructorCall |= methodScope.isConstructorCall; insideTypeAnnotation = methodScope.insideTypeAnnotation; //$FALL-THROUGH$ could duplicate the code below to save a cast - questionable optimization case BLOCK_SCOPE : LocalVariableBinding variableBinding = scope.findVariable(name); // looks in this scope only if (variableBinding != null) { if (foundField != null && foundField.isValidBinding()) return new ProblemFieldBinding( foundField, // closest match foundField.declaringClass, name, ProblemReasons.InheritedNameHidesEnclosingName); if (depth > 0) invocationSite.setDepth(depth); return variableBinding; } break; case CLASS_SCOPE : ClassScope classScope = (ClassScope) scope; ReferenceBinding receiverType = classScope.enclosingReceiverType(); if (!insideTypeAnnotation) { FieldBinding fieldBinding = classScope.findField(receiverType, name, invocationSite, needResolve); // Use next line instead if willing to enable protected access accross inner types // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite); if (fieldBinding != null) { // skip it if we did not find anything if (fieldBinding.problemId() == ProblemReasons.Ambiguous) { if (foundField == null || foundField.problemId() == ProblemReasons.NotVisible) // supercedes any potential InheritedNameHidesEnclosingName problem return fieldBinding; // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead) return new ProblemFieldBinding( foundField, // closest match foundField.declaringClass, name, ProblemReasons.InheritedNameHidesEnclosingName); } ProblemFieldBinding insideProblem = null; if (fieldBinding.isValidBinding()) { if (!fieldBinding.isStatic()) { if (insideConstructorCall) { insideProblem = new ProblemFieldBinding( fieldBinding, // closest match fieldBinding.declaringClass, name, ProblemReasons.NonStaticReferenceInConstructorInvocation); } else if (insideStaticContext) { insideProblem = new ProblemFieldBinding( fieldBinding, // closest match fieldBinding.declaringClass, name, ProblemReasons.NonStaticReferenceInStaticContext); } else if (methodScope != null) { methodScope.resetEnclosingMethodStaticFlag(); } } if (receiverType == fieldBinding.declaringClass || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { // found a valid field in the 'immediate' scope (i.e. not inherited) // OR in 1.4 mode (inherited shadows enclosing) if (foundField == null) { if (depth > 0){ invocationSite.setDepth(depth); invocationSite.setActualReceiverType(receiverType); } // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited) return insideProblem == null ? fieldBinding : insideProblem; } if (foundField.isValidBinding()) // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited) // but only if "valid field" was inherited in the first place. if (foundField.declaringClass != fieldBinding.declaringClass && foundField.declaringClass != foundActualReceiverType) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=316956 // i.e. have we found the same field - do not trust field identity yet return new ProblemFieldBinding( foundField, // closest match foundField.declaringClass, name, ProblemReasons.InheritedNameHidesEnclosingName); } } if (foundField == null || (foundField.problemId() == ProblemReasons.NotVisible && fieldBinding.problemId() != ProblemReasons.NotVisible)) { // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is... foundDepth = depth; foundActualReceiverType = receiverType; foundInsideProblem = insideProblem; foundField = fieldBinding; } } } insideTypeAnnotation = false; depth++; insideStaticContext |= receiverType.isStatic(); // 1EX5I8Z - accessing outer fields within a constructor call is permitted // in order to do so, we change the flag as we exit from the type, not the method // itself, because the class scope is used to retrieve the fields. MethodScope enclosingMethodScope = scope.methodScope(); insideConstructorCall = enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall; break; case COMPILATION_UNIT_SCOPE : break done; } scope = scope.parent; } if (foundInsideProblem != null) return foundInsideProblem; if (foundField != null) { if (foundField.isValidBinding()) { if (foundDepth > 0) { invocationSite.setDepth(foundDepth); invocationSite.setActualReceiverType(foundActualReceiverType); } return foundField; } problemField = foundField; foundField = null; } if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // at this point the scope is a compilation unit scope & need to check for imported static fields unitScope.faultInImports(); // ensure static imports are resolved 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, Binding.TYPE | Binding.FIELD | Binding.METHOD) != null && importBinding.resolvedImport instanceof FieldBinding) { foundField = (FieldBinding) importBinding.resolvedImport; ImportReference importReference = importBinding.reference; if (importReference != null && needResolve) { importReference.bits |= ASTNode.Used; } invocationSite.setActualReceiverType(foundField.declaringClass); if (foundField.isValidBinding()) { return foundField; } if (problemField == null) problemField = foundField; } } } } // 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()) { if (problemField == null) problemField = temp; } else if (temp.isStatic()) { if (foundField == temp) continue; ImportReference importReference = importBinding.reference; if (importReference != null && needResolve) { importReference.bits |= ASTNode.Used; } if (foundInImport) // Answer error binding -- import on demand conflict; name found in two import on demand packages. return new ProblemFieldBinding( foundField, // closest match foundField.declaringClass, name, ProblemReasons.Ambiguous); foundField = temp; foundInImport = true; } } } } } if (foundField != null) { invocationSite.setActualReceiverType(foundField.declaringClass); return foundField; } } } } // We did not find a local or instance variable. if ((mask & Binding.TYPE) != 0) { if ((binding = getBaseType(name)) != null) return binding; binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE, needResolve); if (binding.isValidBinding() || mask == Binding.TYPE) return binding; // answer the problem type binding if we are only looking for a type } else if ((mask & Binding.PACKAGE) != 0) { unitScope.recordSimpleReference(name); if ((binding = env.getTopLevelPackage(name)) != null) return binding; } if (problemField != null) return problemField; if (binding != null && binding.problemId() != ProblemReasons.NotFound) return binding; // answer the better problem binding return new ProblemBinding(name, enclosingSourceType(), ProblemReasons.NotFound); } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } } public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; try { env.missingClassFileLocation = invocationSite; unitScope.recordTypeReference(receiverType); unitScope.recordTypeReferences(argumentTypes); MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes); 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(TypeConstants.INIT, argumentTypes.length); if (methods == Binding.NO_METHODS) return new ProblemMethodBinding( TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound); MethodBinding[] compatible = new MethodBinding[methods.length]; int compatibleIndex = 0; 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(methods[0], TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound); return problemMethod; } // need a more descriptive error... cannot convert from X to Y MethodBinding[] visible = new MethodBinding[compatibleIndex]; int visibleIndex = 0; for (int i = 0; i < compatibleIndex; i++) { MethodBinding method = compatible[i]; if (method.canBeSeenBy(invocationSite, this)) visible[visibleIndex++] = method; } if (visibleIndex == 1) return visible[0]; if (visibleIndex == 0) return new ProblemMethodBinding( compatible[0], TypeConstants.INIT, compatible[0].parameters, ProblemReasons.NotVisible); // 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, receiverType); } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } } public final PackageBinding getCurrentPackage() { Scope scope, unitScope = this; while ((scope = unitScope.parent) != null) unitScope = scope; return ((CompilationUnitScope) unitScope).fPackage; } /** * Returns the modifiers of the innermost enclosing declaration. * @return modifiers */ public int getDeclarationModifiers(){ switch(this.kind){ case Scope.BLOCK_SCOPE : case Scope.METHOD_SCOPE : MethodScope methodScope = methodScope(); if (!methodScope.isInsideInitializer()){ // check method modifiers to see if deprecated MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding; if (context != null) return context.modifiers; } else { SourceTypeBinding type = ((BlockScope) this).referenceType().binding; // inside field declaration ? check field modifier to see if deprecated if (methodScope.initializedField != null) return methodScope.initializedField.modifiers; if (type != null) return type.modifiers; } break; case Scope.CLASS_SCOPE : ReferenceBinding context = ((ClassScope)this).referenceType().binding; if (context != null) return context.modifiers; break; } return -1; } public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) { LookupEnvironment env = environment(); try { env.missingClassFileLocation = invocationSite; FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/); if (field != null) return field; return new ProblemFieldBinding( receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null, fieldName, ProblemReasons.NotFound); } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } } /* API * * Answer the method binding that corresponds to selector, argumentTypes. * Start the lookup at the enclosing type of the receiver. * InvocationSite implements * isSuperAccess(); this is used to determine if the discovered method is visible. * setDepth(int); this is used to record the depth of the discovered method * relative to the enclosing type of the receiver. (If the method is defined * in the enclosing type of the receiver, the depth is 0; in the next enclosing * type, the depth is 1; and so on * * If no visible method is discovered, an error binding is answered. */ public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { boolean insideStaticContext = false; boolean insideConstructorCall = false; boolean insideTypeAnnotation = false; MethodBinding foundMethod = null; MethodBinding foundProblem = null; boolean foundProblemVisible = false; Scope scope = this; MethodScope methodScope = null; int depth = 0; // in 1.4 mode (inherited visible shadows enclosing) CompilerOptions options; boolean inheritedHasPrecedence = (options = compilerOptions()).complianceLevel >= ClassFileConstants.JDK1_4; done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found switch (scope.kind) { case METHOD_SCOPE : methodScope = (MethodScope) scope; insideStaticContext |= methodScope.isStatic; insideConstructorCall |= methodScope.isConstructorCall; insideTypeAnnotation = methodScope.insideTypeAnnotation; break; case CLASS_SCOPE : ClassScope classScope = (ClassScope) scope; ReferenceBinding receiverType = classScope.enclosingReceiverType(); if (!insideTypeAnnotation) { // retrieve an exact visible match (if possible) // compilationUnitScope().recordTypeReference(receiverType); not needed since receiver is the source type MethodBinding methodBinding = classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite); if (methodBinding == null) methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite); if (methodBinding != null) { // skip it if we did not find anything if (foundMethod == null) { if (methodBinding.isValidBinding()) { if (!methodBinding.isStatic() && (insideConstructorCall || insideStaticContext)) { if (foundProblem != null && foundProblem.problemId() != ProblemReasons.NotVisible) return foundProblem; // takes precedence return new ProblemMethodBinding( methodBinding, // closest match methodBinding.selector, methodBinding.parameters, insideConstructorCall ? ProblemReasons.NonStaticReferenceInConstructorInvocation : ProblemReasons.NonStaticReferenceInStaticContext); } else if (!methodBinding.isStatic() && methodScope != null) { methodScope.resetDeclaringClassMethodStaticFlag(receiverType); } if (inheritedHasPrecedence || receiverType == methodBinding.declaringClass || (receiverType.getMethods(selector)) != Binding.NO_METHODS) { // found a valid method in the 'immediate' scope (i.e. not inherited) // OR in 1.4 mode (inherited visible shadows enclosing) // OR the receiverType implemented a method with the correct name // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited) if (foundProblemVisible) { return foundProblem; } if (depth > 0) { invocationSite.setDepth(depth); invocationSite.setActualReceiverType(receiverType); } // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return environment().createGetClassMethod(receiverType, methodBinding, this); } return methodBinding; } if (foundProblem == null || foundProblem.problemId() == ProblemReasons.NotVisible) { if (foundProblem != null) foundProblem = null; // only remember the methodBinding if its the first one found // remember that private methods are visible if defined directly by an enclosing class if (depth > 0) { invocationSite.setDepth(depth); invocationSite.setActualReceiverType(receiverType); } foundMethod = methodBinding; } } else { // methodBinding is a problem method if (methodBinding.problemId() != ProblemReasons.NotVisible && methodBinding.problemId() != ProblemReasons.NotFound) return methodBinding; // return the error now if (foundProblem == null) { foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible } if (! foundProblemVisible && methodBinding.problemId() == ProblemReasons.NotFound) { MethodBinding closestMatch = ((ProblemMethodBinding) methodBinding).closestMatch; if (closestMatch != null && closestMatch.canBeSeenBy(receiverType, invocationSite, this)) { foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible foundProblemVisible = true; } } } } else { // found a valid method so check to see if this is a hiding case if (methodBinding.problemId() == ProblemReasons.Ambiguous || (foundMethod.declaringClass != methodBinding.declaringClass && (receiverType == methodBinding.declaringClass || receiverType.getMethods(selector) != Binding.NO_METHODS))) // ambiguous case -> must qualify the method (javac generates an ambiguous error instead) // otherwise if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited) // NOTE: Unlike fields, a non visible method hides a visible method return new ProblemMethodBinding( methodBinding, // closest match selector, argumentTypes, ProblemReasons.InheritedNameHidesEnclosingName); } } } insideTypeAnnotation = false; depth++; insideStaticContext |= receiverType.isStatic(); // 1EX5I8Z - accessing outer fields within a constructor call is permitted // in order to do so, we change the flag as we exit from the type, not the method // itself, because the class scope is used to retrieve the fields. MethodScope enclosingMethodScope = scope.methodScope(); insideConstructorCall = enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall; break; case COMPILATION_UNIT_SCOPE : break done; } scope = scope.parent; } if (insideStaticContext && options.sourceLevel >= ClassFileConstants.JDK1_5) { if (foundProblem != null) { if (foundProblem.declaringClass != null && foundProblem.declaringClass.id == TypeIds.T_JavaLangObject) return foundProblem; // static imports lose to methods from Object if (foundProblem.problemId() == ProblemReasons.NotFound && foundProblemVisible) { return foundProblem; // visible method selectors take precedence } } // at this point the scope is a compilation unit scope & need to check for imported static methods CompilationUnitScope unitScope = (CompilationUnitScope) scope; unitScope.faultInImports(); // field constants can cause static imports to be accessed before they're resolved ImportBinding[] imports = unitScope.imports; if (imports != null) { ObjectVector visible = null; boolean skipOnDemand = false; // set to true when matched static import of method name so stop looking for on demand methods for (int i = 0, length = imports.length; i < length; i++) { ImportBinding importBinding = imports[i]; if (importBinding.isStatic()) { Binding resolvedImport = importBinding.resolvedImport; MethodBinding possible = null; if (importBinding.onDemand) { if (!skipOnDemand && resolvedImport instanceof ReferenceBinding) // answers closest approximation, may not check argumentTypes or visibility possible = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite, true); } else { if (resolvedImport instanceof MethodBinding) { MethodBinding staticMethod = (MethodBinding) resolvedImport; if (CharOperation.equals(staticMethod.selector, selector)) // answers closest approximation, may not check argumentTypes or visibility possible = findMethod(staticMethod.declaringClass, selector, argumentTypes, invocationSite, true); } else if (resolvedImport instanceof FieldBinding) { // check to see if there are also methods with the same name FieldBinding staticField = (FieldBinding) resolvedImport; if (CharOperation.equals(staticField.name, selector)) { // must find the importRef's type again since the field can be from an inherited type char[][] importName = importBinding.reference.tokens; TypeBinding referencedType = getType(importName, importName.length - 1); if (referencedType != null) // answers closest approximation, may not check argumentTypes or visibility possible = findMethod((ReferenceBinding) referencedType, selector, argumentTypes, invocationSite, true); } } } if (possible != null && possible != foundProblem) { if (!possible.isValidBinding()) { if (foundProblem == null) foundProblem = possible; // answer as error case match } else if (possible.isStatic()) { MethodBinding compatibleMethod = computeCompatibleMethod(possible, argumentTypes, invocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) { if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) { if (visible == null || !visible.contains(compatibleMethod)) { ImportReference importReference = importBinding.reference; if (importReference != null) { importReference.bits |= ASTNode.Used; } if (!skipOnDemand && !importBinding.onDemand) { visible = null; // forget previous matches from on demand imports skipOnDemand = true; } if (visible == null) visible = new ObjectVector(3); visible.add(compatibleMethod); } } else if (foundProblem == null) { foundProblem = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, ProblemReasons.NotVisible); } } else if (foundProblem == null) { foundProblem = compatibleMethod; } } else if (foundProblem == null) { foundProblem = new ProblemMethodBinding(possible, selector, argumentTypes, ProblemReasons.NotFound); } } } } } if (visible != null) { MethodBinding[] temp = new MethodBinding[visible.size]; visible.copyInto(temp); foundMethod = mostSpecificMethodBinding(temp, temp.length, argumentTypes, invocationSite, null); } } } if (foundMethod != null) { invocationSite.setActualReceiverType(foundMethod.declaringClass); return foundMethod; } if (foundProblem != null) return foundProblem; return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); } public final ReferenceBinding getJavaIoSerializable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_IO_SERIALIZABLE); return unitScope.environment.getResolvedType(TypeConstants.JAVA_IO_SERIALIZABLE, this); } public final ReferenceBinding getJavaLangAnnotationAnnotation() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION, this); } public final ReferenceBinding getJavaLangAssertionError() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ASSERTIONERROR); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ASSERTIONERROR, this); } public final ReferenceBinding getJavaLangClass() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLASS); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_CLASS, this); } public final ReferenceBinding getJavaLangCloneable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLONEABLE); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_CLONEABLE, this); } public final ReferenceBinding getJavaLangEnum() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ENUM); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ENUM, this); } public final ReferenceBinding getJavaLangIterable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ITERABLE); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ITERABLE, this); } public final ReferenceBinding getJavaLangObject() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_OBJECT); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, this); } public final ReferenceBinding getJavaLangString() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_STRING); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_STRING, this); } public final ReferenceBinding getJavaLangThrowable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_THROWABLE); return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_THROWABLE, this); } public final ReferenceBinding getJavaUtilIterator() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_UTIL_ITERATOR); return unitScope.environment.getResolvedType(TypeConstants.JAVA_UTIL_ITERATOR, this); } /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType. */ public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) { ReferenceBinding memberType = findMemberType(typeName, enclosingType); if (memberType != null) return memberType; char[][] compoundName = new char[][] { typeName }; return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound); } public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; try { env.missingClassFileLocation = invocationSite; switch (receiverType.kind()) { case Binding.BASE_TYPE : return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); case Binding.ARRAY_TYPE : unitScope.recordTypeReference(receiverType); return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite); } unitScope.recordTypeReference(receiverType); ReferenceBinding currentType = (ReferenceBinding) receiverType; if (!currentType.canBeSeenBy(this)) return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.ReceiverTypeNotVisible); // retrieve an exact visible match (if possible) MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite); if (methodBinding != null) return methodBinding; methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite); if (methodBinding == null) return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound); if (!methodBinding.isValidBinding()) return methodBinding; // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return environment().createGetClassMethod(receiverType, methodBinding, this); } return methodBinding; } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } } /* 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, true); if (binding == null) { char[][] qName = new char[][] { compoundName[0] }; return new ProblemReferenceBinding(qName, environment().createMissingType(null, compoundName), ProblemReasons.NotFound); } if (!binding.isValidBinding()) { if (binding instanceof PackageBinding) { /* missing package */ char[][] qName = new char[][] { compoundName[0] }; return new ProblemReferenceBinding(qName, null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } return binding; } if (!(binding instanceof PackageBinding)) return null; // compoundName does not start with a package int currentIndex = 1, length = compoundName.length; PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < length) { binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); if (binding == null) { return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } if (!binding.isValidBinding()) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null, binding.problemId()); if (!(binding instanceof PackageBinding)) return packageBinding; packageBinding = (PackageBinding) binding; } return new ProblemReferenceBinding(compoundName, null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } /* Answer the package from the compoundName or null if it begins with a type. * Intended to be used while resolving a package name only. * * Internal use only */ public final Binding getOnlyPackage(char[][] compoundName) { compilationUnitScope().recordQualifiedReference(compoundName); Binding binding = getTypeOrPackage(compoundName[0], Binding.PACKAGE, true); if (binding == null || !binding.isValidBinding()) { char[][] qName = new char[][] { compoundName[0] }; return new ProblemReferenceBinding(qName, null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } if (!(binding instanceof PackageBinding)) { return null; // compoundName does not start with a package } int currentIndex = 1, length = compoundName.length; PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < length) { binding = packageBinding.getPackage(compoundName[currentIndex++]); if (binding == null) { return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } if (!binding.isValidBinding()) { return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null, binding.problemId()); } packageBinding = (PackageBinding) binding; } return packageBinding; } /* 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", ...) */ // The return type of this method could be ReferenceBinding if we did not answer base types. // NOTE: We could support looking for Base Types last in the search, however any code using // this feature would be extraordinarily slow. Therefore we don't do this. public final TypeBinding getType(char[] name) { // 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, Binding.TYPE, true); } /* 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), null, ProblemReasons.NotFound); } if (!binding.isValidBinding()) { return new ProblemReferenceBinding( binding instanceof ReferenceBinding ? ((ReferenceBinding)binding).compoundName : CharOperation.arrayConcat(packageBinding.compoundName, name), binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null, binding.problemId()); } ReferenceBinding typeBinding = (ReferenceBinding) binding; if (!typeBinding.canBeSeenBy(this)) return new ProblemReferenceBinding( typeBinding.compoundName, typeBinding, ProblemReasons.NotVisible); return typeBinding; } /* Answer the type binding corresponding to the compoundName. * * 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) { 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 unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(compoundName); Binding binding = getTypeOrPackage(compoundName[0], typeNameLength == 1 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE, true); if (binding == null) { char[][] qName = new char[][] { compoundName[0] }; return new ProblemReferenceBinding(qName, environment().createMissingType(compilationUnitScope().getCurrentPackage(), qName), ProblemReasons.NotFound); } if (!binding.isValidBinding()) { if (binding instanceof PackageBinding) { char[][] qName = new char[][] { compoundName[0] }; return new ProblemReferenceBinding( qName, environment().createMissingType(null, qName), ProblemReasons.NotFound); } return (ReferenceBinding) binding; } int currentIndex = 1; boolean checkVisibility = false; if (binding instanceof PackageBinding) { PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < typeNameLength) { binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility if (binding == null) { char[][] qName = CharOperation.subarray(compoundName, 0, currentIndex); return new ProblemReferenceBinding( qName, environment().createMissingType(packageBinding, qName), ProblemReasons.NotFound); } if (!binding.isValidBinding()) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null, binding.problemId()); if (!(binding instanceof PackageBinding)) break; packageBinding = (PackageBinding) binding; } if (binding instanceof PackageBinding) { char[][] qName = CharOperation.subarray(compoundName, 0, currentIndex); return new ProblemReferenceBinding( qName, environment().createMissingType(null, qName), ProblemReasons.NotFound); } checkVisibility = true; } // binding is now a ReferenceBinding ReferenceBinding typeBinding = (ReferenceBinding) binding; unitScope.recordTypeReference(typeBinding); if (checkVisibility) // handles the fall through case if (!typeBinding.canBeSeenBy(this)) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), typeBinding, ProblemReasons.NotVisible); while (currentIndex < typeNameLength) { typeBinding = getMemberType(compoundName[currentIndex++], typeBinding); if (!typeBinding.isValidBinding()) { if (typeBinding instanceof ProblemReferenceBinding) { ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding; return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), problemBinding.closestReferenceMatch(), typeBinding.problemId()); } return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding)((ReferenceBinding)binding).closestMatch(), typeBinding.problemId()); } } return typeBinding; } /* Internal use only */ final Binding getTypeOrPackage(char[] name, int mask, boolean needResolve) { Scope scope = this; MethodScope methodScope = null; ReferenceBinding foundType = null; boolean insideStaticContext = false; boolean insideTypeAnnotation = false; if ((mask & Binding.TYPE) == 0) { Scope next = scope; while ((next = scope.parent) != null) scope = next; } else { boolean inheritedHasPrecedence = compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found switch (scope.kind) { case METHOD_SCOPE : methodScope = (MethodScope) scope; AbstractMethodDeclaration methodDecl = methodScope.referenceMethod(); if (methodDecl != null) { if (methodDecl.binding != null) { TypeVariableBinding typeVariable = methodDecl.binding.getTypeVariable(name); if (typeVariable != null) return typeVariable; } else { // use the methodDecl's typeParameters to handle problem cases when the method binding doesn't exist TypeParameter[] params = methodDecl.typeParameters(); for (int i = params == null ? 0 : params.length; --i >= 0;) if (CharOperation.equals(params[i].name, name)) if (params[i].binding != null && params[i].binding.isValidBinding()) return params[i].binding; } } insideStaticContext |= methodScope.isStatic; insideTypeAnnotation = methodScope.insideTypeAnnotation; //$FALL-THROUGH$ case BLOCK_SCOPE : ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only if (localType != null) { if (foundType != null && foundType != localType) return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName); return localType; } break; case CLASS_SCOPE : SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding; if (scope == this && (sourceType.tagBits & TagBits.TypeVariablesAreConnected) == 0) { // type variables take precedence over the source type, ex. class X extends X == class X extends Y // but not when we step out to the enclosing type TypeVariableBinding typeVariable = sourceType.getTypeVariable(name); if (typeVariable != null) return typeVariable; if (CharOperation.equals(name, sourceType.sourceName)) return sourceType; insideStaticContext |= sourceType.isStatic(); break; } // member types take precedence over type variables if (!insideTypeAnnotation) { // 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() == ProblemReasons.Ambiguous) { if (foundType == null || foundType.problemId() == ProblemReasons.NotVisible) // supercedes any potential InheritedNameHidesEnclosingName problem return memberType; // make the user qualify the type, likely wants the first inherited type return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName); } if (memberType.isValidBinding()) { if (sourceType == memberType.enclosingType() || inheritedHasPrecedence) { if (insideStaticContext && !memberType.isStatic() && sourceType.isGenericType()) return new ProblemReferenceBinding(new char[][]{name}, memberType, ProblemReasons.NonStaticReferenceInStaticContext); // found a valid type in the 'immediate' scope (i.e. not inherited) // OR in 1.4 mode (inherited visible shadows enclosing) if (foundType == null || (inheritedHasPrecedence && foundType.problemId() == ProblemReasons.NotVisible)) return memberType; // if a valid type was found, complain when another is found in an 'immediate' enclosing type (i.e. not inherited) if (foundType.isValidBinding() && foundType != memberType) return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName); } } if (foundType == null || (foundType.problemId() == ProblemReasons.NotVisible && memberType.problemId() != ProblemReasons.NotVisible)) // only remember the memberType if its the first one found or the previous one was not visible & memberType is... foundType = memberType; } } 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(new char[][]{name}, typeVariable, ProblemReasons.NonStaticReferenceInStaticContext); else if (methodScope != null) methodScope.resetEnclosingMethodStaticFlag(); return typeVariable; } insideStaticContext |= sourceType.isStatic(); insideTypeAnnotation = false; if (CharOperation.equals(sourceType.sourceName, name)) { if (foundType != null && foundType != sourceType && foundType.problemId() != ProblemReasons.NotVisible) return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName); return sourceType; } break; case COMPILATION_UNIT_SCOPE : break done; } scope = scope.parent; } if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible) return foundType; } // at this point the scope is a compilation unit scope CompilationUnitScope unitScope = (CompilationUnitScope) scope; HashtableOfObject typeOrPackageCache = unitScope.typeOrPackageCache; if (typeOrPackageCache != null) { Binding cachedBinding = (Binding) typeOrPackageCache.get(name); if (cachedBinding != null) { // can also include NotFound ProblemReferenceBindings if we already know this name is not found if (cachedBinding instanceof ImportBinding) { // single type import cached in faultInImports(), replace it in the cache with the type ImportReference importReference = ((ImportBinding) cachedBinding).reference; if (importReference != null) { importReference.bits |= ASTNode.Used; } if (cachedBinding instanceof ImportConflictBinding) typeOrPackageCache.put(name, cachedBinding = ((ImportConflictBinding) cachedBinding).conflictingTypeBinding); // already know its visible else typeOrPackageCache.put(name, cachedBinding = ((ImportBinding) cachedBinding).resolvedImport); // already know its visible } if ((mask & Binding.TYPE) != 0) { if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible && cachedBinding.problemId() != ProblemReasons.Ambiguous) return foundType; // problem type from above supercedes NotFound type but not Ambiguous import case if (cachedBinding instanceof ReferenceBinding) return cachedBinding; // cached type found in previous walk below } if ((mask & Binding.PACKAGE) != 0 && cachedBinding instanceof PackageBinding) return cachedBinding; // cached package found in previous walk below } } // ask for the imports + name if ((mask & Binding.TYPE) != 0) { ImportBinding[] imports = unitScope.imports; if (imports != null && typeOrPackageCache == null) { // walk single type imports since faultInImports() has not run yet nextImport : for (int i = 0, length = imports.length; i < length; i++) { ImportBinding importBinding = imports[i]; if (!importBinding.onDemand) { if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) { Binding resolvedImport = unitScope.resolveSingleImport(importBinding, Binding.TYPE); if (resolvedImport == null) continue nextImport; if (resolvedImport instanceof TypeBinding) { ImportReference importReference = importBinding.reference; if (importReference != null) importReference.bits |= ASTNode.Used; return resolvedImport; // already know its visible } } } } } // In this location we had a fix for // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318401 // However, as of today (4.3M6 candidate) this fix seems unnecessary, while causing StackOverflowError in // https://bugs.eclipse.org/bugs/show_bug.cgi?id=401271 // check if the name is in the current package, skip it if its a sub-package PackageBinding currentPackage = unitScope.fPackage; unitScope.recordReference(currentPackage.compoundName, name); Binding binding = currentPackage.getTypeOrPackage(name); if (binding instanceof ReferenceBinding) { ReferenceBinding referenceType = (ReferenceBinding) binding; if ((referenceType.tagBits & TagBits.HasMissingType) == 0) { if (typeOrPackageCache != null) typeOrPackageCache.put(name, referenceType); return referenceType; // type is always visible to its own package } } // check on demand imports if (imports != null) { boolean foundInImport = false; ReferenceBinding type = null; for (int i = 0, length = imports.length; i < length; i++) { ImportBinding someImport = imports[i]; if (someImport.onDemand) { Binding resolvedImport = someImport.resolvedImport; ReferenceBinding temp = null; if (resolvedImport instanceof PackageBinding) { temp = findType(name, (PackageBinding) resolvedImport, currentPackage); } else if (someImport.isStatic()) { temp = findMemberType(name, (ReferenceBinding) resolvedImport); // static imports are allowed to see inherited member types if (temp != null && !temp.isStatic()) temp = null; } else { temp = findDirectMemberType(name, (ReferenceBinding) resolvedImport); } if (temp != type && temp != null) { if (temp.isValidBinding()) { ImportReference importReference = someImport.reference; if (importReference != null) { importReference.bits |= ASTNode.Used; } if (foundInImport) { // Answer error binding -- import on demand conflict; name found in two import on demand packages. temp = new ProblemReferenceBinding(new char[][]{name}, type, ProblemReasons.Ambiguous); if (typeOrPackageCache != null) typeOrPackageCache.put(name, temp); return temp; } type = temp; foundInImport = true; } else if (foundType == null) { foundType = temp; } } } } if (type != null) { if (typeOrPackageCache != null) typeOrPackageCache.put(name, type); return type; } } } unitScope.recordSimpleReference(name); if ((mask & Binding.PACKAGE) != 0) { PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name); if (packageBinding != null) { if (typeOrPackageCache != null) typeOrPackageCache.put(name, packageBinding); return packageBinding; } } // Answer error binding -- could not find name if (foundType == null) { char[][] qName = new char[][] { name }; ReferenceBinding closestMatch = null; if ((mask & Binding.PACKAGE) != 0) { if (needResolve) { closestMatch = environment().createMissingType(unitScope.fPackage, qName); } } else { PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name); if (packageBinding == null || !packageBinding.isValidBinding()) { if (needResolve) { closestMatch = environment().createMissingType(unitScope.fPackage, qName); } } } foundType = new ProblemReferenceBinding(qName, closestMatch, ProblemReasons.NotFound); if (typeOrPackageCache != null && (mask & Binding.PACKAGE) != 0) { // only put NotFound type in cache if you know its not a package typeOrPackageCache.put(name, foundType); } } else if ((foundType.tagBits & TagBits.HasMissingType) != 0) { char[][] qName = new char[][] { name }; foundType = new ProblemReferenceBinding(qName, foundType, ProblemReasons.NotFound); if (typeOrPackageCache != null && (mask & Binding.PACKAGE) != 0) // only put NotFound type in cache if you know its not a package typeOrPackageCache.put(name, foundType); } return foundType; } // 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], Binding.TYPE | Binding.PACKAGE, true); if (!binding.isValidBinding()) return binding; int currentIndex = 1; boolean checkVisibility = false; if (binding instanceof PackageBinding) { PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < nameLength) { binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); if (binding == null) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound); if (!binding.isValidBinding()) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null, binding.problemId()); if (!(binding instanceof PackageBinding)) break; packageBinding = (PackageBinding) binding; } if (binding instanceof PackageBinding) return binding; checkVisibility = true; } // binding is now a ReferenceBinding ReferenceBinding typeBinding = (ReferenceBinding) binding; ReferenceBinding qualifiedType = (ReferenceBinding) environment().convertToRawType(typeBinding, false /*do not force conversion of enclosing types*/); if (checkVisibility) // handles the fall through case if (!typeBinding.canBeSeenBy(this)) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), typeBinding, ProblemReasons.NotVisible); while (currentIndex < nameLength) { typeBinding = getMemberType(compoundName[currentIndex++], typeBinding); // checks visibility if (!typeBinding.isValidBinding()) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding)typeBinding.closestMatch(), typeBinding.problemId()); if (typeBinding.isGenericType()) { qualifiedType = environment().createRawType(typeBinding, qualifiedType); } else { qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType())) ? environment().createParameterizedType(typeBinding, null, qualifiedType) : typeBinding; } } return qualifiedType; } protected boolean hasErasedCandidatesCollisions(TypeBinding one, TypeBinding two, Map invocations, ReferenceBinding type, ASTNode typeRef) { invocations.clear(); TypeBinding[] mecs = minimalErasedCandidates(new TypeBinding[] {one, two}, invocations); if (mecs != null) { nextCandidate: for (int k = 0, max = mecs.length; k < max; k++) { TypeBinding mec = mecs[k]; if (mec == null) continue nextCandidate; Object value = invocations.get(mec); if (value instanceof TypeBinding[]) { TypeBinding[] invalidInvocations = (TypeBinding[]) value; problemReporter().superinterfacesCollide(invalidInvocations[0].erasure(), typeRef, invalidInvocations[0], invalidInvocations[1]); type.tagBits |= TagBits.HierarchyHasProblems; return true; } } } return false; } /** * Returns the immediately enclosing switchCase statement (carried by closest blockScope), */ public CaseStatement innermostSwitchCase() { Scope scope = this; do { if (scope instanceof BlockScope) return ((BlockScope) scope).enclosingCase; scope = scope.parent; } while (scope != null); return null; } // Tie break IS running to determine the most specific method binding. protected boolean isAcceptableMethod(MethodBinding one, MethodBinding two) { TypeBinding[] oneParams = one.parameters; TypeBinding[] twoParams = two.parameters; int oneParamsLength = oneParams.length; int twoParamsLength = twoParams.length; if (oneParamsLength == twoParamsLength) { /* Below 1.5, discard any generics we have left in for the method verifier's benefit, (so it can detect method overriding properly in the presence of generic super types.) This is so as to allow us to determine whether we have been handed an acceptable method in 1.4 terms without all the 1.5isms below kicking in and spoiling the party. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=331446 */ boolean applyErasure = environment().globalOptions.sourceLevel < ClassFileConstants.JDK1_5; next : for (int i = 0; i < oneParamsLength; i++) { TypeBinding oneParam = applyErasure ? oneParams[i].erasure() : oneParams[i]; TypeBinding twoParam = applyErasure ? twoParams[i].erasure() : twoParams[i]; if (oneParam == twoParam || oneParam.isCompatibleWith(twoParam)) { if (two.declaringClass.isRawType()) continue next; TypeBinding leafComponentType = two.original().parameters[i].leafComponentType(); TypeBinding originalTwoParam = applyErasure ? leafComponentType.erasure() : leafComponentType; switch (originalTwoParam.kind()) { case Binding.TYPE_PARAMETER : if (((TypeVariableBinding) originalTwoParam).hasOnlyRawBounds()) continue next; //$FALL-THROUGH$ case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE: case Binding.PARAMETERIZED_TYPE : TypeBinding originalOneParam = one.original().parameters[i].leafComponentType(); switch (originalOneParam.kind()) { case Binding.TYPE : case Binding.GENERIC_TYPE : TypeBinding inheritedTwoParam = oneParam.findSuperTypeOriginatingFrom(twoParam); if (inheritedTwoParam == null || !inheritedTwoParam.leafComponentType().isRawType()) break; return false; case Binding.TYPE_PARAMETER : if (!((TypeVariableBinding) originalOneParam).upperBound().isRawType()) break; return false; case Binding.RAW_TYPE: // originalOneParam is RAW so it cannot be more specific than a wildcard or parameterized type return false; } } } else { if (i == oneParamsLength - 1 && one.isVarargs() && two.isVarargs()) { TypeBinding oType = ((ArrayBinding) oneParam).elementsType(); TypeBinding eType = ((ArrayBinding) twoParam).elementsType(); if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && this.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) { if (oneParam == eType || oneParam.isCompatibleWith(eType)) return true; // special case to choose between 2 varargs methods when the last arg is Object[] } else { if (oType == eType || oType.isCompatibleWith(eType)) return true; // special case to choose between 2 varargs methods when the last arg is Object[] } } return false; } } return true; } if (one.isVarargs() && two.isVarargs()) { if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && this.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7 && oneParamsLength > twoParamsLength) { // special case when autoboxing makes (int, int...) better than (Object...) but not (int...) or (Integer, int...) if (((ArrayBinding) twoParams[twoParamsLength - 1]).elementsType().id != TypeIds.T_JavaLangObject) return false; } // check that each parameter before the vararg parameters are compatible (no autoboxing allowed here) for (int i = (oneParamsLength > twoParamsLength ? twoParamsLength : oneParamsLength) - 2; i >= 0; i--) if (oneParams[i] != twoParams[i] && !oneParams[i].isCompatibleWith(twoParams[i])) return false; if (parameterCompatibilityLevel(one, twoParams, true) == NOT_COMPATIBLE && parameterCompatibilityLevel(two, oneParams, true) == VARARGS_COMPATIBLE) return true; } return false; } public boolean isBoxingCompatibleWith(TypeBinding expressionType, TypeBinding targetType) { LookupEnvironment environment = environment(); if (environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5 || expressionType.isBaseType() == targetType.isBaseType()) return false; // check if autoboxed type is compatible TypeBinding convertedType = environment.computeBoxingType(expressionType); return convertedType == targetType || convertedType.isCompatibleWith(targetType); } /* 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. */ public final boolean isDefinedInField(FieldBinding field) { Scope scope = this; do { if (scope instanceof MethodScope) { MethodScope methodScope = (MethodScope) scope; if (methodScope.initializedField == field) return true; } scope = scope.parent; } while (scope != null); return false; } /* Answer true if the scope is nested inside a given method declaration */ public final boolean isDefinedInMethod(MethodBinding method) { method = method.original(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350738 Scope scope = this; do { if (scope instanceof MethodScope) { ReferenceContext refContext = ((MethodScope) scope).referenceContext; if (refContext instanceof AbstractMethodDeclaration) if (((AbstractMethodDeclaration) refContext).binding == method) return true; } scope = scope.parent; } while (scope != null); return false; } /* Answer whether the type is defined in the same compilation unit as the receiver */ public final boolean isDefinedInSameUnit(ReferenceBinding type) { // find the outer most enclosing type ReferenceBinding enclosingType = type; while ((type = enclosingType.enclosingType()) != null) enclosingType = type; // find the compilation unit scope Scope scope, unitScope = this; while ((scope = unitScope.parent) != null) unitScope = scope; // test that the enclosingType is not part of the compilation unit SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes; for (int i = topLevelTypes.length; --i >= 0;) if (topLevelTypes[i] == enclosingType.original()) return true; return false; } /* Answer true if the scope is nested inside a given type declaration */ public final boolean isDefinedInType(ReferenceBinding type) { Scope scope = this; do { if (scope instanceof ClassScope) if (((ClassScope) scope).referenceContext.binding == type) return true; scope = scope.parent; } while (scope != null); return false; } /** * Returns true if the scope or one of its parent is associated to a given caseStatement, denoting * being part of a given switch case statement. */ public boolean isInsideCase(CaseStatement caseStatement) { Scope scope = this; do { switch (scope.kind) { case Scope.BLOCK_SCOPE : if (((BlockScope) scope).enclosingCase == caseStatement) { return true; } } scope = scope.parent; } while (scope != null); return false; } public boolean isInsideDeprecatedCode(){ switch(this.kind){ case Scope.BLOCK_SCOPE : case Scope.METHOD_SCOPE : MethodScope methodScope = methodScope(); if (!methodScope.isInsideInitializer()){ // check method modifiers to see if deprecated MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding; if (context != null && context.isViewedAsDeprecated()) return true; } else if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated()) { // inside field declaration ? check field modifier to see if deprecated return true; } SourceTypeBinding declaringType = ((BlockScope)this).referenceType().binding; if (declaringType != null) { declaringType.initializeDeprecatedAnnotationTagBits(); // may not have been resolved until then if (declaringType.isViewedAsDeprecated()) return true; } break; case Scope.CLASS_SCOPE : ReferenceBinding context = ((ClassScope)this).referenceType().binding; if (context != null) { context.initializeDeprecatedAnnotationTagBits(); // may not have been resolved until then if (context.isViewedAsDeprecated()) return true; } break; case Scope.COMPILATION_UNIT_SCOPE : // consider import as being deprecated if first type is itself deprecated (123522) CompilationUnitDeclaration unit = referenceCompilationUnit(); if (unit.types != null && unit.types.length > 0) { SourceTypeBinding type = unit.types[0].binding; if (type != null) { type.initializeDeprecatedAnnotationTagBits(); // may not have been resolved until then if (type.isViewedAsDeprecated()) return true; } } } return false; } private boolean isOverriddenMethodGeneric(MethodBinding method) { MethodVerifier verifier = environment().methodVerifier(); ReferenceBinding currentType = method.declaringClass.superclass(); while (currentType != null) { MethodBinding[] currentMethods = currentType.getMethods(method.selector); for (int i = 0, l = currentMethods.length; i < l; i++) { MethodBinding currentMethod = currentMethods[i]; if (currentMethod != null && currentMethod.original().typeVariables != Binding.NO_TYPE_VARIABLES) if (verifier.doesMethodOverride(method, currentMethod)) return true; } currentType = currentType.superclass(); } return false; } public boolean isPossibleSubtypeOfRawType(TypeBinding paramType) { TypeBinding t = paramType.leafComponentType(); if (t.isBaseType()) return false; ReferenceBinding currentType = (ReferenceBinding) t; ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; do { if (currentType.isRawType()) return true; if (!currentType.isHierarchyConnected()) return true; // do not fault in super types right now, so assume one is a raw type ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } while ((currentType = currentType.superclass()) != null); for (int i = 0; i < nextPosition; i++) { currentType = interfacesToVisit[i]; if (currentType.isRawType()) return true; ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } return false; } private TypeBinding leastContainingInvocation(TypeBinding mec, Object invocationData, List lubStack) { if (invocationData == null) return mec; // no alternate invocation if (invocationData instanceof TypeBinding) { // only one invocation, simply return it (array only allocated if more than one) return (TypeBinding) invocationData; } TypeBinding[] invocations = (TypeBinding[]) invocationData; // if mec is an array type, intersect invocation leaf component types, then promote back to array int dim = mec.dimensions(); mec = mec.leafComponentType(); 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, length = invocations.length; i < length; i++) { TypeBinding invocation = invocations[i].leafComponentType(); switch (invocation.kind()) { case Binding.GENERIC_TYPE : TypeVariableBinding[] invocationVariables = invocation.typeVariables(); for (int j = 0; j < argLength; j++) { TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], invocationVariables[j], (ReferenceBinding) mec, j, lubStack); if (bestArgument == null) return null; bestArguments[j] = bestArgument; } break; case Binding.PARAMETERIZED_TYPE : ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)invocation; for (int j = 0; j < argLength; j++) { TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], parameterizedType.arguments[j], (ReferenceBinding) mec, j, lubStack); if (bestArgument == null) return null; bestArguments[j] = bestArgument; } break; case Binding.RAW_TYPE : return dim == 0 ? invocation : environment().createArrayType(invocation, dim); // raw type is taking precedence } } TypeBinding least = environment().createParameterizedType((ReferenceBinding) mec.erasure(), bestArguments, mec.enclosingType()); return dim == 0 ? least : environment().createArrayType(least, dim); } // JLS 15.12.2 private TypeBinding leastContainingTypeArgument(TypeBinding u, TypeBinding v, ReferenceBinding genericType, int rank, List lubStack) { 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.boundKind) { // ? extends U case Wildcard.EXTENDS : switch(wildV.boundKind) { // ? extends U, ? extends V case Wildcard.EXTENDS : TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound,wildV.bound}, lubStack); if (lub == null) return null; // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND); return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS); // ? extends U, ? SUPER V case Wildcard.SUPER : if (wildU.bound == wildV.bound) return wildU.bound; return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND); } break; // ? super U case Wildcard.SUPER : // ? super U, ? super V if (wildU.boundKind == Wildcard.SUPER) { TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound}, this); if (glb == null) return null; return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds } } } else { switch (wildV.boundKind) { // U, ? extends V case Wildcard.EXTENDS : TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,wildV.bound}, lubStack); if (lub == null) return null; // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND); return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS); // U, ? super V case Wildcard.SUPER : TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound}, this); if (glb == null) return null; return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds case Wildcard.UNBOUND : } } } else if (u.isWildcard()) { WildcardBinding wildU = (WildcardBinding) u; switch (wildU.boundKind) { // U, ? extends V case Wildcard.EXTENDS : TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound, v}, lubStack); if (lub == null) return null; // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND); return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS); // U, ? super V case Wildcard.SUPER : TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v}, this); if (glb == null) return null; return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds case Wildcard.UNBOUND : } } TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,v}, lubStack); if (lub == null) return null; // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND); return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS); } // 15.12.2 /** * Returns VoidBinding if types have no intersection (e.g. 2 unrelated interfaces), or null if * no common supertype (e.g. List and List), or the intersection type if possible */ public TypeBinding lowerUpperBound(TypeBinding[] types) { int typeLength = types.length; if (typeLength == 1) { TypeBinding type = types[0]; return type == null ? TypeBinding.VOID : type; } return lowerUpperBound(types, new ArrayList(1)); } // 15.12.2 private TypeBinding lowerUpperBound(TypeBinding[] types, List lubStack) { int typeLength = types.length; if (typeLength == 1) { TypeBinding type = types[0]; return type == null ? TypeBinding.VOID : type; } // cycle detection int stackLength = lubStack.size(); nextLubCheck: for (int i = 0; i < stackLength; i++) { TypeBinding[] lubTypes = (TypeBinding[])lubStack.get(i); int lubTypeLength = lubTypes.length; if (lubTypeLength < typeLength) continue nextLubCheck; nextTypeCheck: for (int j = 0; j < typeLength; j++) { TypeBinding type = types[j]; if (type == null) continue nextTypeCheck; // ignore for (int k = 0; k < lubTypeLength; k++) { TypeBinding lubType = lubTypes[k]; if (lubType == null) continue; // ignore if (lubType == type || lubType.isEquivalentTo(type)) continue nextTypeCheck; // type found, jump to next one } continue nextLubCheck; // type not found in current lubTypes } // all types are included in some lub, cycle detected - stop recursion by answering special value (int) return TypeBinding.INT; } lubStack.add(types); Map invocations = new HashMap(1); TypeBinding[] mecs = minimalErasedCandidates(types, invocations); if (mecs == null) return null; int length = mecs.length; if (length == 0) return TypeBinding.VOID; int count = 0; TypeBinding firstBound = null; int commonDim = -1; for (int i = 0; i < length; i++) { TypeBinding mec = mecs[i]; if (mec == null) continue; mec = leastContainingInvocation(mec, invocations.get(mec), lubStack); if (mec == null) return null; int dim = mec.dimensions(); if (commonDim == -1) { commonDim = dim; } else if (dim != commonDim) { // not all types have same dimension return null; } if (firstBound == null && !mec.leafComponentType().isInterface()) firstBound = mec.leafComponentType(); mecs[count++] = mec; // recompact them to the front } switch (count) { case 0 : return TypeBinding.VOID; case 1 : return mecs[0]; case 2 : if ((commonDim == 0 ? mecs[1].id : mecs[1].leafComponentType().id) == TypeIds.T_JavaLangObject) return mecs[0]; if ((commonDim == 0 ? mecs[0].id : mecs[0].leafComponentType().id) == TypeIds.T_JavaLangObject) return mecs[1]; } TypeBinding[] otherBounds = new TypeBinding[count - 1]; int rank = 0; for (int i = 0; i < count; i++) { TypeBinding mec = commonDim == 0 ? mecs[i] : mecs[i].leafComponentType(); if (mec.isInterface()) { otherBounds[rank++] = mec; } } TypeBinding intersectionType = environment().createWildcard(null, 0, firstBound, otherBounds, Wildcard.EXTENDS); return commonDim == 0 ? intersectionType : environment().createArrayType(intersectionType, commonDim); } public final MethodScope methodScope() { Scope scope = this; do { if (scope instanceof MethodScope) return (MethodScope) scope; scope = scope.parent; } while (scope != null); return null; } /** * Returns the most specific set of types compatible with all given types. * (i.e. most specific common super types) * If no types is given, will return an empty array. If not compatible * reference type is found, returns null. In other cases, will return an array * of minimal erased types, where some nulls may appear (and must simply be * ignored). */ protected TypeBinding[] minimalErasedCandidates(TypeBinding[] types, Map allInvocations) { 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 Binding.NO_TYPES; case 1: return types; } TypeBinding firstType = types[indexOfFirst]; if (firstType.isBaseType()) return null; // record all supertypes of type // intersect with all supertypes of otherType ArrayList typesToVisit = new ArrayList(5); int dim = firstType.dimensions(); TypeBinding leafType = firstType.leafComponentType(); // do not allow type variables/intersection types to match with erasures for free TypeBinding firstErasure; switch(leafType.kind()) { case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : case Binding.ARRAY_TYPE : firstErasure = firstType.erasure(); break; default : firstErasure = firstType; break; } if (firstErasure != firstType) { allInvocations.put(firstErasure, firstType); } typesToVisit.add(firstType); int max = 1; ReferenceBinding currentType; for (int i = 0; i < max; i++) { TypeBinding typeToVisit = (TypeBinding) typesToVisit.get(i); dim = typeToVisit.dimensions(); if (dim > 0) { leafType = typeToVisit.leafComponentType(); switch(leafType.id) { case TypeIds.T_JavaLangObject: if (dim > 1) { // Object[][] supertype is Object[] TypeBinding elementType = ((ArrayBinding)typeToVisit).elementsType(); if (!typesToVisit.contains(elementType)) { typesToVisit.add(elementType); max++; } continue; } //$FALL-THROUGH$ case TypeIds.T_byte: case TypeIds.T_short: case TypeIds.T_char: case TypeIds.T_boolean: case TypeIds.T_int: case TypeIds.T_long: case TypeIds.T_float: case TypeIds.T_double: TypeBinding superType = getJavaIoSerializable(); if (!typesToVisit.contains(superType)) { typesToVisit.add(superType); max++; } superType = getJavaLangCloneable(); if (!typesToVisit.contains(superType)) { typesToVisit.add(superType); max++; } superType = getJavaLangObject(); if (!typesToVisit.contains(superType)) { typesToVisit.add(superType); max++; } continue; default: } typeToVisit = leafType; } currentType = (ReferenceBinding) typeToVisit; if (currentType.isCapture()) { TypeBinding firstBound = ((CaptureBinding) currentType).firstBound; if (firstBound != null && firstBound.isArrayType()) { TypeBinding superType = dim == 0 ? firstBound : (TypeBinding)environment().createArrayType(firstBound, dim); // recreate array if needed if (!typesToVisit.contains(superType)) { typesToVisit.add(superType); max++; TypeBinding superTypeErasure = (firstBound.isTypeVariable() || firstBound.isWildcard() /*&& !itsInterface.isCapture()*/) ? superType : superType.erasure(); if (superTypeErasure != superType) { allInvocations.put(superTypeErasure, superType); } } continue; } } // inject super interfaces prior to superclass ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null) { // can be null during code assist operations that use LookupEnvironment.completeTypeBindings(parsedUnit, buildFieldsAndMethods) for (int j = 0, count = itsInterfaces.length; j < count; j++) { TypeBinding itsInterface = itsInterfaces[j]; TypeBinding superType = dim == 0 ? itsInterface : (TypeBinding)environment().createArrayType(itsInterface, dim); // recreate array if needed if (!typesToVisit.contains(superType)) { typesToVisit.add(superType); max++; TypeBinding superTypeErasure = (itsInterface.isTypeVariable() || itsInterface.isWildcard() /*&& !itsInterface.isCapture()*/) ? superType : superType.erasure(); if (superTypeErasure != superType) { allInvocations.put(superTypeErasure, superType); } } } } TypeBinding itsSuperclass = currentType.superclass(); if (itsSuperclass != null) { TypeBinding superType = dim == 0 ? itsSuperclass : (TypeBinding)environment().createArrayType(itsSuperclass, dim); // recreate array if needed if (!typesToVisit.contains(superType)) { typesToVisit.add(superType); max++; TypeBinding superTypeErasure = (itsSuperclass.isTypeVariable() || itsSuperclass.isWildcard() /*&& !itsSuperclass.isCapture()*/) ? superType : superType.erasure(); if (superTypeErasure != superType) { allInvocations.put(superTypeErasure, superType); } } } } int superLength = typesToVisit.size(); TypeBinding[] erasedSuperTypes = new TypeBinding[superLength]; int rank = 0; for (Iterator iter = typesToVisit.iterator(); iter.hasNext();) { TypeBinding type = (TypeBinding)iter.next(); leafType = type.leafComponentType(); erasedSuperTypes[rank++] = (leafType.isTypeVariable() || leafType.isWildcard() /*&& !leafType.isCapture()*/) ? type : type.erasure(); } // intersecting first type supertypes with other types' ones, nullifying non matching supertypes int remaining = superLength; nextOtherType: for (int i = indexOfFirst+1; i < length; i++) { TypeBinding otherType = types[i]; if (otherType == null) continue nextOtherType; if (otherType.isArrayType()) { nextSuperType: for (int j = 0; j < superLength; j++) { TypeBinding erasedSuperType = erasedSuperTypes[j]; if (erasedSuperType == null || erasedSuperType == otherType) continue nextSuperType; TypeBinding match; if ((match = otherType.findSuperTypeOriginatingFrom(erasedSuperType)) == null) { erasedSuperTypes[j] = null; if (--remaining == 0) return null; continue nextSuperType; } // record invocation Object invocationData = allInvocations.get(erasedSuperType); if (invocationData == null) { allInvocations.put(erasedSuperType, match); // no array for singleton } else if (invocationData instanceof TypeBinding) { if (match != invocationData) { // using an array to record invocations in order (188103) TypeBinding[] someInvocations = { (TypeBinding) invocationData, match, }; allInvocations.put(erasedSuperType, someInvocations); } } else { // using an array to record invocations in order (188103) TypeBinding[] someInvocations = (TypeBinding[]) invocationData; checkExisting: { int invocLength = someInvocations.length; for (int k = 0; k < invocLength; k++) { if (someInvocations[k] == match) break checkExisting; } System.arraycopy(someInvocations, 0, someInvocations = new TypeBinding[invocLength+1], 0, invocLength); allInvocations.put(erasedSuperType, someInvocations); someInvocations[invocLength] = match; } } } continue nextOtherType; } nextSuperType: for (int j = 0; j < superLength; j++) { TypeBinding erasedSuperType = erasedSuperTypes[j]; if (erasedSuperType == null) continue nextSuperType; TypeBinding match; if (erasedSuperType == otherType || erasedSuperType.id == TypeIds.T_JavaLangObject && otherType.isInterface()) { match = erasedSuperType; } else { if (erasedSuperType.isArrayType()) { match = null; } else { match = otherType.findSuperTypeOriginatingFrom(erasedSuperType); } if (match == null) { // incompatible super type erasedSuperTypes[j] = null; if (--remaining == 0) return null; continue nextSuperType; } } // record invocation Object invocationData = allInvocations.get(erasedSuperType); if (invocationData == null) { allInvocations.put(erasedSuperType, match); // no array for singleton } else if (invocationData instanceof TypeBinding) { if (match != invocationData) { // using an array to record invocations in order (188103) TypeBinding[] someInvocations = { (TypeBinding) invocationData, match, }; allInvocations.put(erasedSuperType, someInvocations); } } else { // using an array to record invocations in order (188103) TypeBinding[] someInvocations = (TypeBinding[]) invocationData; checkExisting: { int invocLength = someInvocations.length; for (int k = 0; k < invocLength; k++) { if (someInvocations[k] == match) break checkExisting; } System.arraycopy(someInvocations, 0, someInvocations = new TypeBinding[invocLength+1], 0, invocLength); allInvocations.put(erasedSuperType, someInvocations); someInvocations[invocLength] = match; } } } } // eliminate non minimal super types if (remaining > 1) { nextType: for (int i = 0; i < superLength; i++) { TypeBinding erasedSuperType = erasedSuperTypes[i]; if (erasedSuperType == null) continue nextType; nextOtherType: for (int j = 0; j < superLength; j++) { if (i == j) continue nextOtherType; TypeBinding otherType = erasedSuperTypes[j]; if (otherType == null) continue nextOtherType; if (erasedSuperType instanceof ReferenceBinding) { if (otherType.id == TypeIds.T_JavaLangObject && erasedSuperType.isInterface()) continue nextOtherType; // keep Object for an interface if (erasedSuperType.findSuperTypeOriginatingFrom(otherType) != null) { erasedSuperTypes[j] = null; // discard non minimal supertype remaining--; } } else if (erasedSuperType.isArrayType()) { if (otherType.isArrayType() // keep Object[...] for an interface array (same dimensions) && otherType.leafComponentType().id == TypeIds.T_JavaLangObject && otherType.dimensions() == erasedSuperType.dimensions() && erasedSuperType.leafComponentType().isInterface()) continue nextOtherType; if (erasedSuperType.findSuperTypeOriginatingFrom(otherType) != null) { erasedSuperTypes[j] = null; // discard non minimal supertype remaining--; } } } } } return erasedSuperTypes; } // 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 * superclass and so on. We want to find the one which matches best. * * Since the receiver type is a class, we know each method's declaring class is * either the receiver type or one of its superclasses. It is an error if the best match * 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, InvocationSite invocationSite) { MethodBinding previous = null; nextVisible : for (int i = 0; i < visibleSize; 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 for (int j = 0; j < visibleSize; j++) { if (i == j) continue; if (!visible[j].areParametersCompatibleWith(method.parameters)) continue nextVisible; } compilationUnitScope().recordTypeReferences(method.thrownExceptions); return method; } return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous); } // 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 * but unrelated superinterfaces may define the same method in acceptable but * not identical ways... we just take the best match that we find since any class which * implements the receiver interface MUST implement all signatures for the method... * in which case the best match is correct. * * NOTE: This is different than javac... in the following example, the message send of * bar(X) in class Y is supposed to be ambiguous. But any class which implements the * interface I MUST implement both signatures for bar. If this class was the receiver of * the message send instead of the interface I, then no problem would be reported. * interface I1 { void bar(J j); } interface I2 { // void bar(J j); void bar(Object o); } interface I extends I1, I2 {} interface J {} class X implements J {} class Y extends X { public void foo(I i, X x) { i.bar(x); } } */ protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) { nextVisible : for (int i = 0; i < visibleSize; i++) { MethodBinding method = visible[i]; for (int j = 0; j < visibleSize; j++) { if (i == j) continue; if (!visible[j].areParametersCompatibleWith(method.parameters)) continue nextVisible; } compilationUnitScope().recordTypeReferences(method.thrownExceptions); return method; } return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous); } // caveat: this is not a direct implementation of JLS protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, final InvocationSite invocationSite, ReferenceBinding receiverType) { int[] compatibilityLevels = new int[visibleSize]; for (int i = 0; i < visibleSize; i++) compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes); InvocationSite tieBreakInvocationSite = new InvocationSite() { public TypeBinding[] genericTypeArguments() { return null; } // ignore genericTypeArgs public boolean isSuperAccess() { return invocationSite.isSuperAccess(); } public boolean isTypeAccess() { return invocationSite.isTypeAccess(); } public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */} public void setDepth(int depth) { /* ignore */} public void setFieldIndex(int depth) { /* ignore */} public int sourceStart() { return invocationSite.sourceStart(); } public int sourceEnd() { return invocationSite.sourceStart(); } public TypeBinding expectedType() { return invocationSite.expectedType(); } }; MethodBinding[] moreSpecific = new MethodBinding[visibleSize]; int count = 0; for (int level = 0, max = VARARGS_COMPATIBLE; level <= max; level++) { nextVisible : for (int i = 0; i < visibleSize; i++) { if (compatibilityLevels[i] != level) continue nextVisible; max = level; // do not examine further categories, will either return mostSpecific or report ambiguous case MethodBinding current = visible[i]; MethodBinding original = current.original(); MethodBinding tiebreakMethod = current.tiebreakMethod(); for (int j = 0; j < visibleSize; j++) { if (i == j || compatibilityLevels[j] != level) continue; MethodBinding next = visible[j]; if (original == next.original()) { // parameterized superclasses & interfaces may be walked twice from different paths so skip next from now on compatibilityLevels[j] = -1; continue; } MethodBinding methodToTest = next; if (next instanceof ParameterizedGenericMethodBinding) { ParameterizedGenericMethodBinding pNext = (ParameterizedGenericMethodBinding) next; if (pNext.isRaw && !pNext.isStatic()) { // hold onto the raw substituted method } else { methodToTest = pNext.originalMethod; } } MethodBinding acceptable = computeCompatibleMethod(methodToTest, tiebreakMethod.parameters, tieBreakInvocationSite, level == VARARGS_COMPATIBLE); /* There are 4 choices to consider with current & next : foo(B) & foo(A) where B extends A 1. the 2 methods are equal (both accept each others parameters) -> want to continue 2. current has more specific parameters than next (so acceptable is a valid method) -> want to continue 3. current has less specific parameters than next (so acceptable is null) -> go on to next 4. current and next are not compatible with each other (so acceptable is null) -> go on to next */ if (acceptable == null || !acceptable.isValidBinding()) continue nextVisible; if (!isAcceptableMethod(tiebreakMethod, acceptable)) continue nextVisible; // pick a concrete method over a bridge method when parameters are equal since the return type of the concrete method is more specific if (current.isBridge() && !next.isBridge()) if (tiebreakMethod.areParametersEqual(acceptable)) continue nextVisible; // skip current so acceptable wins over this bridge method } moreSpecific[i] = current; count++; } } if (count == 1) { for (int i = 0; i < visibleSize; i++) { if (moreSpecific[i] != null) { compilationUnitScope().recordTypeReferences(visible[i].thrownExceptions); return visible[i]; } } } else if (count == 0) { return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous); } // found several methods that are mutually acceptable -> must be equal // so now with the first acceptable method, find the 'correct' inherited method for each other acceptable method AND // see if they are equal after substitution of type variables (do the type variables have to be equal to be considered an override???) if (receiverType != null) receiverType = receiverType instanceof CaptureBinding ? receiverType : (ReferenceBinding) receiverType.erasure(); nextSpecific : for (int i = 0; i < visibleSize; i++) { MethodBinding current = moreSpecific[i]; if (current != null) { ReferenceBinding[] mostSpecificExceptions = null; MethodBinding original = current.original(); boolean shouldIntersectExceptions = original.declaringClass.isAbstract() && original.thrownExceptions != Binding.NO_EXCEPTIONS; // only needed when selecting from interface methods for (int j = 0; j < visibleSize; j++) { MethodBinding next = moreSpecific[j]; if (next == null || i == j) continue; MethodBinding original2 = next.original(); if (original.declaringClass == original2.declaringClass) break nextSpecific; // duplicates thru substitution if (!original.isAbstract()) { if (original2.isAbstract()) continue; // only compare current against other concrete methods original2 = original.findOriginalInheritedMethod(original2); if (original2 == null) continue nextSpecific; // current's declaringClass is not a subtype of next's declaringClass if (current.hasSubstitutedParameters() || original.typeVariables != Binding.NO_TYPE_VARIABLES) { if (!environment().methodVerifier().isParameterSubsignature(original, original2)) continue nextSpecific; // current does not override next } } else if (receiverType != null) { // should not be null if original isAbstract, but be safe TypeBinding superType = receiverType.findSuperTypeOriginatingFrom(original.declaringClass.erasure()); if (original.declaringClass == superType || !(superType instanceof ReferenceBinding)) { // keep original } else { // must find inherited method with the same substituted variables MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(original.selector, argumentTypes.length); for (int m = 0, l = superMethods.length; m < l; m++) { if (superMethods[m].original() == original) { original = superMethods[m]; break; } } } superType = receiverType.findSuperTypeOriginatingFrom(original2.declaringClass.erasure()); if (original2.declaringClass == superType || !(superType instanceof ReferenceBinding)) { // keep original2 } else { // must find inherited method with the same substituted variables MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(original2.selector, argumentTypes.length); for (int m = 0, l = superMethods.length; m < l; m++) { if (superMethods[m].original() == original2) { original2 = superMethods[m]; break; } } } if (original.typeVariables != Binding.NO_TYPE_VARIABLES) original2 = original.computeSubstitutedMethod(original2, environment()); if (original2 == null || !original.areParameterErasuresEqual(original2)) continue nextSpecific; // current does not override next if (original.returnType != original2.returnType) { if (next.original().typeVariables != Binding.NO_TYPE_VARIABLES) { if (original.returnType.erasure().findSuperTypeOriginatingFrom(original2.returnType.erasure()) == null) continue nextSpecific; } else if (!current.returnType.isCompatibleWith(next.returnType)) { continue nextSpecific; } // continue with original 15.12.2.5 } if (shouldIntersectExceptions && original2.declaringClass.isInterface()) { if (current.thrownExceptions != next.thrownExceptions) { if (next.thrownExceptions == Binding.NO_EXCEPTIONS) { mostSpecificExceptions = Binding.NO_EXCEPTIONS; } else { if (mostSpecificExceptions == null) { mostSpecificExceptions = current.thrownExceptions; } int mostSpecificLength = mostSpecificExceptions.length; ReferenceBinding[] nextExceptions = getFilteredExceptions(next); int nextLength = nextExceptions.length; SimpleSet temp = new SimpleSet(mostSpecificLength); boolean changed = false; nextException : for (int t = 0; t < mostSpecificLength; t++) { ReferenceBinding exception = mostSpecificExceptions[t]; for (int s = 0; s < nextLength; s++) { ReferenceBinding nextException = nextExceptions[s]; if (exception.isCompatibleWith(nextException)) { temp.add(exception); continue nextException; } else if (nextException.isCompatibleWith(exception)) { temp.add(nextException); changed = true; continue nextException; } else { changed = true; } } } if (changed) { mostSpecificExceptions = temp.elementSize == 0 ? Binding.NO_EXCEPTIONS : new ReferenceBinding[temp.elementSize]; temp.asArray(mostSpecificExceptions); } } } } } } if (mostSpecificExceptions != null && mostSpecificExceptions != current.thrownExceptions) { return new MostSpecificExceptionMethodBinding(current, mostSpecificExceptions); } return current; } } // if all moreSpecific methods are equal then see if duplicates exist because of substitution return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous); } private ReferenceBinding[] getFilteredExceptions(MethodBinding method) { // http://bugs.eclipse.org/387612 - Unreachable catch block...exception is never thrown from the try // Need to filter redundant exceptions within the same throws clause. // In this filtering the *most general* exception wins in order to capture all possible exceptions // that could be thrown by the given method. ReferenceBinding[] allExceptions = method.thrownExceptions; int length = allExceptions.length; if (length < 2) return allExceptions; ReferenceBinding[] filteredExceptions = new ReferenceBinding[length]; int count = 0; currents: for (int i = 0; i < length; i++) { ReferenceBinding currentException = allExceptions[i]; for (int j = 0; j < length; j++) { if (i == j) continue; if (currentException == allExceptions[j]) { // duplicate same exception if (i < j) break; // take only the first occurrence else continue currents; // skip } if (currentException.isCompatibleWith(allExceptions[j])) { continue currents; // skip } } filteredExceptions[count++] = currentException; } if (count != length) { ReferenceBinding[] tmp = new ReferenceBinding[count]; System.arraycopy(filteredExceptions, 0, tmp, 0, count); return tmp; } return allExceptions; } public final ClassScope outerMostClassScope() { ClassScope lastClassScope = null; Scope scope = this; do { if (scope instanceof ClassScope) lastClassScope = (ClassScope) scope; scope = scope.parent; } while (scope != null); return lastClassScope; // may answer null if no class around } public final MethodScope outerMostMethodScope() { MethodScope lastMethodScope = null; Scope scope = this; do { if (scope instanceof MethodScope) lastMethodScope = (MethodScope) scope; scope = scope.parent; } while (scope != null); return lastMethodScope; // may answer null if no method around } public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) { return parameterCompatibilityLevel(method, arguments, false); } public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments, boolean tiebreakingVarargsMethods) { TypeBinding[] parameters = method.parameters; int paramLength = parameters.length; int argLength = arguments.length; CompilerOptions compilerOptions = compilerOptions(); if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_5) { if (paramLength != argLength) return NOT_COMPATIBLE; for (int i = 0; i < argLength; i++) { TypeBinding param = parameters[i]; TypeBinding arg = arguments[i]; //https://bugs.eclipse.org/bugs/show_bug.cgi?id=330445 if (arg != param && !arg.isCompatibleWith(param.erasure())) return NOT_COMPATIBLE; } return COMPATIBLE; } if (tiebreakingVarargsMethods) { if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) { tiebreakingVarargsMethods = false; } } int level = COMPATIBLE; // no autoboxing or varargs support needed int lastIndex = argLength; LookupEnvironment env = environment(); 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) { level = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods); if (level == NOT_COMPATIBLE) { // expect X[], is it called with X param = ((ArrayBinding) param).elementsType(); if (tiebreakingVarargsMethods) { arg = ((ArrayBinding) arg).elementsType(); } if (parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods) == NOT_COMPATIBLE) return NOT_COMPATIBLE; level = VARARGS_COMPATIBLE; // varargs support needed } } } else { if (paramLength < argLength) { // all remaining 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 = (tiebreakingVarargsMethods && (i == (argLength - 1))) ? ((ArrayBinding)arguments[i]).elementsType() : arguments[i]; if (param != arg && parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods) == NOT_COMPATIBLE) 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 } } else if (paramLength != argLength) { return NOT_COMPATIBLE; } // now compare standard arguments from 0 to lastIndex for (int i = 0; i < lastIndex; i++) { TypeBinding param = parameters[i]; TypeBinding arg = (tiebreakingVarargsMethods && (i == (argLength - 1))) ? ((ArrayBinding)arguments[i]).elementsType() : arguments[i]; if (arg != param) { int newLevel = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods); if (newLevel == NOT_COMPATIBLE) return NOT_COMPATIBLE; if (newLevel > level) level = newLevel; } } return level; } private int parameterCompatibilityLevel(TypeBinding arg, TypeBinding param, LookupEnvironment env, boolean tieBreakingVarargsMethods) { // only called if env.options.sourceLevel >= ClassFileConstants.JDK1_5 if (arg.isCompatibleWith(param, this)) return COMPATIBLE; if (tieBreakingVarargsMethods && (this.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_7 || !CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation)) { /* 15.12.2.5 Choosing the Most Specific Method, ... One variable arity member method named m is more specific than another variable arity member method of the same name if either ... Only subtypes relationship should be used. Actually this is true even for fixed arity methods, but in practice is not an issue since we run the algorithm multiple times for each compatibility level. https://bugs.eclipse.org/bugs/show_bug.cgi?id=346038, https://bugs.eclipse.org/bugs/show_bug.cgi?id=346039. */ return NOT_COMPATIBLE; } if (arg.isBaseType() != param.isBaseType()) { TypeBinding convertedType = env.computeBoxingType(arg); if (convertedType == param || convertedType.isCompatibleWith(param)) return AUTOBOX_COMPATIBLE; } return NOT_COMPATIBLE; } public abstract ProblemReporter problemReporter(); public final CompilationUnitDeclaration referenceCompilationUnit() { Scope scope, unitScope = this; while ((scope = unitScope.parent) != null) unitScope = scope; return ((CompilationUnitScope) unitScope).referenceContext; } /** * Returns the nearest reference context, starting from current scope. * If starting on a class, it will return current class. If starting on unitScope, returns unit. */ public ReferenceContext referenceContext() { Scope current = this; do { switch(current.kind) { case METHOD_SCOPE : return ((MethodScope) current).referenceContext; case CLASS_SCOPE : return ((ClassScope) current).referenceContext; case COMPILATION_UNIT_SCOPE : return ((CompilationUnitScope) current).referenceContext; } } while ((current = current.parent) != null); return null; } public void deferBoundCheck(TypeReference typeRef) { if (this.kind == CLASS_SCOPE) { ClassScope classScope = (ClassScope) this; if (classScope.deferredBoundChecks == null) { classScope.deferredBoundChecks = new ArrayList(3); classScope.deferredBoundChecks.add(typeRef); } else if (!classScope.deferredBoundChecks.contains(typeRef)) { classScope.deferredBoundChecks.add(typeRef); } } } // start position in this scope - for ordering scopes vs. variables int startIndex() { return 0; } /* Given an allocation type and arguments at the allocation site, answer a synthetic generic static factory method that could instead be invoked with identical results. Return null if no compatible, visible, most specific method could be found. This method is modeled after Scope.getConstructor and Scope.getMethod. */ public MethodBinding getStaticFactory (ReferenceBinding allocationType, ReferenceBinding originalEnclosingType, TypeBinding[] argumentTypes, final InvocationSite allocationSite) { TypeVariableBinding[] classTypeVariables = allocationType.typeVariables(); int classTypeVariablesArity = classTypeVariables.length; MethodBinding[] methods = allocationType.getMethods(TypeConstants.INIT, argumentTypes.length); MethodBinding [] staticFactories = new MethodBinding[methods.length]; int sfi = 0; for (int i = 0, length = methods.length; i < length; i++) { MethodBinding method = methods[i]; int paramLength = method.parameters.length; boolean isVarArgs = method.isVarargs(); if (argumentTypes.length != paramLength) if (!isVarArgs || argumentTypes.length < paramLength - 1) continue; // incompatible TypeVariableBinding[] methodTypeVariables = method.typeVariables(); int methodTypeVariablesArity = methodTypeVariables.length; MethodBinding staticFactory = new MethodBinding(method.modifiers | ClassFileConstants.AccStatic, TypeConstants.SYNTHETIC_STATIC_FACTORY, null, null, null, method.declaringClass); staticFactory.typeVariables = new TypeVariableBinding[classTypeVariablesArity + methodTypeVariablesArity]; final SimpleLookupTable map = new SimpleLookupTable(classTypeVariablesArity + methodTypeVariablesArity); // Rename each type variable T of the type to T' final LookupEnvironment environment = environment(); for (int j = 0; j < classTypeVariablesArity; j++) { map.put(classTypeVariables[j], staticFactory.typeVariables[j] = new TypeVariableBinding(CharOperation.concat(classTypeVariables[j].sourceName, "'".toCharArray()), //$NON-NLS-1$ staticFactory, j, environment)); } // Rename each type variable U of method U to U''. for (int j = classTypeVariablesArity, max = classTypeVariablesArity + methodTypeVariablesArity; j < max; j++) { map.put(methodTypeVariables[j - classTypeVariablesArity], (staticFactory.typeVariables[j] = new TypeVariableBinding(CharOperation.concat(methodTypeVariables[j - classTypeVariablesArity].sourceName, "''".toCharArray()), //$NON-NLS-1$ staticFactory, j, environment))); } ReferenceBinding enclosingType = originalEnclosingType; while (enclosingType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=345968 if (enclosingType.kind() == Binding.PARAMETERIZED_TYPE) { final ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) enclosingType; final ReferenceBinding genericType = parameterizedType.genericType(); TypeVariableBinding[] enclosingClassTypeVariables = genericType.typeVariables(); int enclosingClassTypeVariablesArity = enclosingClassTypeVariables.length; for (int j = 0; j < enclosingClassTypeVariablesArity; j++) { map.put(enclosingClassTypeVariables[j], parameterizedType.arguments[j]); } } enclosingType = enclosingType.enclosingType(); } final Scope scope = this; Substitution substitution = new Substitution() { public LookupEnvironment environment() { return scope.environment(); } public boolean isRawSubstitution() { return false; } public TypeBinding substitute(TypeVariableBinding typeVariable) { TypeBinding retVal = (TypeBinding) map.get(typeVariable); return retVal != null ? retVal : typeVariable; } }; // initialize new variable bounds for (int j = 0, max = classTypeVariablesArity + methodTypeVariablesArity; j < max; j++) { TypeVariableBinding originalVariable = j < classTypeVariablesArity ? classTypeVariables[j] : methodTypeVariables[j - classTypeVariablesArity]; TypeBinding substitutedType = (TypeBinding) map.get(originalVariable); if (substitutedType instanceof TypeVariableBinding) { TypeVariableBinding substitutedVariable = (TypeVariableBinding) substitutedType; TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass); ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces); if (originalVariable.firstBound != null) { substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass ? substitutedSuperclass // could be array type or interface : substitutedInterfaces[0]; } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); substitutedVariable.superInterfaces = substitutedInterfaces; break; default: if (substitutedSuperclass.isInterface()) { substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); int interfaceCount = substitutedInterfaces.length; System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount); substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass; substitutedVariable.superInterfaces = substitutedInterfaces; } else { substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface substitutedVariable.superInterfaces = substitutedInterfaces; } } } } TypeVariableBinding[] returnTypeParameters = new TypeVariableBinding[classTypeVariablesArity]; for (int j = 0; j < classTypeVariablesArity; j++) { returnTypeParameters[j] = (TypeVariableBinding) map.get(classTypeVariables[j]); } staticFactory.returnType = environment.createParameterizedType(allocationType, returnTypeParameters, allocationType.enclosingType()); staticFactory.parameters = Scope.substitute(substitution, method.parameters); staticFactory.thrownExceptions = Scope.substitute(substitution, method.thrownExceptions); if (staticFactory.thrownExceptions == null) { staticFactory.thrownExceptions = Binding.NO_EXCEPTIONS; } staticFactories[sfi++] = new ParameterizedMethodBinding((ParameterizedTypeBinding) environment.convertToParameterizedType(staticFactory.declaringClass), staticFactory); } if (sfi == 0) return null; if (sfi != methods.length) { System.arraycopy(staticFactories, 0, staticFactories = new MethodBinding[sfi], 0, sfi); } MethodBinding[] compatible = new MethodBinding[sfi]; int compatibleIndex = 0; for (int i = 0; i < sfi; i++) { MethodBinding compatibleMethod = computeCompatibleMethod(staticFactories[i], argumentTypes, allocationSite); if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) compatible[compatibleIndex++] = compatibleMethod; } } if (compatibleIndex == 0) { return null; } MethodBinding[] visible = new MethodBinding[compatibleIndex]; int visibleIndex = 0; for (int i = 0; i < compatibleIndex; i++) { MethodBinding method = compatible[i]; if (method.canBeSeenBy(allocationSite, this)) visible[visibleIndex++] = method; } if (visibleIndex == 0) { return null; } return visibleIndex == 1 ? visible[0] : mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, allocationSite, allocationType); } public void validateNullAnnotation(long tagBits, TypeReference typeRef, Annotation[] annotations) { long nullAnnotationTagBit = tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable); if (nullAnnotationTagBit != 0) { TypeBinding type = typeRef.resolvedType; if (type != null && type.isBaseType()) { char[][] annotationName = (nullAnnotationTagBit == TagBits.AnnotationNonNull) ? environment().getNonNullAnnotationName() : environment().getNullableAnnotationName(); problemReporter().illegalAnnotationForBaseType(typeRef, annotations, annotationName[annotationName.length-1], nullAnnotationTagBit); } } } } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding0000644000175000001440000000420012212041344032462 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; /** * Specific local variable location used to: * - either provide emulation for outer local variables used from within innerclass constructs, * - or provide emulation to enclosing instances. * When it is mapping to an outer local variable, this actual outer local is accessible through * the public field #actualOuterLocalVariable. * * Such a synthetic argument binding will be inserted in all constructors of local innertypes before * the user arguments. */ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; public class SyntheticArgumentBinding extends LocalVariableBinding { { this.tagBits |= TagBits.IsArgument; this.useFlag = USED; } // if the argument is mapping to an outer local variable, this denotes the outer actual variable public LocalVariableBinding actualOuterLocalVariable; // if the argument has a matching synthetic field public FieldBinding matchingField; public SyntheticArgumentBinding(LocalVariableBinding actualOuterLocalVariable) { super( CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name), actualOuterLocalVariable.type, ClassFileConstants.AccFinal, true); this.actualOuterLocalVariable = actualOuterLocalVariable; } public SyntheticArgumentBinding(ReferenceBinding enclosingType) { super( CharOperation.concat( TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, String.valueOf(enclosingType.depth()).toCharArray()), enclosingType, ClassFileConstants.AccFinal, true); } } ././@LongLink0000644000000000000000000000015112251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.0000644000175000001440000000616112212041344032312 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.lang.reflect.Field; import org.eclipse.jdt.core.compiler.CharOperation; public class ProblemReferenceBinding extends ReferenceBinding { ReferenceBinding closestMatch; private int problemReason; // NOTE: must only answer the subset of the name related to the problem public ProblemReferenceBinding(char[][] compoundName, ReferenceBinding closestMatch, int problemReason) { this.compoundName = compoundName; this.closestMatch = closestMatch; this.problemReason = problemReason; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#closestMatch() */ public TypeBinding closestMatch() { return this.closestMatch; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#closestMatch() */ public ReferenceBinding closestReferenceMatch() { return this.closestMatch; } public boolean hasTypeBit(int bit) { if (this.closestMatch != null) return this.closestMatch.hasTypeBit(bit); return false; } /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. */ public int problemId() { return this.problemReason; } public static String problemReasonString(int problemReason) { try { Class reasons = ProblemReasons.class; String simpleName = reasons.getName(); int lastDot = simpleName.lastIndexOf('.'); if (lastDot >= 0) { simpleName = simpleName.substring(lastDot+1); } Field[] fields = reasons.getFields(); for (int i = 0, length = fields.length; i < length; i++) { Field field = fields[i]; if (!field.getType().equals(int.class)) continue; if (field.getInt(reasons) == problemReason) { return simpleName + '.' + field.getName(); } } } catch (IllegalAccessException e) { // do nothing } return "unknown"; //$NON-NLS-1$ } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#shortReadableName() */ public char[] shortReadableName() { return readableName(); } public String toString() { StringBuffer buffer = new StringBuffer(10); buffer.append("ProblemType:[compoundName="); //$NON-NLS-1$ buffer.append(this.compoundName == null ? "" : new String(CharOperation.concatWith(this.compoundName,'.'))); //$NON-NLS-1$ buffer.append("][problemID=").append(problemReasonString(this.problemReason)); //$NON-NLS-1$ buffer.append("][closestMatch="); //$NON-NLS-1$ buffer.append(this.closestMatch == null ? "" : this.closestMatch.toString()); //$NON-NLS-1$ buffer.append("]"); //$NON-NLS-1$ return buffer.toString(); } } ././@LongLink0000644000000000000000000000016212251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/IQualifiedTypeResolutionListener.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/IQualifiedTypeResolution0000644000175000001440000000232612212041344032463 0ustar dokousers/******************************************************************************* * Copyright (c) 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; /** * A listener, which gets notified when a type binding has been discovered. *

* This interface may be implemented by clients. *

*/ public interface IQualifiedTypeResolutionListener { /** * Notifies that the given resolution has been found for the given type reference. Some of the bindings are * intermediate types i.e. qualifying types. * * @param typeReference * the type reference * @param resolution * the resolution found */ public void recordResolution(QualifiedTypeReference typeReference, TypeBinding resolution); } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SyntheticFieldBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SyntheticFieldBinding.ja0000644000175000001440000000202112212041344032313 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.impl.Constant; public class SyntheticFieldBinding extends FieldBinding { public int index; public SyntheticFieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant, int index) { super(name, type, modifiers, declaringClass, constant); this.index = index; this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java0000644000175000001440000002257312212041344030030 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource * bug 186342 - [compiler][null] Using annotations for null checking * bug 358903 - Filter practically unimportant resource leak warnings * bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account * bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions *******************************************************************************/ 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 // 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_JavaLangObject = 1; final int T_char = 2; final int T_byte = 3; final int T_short = 4; final int T_boolean = 5; final int T_void = 6; final int T_long = 7; final int T_double = 8; final int T_float = 9; final int T_int = 10; final int T_JavaLangString = 11; final int T_null = 12; //=========end of 4 bits constraint=========== // well-known exception types final int T_JavaLangClass = 16; final int T_JavaLangStringBuffer = 17; final int T_JavaLangSystem = 18; final int T_JavaLangError = 19; final int T_JavaLangReflectConstructor = 20; final int T_JavaLangThrowable = 21; final int T_JavaLangNoClassDefError = 22; final int T_JavaLangClassNotFoundException = 23; final int T_JavaLangRuntimeException = 24; final int T_JavaLangException = 25; // wrapper types final int T_JavaLangByte = 26; final int T_JavaLangShort = 27; final int T_JavaLangCharacter = 28; final int T_JavaLangInteger = 29; final int T_JavaLangLong = 30; final int T_JavaLangFloat = 31; final int T_JavaLangDouble = 32; final int T_JavaLangBoolean = 33; final int T_JavaLangVoid = 34; // 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 T_JavaIoPrintStream = 53; final int T_JavaLangReflectField = 54; final int T_JavaLangReflectMethod = 55; final int T_JavaIoExternalizable = 56; final int T_JavaIoObjectStreamException = 57; final int T_JavaIoException = 58; final int T_JavaUtilCollection = 59; // java 7 final int T_JavaLangSafeVarargs = 60; final int T_JavaLangInvokeMethodHandlePolymorphicSignature = 61; // java 7 java.lang.AutoCloseable final int T_JavaLangAutoCloseable = 62; // new in 3.8 for null annotations: final int T_ConfiguredAnnotationNullable = 65; final int T_ConfiguredAnnotationNonNull = 66; final int T_ConfiguredAnnotationNonNullByDefault = 67; // new in 3.8 to identify org.eclipse.core.runtime.Assert final int T_OrgEclipseCoreRuntimeAssert = 68; // new in 3.9 to identify more assertion utilities: final int T_JunitFrameworkAssert = 69; final int T_OrgJunitAssert = 70; final int T_OrgApacheCommonsLangValidate = 71; final int T_OrgApacheCommonsLang3Validate = 72; final int T_ComGoogleCommonBasePreconditions = 73; final int T_JavaUtilObjects = 74; // new in 3.9 to identify known @Inject annotations final int T_JavaxInjectInject = 80; final int T_ComGoogleInjectInject = 81; 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_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); final int Byte2Char = T_byte + (T_char << 4); final int Byte2Int = T_byte + (T_int << 4); 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_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); final int Short2Int = T_short + (T_int << 4); 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_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); final int Char2Int = T_char + (T_int << 4); 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_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); final int Int2Int = T_int + (T_int << 4); 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_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); final int Long2Int = T_long + (T_int << 4); 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_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); final int Float2Int = T_float + (T_int << 4); 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_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); final int Double2Int = T_double + (T_int << 4); 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_JavaLangString << 4); final int String2String = T_JavaLangString + (T_JavaLangString << 4); final int Object2String = T_JavaLangObject + (T_JavaLangString << 4); final int Null2Null = T_null + (T_null << 4); final int Null2String = T_null + (T_JavaLangString << 4); final int Object2Object = T_JavaLangObject + (T_JavaLangObject << 4); final int Object2byte = T_JavaLangObject + (T_byte << 4); final int Object2short = T_JavaLangObject + (T_short << 4); final int Object2char = T_JavaLangObject + (T_char << 4); final int Object2int = T_JavaLangObject + (T_int << 4); final int Object2long = T_JavaLangObject + (T_long << 4); final int Object2float = T_JavaLangObject + (T_float << 4); final int Object2double = T_JavaLangObject + (T_double << 4); final int Object2boolean = T_JavaLangObject + (T_boolean << 4); final int BOXING = 0x200; final int UNBOXING = 0x400; /** * Marks a type whose type bits have not yet been initialized. * @see ReferenceBinding#hasTypeBit(int) */ final int BitUninitialized = 0x8000000; /** * Marks all sub-types of java.lang.AutoCloseable. * @see ReferenceBinding#hasTypeBit(int) */ final int BitAutoCloseable = 1; /** * Marks all sub-types of java.io.Closeable. * @see ReferenceBinding#hasTypeBit(int) */ final int BitCloseable = 2; /** * Bit for members of a white list: * Subtypes of Closeable that wrap another resource without directly holding any OS resources. */ final int BitWrapperCloseable = 4; /** * Bit for members of a white list: * Subtypes of Closeable that do not hold an OS resource that needs to be released. */ final int BitResourceFreeCloseable = 8; /** * Set of type bits that should be inherited by any sub types. */ final int InheritableBits = BitAutoCloseable | BitCloseable; } ././@LongLink0000644000000000000000000000015412251602427011643 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBindi0000644000175000001440000000746612212041344032446 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.core.compiler.CharOperation; public class UnresolvedReferenceBinding extends ReferenceBinding { 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, LookupEnvironment environment) { if (this.resolvedType != null) { // the type reference B.M> means a signature of LB.M;>; // when the ParameterizedType for Unresolved B is created with args B.M, the Unresolved B is resolved before the wrapper is added wrapper.swapUnresolved(this, this.resolvedType, environment); return; } 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; } } public String debugName() { return toString(); } public boolean hasTypeBit(int bit) { // shouldn't happen since we are not called before analyseCode(), but play safe: return false; } 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 // report the missing class file first - only if not resolving a previously missing type if ((this.tagBits & TagBits.HasMissingType) == 0 && !environment.mayTolerateMissingType) { environment.problemReporter.isClassPathCorrect( this.compoundName, environment.unitBeingCompleted, environment.missingClassFileLocation); } // create a proxy for the missing BinaryType targetType = environment.createMissingType(null, this.compoundName); } setResolvedType(targetType, environment); } if (convertGenericToRawType) { targetType = (ReferenceBinding) environment.convertUnresolvedBinaryToRawType(targetType); } return targetType; } void setResolvedType(ReferenceBinding targetType, LookupEnvironment environment) { if (this.resolvedType == targetType) return; // already resolved // 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 " + ((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$ } } ././@LongLink0000644000000000000000000000015612251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SourceTypeCollisionException.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SourceTypeCollisionExcep0000644000175000001440000000152412212041344032463 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; public class SourceTypeCollisionException extends RuntimeException { private static final long serialVersionUID = 4798247636899127380L; public ICompilationUnit[] newAnnotationProcessorUnits; } ././@LongLink0000644000000000000000000000016412251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMet0000644000175000001440000000272712212041344032443 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; /** * Pseudo method binding used to wrapper a real method, and expose less exceptions than original. * For other protocols, it should delegate to original method */ public class MostSpecificExceptionMethodBinding extends MethodBinding { private MethodBinding originalMethod; public MostSpecificExceptionMethodBinding (MethodBinding originalMethod, ReferenceBinding[] mostSpecificExceptions) { super( originalMethod.modifiers, originalMethod.selector, originalMethod.returnType, originalMethod.parameters, mostSpecificExceptions, originalMethod.declaringClass); this.originalMethod = originalMethod; this.parameterNonNullness = originalMethod.parameterNonNullness; } public MethodBinding original() { return this.originalMethod.original(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java0000644000175000001440000000600412212041344031740 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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; private boolean use15specifics; public SignatureWrapper(char[] signature, boolean use15specifics) { this.signature = signature; this.start = 0; this.end = this.bracket = -1; this.use15specifics = use15specifics; } public SignatureWrapper(char [] signature) { this(signature, true); } 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; } if (this.use15specifics || this.end != this.bracket) { this.start = this.end + 1; // skip ';' } else { this.start = skipAngleContents(this.end) + 1; // skip <<>*>; this.bracket = -1; } return this.end; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, do not expose generics if we shouldn't public int skipAngleContents(int i) { if (this.signature[i] != '<') { return i; } int depth = 0, length = this.signature.length; for (++i; i < length; i++) { switch(this.signature[i]) { case '<' : depth++; break; case '>' : if (--depth < 0) return i + 1; break; } } return i; } 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$ } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java0000644000175000001440000003605612212041344030766 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 185682 - Increment/decrement operators mark local variables as read * bug 331649 - [compiler][null] consider null annotations for fields *******************************************************************************/ 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.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; public class FieldBinding extends VariableBinding { public ReferenceBinding declaringClass; public int compoundUseFlag = 0; // number or accesses via postIncrement or compoundAssignment protected FieldBinding() { super(null, null, 0, null); // for creating problem field } public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) { super(name, type, modifiers, constant); this.declaringClass = declaringClass; } // special API used to change field declaring class for runtime visibility check public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) { super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant()); this.declaringClass = declaringClass; this.id = initialFieldBinding.id; setAnnotations(initialFieldBinding.getAnnotations()); } /* API * Answer the receiver's binding type from Binding.BindingID. */ public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, ReferenceBinding declaringClass) { this(field.name, type, modifiers, declaringClass, null); field.binding = this; // record binding in declaration } public final boolean canBeSeenBy(PackageBinding invocationPackage) { if (isPublic()) return true; if (isPrivate()) return false; // isProtected() or isDefault() return invocationPackage == this.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. * * NOTE: Cannot invoke this method with a compilation unit scope. */ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { if (isPublic()) return true; SourceTypeBinding invocationType = scope.enclosingSourceType(); if (invocationType == this.declaringClass && invocationType == receiverType) return true; if (invocationType == null) // static import call return !isPrivate() && scope.getCurrentPackage() == this.declaringClass.fPackage; if (isProtected()) { // answer true if the invocationType is the declaringClass or they are in the same package // OR the invocationType is a subclass of the declaringClass // AND the receiverType is the invocationType or its subclass // OR the method is a static method accessed directly through a type // OR previous assertions are true for one of the enclosing type if (invocationType == this.declaringClass) return true; if (invocationType.fPackage == this.declaringClass.fPackage) return true; ReferenceBinding currentType = invocationType; int depth = 0; ReferenceBinding receiverErasure = (ReferenceBinding)receiverType.erasure(); ReferenceBinding declaringErasure = (ReferenceBinding) this.declaringClass.erasure(); do { if (currentType.findSuperTypeOriginatingFrom(declaringErasure) != null) { if (invocationSite.isSuperAccess()) return true; // receiverType can be an array binding in one case... see if you can change it if (receiverType instanceof ArrayBinding) return false; if (isStatic()) { if (depth > 0) invocationSite.setDepth(depth); return true; // see 1FMEPDL - return invocationSite.isTypeAccess(); } if (currentType == receiverErasure || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) { if (depth > 0) invocationSite.setDepth(depth); return true; } } depth++; currentType = currentType.enclosingType(); } while (currentType != null); return false; } if (isPrivate()) { // answer true if the receiverType is the declaringClass // AND the invocationType and the declaringClass have a common enclosingType receiverCheck: { if (receiverType != this.declaringClass) { // special tolerance for type variable direct bounds, but only if compliance <= 1.6, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622 if (scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_6 && receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(this.declaringClass.erasure())) break receiverCheck; return false; } } if (invocationType != this.declaringClass) { ReferenceBinding outerInvocationType = invocationType; ReferenceBinding temp = outerInvocationType.enclosingType(); while (temp != null) { outerInvocationType = temp; temp = temp.enclosingType(); } ReferenceBinding outerDeclaringClass = (ReferenceBinding) this.declaringClass.erasure(); temp = outerDeclaringClass.enclosingType(); while (temp != null) { outerDeclaringClass = temp; temp = temp.enclosingType(); } if (outerInvocationType != outerDeclaringClass) return false; } return true; } // isDefault() PackageBinding declaringPackage = this.declaringClass.fPackage; if (invocationType.fPackage != declaringPackage) return false; // receiverType can be an array binding in one case... see if you can change it if (receiverType instanceof ArrayBinding) return false; TypeBinding originalDeclaringClass = this.declaringClass.original(); ReferenceBinding currentType = (ReferenceBinding) receiverType; do { if (currentType.isCapture()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=285002 if (originalDeclaringClass == currentType.erasure().original()) return true; } else { if (originalDeclaringClass == currentType.original()) return true; } PackageBinding currentPackage = currentType.fPackage; // package could be null for wildcards/intersection types, ignore and recurse in superclass if (currentPackage != null && currentPackage != declaringPackage) return false; } while ((currentType = currentType.superclass()) != null); return false; } /* * declaringUniqueKey dot fieldName ) returnTypeUniqueKey * p.X { X x} --> Lp/X;.x)p/X; */ public char[] computeUniqueKey(boolean isLeaf) { // declaring key char[] declaringKey = this.declaringClass == null /*case of length field for an array*/ ? CharOperation.NO_CHAR : this.declaringClass.computeUniqueKey(false/*not a leaf*/); int declaringLength = declaringKey.length; // name int nameLength = this.name.length; // return type char[] returnTypeKey = this.type == null ? new char[] {'V'} : this.type.computeUniqueKey(false/*not a leaf*/); int returnTypeLength = returnTypeKey.length; char[] uniqueKey = new char[declaringLength + 1 + nameLength + 1 + returnTypeLength]; int index = 0; System.arraycopy(declaringKey, 0, uniqueKey, index, declaringLength); index += declaringLength; uniqueKey[index++] = '.'; System.arraycopy(this.name, 0, uniqueKey, index, nameLength); index += nameLength; uniqueKey[index++] = ')'; System.arraycopy(returnTypeKey, 0, uniqueKey, index, returnTypeLength); return uniqueKey; } public Constant constant() { Constant fieldConstant = this.constant; if (fieldConstant == null) { if (isFinal()) { //The field has not been yet type checked. //It also means that the field is not coming from a class that //has already been compiled. It can only be from a class within //compilation units to process. Thus the field is NOT from a BinaryTypeBinbing FieldBinding originalField = original(); if (originalField.declaringClass instanceof SourceTypeBinding) { SourceTypeBinding sourceType = (SourceTypeBinding) originalField.declaringClass; if (sourceType.scope != null) { TypeDeclaration typeDecl = sourceType.scope.referenceContext; FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField); MethodScope initScope = originalField.isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope; boolean old = initScope.insideTypeAnnotation; try { initScope.insideTypeAnnotation = false; fieldDecl.resolve(initScope); //side effect on binding } finally { initScope.insideTypeAnnotation = old; } fieldConstant = originalField.constant == null ? Constant.NotAConstant : originalField.constant; } else { fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check) } } else { fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check) } } else { fieldConstant = Constant.NotAConstant; } this.constant = fieldConstant; } return fieldConstant; } public void fillInDefaultNonNullness(FieldDeclaration sourceField, Scope scope) { if ( this.type != null && !this.type.isBaseType() && (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0) { this.tagBits |= TagBits.AnnotationNonNull; } else if ((this.tagBits & TagBits.AnnotationNonNull) != 0) { scope.problemReporter().nullAnnotationIsRedundant(sourceField); } } /** * X t --> LX; */ public char[] genericSignature() { if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) return null; return this.type.genericTypeSignature(); } public final int getAccessFlags() { return this.modifiers & ExtraCompilerModifiers.AccJustFlag; } public AnnotationBinding[] getAnnotations() { FieldBinding originalField = original(); ReferenceBinding declaringClassBinding = originalField.declaringClass; if (declaringClassBinding == null) { return Binding.NO_ANNOTATIONS; } return declaringClassBinding.retrieveAnnotations(originalField); } /** * Compute the tagbits for standard annotations. For source types, these could require * lazily resolving corresponding annotation nodes, in case of forward references. * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits() */ public long getAnnotationTagBits() { FieldBinding originalField = original(); if ((originalField.tagBits & TagBits.AnnotationResolved) == 0 && originalField.declaringClass instanceof SourceTypeBinding) { ClassScope scope = ((SourceTypeBinding) originalField.declaringClass).scope; if (scope == null) { // synthetic fields do not have a scope nor any annotations this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); return 0; } TypeDeclaration typeDecl = scope.referenceContext; FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField); if (fieldDecl != null) { MethodScope initializationScope = isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope; FieldBinding previousField = initializationScope.initializedField; int previousFieldID = initializationScope.lastVisibleFieldID; try { initializationScope.initializedField = originalField; initializationScope.lastVisibleFieldID = originalField.id; ASTNode.resolveAnnotations(initializationScope, fieldDecl.annotations, originalField); } finally { initializationScope.initializedField = previousField; initializationScope.lastVisibleFieldID = previousFieldID; } } } return originalField.tagBits; } public final boolean isDefault() { return !isPublic() && !isProtected() && !isPrivate(); } /* Answer true if the receiver is a deprecated field */ /* Answer true if the receiver has default visibility */ public final boolean isDeprecated() { return (this.modifiers & ClassFileConstants.AccDeprecated) != 0; } /* Answer true if the receiver has private visibility */ public final boolean isPrivate() { return (this.modifiers & ClassFileConstants.AccPrivate) != 0; } /* Answer true if the receiver has private visibility or is enclosed by a class that does. */ public final boolean isOrEnclosedByPrivateType() { if ((this.modifiers & ClassFileConstants.AccPrivate) != 0) return true; return this.declaringClass != null && this.declaringClass.isOrEnclosedByPrivateType(); } /* Answer true if the receiver has private visibility and is used locally */ public final boolean isProtected() { return (this.modifiers & ClassFileConstants.AccProtected) != 0; } /* Answer true if the receiver has public visibility */ public final boolean isPublic() { return (this.modifiers & ClassFileConstants.AccPublic) != 0; } /* Answer true if the receiver is a static field */ public final boolean isStatic() { return (this.modifiers & ClassFileConstants.AccStatic) != 0; } /* Answer true if the receiver is not defined in the source of the declaringClass */ public final boolean isSynthetic() { return (this.modifiers & ClassFileConstants.AccSynthetic) != 0; } /* Answer true if the receiver is a transient field */ public final boolean isTransient() { return (this.modifiers & ClassFileConstants.AccTransient) != 0; } /* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types) */ public final boolean isUsed() { return (this.modifiers & ExtraCompilerModifiers.AccLocallyUsed) != 0 || this.compoundUseFlag > 0; } /* Answer true if the only use of this field is in compound assignment or post increment */ public final boolean isUsedOnlyInCompound() { return (this.modifiers & ExtraCompilerModifiers.AccLocallyUsed) == 0 && this.compoundUseFlag > 0; } /* Answer true if the receiver has protected visibility */ public final boolean isViewedAsDeprecated() { return (this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0; } /* Answer true if the receiver is a volatile field */ public final boolean isVolatile() { return (this.modifiers & ClassFileConstants.AccVolatile) != 0; } public final int kind() { return FIELD; } /* Answer true if the receiver is visible to the invocationPackage. */ /** * Returns the original field (as opposed to parameterized instances) */ public FieldBinding original() { return this; } public void setAnnotations(AnnotationBinding[] annotations) { this.declaringClass.storeAnnotations(this, annotations); } public FieldDeclaration sourceField() { SourceTypeBinding sourceType; try { sourceType = (SourceTypeBinding) this.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; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java0000644000175000001440000000554612212041344031470 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 331649 - [compiler][null] consider null annotations for fields *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; public abstract class VariableBinding extends Binding { public int modifiers; public TypeBinding type; public char[] name; protected Constant constant; public int id; // for flow-analysis (position in flowInfo bit vector) public long tagBits; public VariableBinding(char[] name, TypeBinding type, int modifiers, Constant constant) { this.name = name; this.type = type; this.modifiers = modifiers; this.constant = constant; if (type != null) { this.tagBits |= (type.tagBits & TagBits.HasMissingType); } } public Constant constant() { return this.constant; } public abstract AnnotationBinding[] getAnnotations(); public final boolean isBlankFinal(){ return (this.modifiers & ExtraCompilerModifiers.AccBlankFinal) != 0; } /* Answer true if the receiver is final and cannot be changed */ public final boolean isFinal() { return (this.modifiers & ClassFileConstants.AccFinal) != 0; } public final boolean isEffectivelyFinal() { return (this.tagBits & TagBits.IsEffectivelyFinal) != 0; } /** Answer true if null annotations are enabled and this field is specified @NonNull */ public boolean isNonNull() { return (this.tagBits & TagBits.AnnotationNonNull) != 0; } /** Answer true if null annotations are enabled and this field is specified @Nullable */ public boolean isNullable() { return (this.tagBits & TagBits.AnnotationNullable) != 0; } public char[] readableName() { return this.name; } public void setConstant(Constant constant) { this.constant = constant; } public String toString() { StringBuffer output = new StringBuffer(10); ASTNode.printModifiers(this.modifiers, output); if ((this.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) { output.append("[unresolved] "); //$NON-NLS-1$ } output.append(this.type != null ? this.type.debugName() : ""); //$NON-NLS-1$ output.append(" "); //$NON-NLS-1$ output.append((this.name != null) ? new String(this.name) : ""); //$NON-NLS-1$ return output.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java0000644000175000001440000000723112212041344031643 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.*; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; public class ElementValuePair { char[] name; public Object value; public MethodBinding binding; public static Object getValue(Expression expression) { if (expression == null) return null; Constant constant = expression.constant; // literals would hit this case. if (constant != null && constant != Constant.NotAConstant) return constant; if (expression instanceof Annotation) return ((Annotation) expression).getCompilerAnnotation(); if (expression instanceof ArrayInitializer) { Expression[] exprs = ((ArrayInitializer) expression).expressions; int length = exprs == null ? 0 : exprs.length; Object[] values = new Object[length]; for (int i = 0; i < length; i++) values[i] = getValue(exprs[i]); return values; } if (expression instanceof ClassLiteralAccess) return ((ClassLiteralAccess) expression).targetType; if (expression instanceof Reference) { FieldBinding fieldBinding = null; if (expression instanceof FieldReference) { fieldBinding = ((FieldReference) expression).fieldBinding(); } else if (expression instanceof NameReference) { Binding binding = ((NameReference) expression).binding; if (binding != null && binding.kind() == Binding.FIELD) fieldBinding = (FieldBinding) binding; } if (fieldBinding != null && (fieldBinding.modifiers & ClassFileConstants.AccEnum) > 0) return fieldBinding; } // something that isn't a compile time constant. return null; } public ElementValuePair(char[] name, Expression expression, MethodBinding binding) { this(name, ElementValuePair.getValue(expression), binding); } public ElementValuePair(char[] name, Object value, MethodBinding binding) { this.name = name; this.value = value; this.binding = binding; } /** * @return the name of the element value pair. */ public char[] getName() { return this.name; } /** * @return the method binding that defined this member value pair or null if no such binding exists. */ public MethodBinding getMethodBinding() { return this.binding; } /** * Return {@link TypeBinding} for member value of type {@link java.lang.Class} * Return {@link org.eclipse.jdt.internal.compiler.impl.Constant} for member of primitive type or String * Return {@link FieldBinding} for enum constant * Return {@link AnnotationBinding} for annotation instance * Return Object[] for member value of array type. * @return the value of this member value pair or null if the value is missing or is not a compile-time constant */ public Object getValue() { return this.value; } void setMethodBinding(MethodBinding binding) { // lazily set after annotation type was resolved this.binding = binding; } void setValue(Object value) { // can be modified after the initialization if holding an unresolved ref this.value = value; } public String toString() { StringBuffer buffer = new StringBuffer(5); buffer.append(this.name).append(" = "); //$NON-NLS-1$ buffer.append(this.value); return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java0000644000175000001440000013054312212041344031157 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 367203 - [compiler][null] detect assigning null to nonnull argument * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 365662 - [compiler][null] warn on contradictory and redundant null annotations * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults * bug 388281 - [compiler][null] inheritance of null annotations as an option *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.List; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.util.Util; public class MethodBinding extends Binding { public int modifiers; public char[] selector; public TypeBinding returnType; public TypeBinding[] parameters; public ReferenceBinding[] thrownExceptions; public ReferenceBinding declaringClass; public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES; char[] signature; public long tagBits; /** Store nullness information from annotation (incl. applicable default). */ public Boolean[] parameterNonNullness; // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared protected MethodBinding() { // for creating problem or synthetic method } 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 = (parameters == null || parameters.length == 0) ? Binding.NO_PARAMETERS : parameters; this.thrownExceptions = (thrownExceptions == null || thrownExceptions.length == 0) ? Binding.NO_EXCEPTIONS : thrownExceptions; this.declaringClass = declaringClass; // propagate the strictfp & deprecated modifiers if (this.declaringClass != null) { if (this.declaringClass.isStrictfp()) if (!(isNative() || isAbstract())) this.modifiers |= ClassFileConstants.AccStrictfp; } } public MethodBinding(int modifiers, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) { this(modifiers, TypeConstants.INIT, TypeBinding.VOID, parameters, thrownExceptions, declaringClass); } // special API used to change method declaring class for runtime visibility check public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) { this.modifiers = initialMethodBinding.modifiers; this.selector = initialMethodBinding.selector; this.returnType = initialMethodBinding.returnType; this.parameters = initialMethodBinding.parameters; this.thrownExceptions = initialMethodBinding.thrownExceptions; this.declaringClass = declaringClass; declaringClass.storeAnnotationHolder(this, initialMethodBinding.declaringClass.retrieveAnnotationHolder(initialMethodBinding, 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 (this.parameters == args) return true; int length = this.parameters.length; if (length != args.length) return false; for (int i = 0; i < length; i++) if (this.parameters[i] != args[i] && this.parameters[i].erasure() != args[i].erasure()) return false; return true; } /* * Returns true if given parameters are compatible with this method parameters. * Callers to this method should first check that the number of TypeBindings * passed as argument matches this MethodBinding number of parameters */ 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 = this.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) this.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 (this.parameters[i] != arguments[i] && !arguments[i].isCompatibleWith(this.parameters[i])) return false; return true; } /* Answer true if the argument types & the receiver's parameters are equal */ public final boolean areParametersEqual(MethodBinding method) { TypeBinding[] args = method.parameters; if (this.parameters == args) return true; int length = this.parameters.length; if (length != args.length) return false; for (int i = 0; i < length; i++) if (this.parameters[i] != args[i]) return false; return true; } /* API * Answer the receiver's binding type from Binding.BindingID. */ /* Answer true if the type variables have the same erasure */ public final boolean areTypeVariableErasuresEqual(MethodBinding method) { TypeVariableBinding[] vars = method.typeVariables; if (this.typeVariables == vars) return true; int length = this.typeVariables.length; if (length != vars.length) return false; for (int i = 0; i < length; i++) if (this.typeVariables[i] != vars[i] && this.typeVariables[i].erasure() != vars[i].erasure()) return false; return true; } MethodBinding asRawMethod(LookupEnvironment env) { if (this.typeVariables == Binding.NO_TYPE_VARIABLES) return this; // substitute type arguments with raw types int length = this.typeVariables.length; TypeBinding[] arguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeVariableBinding var = this.typeVariables[i]; if (var.boundsCount() <= 1) { arguments[i] = env.convertToRawType(var.upperBound(), false /*do not force conversion of enclosing types*/); } else { // use an intersection type to retain full bound information if more than 1 bound TypeBinding[] itsSuperinterfaces = var.superInterfaces(); int superLength = itsSuperinterfaces.length; TypeBinding rawFirstBound = null; TypeBinding[] rawOtherBounds = null; if (var.boundsCount() == superLength) { rawFirstBound = env.convertToRawType(itsSuperinterfaces[0], false); rawOtherBounds = new TypeBinding[superLength - 1]; for (int s = 1; s < superLength; s++) rawOtherBounds[s - 1] = env.convertToRawType(itsSuperinterfaces[s], false); } else { rawFirstBound = env.convertToRawType(var.superclass(), false); rawOtherBounds = new TypeBinding[superLength]; for (int s = 0; s < superLength; s++) rawOtherBounds[s] = env.convertToRawType(itsSuperinterfaces[s], false); } arguments[i] = env.createWildcard(null, 0, rawFirstBound, rawOtherBounds, org.eclipse.jdt.internal.compiler.ast.Wildcard.EXTENDS); } } return env.createParameterizedGenericMethod(this, arguments); } /* 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. * * NOTE: This method should ONLY be sent if the receiver is a constructor. * * NOTE: Cannot invoke this method with a compilation unit scope. */ public final boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) { if (isPublic()) return true; SourceTypeBinding invocationType = scope.enclosingSourceType(); if (invocationType == this.declaringClass) return true; if (isProtected()) { // answer true if the receiver is in the same package as the invocationType if (invocationType.fPackage == this.declaringClass.fPackage) return true; return invocationSite.isSuperAccess(); } if (isPrivate()) { // answer true if the invocationType and the declaringClass have a common enclosingType // already know they are not the identical type ReferenceBinding outerInvocationType = invocationType; ReferenceBinding temp = outerInvocationType.enclosingType(); while (temp != null) { outerInvocationType = temp; temp = temp.enclosingType(); } ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.declaringClass.erasure(); temp = outerDeclaringClass.enclosingType(); while (temp != null) { outerDeclaringClass = temp; temp = temp.enclosingType(); } return outerInvocationType == outerDeclaringClass; } // isDefault() return invocationType.fPackage == this.declaringClass.fPackage; } public final boolean canBeSeenBy(PackageBinding invocationPackage) { if (isPublic()) return true; if (isPrivate()) return false; // isProtected() or isDefault() return invocationPackage == this.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. * * NOTE: Cannot invoke this method with a compilation unit scope. */ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { if (isPublic()) return true; SourceTypeBinding invocationType = scope.enclosingSourceType(); if (invocationType == this.declaringClass && invocationType == receiverType) return true; if (invocationType == null) // static import call return !isPrivate() && scope.getCurrentPackage() == this.declaringClass.fPackage; if (isProtected()) { // answer true if the invocationType is the declaringClass or they are in the same package // OR the invocationType is a subclass of the declaringClass // AND the receiverType is the invocationType or its subclass // OR the method is a static method accessed directly through a type // OR previous assertions are true for one of the enclosing type if (invocationType == this.declaringClass) return true; if (invocationType.fPackage == this.declaringClass.fPackage) return true; ReferenceBinding currentType = invocationType; TypeBinding receiverErasure = receiverType.erasure(); ReferenceBinding declaringErasure = (ReferenceBinding) this.declaringClass.erasure(); int depth = 0; do { if (currentType.findSuperTypeOriginatingFrom(declaringErasure) != null) { if (invocationSite.isSuperAccess()) return true; // receiverType can be an array binding in one case... see if you can change it if (receiverType instanceof ArrayBinding) return false; if (isStatic()) { if (depth > 0) invocationSite.setDepth(depth); return true; // see 1FMEPDL - return invocationSite.isTypeAccess(); } if (currentType == receiverErasure || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) { if (depth > 0) invocationSite.setDepth(depth); return true; } } depth++; currentType = currentType.enclosingType(); } while (currentType != null); return false; } if (isPrivate()) { // answer true if the receiverType is the declaringClass // AND the invocationType and the declaringClass have a common enclosingType receiverCheck: { if (receiverType != this.declaringClass) { // special tolerance for type variable direct bounds, but only if compliance <= 1.6, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622 if (scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_6 && receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(this.declaringClass.erasure())) break receiverCheck; return false; } } if (invocationType != this.declaringClass) { ReferenceBinding outerInvocationType = invocationType; ReferenceBinding temp = outerInvocationType.enclosingType(); while (temp != null) { outerInvocationType = temp; temp = temp.enclosingType(); } ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.declaringClass.erasure(); temp = outerDeclaringClass.enclosingType(); while (temp != null) { outerDeclaringClass = temp; temp = temp.enclosingType(); } if (outerInvocationType != outerDeclaringClass) return false; } return true; } // isDefault() PackageBinding declaringPackage = this.declaringClass.fPackage; if (invocationType.fPackage != declaringPackage) return false; // receiverType can be an array binding in one case... see if you can change it if (receiverType instanceof ArrayBinding) return false; TypeBinding originalDeclaringClass = this.declaringClass.original(); ReferenceBinding currentType = (ReferenceBinding) (receiverType); do { if (currentType.isCapture()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=285002 if (originalDeclaringClass == currentType.erasure().original()) return true; } else { if (originalDeclaringClass == currentType.original()) return true; } PackageBinding currentPackage = currentType.fPackage; // package could be null for wildcards/intersection types, ignore and recurse in superclass if (currentPackage != null && currentPackage != declaringPackage) return false; } while ((currentType = currentType.superclass()) != null); return false; } public List collectMissingTypes(List missingTypes) { if ((this.tagBits & TagBits.HasMissingType) != 0) { missingTypes = this.returnType.collectMissingTypes(missingTypes); for (int i = 0, max = this.parameters.length; i < max; i++) { missingTypes = this.parameters[i].collectMissingTypes(missingTypes); } for (int i = 0, max = this.thrownExceptions.length; i < max; i++) { missingTypes = this.thrownExceptions[i].collectMissingTypes(missingTypes); } for (int i = 0, max = this.typeVariables.length; i < max; i++) { TypeVariableBinding variable = this.typeVariables[i]; missingTypes = variable.superclass().collectMissingTypes(missingTypes); ReferenceBinding[] interfaces = variable.superInterfaces(); for (int j = 0, length = interfaces.length; j < length; j++) { missingTypes = interfaces[j].collectMissingTypes(missingTypes); } } } return missingTypes; } MethodBinding computeSubstitutedMethod(MethodBinding method, LookupEnvironment env) { int length = this.typeVariables.length; TypeVariableBinding[] vars = method.typeVariables; if (length != vars.length) return null; // must substitute to detect cases like: // > void dup() {} // > Object dup() {return null;} ParameterizedGenericMethodBinding substitute = env.createParameterizedGenericMethod(method, this.typeVariables); for (int i = 0; i < length; i++) if (!this.typeVariables[i].isInterchangeableWith(vars[i], substitute)) return null; return substitute; } /* * declaringUniqueKey dot selector genericSignature * p.X { void bar(X t) } --> Lp/X;.bar(LX;)V */ public char[] computeUniqueKey(boolean isLeaf) { // declaring class char[] declaringKey = this.declaringClass.computeUniqueKey(false/*not a leaf*/); int declaringLength = declaringKey.length; // selector int selectorLength = this.selector == TypeConstants.INIT ? 0 : this.selector.length; // generic signature char[] sig = genericSignature(); boolean isGeneric = sig != null; if (!isGeneric) sig = signature(); int signatureLength = sig.length; // thrown exceptions int thrownExceptionsLength = this.thrownExceptions.length; int thrownExceptionsSignatureLength = 0; char[][] thrownExceptionsSignatures = null; boolean addThrownExceptions = thrownExceptionsLength > 0 && (!isGeneric || CharOperation.lastIndexOf('^', sig) < 0); if (addThrownExceptions) { thrownExceptionsSignatures = new char[thrownExceptionsLength][]; for (int i = 0; i < thrownExceptionsLength; i++) { if (this.thrownExceptions[i] != null) { thrownExceptionsSignatures[i] = this.thrownExceptions[i].signature(); thrownExceptionsSignatureLength += thrownExceptionsSignatures[i].length + 1; // add one char for separator } } } char[] uniqueKey = new char[declaringLength + 1 + selectorLength + signatureLength + thrownExceptionsSignatureLength]; int index = 0; System.arraycopy(declaringKey, 0, uniqueKey, index, declaringLength); index = declaringLength; uniqueKey[index++] = '.'; System.arraycopy(this.selector, 0, uniqueKey, index, selectorLength); index += selectorLength; System.arraycopy(sig, 0, uniqueKey, index, signatureLength); if (thrownExceptionsSignatureLength > 0) { index += signatureLength; for (int i = 0; i < thrownExceptionsLength; i++) { char[] thrownExceptionSignature = thrownExceptionsSignatures[i]; if (thrownExceptionSignature != null) { uniqueKey[index++] = '|'; int length = thrownExceptionSignature.length; System.arraycopy(thrownExceptionSignature, 0, uniqueKey, index, length); index += length; } } } return uniqueKey; } /* Answer the receiver's constant pool name. * * for constructors * for clinit methods * or the source name of the method */ public final char[] constantPoolName() { return this.selector; } /** * After method verifier has finished, fill in missing @NonNull specification from the applicable default. */ protected void fillInDefaultNonNullness(AbstractMethodDeclaration sourceMethod) { if (this.parameterNonNullness == null) this.parameterNonNullness = new Boolean[this.parameters.length]; boolean added = false; int length = this.parameterNonNullness.length; for (int i = 0; i < length; i++) { if (this.parameters[i].isBaseType()) continue; if (this.parameterNonNullness[i] == null) { added = true; this.parameterNonNullness[i] = Boolean.TRUE; if (sourceMethod != null) { sourceMethod.arguments[i].binding.tagBits |= TagBits.AnnotationNonNull; } } else if (sourceMethod != null && this.parameterNonNullness[i].booleanValue()) { sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i); } } if (added) this.tagBits |= TagBits.HasParameterAnnotations; if ( this.returnType != null && !this.returnType.isBaseType() && (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0) { this.tagBits |= TagBits.AnnotationNonNull; } else if (sourceMethod != null && (this.tagBits & TagBits.AnnotationNonNull) != 0) { sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/); } } public MethodBinding findOriginalInheritedMethod(MethodBinding inheritedMethod) { MethodBinding inheritedOriginal = inheritedMethod.original(); TypeBinding superType = this.declaringClass.findSuperTypeOriginatingFrom(inheritedOriginal.declaringClass); if (superType == null || !(superType instanceof ReferenceBinding)) return null; if (inheritedOriginal.declaringClass != superType) { // must find inherited method with the same substituted variables MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(inheritedOriginal.selector, inheritedOriginal.parameters.length); for (int m = 0, l = superMethods.length; m < l; m++) if (superMethods[m].original() == inheritedOriginal) return superMethods[m]; } return inheritedOriginal; } /** *
 *(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 & ExtraCompilerModifiers.AccGenericSignature) == 0) return null; StringBuffer sig = new StringBuffer(10); if (this.typeVariables != Binding.NO_TYPE_VARIABLES) { 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 & ExtraCompilerModifiers.AccGenericSignature) != 0) { needExceptionSignatures = true; break; } } if (needExceptionSignatures) { for (int i = 0; i < length; i++) { sig.append('^'); 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 this.modifiers & ExtraCompilerModifiers.AccJustFlag; } public AnnotationBinding[] getAnnotations() { MethodBinding originalMethod = original(); return originalMethod.declaringClass.retrieveAnnotations(originalMethod); } /** * Compute the tagbits for standard annotations. For source types, these could require * lazily resolving corresponding annotation nodes, in case of forward references. * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits() */ public long getAnnotationTagBits() { MethodBinding originalMethod = original(); if ((originalMethod.tagBits & TagBits.AnnotationResolved) == 0 && originalMethod.declaringClass instanceof SourceTypeBinding) { ClassScope scope = ((SourceTypeBinding) originalMethod.declaringClass).scope; if (scope != null) { TypeDeclaration typeDecl = scope.referenceContext; AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod); if (methodDecl != null) ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod); long nullDefaultBits = this.tagBits & (TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault); if (nullDefaultBits != 0 && this.declaringClass instanceof SourceTypeBinding) { SourceTypeBinding declaringSourceType = (SourceTypeBinding) this.declaringClass; if (declaringSourceType.checkRedundantNullnessDefaultOne(methodDecl, methodDecl.annotations, nullDefaultBits)) { declaringSourceType.checkRedundantNullnessDefaultRecurse(methodDecl, methodDecl.annotations, nullDefaultBits); } } } } return originalMethod.tagBits; } /** * @return the default value for this annotation method or null if there is no default value */ public Object getDefaultValue() { MethodBinding originalMethod = original(); if ((originalMethod.tagBits & TagBits.DefaultValueResolved) == 0) { //The method has not been resolved nor has its class been resolved. //It can only be from a source type within compilation units to process. if (originalMethod.declaringClass instanceof SourceTypeBinding) { SourceTypeBinding sourceType = (SourceTypeBinding) originalMethod.declaringClass; if (sourceType.scope != null) { AbstractMethodDeclaration methodDeclaration = originalMethod.sourceMethod(); if (methodDeclaration != null && methodDeclaration.isAnnotationMethod()) { methodDeclaration.resolve(sourceType.scope); } } } originalMethod.tagBits |= TagBits.DefaultValueResolved; } AnnotationHolder holder = originalMethod.declaringClass.retrieveAnnotationHolder(originalMethod, true); return holder == null ? null : holder.getDefaultValue(); } /** * @return the annotations for each of the method parameters or null> * if there's no parameter or no annotation at all. */ public AnnotationBinding[][] getParameterAnnotations() { int length; if ((length = this.parameters.length) == 0) { return null; } MethodBinding originalMethod = original(); AnnotationHolder holder = originalMethod.declaringClass.retrieveAnnotationHolder(originalMethod, true); AnnotationBinding[][] allParameterAnnotations = holder == null ? null : holder.getParameterAnnotations(); if (allParameterAnnotations == null && (this.tagBits & TagBits.HasParameterAnnotations) != 0) { allParameterAnnotations = new AnnotationBinding[length][]; // forward reference to method, where param annotations have not yet been associated to method if (this.declaringClass instanceof SourceTypeBinding) { SourceTypeBinding sourceType = (SourceTypeBinding) this.declaringClass; if (sourceType.scope != null) { AbstractMethodDeclaration methodDecl = sourceType.scope.referenceType().declarationOf(this); for (int i = 0; i < length; i++) { Argument argument = methodDecl.arguments[i]; if (argument.annotations != null) { ASTNode.resolveAnnotations(methodDecl.scope, argument.annotations, argument.binding); allParameterAnnotations[i] = argument.binding.getAnnotations(); } else { allParameterAnnotations[i] = Binding.NO_ANNOTATIONS; } } } else { for (int i = 0; i < length; i++) { allParameterAnnotations[i] = Binding.NO_ANNOTATIONS; } } } else { for (int i = 0; i < length; i++) { allParameterAnnotations[i] = Binding.NO_ANNOTATIONS; } } setParameterAnnotations(allParameterAnnotations); } return allParameterAnnotations; } 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 */ public final boolean isAbstract() { return (this.modifiers & ClassFileConstants.AccAbstract) != 0; } /* Answer true if the receiver is a bridge method */ public final boolean isBridge() { return (this.modifiers & ClassFileConstants.AccBridge) != 0; } /* Answer true if the receiver is a constructor */ public final boolean isConstructor() { return this.selector == TypeConstants.INIT; } /* Answer true if the receiver has default visibility */ public final boolean isDefault() { return !isPublic() && !isProtected() && !isPrivate(); } /* Answer true if the receiver is a system generated default abstract method */ public final boolean isDefaultAbstract() { return (this.modifiers & ExtraCompilerModifiers.AccDefaultAbstract) != 0; } /* Answer true if the receiver is a deprecated method */ public final boolean isDeprecated() { return (this.modifiers & ClassFileConstants.AccDeprecated) != 0; } /* Answer true if the receiver is final and cannot be overridden */ public final boolean isFinal() { return (this.modifiers & ClassFileConstants.AccFinal) != 0; } /* Answer true if the receiver is implementing another method * in other words, it is overriding and concrete, and overriden method is abstract * Only set for source methods */ public final boolean isImplementing() { return (this.modifiers & ExtraCompilerModifiers.AccImplementing) != 0; } /* * Answer true if the receiver is a "public static void main(String[])" method */ public final boolean isMain() { if (this.selector.length == 4 && CharOperation.equals(this.selector, TypeConstants.MAIN) && ((this.modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccStatic)) != 0) && TypeBinding.VOID == this.returnType && this.parameters.length == 1) { TypeBinding paramType = this.parameters[0]; if (paramType.dimensions() == 1 && paramType.leafComponentType().id == TypeIds.T_JavaLangString) { return true; } } return false; } /* Answer true if the receiver is a native method */ public final boolean isNative() { return (this.modifiers & ClassFileConstants.AccNative) != 0; } /* Answer true if the receiver is overriding another method * Only set for source methods */ public final boolean isOverriding() { return (this.modifiers & ExtraCompilerModifiers.AccOverriding) != 0; } /* Answer true if the receiver has private visibility */ public final boolean isPrivate() { return (this.modifiers & ClassFileConstants.AccPrivate) != 0; } /* Answer true if the receiver has private visibility or if any of its enclosing types do. */ public final boolean isOrEnclosedByPrivateType() { if ((this.modifiers & ClassFileConstants.AccPrivate) != 0) return true; return this.declaringClass != null && this.declaringClass.isOrEnclosedByPrivateType(); } /* Answer true if the receiver has protected visibility */ public final boolean isProtected() { return (this.modifiers & ClassFileConstants.AccProtected) != 0; } /* Answer true if the receiver has public visibility */ public final boolean isPublic() { return (this.modifiers & ClassFileConstants.AccPublic) != 0; } /* Answer true if the receiver is a static method */ public final boolean isStatic() { return (this.modifiers & ClassFileConstants.AccStatic) != 0; } /* Answer true if all float operations must adher to IEEE 754 float/double rules */ public final boolean isStrictfp() { return (this.modifiers & ClassFileConstants.AccStrictfp) != 0; } /* Answer true if the receiver is a synchronized method */ public final boolean isSynchronized() { return (this.modifiers & ClassFileConstants.AccSynchronized) != 0; } /* Answer true if the receiver has public visibility */ public final boolean isSynthetic() { return (this.modifiers & ClassFileConstants.AccSynthetic) != 0; } /* Answer true if the receiver has private visibility and is used locally */ public final boolean isUsed() { return (this.modifiers & ExtraCompilerModifiers.AccLocallyUsed) != 0; } /* Answer true if the receiver method has varargs */ public boolean isVarargs() { return (this.modifiers & ClassFileConstants.AccVarargs) != 0; } public boolean isPolymorphic() { return false; } /* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types) */ public final boolean isViewedAsDeprecated() { return (this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0; } public final int kind() { return Binding.METHOD; } /* Answer true if the receiver is visible to the invocationPackage. */ /** * Returns the original method (as opposed to parameterized/polymorphic instances) */ public MethodBinding original() { return this; } public char[] readableName() /* foo(int, Thread) */ { StringBuffer buffer = new StringBuffer(this.parameters.length + 1 * 20); if (isConstructor()) buffer.append(this.declaringClass.sourceName()); else buffer.append(this.selector); buffer.append('('); if (this.parameters != Binding.NO_PARAMETERS) { for (int i = 0, length = this.parameters.length; i < length; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append(this.parameters[i].sourceName()); } } buffer.append(')'); return buffer.toString().toCharArray(); } public void setAnnotations(AnnotationBinding[] annotations) { this.declaringClass.storeAnnotations(this, annotations); } public void setAnnotations(AnnotationBinding[] annotations, AnnotationBinding[][] parameterAnnotations, Object defaultValue, LookupEnvironment optionalEnv) { this.declaringClass.storeAnnotationHolder(this, AnnotationHolder.storeAnnotations(annotations, parameterAnnotations, defaultValue, optionalEnv)); } public void setDefaultValue(Object defaultValue) { MethodBinding originalMethod = original(); originalMethod.tagBits |= TagBits.DefaultValueResolved; AnnotationHolder holder = this.declaringClass.retrieveAnnotationHolder(this, false); if (holder == null) setAnnotations(null, null, defaultValue, null); else setAnnotations(holder.getAnnotations(), holder.getParameterAnnotations(), defaultValue, null); } public void setParameterAnnotations(AnnotationBinding[][] parameterAnnotations) { AnnotationHolder holder = this.declaringClass.retrieveAnnotationHolder(this, false); if (holder == null) setAnnotations(null, parameterAnnotations, null, null); else setAnnotations(holder.getAnnotations(), parameterAnnotations, holder.getDefaultValue(), null); } protected final void setSelector(char[] selector) { this.selector = selector; this.signature = null; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName() */ public char[] shortReadableName() { StringBuffer buffer = new StringBuffer(this.parameters.length + 1 * 20); if (isConstructor()) buffer.append(this.declaringClass.shortReadableName()); else buffer.append(this.selector); buffer.append('('); if (this.parameters != Binding.NO_PARAMETERS) { for (int i = 0, length = this.parameters.length; i < length; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append(this.parameters[i].shortReadableName()); } } buffer.append(')'); int nameLength = buffer.length(); char[] shortReadableName = new char[nameLength]; buffer.getChars(0, nameLength, shortReadableName, 0); return shortReadableName; } /* Answer the receiver's signature. * * NOTE: This method should only be used during/after code gen. * The signature is cached so if the signature of the return type or any parameter * type changes, the cached state is invalid. */ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ { if (this.signature != null) return this.signature; StringBuffer buffer = new StringBuffer(this.parameters.length + 1 * 20); buffer.append('('); TypeBinding[] targetParameters = this.parameters; boolean isConstructor = isConstructor(); if (isConstructor && this.declaringClass.isEnum()) { // insert String name,int ordinal buffer.append(ConstantPool.JavaLangStringSignature); buffer.append(TypeBinding.INT.signature()); } boolean needSynthetics = isConstructor && this.declaringClass.isNestedType(); if (needSynthetics) { // take into account the synthetic argument type signatures as well ReferenceBinding[] syntheticArgumentTypes = this.declaringClass.syntheticEnclosingInstanceTypes(); if (syntheticArgumentTypes != null) { for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) { buffer.append(syntheticArgumentTypes[i].signature()); } } if (this instanceof SyntheticMethodBinding) { targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters; } } if (targetParameters != Binding.NO_PARAMETERS) { for (int i = 0; i < targetParameters.length; i++) { buffer.append(targetParameters[i].signature()); } } if (needSynthetics) { SyntheticArgumentBinding[] syntheticOuterArguments = this.declaringClass.syntheticOuterLocalVariables(); int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length; for (int i = 0; i < count; i++) { buffer.append(syntheticOuterArguments[i].type.signature()); } // move the extra padding arguments of the synthetic constructor invocation to the end for (int i = targetParameters.length, extraLength = this.parameters.length; i < extraLength; i++) { buffer.append(this.parameters[i].signature()); } } buffer.append(')'); if (this.returnType != null) buffer.append(this.returnType.signature()); int nameLength = buffer.length(); this.signature = new char[nameLength]; buffer.getChars(0, nameLength, this.signature, 0); return this.signature; } /* * This method is used to record references to nested types inside the method signature. * This is the one that must be used during code generation. * * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=171184 */ public final char[] signature(ClassFile classFile) { if (this.signature != null) { if ((this.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { // we need to record inner classes references boolean isConstructor = isConstructor(); TypeBinding[] targetParameters = this.parameters; boolean needSynthetics = isConstructor && this.declaringClass.isNestedType(); if (needSynthetics) { // take into account the synthetic argument type signatures as well ReferenceBinding[] syntheticArgumentTypes = this.declaringClass.syntheticEnclosingInstanceTypes(); if (syntheticArgumentTypes != null) { for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) { ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i]; if ((syntheticArgumentType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(classFile, syntheticArgumentType); } } } if (this instanceof SyntheticMethodBinding) { targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters; } } if (targetParameters != Binding.NO_PARAMETERS) { for (int i = 0, max = targetParameters.length; i < max; i++) { TypeBinding targetParameter = targetParameters[i]; TypeBinding leafTargetParameterType = targetParameter.leafComponentType(); if ((leafTargetParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(classFile, leafTargetParameterType); } } } if (needSynthetics) { // move the extra padding arguments of the synthetic constructor invocation to the end for (int i = targetParameters.length, extraLength = this.parameters.length; i < extraLength; i++) { TypeBinding parameter = this.parameters[i]; TypeBinding leafParameterType = parameter.leafComponentType(); if ((leafParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(classFile, leafParameterType); } } } if (this.returnType != null) { TypeBinding ret = this.returnType.leafComponentType(); if ((ret.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(classFile, ret); } } } return this.signature; } StringBuffer buffer = new StringBuffer((this.parameters.length + 1) * 20); buffer.append('('); TypeBinding[] targetParameters = this.parameters; boolean isConstructor = isConstructor(); if (isConstructor && this.declaringClass.isEnum()) { // insert String name,int ordinal buffer.append(ConstantPool.JavaLangStringSignature); buffer.append(TypeBinding.INT.signature()); } boolean needSynthetics = isConstructor && this.declaringClass.isNestedType(); if (needSynthetics) { // take into account the synthetic argument type signatures as well ReferenceBinding[] syntheticArgumentTypes = this.declaringClass.syntheticEnclosingInstanceTypes(); if (syntheticArgumentTypes != null) { for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) { ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i]; if ((syntheticArgumentType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { this.tagBits |= TagBits.ContainsNestedTypeReferences; Util.recordNestedType(classFile, syntheticArgumentType); } buffer.append(syntheticArgumentType.signature()); } } if (this instanceof SyntheticMethodBinding) { targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters; } } if (targetParameters != Binding.NO_PARAMETERS) { for (int i = 0, max = targetParameters.length; i < max; i++) { TypeBinding targetParameter = targetParameters[i]; TypeBinding leafTargetParameterType = targetParameter.leafComponentType(); if ((leafTargetParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { this.tagBits |= TagBits.ContainsNestedTypeReferences; Util.recordNestedType(classFile, leafTargetParameterType); } buffer.append(targetParameter.signature()); } } if (needSynthetics) { SyntheticArgumentBinding[] syntheticOuterArguments = this.declaringClass.syntheticOuterLocalVariables(); int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length; for (int i = 0; i < count; i++) { buffer.append(syntheticOuterArguments[i].type.signature()); } // move the extra padding arguments of the synthetic constructor invocation to the end for (int i = targetParameters.length, extraLength = this.parameters.length; i < extraLength; i++) { TypeBinding parameter = this.parameters[i]; TypeBinding leafParameterType = parameter.leafComponentType(); if ((leafParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { this.tagBits |= TagBits.ContainsNestedTypeReferences; Util.recordNestedType(classFile, leafParameterType); } buffer.append(parameter.signature()); } } buffer.append(')'); if (this.returnType != null) { TypeBinding ret = this.returnType.leafComponentType(); if ((ret.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { this.tagBits |= TagBits.ContainsNestedTypeReferences; Util.recordNestedType(classFile, ret); } buffer.append(this.returnType.signature()); } int nameLength = buffer.length(); this.signature = new char[nameLength]; buffer.getChars(0, nameLength, this.signature, 0); return this.signature; } public final int sourceEnd() { AbstractMethodDeclaration method = sourceMethod(); if (method == null) { if (this.declaringClass instanceof SourceTypeBinding) return ((SourceTypeBinding) this.declaringClass).sourceEnd(); return 0; } return method.sourceEnd; } public AbstractMethodDeclaration sourceMethod() { if (isSynthetic()) { return null; } SourceTypeBinding sourceType; try { sourceType = (SourceTypeBinding) this.declaringClass; } catch (ClassCastException e) { return null; } AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods; if (methods != null) { for (int i = methods.length; --i >= 0;) if (this == methods[i].binding) return methods[i]; } return null; } public final int sourceStart() { AbstractMethodDeclaration method = sourceMethod(); if (method == null) { if (this.declaringClass instanceof SourceTypeBinding) return ((SourceTypeBinding) this.declaringClass).sourceStart(); return 0; } return method.sourceStart; } /** * 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 String toString() { StringBuffer output = new StringBuffer(10); if ((this.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) { output.append("[unresolved] "); //$NON-NLS-1$ } ASTNode.printModifiers(this.modifiers, output); output.append(this.returnType != null ? this.returnType.debugName() : ""); //$NON-NLS-1$ output.append(" "); //$NON-NLS-1$ output.append(this.selector != null ? new String(this.selector) : ""); //$NON-NLS-1$ output.append("("); //$NON-NLS-1$ if (this.parameters != null) { if (this.parameters != Binding.NO_PARAMETERS) { for (int i = 0, length = this.parameters.length; i < length; i++) { if (i > 0) output.append(", "); //$NON-NLS-1$ output.append(this.parameters[i] != null ? this.parameters[i].debugName() : ""); //$NON-NLS-1$ } } } else { output.append(""); //$NON-NLS-1$ } output.append(") "); //$NON-NLS-1$ if (this.thrownExceptions != null) { if (this.thrownExceptions != Binding.NO_EXCEPTIONS) { output.append("throws "); //$NON-NLS-1$ for (int i = 0, length = this.thrownExceptions.length; i < length; i++) { if (i > 0) output.append(", "); //$NON-NLS-1$ output.append((this.thrownExceptions[i] != null) ? this.thrownExceptions[i].debugName() : ""); //$NON-NLS-1$ } } } else { output.append(""); //$NON-NLS-1$ } return output.toString(); } public TypeVariableBinding[] typeVariables() { return this.typeVariables; } public boolean hasNonNullDefault() { if ((this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) return true; if ((this.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) return false; return this.declaringClass.hasNonNullDefault(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java0000644000175000001440000002300012212041344032036 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.Annotation; /** * Represents JSR 175 Annotation instances in the type-system. */ public class AnnotationBinding { // do not access directly - use getters instead (UnresolvedAnnotationBinding // resolves types for type and pair contents just in time) ReferenceBinding type; ElementValuePair[] pairs; /** * Add the standard annotations encoded in the tag bits to the recorded annotations. * * @param recordedAnnotations existing annotations already created * @param annotationTagBits * @param env * @return the combined list of annotations */ public static AnnotationBinding[] addStandardAnnotations(AnnotationBinding[] recordedAnnotations, long annotationTagBits, LookupEnvironment env) { // NOTE: expect annotations to be requested just once so there is no need to store the standard annotations // and all of the standard annotations created by this method are fully resolved since the sender is expected to use them immediately if ((annotationTagBits & TagBits.AllStandardAnnotationsMask) == 0) { return recordedAnnotations; } int count = 0; if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0) count++; if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0) count++; if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0) count++; if ((annotationTagBits & TagBits.AnnotationDocumented) != 0) count++; if ((annotationTagBits & TagBits.AnnotationInherited) != 0) count++; if ((annotationTagBits & TagBits.AnnotationOverride) != 0) count++; if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0) count++; if ((annotationTagBits & TagBits.AnnotationPolymorphicSignature) != 0) count++; if ((annotationTagBits & TagBits.AnnotationSafeVarargs) != 0) count++; if (count == 0) { // this is possible if bits were set for null annotations return recordedAnnotations; } int index = recordedAnnotations.length; AnnotationBinding[] result = new AnnotationBinding[index + count]; System.arraycopy(recordedAnnotations, 0, result, 0, index); if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0) result[index++] = buildTargetAnnotation(annotationTagBits, env); if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0) result[index++] = buildRetentionAnnotation(annotationTagBits, env); if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0) result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_DEPRECATED, env); if ((annotationTagBits & TagBits.AnnotationDocumented) != 0) result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED, env); if ((annotationTagBits & TagBits.AnnotationInherited) != 0) result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_INHERITED, env); if ((annotationTagBits & TagBits.AnnotationOverride) != 0) result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, env); if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0) result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, env); if ((annotationTagBits & TagBits.AnnotationPolymorphicSignature) != 0) result[index++] = buildMarkerAnnotationForMemberType(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE, env); if ((annotationTagBits & TagBits.AnnotationSafeVarargs) != 0) result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SAFEVARARGS, env); return result; } private static AnnotationBinding buildMarkerAnnotationForMemberType(char[][] compoundName, LookupEnvironment env) { ReferenceBinding type = env.getResolvedType(compoundName, null); // since this is a member type name using '$' the return binding is a // problem reference binding with reason ProblemReasons.InternalNameProvided if (!type.isValidBinding()) { type = ((ProblemReferenceBinding) type).closestMatch; } return env.createAnnotation(type, Binding.NO_ELEMENT_VALUE_PAIRS); } private static AnnotationBinding buildMarkerAnnotation(char[][] compoundName, LookupEnvironment env) { ReferenceBinding type = env.getResolvedType(compoundName, null); return env.createAnnotation(type, Binding.NO_ELEMENT_VALUE_PAIRS); } private static AnnotationBinding buildRetentionAnnotation(long bits, LookupEnvironment env) { ReferenceBinding retentionPolicy = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY, null); Object value = null; if ((bits & TagBits.AnnotationRuntimeRetention) == TagBits.AnnotationRuntimeRetention) { value = retentionPolicy.getField(TypeConstants.UPPER_RUNTIME, true); } else if ((bits & TagBits.AnnotationClassRetention) != 0) { value = retentionPolicy.getField(TypeConstants.UPPER_CLASS, true); } else if ((bits & TagBits.AnnotationSourceRetention) != 0) { value = retentionPolicy.getField(TypeConstants.UPPER_SOURCE, true); } return env.createAnnotation( env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTION, null), new ElementValuePair[] { new ElementValuePair(TypeConstants.VALUE, value, null) }); } private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironment env) { ReferenceBinding target = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_TARGET, null); if ((bits & TagBits.AnnotationTarget) != 0) return new AnnotationBinding(target, Binding.NO_ELEMENT_VALUE_PAIRS); int arraysize = 0; if ((bits & TagBits.AnnotationForAnnotationType) != 0) arraysize++; if ((bits & TagBits.AnnotationForConstructor) != 0) arraysize++; if ((bits & TagBits.AnnotationForField) != 0) arraysize++; if ((bits & TagBits.AnnotationForLocalVariable) != 0) arraysize++; if ((bits & TagBits.AnnotationForMethod) != 0) arraysize++; if ((bits & TagBits.AnnotationForPackage) != 0) arraysize++; if ((bits & TagBits.AnnotationForParameter) != 0) arraysize++; if ((bits & TagBits.AnnotationForType) != 0) arraysize++; Object[] value = new Object[arraysize]; if (arraysize > 0) { ReferenceBinding elementType = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE, null); int index = 0; if ((bits & TagBits.AnnotationForAnnotationType) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_ANNOTATION_TYPE, true); if ((bits & TagBits.AnnotationForConstructor) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_CONSTRUCTOR, true); if ((bits & TagBits.AnnotationForField) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_FIELD, true); if ((bits & TagBits.AnnotationForLocalVariable) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_LOCAL_VARIABLE, true); if ((bits & TagBits.AnnotationForMethod) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_METHOD, true); if ((bits & TagBits.AnnotationForPackage) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_PACKAGE, true); if ((bits & TagBits.AnnotationForParameter) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_PARAMETER, true); if ((bits & TagBits.AnnotationForType) != 0) value[index++] = elementType.getField(TypeConstants.TYPE, true); } return env.createAnnotation( target, new ElementValuePair[] { new ElementValuePair(TypeConstants.VALUE, value, null) }); } AnnotationBinding(ReferenceBinding type, ElementValuePair[] pairs) { this.type = type; this.pairs = pairs; } AnnotationBinding(Annotation astAnnotation) { this((ReferenceBinding) astAnnotation.resolvedType, astAnnotation.computeElementValuePairs()); } /* * Computes a key that uniquely identifies this binding, using the given recipient's unique key. * recipientKey @ typeKey * @MyAnnot void bar() --> Lp/X;.bar()V@Lp/MyAnnot; */ public char[] computeUniqueKey(char[] recipientKey) { char[] typeKey = this.type.computeUniqueKey(false); int recipientKeyLength = recipientKey.length; char[] uniqueKey = new char[recipientKeyLength+1+typeKey.length]; System.arraycopy(recipientKey, 0, uniqueKey, 0, recipientKeyLength); uniqueKey[recipientKeyLength] = '@'; System.arraycopy(typeKey, 0, uniqueKey, recipientKeyLength+1, typeKey.length); return uniqueKey; } public ReferenceBinding getAnnotationType() { return this.type; } public ElementValuePair[] getElementValuePairs() { return this.pairs; } public static void setMethodBindings(ReferenceBinding type, ElementValuePair[] pairs) { // set the method bindings of each element value pair for (int i = pairs.length; --i >= 0;) { ElementValuePair pair = pairs[i]; MethodBinding[] methods = type.getMethods(pair.getName()); // there should be exactly one since the type is an annotation type. if (methods != null && methods.length == 1) pair.setMethodBinding(methods[0]); } } public String toString() { StringBuffer buffer = new StringBuffer(5); buffer.append('@').append(this.type.sourceName); if (this.pairs != null && this.pairs.length > 0) { buffer.append("{ "); //$NON-NLS-1$ for (int i = 0, max = this.pairs.length; i < max; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append(this.pairs[i]); } buffer.append('}'); } return buffer.toString(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java0000644000175000001440000003016712212041344031273 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage; import org.eclipse.jdt.internal.compiler.util.HashtableOfType; public class PackageBinding extends Binding implements TypeConstants { public long tagBits = 0; // See values in the interface TagBits below public char[][] compoundName; PackageBinding parent; public LookupEnvironment environment; HashtableOfType knownTypes; HashtableOfPackage knownPackages; // code representing the default that has been defined for this package (using @NonNullByDefault) // one of Binding.{NO_NULL_DEFAULT,NULL_UNSPECIFIED_BY_DEFAULT,NONNULL_BY_DEFAULT} protected int defaultNullness = NO_NULL_DEFAULT; protected PackageBinding() { // for creating problem package } public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) { this(new char[][] {topLevelPackageName}, null, environment); } /* Create the default package. */ public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) { this.compoundName = compoundName; this.parent = parent; this.environment = environment; this.knownTypes = null; // initialized if used... class counts can be very large 300-600 this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3 if (compoundName != CharOperation.NO_CHAR_CHAR) checkIfNullAnnotationPackage(); } public PackageBinding(LookupEnvironment environment) { this(CharOperation.NO_CHAR_CHAR, null, environment); } private void addNotFoundPackage(char[] simpleName) { this.knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage); } private void addNotFoundType(char[] simpleName) { if (this.knownTypes == null) this.knownTypes = new HashtableOfType(25); this.knownTypes.put(simpleName, LookupEnvironment.TheNotFoundType); } void addPackage(PackageBinding element) { if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit(); this.knownPackages.put(element.compoundName[element.compoundName.length - 1], element); } void addType(ReferenceBinding element) { if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit(); if (this.knownTypes == null) this.knownTypes = new HashtableOfType(25); this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element); if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) if (element.isAnnotationType() || element instanceof UnresolvedReferenceBinding) // unresolved types don't yet have the modifiers set checkIfNullAnnotationType(element); } void clearMissingTagBit() { PackageBinding current = this; do { current.tagBits &= ~TagBits.HasMissingType; } while ((current = current.parent) != null); } /* * slash separated name * org.eclipse.jdt.core --> org/eclipse/jdt/core */ public char[] computeUniqueKey(boolean isLeaf) { return CharOperation.concatWith(this.compoundName, '/'); } private PackageBinding findPackage(char[] name) { if (!this.environment.isPackage(this.compoundName, name)) return null; char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name); PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, this.environment); addPackage(subPackageBinding); return subPackageBinding; } /* Answer the subpackage named name; ask the oracle for the package if its not in the cache. * Answer null if it could not be resolved. * * NOTE: This should only be used when we know there is NOT a type with the same name. */ PackageBinding getPackage(char[] name) { PackageBinding binding = getPackage0(name); if (binding != null) { if (binding == LookupEnvironment.TheNotFoundPackage) return null; else return binding; } if ((binding = findPackage(name)) != null) return binding; // not found so remember a problem package binding in the cache for future lookups addNotFoundPackage(name); return null; } /* Answer the subpackage named name if it exists in the cache. * Answer theNotFoundPackage if it could not be resolved the first time * it was looked up, otherwise answer null. * * NOTE: Senders must convert theNotFoundPackage into a real problem * package if its to returned. */ PackageBinding getPackage0(char[] name) { return this.knownPackages.get(name); } /* Answer the type named name; ask the oracle for the type if its not in the cache. * Answer a NotVisible problem type if the type is not visible from the invocationPackage. * Answer null if it could not be resolved. * * NOTE: This should only be used by source types/scopes which know there is NOT a * package with the same name. */ ReferenceBinding getType(char[] name) { ReferenceBinding referenceBinding = getType0(name); if (referenceBinding == null) { if ((referenceBinding = this.environment.askForType(this, name)) == null) { // not found so remember a problem type binding in the cache for future lookups addNotFoundType(name); return null; } } if (referenceBinding == LookupEnvironment.TheNotFoundType) return null; referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this.environment, false /* no raw conversion for now */); if (referenceBinding.isNestedType()) return new ProblemReferenceBinding(new char[][]{ name }, referenceBinding, ProblemReasons.InternalNameProvided); return referenceBinding; } /* Answer the type named name 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: Senders must convert theNotFoundType into a real problem * reference type if its to returned. */ ReferenceBinding getType0(char[] name) { if (this.knownTypes == null) return null; return this.knownTypes.get(name); } /* Answer the package or type named name; ask the oracle if it is not in the cache. * Answer null if it could not be resolved. * * When collisions exist between a type name & a package name, answer the type. * Treat the package as if it does not exist... a problem was already reported when the type was defined. * * NOTE: no visibility checks are performed. * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES. */ public Binding getTypeOrPackage(char[] name) { ReferenceBinding referenceBinding = getType0(name); if (referenceBinding != null && referenceBinding != LookupEnvironment.TheNotFoundType) { referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this.environment, false /* no raw conversion for now */); if (referenceBinding.isNestedType()) { return new ProblemReferenceBinding(new char[][]{name}, referenceBinding, ProblemReasons.InternalNameProvided); } if ((referenceBinding.tagBits & TagBits.HasMissingType) == 0) { return referenceBinding; } // referenceBinding is a MissingType, will return it if no package is found } PackageBinding packageBinding = getPackage0(name); if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage) { return packageBinding; } if (referenceBinding == null) { // have not looked for it before if ((referenceBinding = this.environment.askForType(this, name)) != null) { if (referenceBinding.isNestedType()) { return new ProblemReferenceBinding(new char[][]{name}, referenceBinding, ProblemReasons.InternalNameProvided); } return referenceBinding; } // Since name could not be found, add a problem binding // to the collections so it will be reported as an error next time. addNotFoundType(name); } if (packageBinding == null) { // have not looked for it before if ((packageBinding = findPackage(name)) != null) { return packageBinding; } if (referenceBinding != null && referenceBinding != LookupEnvironment.TheNotFoundType) { return referenceBinding; // found cached missing type - check if package conflict } addNotFoundPackage(name); } return null; } public final boolean isViewedAsDeprecated() { if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) { this.tagBits |= TagBits.DeprecatedAnnotationResolved; if (this.compoundName != CharOperation.NO_CHAR_CHAR) { ReferenceBinding packageInfo = this.getType(TypeConstants.PACKAGE_INFO_NAME); if (packageInfo != null) { packageInfo.initializeDeprecatedAnnotationTagBits(); this.tagBits |= packageInfo.tagBits & TagBits.AllStandardAnnotationsMask; } } } return (this.tagBits & TagBits.AnnotationDeprecated) != 0; } /* API * Answer the receiver's binding type from Binding.BindingID. */ public final int kind() { return Binding.PACKAGE; } public int problemId() { if ((this.tagBits & TagBits.HasMissingType) != 0) return ProblemReasons.NotFound; return ProblemReasons.NoError; } void checkIfNullAnnotationPackage() { LookupEnvironment env = this.environment; if (env.globalOptions.isAnnotationBasedNullAnalysisEnabled) { if (isPackageOfQualifiedTypeName(this.compoundName, env.getNullableAnnotationName())) env.nullableAnnotationPackage = this; if (isPackageOfQualifiedTypeName(this.compoundName, env.getNonNullAnnotationName())) env.nonnullAnnotationPackage = this; if (isPackageOfQualifiedTypeName(this.compoundName, env.getNonNullByDefaultAnnotationName())) env.nonnullByDefaultAnnotationPackage = this; } } private boolean isPackageOfQualifiedTypeName(char[][] packageName, char[][] typeName) { int length; if (typeName == null || (length = packageName.length) != typeName.length -1) return false; for (int i=0; i= ClassFileConstants.JDK1_5 && environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5; } boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { return isParameterSubsignature(one, two) && areReturnTypesCompatible(one, two); } boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) { if (one.returnType == two.returnType) return true; if (areTypesEqual(one.returnType, two.returnType)) return true; // when sourceLevel < 1.5 but compliance >= 1.5, allow return types in binaries to be compatible instead of just equal if (this.allowCompatibleReturnTypes && one.declaringClass instanceof BinaryTypeBinding && two.declaringClass instanceof BinaryTypeBinding) { return areReturnTypesCompatible0(one, two); } return false; } boolean areReturnTypesCompatible0(MethodBinding one, MethodBinding two) { // short is compatible with int, but as far as covariance is concerned, its not if (one.returnType.isBaseType()) return false; if (!one.declaringClass.isInterface() && one.declaringClass.id == TypeIds.T_JavaLangObject) return two.returnType.isCompatibleWith(one.returnType); // interface methods inherit from Object return one.returnType.isCompatibleWith(two.returnType); } boolean canSkipInheritedMethods() { if (this.type.superclass() != null && this.type.superclass().isAbstract()) return false; return this.type.superInterfaces() == Binding.NO_SUPERINTERFACES; } boolean canSkipInheritedMethods(MethodBinding one, MethodBinding two) { return two == null // already know one is not null || one.declaringClass == two.declaringClass; } 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 { problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod); } } } void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length, MethodBinding[] allInheritedMethods) { if (this.type.isAnnotationType()) { // annotation cannot override any method problemReporter().annotationCannotOverrideMethod(currentMethod, methods[length - 1]); return; // do not repoort against subsequent inherited methods } CompilerOptions options = this.type.scope.compilerOptions(); // need to find the overridden methods to avoid blaming this type for issues which are already reported against a supertype // but cannot ignore an overridden inherited method completely when it comes to checking for bridge methods int[] overriddenInheritedMethods = length > 1 ? findOverriddenInheritedMethods(methods, length) : null; nextMethod : for (int i = length; --i >= 0;) { MethodBinding inheritedMethod = methods[i]; if (overriddenInheritedMethods == null || overriddenInheritedMethods[i] == 0) { if (currentMethod.isStatic() != inheritedMethod.isStatic()) { // Cannot override a static method or hide an instance method problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod); continue nextMethod; } // want to tag currentMethod even if return types are not equal if (inheritedMethod.isAbstract()) { if (inheritedMethod.declaringClass.isInterface()) { currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing; } else { currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing | ExtraCompilerModifiers.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 if (inheritedMethod.isPublic() || !this.type.isInterface()) { // interface I { @Override Object clone(); } does not override Object#clone() currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding; } if (!areReturnTypesCompatible(currentMethod, inheritedMethod) && (currentMethod.returnType.tagBits & TagBits.HasMissingType) == 0) { if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod)) continue nextMethod; } reportRawReferences(currentMethod, inheritedMethod); // if they were deferred, emit them now. if (currentMethod.thrownExceptions != Binding.NO_EXCEPTIONS) checkExceptions(currentMethod, inheritedMethod); if (inheritedMethod.isFinal()) problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod); if (!isAsVisible(currentMethod, inheritedMethod)) problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod); if(inheritedMethod.isSynchronized() && !currentMethod.isSynchronized()) { problemReporter(currentMethod).missingSynchronizedOnInheritedMethod(currentMethod, inheritedMethod); } if (options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) { if (!currentMethod.isViewedAsDeprecated() || options.reportDeprecationInsideDeprecatedCode) { // check against the other inherited methods to see if they hide this inheritedMethod ReferenceBinding declaringClass = inheritedMethod.declaringClass; if (declaringClass.isInterface()) for (int j = length; --j >= 0;) if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false)) continue nextMethod; problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod); } } } checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods); } } public void reportRawReferences(MethodBinding currentMethod, MethodBinding inheritedMethod) { // nothing to do here. Real action happens at 1.5+ } void checkConcreteInheritedMethod(MethodBinding concreteMethod, MethodBinding[] abstractMethods) { // 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 problemReporter().staticInheritedMethodConflicts(this.type, concreteMethod, abstractMethods); if (!concreteMethod.isPublic()) { int index = 0, length = abstractMethods.length; if (concreteMethod.isProtected()) { for (; index < length; index++) if (abstractMethods[index].isPublic()) break; } else if (concreteMethod.isDefault()) { for (; index < length; index++) if (!abstractMethods[index].isDefault()) break; } if (index < length) problemReporter().inheritedMethodReducesVisibility(this.type, concreteMethod, abstractMethods); } if (concreteMethod.thrownExceptions != Binding.NO_EXCEPTIONS) for (int i = abstractMethods.length; --i >= 0;) checkExceptions(concreteMethod, abstractMethods[i]); // A subclass inheriting this method and putting it up as the implementation to meet its own // obligations should qualify as a use. if (concreteMethod.isOrEnclosedByPrivateType()) concreteMethod.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } /* "8.4.4" 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). */ 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 && !isSameClassOrSubclassOf(newException, inheritedExceptions[j])){/*empty*/} if (j == -1) if (!newException.isUncheckedException(false) && (newException.tagBits & TagBits.HasMissingType) == 0) { problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException); } } } void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) { // no op before 1.5 } void checkForMissingHashCodeMethod() { MethodBinding[] choices = this.type.getMethods(TypeConstants.EQUALS); boolean overridesEquals = false; for (int i = choices.length; !overridesEquals && --i >= 0;) overridesEquals = choices[i].parameters.length == 1 && choices[i].parameters[0].id == TypeIds.T_JavaLangObject; if (overridesEquals) { MethodBinding hashCodeMethod = this.type.getExactMethod(TypeConstants.HASHCODE, Binding.NO_PARAMETERS, null); if (hashCodeMethod != null && hashCodeMethod.declaringClass.id == TypeIds.T_JavaLangObject) this.problemReporter().shouldImplementHashcode(this.type); } } void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { if (superInterfaces == Binding.NO_SUPERINTERFACES) return; SimpleSet interfacesToCheck = new SimpleSet(superInterfaces.length); SimpleSet redundantInterfaces = null; // bark but once. for (int i = 0, l = superInterfaces.length; i < l; i++) { ReferenceBinding toCheck = superInterfaces[i]; for (int j = 0; j < l; j++) { ReferenceBinding implementedInterface = superInterfaces[j]; if (i != j && toCheck.implementsInterface(implementedInterface, true)) { if (redundantInterfaces == null) { redundantInterfaces = new SimpleSet(3); } else if (redundantInterfaces.includes(implementedInterface)) { continue; } redundantInterfaces.add(implementedInterface); TypeReference[] refs = this.type.scope.referenceContext.superInterfaces; for (int r = 0, rl = refs.length; r < rl; r++) { if (refs[r].resolvedType == toCheck) { problemReporter().redundantSuperInterface(this.type, refs[j], implementedInterface, toCheck); break; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=320911 } } } } interfacesToCheck.add(toCheck); } ReferenceBinding[] itsInterfaces = null; SimpleSet inheritedInterfaces = new SimpleSet(5); ReferenceBinding superType = superclass; while (superType != null && superType.isValidBinding()) { if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { for (int i = 0, l = itsInterfaces.length; i < l; i++) { ReferenceBinding inheritedInterface = itsInterfaces[i]; if (!inheritedInterfaces.includes(inheritedInterface) && inheritedInterface.isValidBinding()) { if (interfacesToCheck.includes(inheritedInterface)) { if (redundantInterfaces == null) { redundantInterfaces = new SimpleSet(3); } else if (redundantInterfaces.includes(inheritedInterface)) { continue; } redundantInterfaces.add(inheritedInterface); TypeReference[] refs = this.type.scope.referenceContext.superInterfaces; for (int r = 0, rl = refs.length; r < rl; r++) { if (refs[r].resolvedType == inheritedInterface) { problemReporter().redundantSuperInterface(this.type, refs[r], inheritedInterface, superType); break; } } } else { inheritedInterfaces.add(inheritedInterface); } } } } superType = superType.superclass(); } int nextPosition = inheritedInterfaces.elementSize; if (nextPosition == 0) return; ReferenceBinding[] interfacesToVisit = new ReferenceBinding[nextPosition]; inheritedInterfaces.asArray(interfacesToVisit); for (int i = 0; i < nextPosition; i++) { superType = interfacesToVisit[i]; if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); for (int a = 0; a < itsLength; a++) { ReferenceBinding inheritedInterface = itsInterfaces[a]; if (!inheritedInterfaces.includes(inheritedInterface) && inheritedInterface.isValidBinding()) { if (interfacesToCheck.includes(inheritedInterface)) { if (redundantInterfaces == null) { redundantInterfaces = new SimpleSet(3); } else if (redundantInterfaces.includes(inheritedInterface)) { continue; } redundantInterfaces.add(inheritedInterface); TypeReference[] refs = this.type.scope.referenceContext.superInterfaces; for (int r = 0, rl = refs.length; r < rl; r++) { if (refs[r].resolvedType == inheritedInterface) { problemReporter().redundantSuperInterface(this.type, refs[r], inheritedInterface, superType); break; } } } else { inheritedInterfaces.add(inheritedInterface); interfacesToVisit[nextPosition++] = inheritedInterface; } } } } } } void checkInheritedMethods(MethodBinding[] methods, int length, boolean[] isOverridden) { /* 1. find concrete method 2. if it doesn't exist then find first inherited abstract method whose return type is compatible with all others if no such method exists then report incompatible return type error otherwise report abstract method must be implemented 3. if concrete method exists, check to see if its return type is compatible with all others if it is then check concrete method against abstract methods if its not, then find most specific abstract method & report abstract method must be implemented since concrete method is insufficient if no most specific return type abstract method exists, then report incompatible return type with all inherited methods */ MethodBinding concreteMethod = this.type.isInterface() || methods[0].isAbstract() ? null : methods[0]; if (concreteMethod == null) { MethodBinding bestAbstractMethod = length == 1 ? methods[0] : findBestInheritedAbstractMethod(methods, length); boolean noMatch = bestAbstractMethod == null; if (noMatch) bestAbstractMethod = methods[0]; if (mustImplementAbstractMethod(bestAbstractMethod.declaringClass)) { TypeDeclaration typeDeclaration = this.type.scope.referenceContext; MethodBinding superclassAbstractMethod = methods[0]; if (superclassAbstractMethod == bestAbstractMethod || superclassAbstractMethod.declaringClass.isInterface()) { if (typeDeclaration != null) { MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(bestAbstractMethod); missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, bestAbstractMethod); } else { problemReporter().abstractMethodMustBeImplemented(this.type, bestAbstractMethod); } } else { if (typeDeclaration != null) { MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(bestAbstractMethod); missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, bestAbstractMethod, superclassAbstractMethod); } else { problemReporter().abstractMethodMustBeImplemented(this.type, bestAbstractMethod, superclassAbstractMethod); } } } else if (noMatch) { problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length, isOverridden); } return; } if (length < 2) return; // nothing else to check int index = length; while (--index > 0 && checkInheritedReturnTypes(concreteMethod, methods[index])) {/*empty*/} if (index > 0) { // concreteMethod is not the best match MethodBinding bestAbstractMethod = findBestInheritedAbstractMethod(methods, length); if (bestAbstractMethod == null) problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length, isOverridden); else // can only happen in >= 1.5 since return types must be equal prior to 1.5 problemReporter().abstractMethodMustBeImplemented(this.type, bestAbstractMethod, concreteMethod); return; } MethodBinding[] abstractMethods = new MethodBinding[length - 1]; index = 0; for (int i = 0; i < length; i++) if (methods[i].isAbstract()) abstractMethods[index++] = methods[i]; if (index == 0) return; // can happen with methods that contain 'equal' Missing Types, see bug 257384 if (index < abstractMethods.length) System.arraycopy(abstractMethods, 0, abstractMethods = new MethodBinding[index], 0, index); checkConcreteInheritedMethod(concreteMethod, abstractMethods); } boolean checkInheritedReturnTypes(MethodBinding method, MethodBinding otherMethod) { if (areReturnTypesCompatible(method, otherMethod)) return true; if (!this.type.isInterface()) if (method.declaringClass.isClass() || !this.type.implementsInterface(method.declaringClass, false)) if (otherMethod.declaringClass.isClass() || !this.type.implementsInterface(otherMethod.declaringClass, false)) return true; // do not complain since the superclass already got blamed return false; } /* For each inherited method identifier (message pattern - vm signature minus the return type) if current method exists if current's vm signature does not match an inherited signature then complain else compare current's exceptions & visibility against each inherited method else if inherited methods = 1 if inherited is abstract && type is NOT an interface or abstract, complain else if vm signatures do not match complain else find the concrete implementation amongst the abstract methods (can only be 1) if one exists then it must be a public instance method compare concrete's exceptions against each abstract method else complain about missing implementation only if type is NOT an interface or abstract */ abstract void checkMethods(); 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 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 (areMethodsCompatible(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 problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod); } void computeInheritedMethods() { ReferenceBinding superclass = this.type.isInterface() ? this.type.scope.getJavaLangObject() // check interface methods against Object : this.type.superclass(); // class or enum computeInheritedMethods(superclass, this.type.superInterfaces()); checkForRedundantSuperinterfaces(superclass, this.type.superInterfaces()); } /* Binding creation is responsible for reporting: - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations) - plus invalid modifiers given the context... examples: - interface methods can only be public - abstract methods can only be defined by abstract classes - collisions... 2 methods with identical vmSelectors - multiple methods with the same message pattern but different return types - ambiguous, invisible or missing return/argument/exception types - check the type of any array is not void - check that each exception type is Throwable or a subclass of it */ void computeInheritedMethods(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { // 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, however // see usage of canOverridingMethodDifferInErasure below. this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type ReferenceBinding superType = superclass; HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods while (superType != null && superType.isValidBinding()) { 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) { existing : for (int i = 0, length = existingMethods.length; i < length; i++) { MethodBinding existingMethod = existingMethods[i]; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358, skip inherited method only if any overriding version // in a subclass is guaranteed to have the same erasure as an existing method. if (existingMethod.declaringClass != inheritedMethod.declaringClass && areMethodsCompatible(existingMethod, inheritedMethod) && !canOverridingMethodDifferInErasure(existingMethod, inheritedMethod)) { if (inheritedMethod.isDefault()) { if (inheritedMethod.isAbstract()) { checkPackagePrivateAbstractMethod(inheritedMethod); } else if (existingMethod.declaringClass.fPackage != inheritedMethod.declaringClass.fPackage) { if (this.type.fPackage == inheritedMethod.declaringClass.fPackage && !areReturnTypesCompatible(inheritedMethod, existingMethod)) continue existing; // may need to record incompatible return type } } continue nextMethod; } } } if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == this.type.fPackage) { if (existingMethods == null) { existingMethods = new MethodBinding[] {inheritedMethod}; } else { 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 { MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector); if (nonVisible != null) for (int i = 0, l = nonVisible.length; i < l; i++) if (areMethodsCompatible(nonVisible[i], inheritedMethod)) continue nextMethod; 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 && !inheritedMethod.isStatic()) { // non visible methods cannot be overridden so a warning is issued foundMatch : for (int i = 0, length = current.length; i < length; i++) { if (!current[i].isStatic() && areMethodsCompatible(current[i], inheritedMethod)) { problemReporter().overridesPackageDefaultMethod(current[i], inheritedMethod); break foundMatch; } } } } } superType = superType.superclass(); } List superIfcList = new ArrayList(); HashSet seenTypes = new HashSet(); collectAllDistinctSuperInterfaces(superInterfaces, seenTypes, superIfcList); ReferenceBinding currentSuper = superclass; while (currentSuper != null && currentSuper.id != TypeIds.T_JavaLangObject) { collectAllDistinctSuperInterfaces(currentSuper.superInterfaces(), seenTypes, superIfcList); currentSuper = currentSuper.superclass(); } if (superIfcList.size() == 0) return; if (superIfcList.size() == 1) { superInterfaces = new ReferenceBinding[] { (ReferenceBinding) superIfcList.get(0) }; } else { superInterfaces = (ReferenceBinding[]) superIfcList.toArray(new ReferenceBinding[superIfcList.size()]); superInterfaces = Sorting.sortTypes(superInterfaces); } SimpleSet skip = findSuperinterfaceCollisions(superclass, superInterfaces); int len = superInterfaces.length; for (int i = len-1; i >= 0; i--) { superType = superInterfaces[i]; if (superType.isValidBinding()) { if (skip != null && skip.includes(superType)) continue; MethodBinding[] methods = superType.unResolvedMethods(); nextMethod : for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public MethodBinding inheritedMethod = methods[m]; MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector); if (existingMethods == null) { existingMethods = new MethodBinding[] {inheritedMethod}; } else { int length = existingMethods.length; // look to see if any of the existingMethods implement this inheritedMethod // https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358, skip inherited method only if any overriding version // in a subclass is guaranteed to have the same erasure as an existing method. for (int e = 0; e < length; e++) if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType) && !canOverridingMethodDifferInErasure(existingMethods[e], inheritedMethod)) 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] = inheritedMethod; } this.inheritedMethods.put(inheritedMethod.selector, existingMethods); } } } } void collectAllDistinctSuperInterfaces(ReferenceBinding[] superInterfaces, Set seen, List result) { // use 'seen' to avoid duplicates, use result to maintain stable order int length = superInterfaces.length; for (int i=0; i= 0;) { MethodBinding method = methods[m]; if (!(method.isConstructor() || method.isDefaultAbstract())) { // keep all methods which are NOT constructors or default abstract MethodBinding[] existingMethods = (MethodBinding[]) this.currentMethods.get(method.selector); if (existingMethods == null) existingMethods = new MethodBinding[1]; else System.arraycopy(existingMethods, 0, (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1); existingMethods[existingMethods.length - 1] = method; this.currentMethods.put(method.selector, existingMethods); } } } MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { if (inheritedMethod == null) return null; if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match return inheritedMethod; } boolean couldMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)) return false; if (method == inheritedMethod || method.isStatic() || inheritedMethod.isStatic()) return false; if (inheritedMethod.isPrivate()) return false; if (inheritedMethod.isDefault() && method.declaringClass.getPackage() != inheritedMethod.declaringClass.getPackage()) return false; if (!method.isPublic()) { // inheritedMethod is either public or protected & method is less than public if (inheritedMethod.isPublic()) return false; if (inheritedMethod.isProtected() && !method.isProtected()) return false; } return true; } // Answer whether the method overrides the inheritedMethod // Check the necessary visibility rules & inheritance from the inheritedMethod's declaringClass // See isMethodSubsignature() for parameter comparisons public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { if (!couldMethodOverride(method, inheritedMethod)) return false; inheritedMethod = inheritedMethod.original(); TypeBinding match = method.declaringClass.findSuperTypeOriginatingFrom(inheritedMethod.declaringClass); if (!(match instanceof ReferenceBinding)) return false; // method's declaringClass does not inherit from inheritedMethod's return isParameterSubsignature(method, inheritedMethod); } SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { return null; // noop in 1.4 } MethodBinding findBestInheritedAbstractMethod(MethodBinding[] methods, int length) { findMethod : for (int i = 0; i < length; i++) { MethodBinding method = methods[i]; // when unexpectedly seeing a non-abstract interface method regard it as abstract, too, for this check: if (!(method.isAbstract() || method.declaringClass.isInterface())) continue findMethod; for (int j = 0; j < length; j++) { if (i == j) continue; if (!checkInheritedReturnTypes(method, methods[j])) { if (this.type.isInterface() && methods[j].declaringClass.id == TypeIds.T_JavaLangObject) return method; // do not complain since the super interface already got blamed continue findMethod; } } return method; } return null; } int[] findOverriddenInheritedMethods(MethodBinding[] methods, int length) { // NOTE assumes length > 1 // inherited methods are added as we walk up the superclass hierarchy, then each superinterface // so method[1] from a class can NOT override method[0], but methods from superinterfaces can // since superinterfaces can be added from different superclasses or other superinterfaces int[] toSkip = null; int i = 0; ReferenceBinding declaringClass = methods[i].declaringClass; if (!declaringClass.isInterface()) { // in the first pass, skip overridden methods from superclasses // only keep methods from the closest superclass, all others from higher superclasses can be skipped // NOTE: methods were added in order by walking up the superclass hierarchy ReferenceBinding declaringClass2 = methods[++i].declaringClass; while (declaringClass == declaringClass2) { if (++i == length) return null; declaringClass2 = methods[i].declaringClass; } if (!declaringClass2.isInterface()) { // skip all methods from different superclasses if (declaringClass.fPackage != declaringClass2.fPackage && methods[i].isDefault()) return null; toSkip = new int[length]; do { toSkip[i] = -1; if (++i == length) return toSkip; declaringClass2 = methods[i].declaringClass; } while (!declaringClass2.isInterface()); } } // in the second pass, skip overridden methods from superinterfaces // NOTE: superinterfaces can appear in 'random' order nextMethod : for (; i < length; i++) { if (toSkip != null && toSkip[i] == -1) continue nextMethod; declaringClass = methods[i].declaringClass; for (int j = i + 1; j < length; j++) { if (toSkip != null && toSkip[j] == -1) continue; ReferenceBinding declaringClass2 = methods[j].declaringClass; if (declaringClass == declaringClass2) continue; if (declaringClass.implementsInterface(declaringClass2, true)) { if (toSkip == null) toSkip = new int[length]; toSkip[j] = -1; } else if (declaringClass2.implementsInterface(declaringClass, true)) { if (toSkip == null) toSkip = new int[length]; toSkip[i] = -1; continue nextMethod; } } } return toSkip; } boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) { if (inheritedMethod.modifiers == newMethod.modifiers) return true; if (newMethod.isPublic()) return true; // Covers everything if (inheritedMethod.isPublic()) return false; if (newMethod.isProtected()) return true; if (inheritedMethod.isProtected()) return false; return !newMethod.isPrivate(); // The inheritedMethod cannot be private since it would not be visible } 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); } public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) { return org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector) && isParameterSubsignature(method, inheritedMethod); } boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { return areParametersEqual(method, inheritedMethod); } boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) { do { if (testClass == superclass) return true; } while ((testClass = testClass.superclass()) != null); return false; } 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 if (!mustImplementAbstractMethods()) return false; ReferenceBinding superclass = this.type.superclass(); if (declaringClass.isClass()) { while (superclass.isAbstract() && superclass != declaringClass) superclass = superclass.superclass(); // find the first concrete superclass or the abstract declaringClass } else { if (this.type.implementsInterface(declaringClass, false)) if (!superclass.implementsInterface(declaringClass, true)) // only if a superclass does not also implement the interface return true; while (superclass.isAbstract() && !superclass.implementsInterface(declaringClass, false)) superclass = superclass.superclass(); // find the first concrete superclass or the superclass which implements the interface } return superclass.isAbstract(); // if it is a concrete class then we have already reported problem against it } boolean mustImplementAbstractMethods() { return !this.type.isInterface() && !this.type.isAbstract(); } ProblemReporter problemReporter() { return this.type.scope.problemReporter(); } ProblemReporter problemReporter(MethodBinding currentMethod) { ProblemReporter reporter = problemReporter(); if (currentMethod.declaringClass == this.type && currentMethod.sourceMethod() != null) // only report against the currentMethod if its implemented by the type reporter.referenceContext = currentMethod.sourceMethod(); return reporter; } /** * Return true and report an incompatibleReturnType error if currentMethod's * return type is strictly incompatible with inheritedMethod's, else return * false and report an unchecked conversion warning. Do not call when * areReturnTypesCompatible(currentMethod, inheritedMethod) returns true. * @param currentMethod the (potentially) inheriting method * @param inheritedMethod the inherited method * @return true if currentMethod's return type is strictly incompatible with * inheritedMethod's */ boolean reportIncompatibleReturnTypeError(MethodBinding currentMethod, MethodBinding inheritedMethod) { problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod); return true; } ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) { ReferenceBinding[] exceptions = method.thrownExceptions; if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return exceptions; if (!(method.declaringClass instanceof BinaryTypeBinding)) return Binding.NO_EXCEPTIONS; // safety check for (int i = exceptions.length; --i >= 0;) exceptions[i] = (ReferenceBinding) BinaryTypeBinding.resolveType(exceptions[i], this.environment, true /* raw conversion */); return exceptions; } void verify() { computeMethods(); computeInheritedMethods(); checkMethods(); if (this.type.isClass()) checkForMissingHashCodeMethod(); } void verify(SourceTypeBinding someType) { if (this.type == null) { try { this.type = someType; verify(); } finally { this.type = null; } } else { this.environment.newMethodVerifier().verify(someType); } } public String toString() { StringBuffer buffer = new StringBuffer(10); buffer.append("MethodVerifier for type: "); //$NON-NLS-1$ buffer.append(this.type.readableName()); buffer.append('\n'); buffer.append("\t-inherited methods: "); //$NON-NLS-1$ buffer.append(this.inheritedMethods); return buffer.toString(); } } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/InnerEmulationDependency.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/InnerEmulationDependency0000644000175000001440000000157312212041344032454 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; public class InnerEmulationDependency{ public BlockScope scope; public boolean wasEnclosingInstanceSupplied; public InnerEmulationDependency(BlockScope scope, boolean wasEnclosingInstanceSupplied) { this.scope = scope; this.wasEnclosingInstanceSupplied = wasEnclosingInstanceSupplied; } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.jav0000644000175000001440000002345512212041344032301 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 185682 - Increment/decrement operators mark local variables as read * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 331649 - [compiler][null] consider null annotations for fields *******************************************************************************/ 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.Annotation; import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; 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 { public int resolvedPosition; // for code generation (position in method context) public static final int UNUSED = 0; public static final int USED = 1; public static final int FAKE_USED = 2; public int useFlag; // for flow analysis (default is UNUSED), values < 0 indicate the number of compound uses (postIncrement or compoundAssignment) public BlockScope declaringScope; // back-pointer to its declaring scope public LocalDeclaration declaration; // for source-positions public int[] initializationPCs; public int initializationCount = 0; public FakedTrackingVariable closeTracker; // track closing of instances of type AutoCloseable, maybe null // 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) { super(name, type, modifiers, isArgument ? Constant.NotAConstant : null); if (isArgument) this.tagBits |= TagBits.IsArgument; this.tagBits |= TagBits.IsEffectivelyFinal; } // regular local variable or argument public LocalVariableBinding(LocalDeclaration declaration, TypeBinding type, int modifiers, boolean isArgument) { this(declaration.name, type, modifiers, isArgument); this.declaration = declaration; this.tagBits |= TagBits.IsEffectivelyFinal; } /* API * Answer the receiver's binding type from Binding.BindingID. */ public final int kind() { return LOCAL; } /* * declaringUniqueKey # scopeIndex(0-based) # varName [# occurrenceCount(0-based)] * p.X { void foo() { int local; int local;} } --> Lp/X;.foo()V#1#local#1 */ public char[] computeUniqueKey(boolean isLeaf) { StringBuffer buffer = new StringBuffer(); // declaring method or type BlockScope scope = this.declaringScope; int occurenceCount = 0; if (scope != null) { // the scope can be null. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=185129 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(false/*not a leaf*/)); } } else if (referenceContext instanceof TypeDeclaration) { TypeBinding typeBinding = ((TypeDeclaration) referenceContext).binding; if (typeBinding != null) { buffer.append(typeBinding.computeUniqueKey(false/*not a leaf*/)); } } // scope index getScopeKey(scope, buffer); // find number of occurences of a variable with the same name in the scope LocalVariableBinding[] locals = scope.locals; for (int i = 0; i < scope.localIndex; i++) { // use linear search assuming the number of locals per scope is low LocalVariableBinding local = locals[i]; if (CharOperation.equals(this.name, local.name)) { if (this == local) break; occurenceCount++; } } } // variable name buffer.append('#'); buffer.append(this.name); // add occurence count to avoid same key for duplicate variables // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=149590) if (occurenceCount > 0) { buffer.append('#'); buffer.append(occurenceCount); } int length = buffer.length(); char[] uniqueKey = new char[length]; buffer.getChars(0, length, uniqueKey, 0); return uniqueKey; } public AnnotationBinding[] getAnnotations() { if (this.declaringScope == null) { if ((this.tagBits & TagBits.AnnotationResolved) != 0) { // annotation are already resolved if (this.declaration == null) { return Binding.NO_ANNOTATIONS; } Annotation[] annotations = this.declaration.annotations; if (annotations != null) { int length = annotations.length; AnnotationBinding[] annotationBindings = new AnnotationBinding[length]; for (int i = 0; i < length; i++) { AnnotationBinding compilerAnnotation = annotations[i].getCompilerAnnotation(); if (compilerAnnotation == null) { return Binding.NO_ANNOTATIONS; } annotationBindings[i] = compilerAnnotation; } return annotationBindings; } } return Binding.NO_ANNOTATIONS; } SourceTypeBinding sourceType = this.declaringScope.enclosingSourceType(); if (sourceType == null) return Binding.NO_ANNOTATIONS; AnnotationBinding[] annotations = sourceType.retrieveAnnotations(this); if ((this.tagBits & TagBits.AnnotationResolved) == 0) { if (((this.tagBits & TagBits.IsArgument) != 0) && this.declaration != null) { Annotation[] annotationNodes = this.declaration.annotations; if (annotationNodes != null) { int length = annotationNodes.length; ASTNode.resolveAnnotations(this.declaringScope, annotationNodes, this); annotations = new AnnotationBinding[length]; for (int i = 0; i < length; i++) annotations[i] = new AnnotationBinding(annotationNodes[i]); setAnnotations(annotations, this.declaringScope); } } } return annotations; } 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() { return this.declaration == null && (this.tagBits & TagBits.IsArgument) == 0; } public void recordInitializationEndPC(int pc) { if (this.initializationPCs[((this.initializationCount - 1) << 1) + 1] == -1) this.initializationPCs[((this.initializationCount - 1) << 1) + 1] = pc; } public void recordInitializationStartPC(int pc) { if (this.initializationPCs == null) { return; } if (this.initializationCount > 0) { int previousEndPC = this.initializationPCs[ ((this.initializationCount - 1) << 1) + 1]; // interval still open, keep using it (108180) if (previousEndPC == -1) { return; } // optimize cases where reopening a contiguous interval if (previousEndPC == pc) { this.initializationPCs[ ((this.initializationCount - 1) << 1) + 1] = -1; // reuse previous interval (its range will be augmented) return; } } int index = this.initializationCount << 1; if (index == this.initializationPCs.length) { System.arraycopy(this.initializationPCs, 0, (this.initializationPCs = new int[this.initializationCount << 2]), 0, index); } this.initializationPCs[index] = pc; this.initializationPCs[index + 1] = -1; this.initializationCount++; } public void setAnnotations(AnnotationBinding[] annotations, Scope scope) { // note: we don's use this.declaringScope because we might be called before Scope.addLocalVariable(this) // which is where this.declaringScope is set. if (scope == null) return; SourceTypeBinding sourceType = scope.enclosingSourceType(); if (sourceType != null) sourceType.storeAnnotations(this, annotations); } public void resetInitializations() { this.initializationCount = 0; this.initializationPCs = null; } public String toString() { String s = super.toString(); switch (this.useFlag){ case USED: s += "[pos: " + String.valueOf(this.resolvedPosition) + "]"; //$NON-NLS-2$ //$NON-NLS-1$ break; case UNUSED: s += "[pos: unused]"; //$NON-NLS-1$ break; case FAKE_USED: s += "[pos: fake_used]"; //$NON-NLS-1$ break; } s += "[id:" + String.valueOf(this.id) + "]"; //$NON-NLS-2$ //$NON-NLS-1$ if (this.initializationCount > 0) { s += "[pc: "; //$NON-NLS-1$ for (int i = 0; i < this.initializationCount; i++) { if (i > 0) s += ", "; //$NON-NLS-1$ s += String.valueOf(this.initializationPCs[i << 1]) + "-" + ((this.initializationPCs[(i << 1) + 1] == -1) ? "?" : String.valueOf(this.initializationPCs[(i<< 1) + 1])); //$NON-NLS-2$ //$NON-NLS-1$ } s += "]"; //$NON-NLS-1$ } return s; } public boolean isParameter() { return ((this.tagBits & TagBits.IsArgument) != 0); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java0000644000175000001440000004621312212041344032326 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac * bug 349326 - [1.7] new warning for missing try-with-resources * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource * bug 358903 - Filter practically unimportant resource leak warnings * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; /** * 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 TypeBinding firstBound; // actual resolved variable supertypes (if no superclass bound, then associated to Object) public ReferenceBinding superclass; public ReferenceBinding[] superInterfaces; public char[] genericTypeSignature; LookupEnvironment environment; public TypeVariableBinding(char[] sourceName, Binding declaringElement, int rank, LookupEnvironment environment) { this.sourceName = sourceName; this.declaringElement = declaringElement; this.rank = rank; this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat type var as public this.tagBits |= TagBits.HasTypeVariable; this.environment = environment; this.typeBits = TypeIds.BitUninitialized; } /** * Returns true if the argument type satisfies all bounds of the type parameter */ public int boundCheck(Substitution substitution, TypeBinding argumentType, Scope scope) { int code = internalBoundCheck(substitution, argumentType, scope); if (code == TypeConstants.MISMATCH) { if (argumentType instanceof TypeVariableBinding && scope != null) { TypeBinding bound = ((TypeVariableBinding)argumentType).firstBound; if (bound instanceof ParameterizedTypeBinding) { int code2 = boundCheck(substitution, bound.capture(scope, -1), scope); // no position needed as this capture will never escape this context return Math.min(code, code2); } } } return code; } private int internalBoundCheck(Substitution substitution, TypeBinding argumentType, Scope scope) { if (argumentType == TypeBinding.NULL || argumentType == this) { return TypeConstants.OK; } boolean hasSubstitution = substitution != null; if (!(argumentType instanceof ReferenceBinding || argumentType.isArrayType())) return TypeConstants.MISMATCH; // special case for re-entrant source types (selection, code assist, etc)... // can request additional types during hierarchy walk that are found as source types that also 'need' to connect their hierarchy if (this.superclass == null) return TypeConstants.OK; if (argumentType.kind() == Binding.WILDCARD_TYPE) { WildcardBinding wildcard = (WildcardBinding) argumentType; switch(wildcard.boundKind) { case Wildcard.EXTENDS : TypeBinding wildcardBound = wildcard.bound; if (wildcardBound == this) return TypeConstants.OK; boolean isArrayBound = wildcardBound.isArrayType(); if (!wildcardBound.isInterface()) { TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superclass) : this.superclass; if (substitutedSuperType.id != TypeIds.T_JavaLangObject) { if (isArrayBound) { if (!wildcardBound.isCompatibleWith(substitutedSuperType, scope)) return TypeConstants.MISMATCH; } else { TypeBinding match = wildcardBound.findSuperTypeOriginatingFrom(substitutedSuperType); if (match != null) { if (substitutedSuperType.isProvablyDistinct(match)) { return TypeConstants.MISMATCH; } } else { match = substitutedSuperType.findSuperTypeOriginatingFrom(wildcardBound); if (match != null) { if (match.isProvablyDistinct(wildcardBound)) { return TypeConstants.MISMATCH; } } else { if (!wildcardBound.isTypeVariable() && !substitutedSuperType.isTypeVariable()) { return TypeConstants.MISMATCH; } } } } } } boolean mustImplement = isArrayBound || ((ReferenceBinding)wildcardBound).isFinal(); for (int i = 0, length = this.superInterfaces.length; i < length; i++) { TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces[i]) : this.superInterfaces[i]; if (isArrayBound) { if (!wildcardBound.isCompatibleWith(substitutedSuperType, scope)) return TypeConstants.MISMATCH; } else { TypeBinding match = wildcardBound.findSuperTypeOriginatingFrom(substitutedSuperType); if (match != null) { if (substitutedSuperType.isProvablyDistinct(match)) { return TypeConstants.MISMATCH; } } else if (mustImplement) { return TypeConstants.MISMATCH; // cannot be extended further to satisfy missing bounds } } } break; case Wildcard.SUPER : // if the wildcard is lower-bounded by a type variable that has no relevant upper bound there's nothing to check here (bug 282152): if (wildcard.bound.isTypeVariable() && ((TypeVariableBinding)wildcard.bound).superclass.id == TypeIds.T_JavaLangObject) break; return boundCheck(substitution, wildcard.bound, scope); case Wildcard.UNBOUND : break; } return TypeConstants.OK; } boolean unchecked = false; if (this.superclass.id != TypeIds.T_JavaLangObject) { TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superclass) : this.superclass; if (substitutedSuperType != argumentType) { if (!argumentType.isCompatibleWith(substitutedSuperType, scope)) { return TypeConstants.MISMATCH; } TypeBinding match = argumentType.findSuperTypeOriginatingFrom(substitutedSuperType); if (match != null){ // Enum#RAW is not a substitute for > (86838) if (match.isRawType() && substitutedSuperType.isBoundParameterizedType()) unchecked = true; } } } for (int i = 0, length = this.superInterfaces.length; i < length; i++) { TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces[i]) : this.superInterfaces[i]; if (substitutedSuperType != argumentType) { if (!argumentType.isCompatibleWith(substitutedSuperType, scope)) { return TypeConstants.MISMATCH; } TypeBinding match = argumentType.findSuperTypeOriginatingFrom(substitutedSuperType); if (match != null){ // Enum#RAW is not a substitute for > (86838) if (match.isRawType() && substitutedSuperType.isBoundParameterizedType()) unchecked = true; } } } return unchecked ? TypeConstants.UNCHECKED : TypeConstants.OK; } public int boundsCount() { if (this.firstBound == null) { return 0; } else if (this.firstBound == this.superclass) { return this.superInterfaces.length + 1; } else { return this.superInterfaces.length; } } /** * @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.collectSubstitutes(Collection>, Map), will populate Map with: T --> List * Constraints: * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1)) * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0)) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2)) */ public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { // only infer for type params of the generic method if (this.declaringElement != inferenceContext.genericMethod) return; // cannot infer anything from a null type switch (actualType.kind()) { case Binding.BASE_TYPE : if (actualType == TypeBinding.NULL) return; TypeBinding boxedType = scope.environment().computeBoxingType(actualType); if (boxedType == actualType) return; actualType = boxedType; break; case Binding.WILDCARD_TYPE : return; // wildcards are not true type expressions (JLS 15.12.2.7, p.453 2nd discussion) } // reverse constraint, to reflect variable on rhs: A << T --> T >: A int variableConstraint; switch(constraint) { case TypeConstants.CONSTRAINT_EQUAL : variableConstraint = TypeConstants.CONSTRAINT_EQUAL; break; case TypeConstants.CONSTRAINT_EXTENDS : variableConstraint = TypeConstants.CONSTRAINT_SUPER; break; default: //case CONSTRAINT_SUPER : variableConstraint =TypeConstants.CONSTRAINT_EXTENDS; break; } inferenceContext.recordSubstitute(this, actualType, variableConstraint); } /* * declaringUniqueKey : genericTypeSignature * p.X { ... } --> Lp/X;:TT; * p.X { void foo() {...} } --> Lp/X;.foo()V:TT; */ public char[] computeUniqueKey(boolean isLeaf) { StringBuffer buffer = new StringBuffer(); Binding declaring = this.declaringElement; if (!isLeaf && declaring.kind() == Binding.METHOD) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=97902 MethodBinding methodBinding = (MethodBinding) declaring; ReferenceBinding declaringClass = methodBinding.declaringClass; buffer.append(declaringClass.computeUniqueKey(false/*not a leaf*/)); buffer.append(':'); MethodBinding[] methods = declaringClass.methods(); if (methods != null) for (int i = 0, length = methods.length; i < length; i++) { MethodBinding binding = methods[i]; if (binding == methodBinding) { buffer.append(i); break; } } } else { buffer.append(declaring.computeUniqueKey(false/*not a leaf*/)); buffer.append(':'); } buffer.append(genericTypeSignature()); int length = buffer.length(); char[] uniqueKey = new char[length]; buffer.getChars(0, length, uniqueKey, 0); return uniqueKey; } public char[] constantPoolName() { /* java/lang/Object */ if (this.firstBound != null) { return this.firstBound.constantPoolName(); } return this.superclass.constantPoolName(); // java/lang/Object } /** * @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 } /** * 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 == null ? 0 : this.superInterfaces.length; if (interfaceLength == 0 || this.firstBound == this.superclass) { if (this.superclass != null) 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, ';'); } boolean hasOnlyRawBounds() { if (this.superclass != null && this.firstBound == this.superclass) if (!this.superclass.isRawType()) return false; if (this.superInterfaces != null) for (int i = 0, l = this.superInterfaces.length; i < l; i++) if (!this.superInterfaces[i].isRawType()) return false; return true; } public boolean hasTypeBit(int bit) { if (this.typeBits == TypeIds.BitUninitialized) { // initialize from bounds this.typeBits = 0; if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized)) this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); if (this.superInterfaces != null) for (int i = 0, l = this.superInterfaces.length; i < l; i++) if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized)) this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); } return (this.typeBits & bit) != 0; } /** * 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; } public boolean isHierarchyConnected() { return (this.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0; } /** * Returns true if the 2 variables are playing exact same role: they have * the same bounds, providing one is substituted with the other: > is interchangeable with >. */ public boolean isInterchangeableWith(TypeVariableBinding otherVariable, Substitution substitute) { if (this == otherVariable) return true; int length = this.superInterfaces.length; if (length != otherVariable.superInterfaces.length) return false; if (this.superclass != Scope.substitute(substitute, otherVariable.superclass)) return false; next : for (int i = 0; i < length; i++) { TypeBinding superType = Scope.substitute(substitute, otherVariable.superInterfaces[i]); for (int j = 0; j < length; j++) if (superType == this.superInterfaces[j]) continue next; return false; // not a match } return true; } /** * Returns true if the type was declared as a type variable */ public boolean isTypeVariable() { return true; } // /** // * Returns the original type variable for a given variable. // * Only different from receiver for type variables of generic methods of parameterized types // * e.g. X { U foo(V1) } --> X { String foo(V2) } // * and V2.original() --> V1 // */ // public TypeVariableBinding original() { // if (this.declaringElement.kind() == Binding.METHOD) { // MethodBinding originalMethod = ((MethodBinding)this.declaringElement).original(); // if (originalMethod != this.declaringElement) { // return originalMethod.typeVariables[this.rank]; // } // } else { // ReferenceBinding originalType = (ReferenceBinding)((ReferenceBinding)this.declaringElement).erasure(); // if (originalType != this.declaringElement) { // return originalType.typeVariables()[this.rank]; // } // } // return this; // } public int kind() { return Binding.TYPE_PARAMETER; } public TypeBinding[] otherUpperBounds() { if (this.firstBound == null) return Binding.NO_TYPES; if (this.firstBound == this.superclass) return this.superInterfaces; int otherLength = this.superInterfaces.length - 1; if (otherLength > 0) { TypeBinding[] otherBounds; System.arraycopy(this.superInterfaces, 1, otherBounds = new TypeBinding[otherLength], 0, otherLength); return otherBounds; } return Binding.NO_TYPES; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#readableName() */ public char[] readableName() { return this.sourceName; } ReferenceBinding resolve() { if ((this.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return this; TypeBinding oldSuperclass = this.superclass, oldFirstInterface = null; if (this.superclass != null) { ReferenceBinding resolveType = (ReferenceBinding) BinaryTypeBinding.resolveType(this.superclass, this.environment, true /* raw conversion */); this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences; this.superclass = resolveType; } ReferenceBinding[] interfaces = this.superInterfaces; int length; if ((length = interfaces.length) != 0) { oldFirstInterface = interfaces[0]; for (int i = length; --i >= 0;) { ReferenceBinding resolveType = (ReferenceBinding) BinaryTypeBinding.resolveType(interfaces[i], this.environment, true /* raw conversion */); this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences; interfaces[i] = resolveType; } } // refresh the firstBound in case it changed if (this.firstBound != null) { if (this.firstBound == oldSuperclass) { this.firstBound = this.superclass; } else if (this.firstBound == oldFirstInterface) { this.firstBound = interfaces[0]; } } this.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; return this; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#shortReadableName() */ public char[] shortReadableName() { return readableName(); } public ReferenceBinding superclass() { return this.superclass; } public ReferenceBinding[] superInterfaces() { return this.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 != Binding.NO_SUPERINTERFACES) { 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(); } /** * Upper bound doesn't perform erasure */ public TypeBinding upperBound() { if (this.firstBound != null) { return this.firstBound; } return this.superclass; // java/lang/Object } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/AnnotationHolder.java0000644000175000001440000000646212212041344031716 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; public class AnnotationHolder { AnnotationBinding[] annotations; static AnnotationHolder storeAnnotations(AnnotationBinding[] annotations, AnnotationBinding[][] parameterAnnotations, Object defaultValue, LookupEnvironment optionalEnv) { if (parameterAnnotations != null) { boolean isEmpty = true; for (int i = parameterAnnotations.length; isEmpty && --i >= 0;) if (parameterAnnotations[i] != null && parameterAnnotations[i].length > 0) isEmpty = false; if (isEmpty) parameterAnnotations = null; // does not have any } if (defaultValue != null) return new AnnotationMethodHolder(annotations, parameterAnnotations, defaultValue, optionalEnv); if (parameterAnnotations != null) return new MethodHolder(annotations, parameterAnnotations); return new AnnotationHolder().setAnnotations(annotations); } AnnotationBinding[] getAnnotations() { return this.annotations; } Object getDefaultValue() { return null; } public AnnotationBinding[][] getParameterAnnotations() { return null; } AnnotationBinding[] getParameterAnnotations(int paramIndex) { return Binding.NO_ANNOTATIONS; } AnnotationHolder setAnnotations(AnnotationBinding[] annotations) { if (annotations == null || annotations.length == 0) return null; // no longer needed this.annotations = annotations; return this; } static class MethodHolder extends AnnotationHolder { AnnotationBinding[][] parameterAnnotations; // is null if empty MethodHolder(AnnotationBinding[] annotations, AnnotationBinding[][] parameterAnnotations) { super(); setAnnotations(annotations); this.parameterAnnotations = parameterAnnotations; } public AnnotationBinding[][] getParameterAnnotations() { return this.parameterAnnotations; } AnnotationBinding[] getParameterAnnotations(int paramIndex) { AnnotationBinding[] result = this.parameterAnnotations == null ? null : this.parameterAnnotations[paramIndex]; return result == null ? Binding.NO_ANNOTATIONS : result; } AnnotationHolder setAnnotations(AnnotationBinding[] annotations) { this.annotations = annotations == null || annotations.length == 0 ? Binding.NO_ANNOTATIONS : annotations; return this; } } static class AnnotationMethodHolder extends MethodHolder { Object defaultValue; LookupEnvironment env; AnnotationMethodHolder(AnnotationBinding[] annotations, AnnotationBinding[][] parameterAnnotations, Object defaultValue, LookupEnvironment optionalEnv) { super(annotations, parameterAnnotations); this.defaultValue = defaultValue; this.env = optionalEnv; } Object getDefaultValue() { if (this.defaultValue instanceof UnresolvedReferenceBinding) { if (this.env == null) throw new IllegalStateException(); this.defaultValue = ((UnresolvedReferenceBinding) this.defaultValue).resolve(this.env, false); } return this.defaultValue; } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java0000644000175000001440000000424512212041344032007 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.core.compiler.CharOperation; public final class MemberTypeBinding extends NestedTypeBinding { public MemberTypeBinding(char[][] compoundName, ClassScope scope, SourceTypeBinding enclosingType) { super(compoundName, scope, enclosingType); this.tagBits |= TagBits.MemberTypeMask; } void checkSyntheticArgsAndFields() { if (isStatic()) return; if (isInterface()) return; this.addSyntheticArgumentAndField(this.enclosingType); } /* Answer the receiver's constant pool name. * * NOTE: This method should only be used during/after code gen. */ public char[] constantPoolName() /* java/lang/Object */ { if (this.constantPoolName != null) return this.constantPoolName; return this.constantPoolName = CharOperation.concat(enclosingType().constantPoolName(), this.sourceName, '$'); } /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits() */ public void initializeDeprecatedAnnotationTagBits() { if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) { super.initializeDeprecatedAnnotationTagBits(); if ((this.tagBits & TagBits.AnnotationDeprecated) == 0) { // check enclosing type ReferenceBinding enclosing; if (((enclosing = enclosingType()).tagBits & TagBits.DeprecatedAnnotationResolved) == 0) { enclosing.initializeDeprecatedAnnotationTagBits(); } if (enclosing.isViewedAsDeprecated()) { this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; } } } } public String toString() { return "Member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$ } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java0000644000175000001440000015764012212041344031644 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 358903 - Filter practically unimportant resource leak warnings * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account * bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.Arrays; import java.util.Comparator; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; /* Not all fields defined by this type (& its subclasses) are initialized when it is created. Some are initialized only when needed. Accessors have been provided for some public fields so all TypeBindings have the same API... but access public fields directly whenever possible. Non-public fields have accessors which should be used everywhere you expect the field to be initialized. null is NOT a valid value for a non-public field... it just means the field is not initialized. */ abstract public class ReferenceBinding extends TypeBinding { public char[][] compoundName; public char[] sourceName; public int modifiers; public PackageBinding fPackage; char[] fileName; char[] constantPoolName; char[] signature; private SimpleLookupTable compatibleCache; int typeBits; // additional bits characterizing this type public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */ public boolean hasTypeBit(int bit) { return false; } }; private static final Comparator FIELD_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { char[] n1 = ((FieldBinding) o1).name; char[] n2 = ((FieldBinding) o2).name; return ReferenceBinding.compare(n1, n2, n1.length, n2.length); } }; private static final Comparator METHOD_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { MethodBinding m1 = (MethodBinding) o1; MethodBinding m2 = (MethodBinding) o2; char[] s1 = m1.selector; char[] s2 = m2.selector; int c = ReferenceBinding.compare(s1, s2, s1.length, s2.length); return c == 0 ? m1.parameters.length - m2.parameters.length : c; } }; public static FieldBinding binarySearch(char[] name, FieldBinding[] sortedFields) { if (sortedFields == null) return null; int max = sortedFields.length; if (max == 0) return null; int left = 0, right = max - 1, nameLength = name.length; int mid = 0; char[] midName; while (left <= right) { mid = left + (right - left) /2; int compare = compare(name, midName = sortedFields[mid].name, nameLength, midName.length); if (compare < 0) { right = mid-1; } else if (compare > 0) { left = mid+1; } else { return sortedFields[mid]; } } return null; } /** * Returns a combined range value representing: (start + (end<<32)), where start is the index of the first matching method * (remember methods are sorted alphabetically on selectors), and end is the index of last contiguous methods with same * selector. * -1 means no method got found * @param selector * @param sortedMethods * @return (start + (end<<32)) or -1 if no method found */ public static long binarySearch(char[] selector, MethodBinding[] sortedMethods) { if (sortedMethods == null) return -1; int max = sortedMethods.length; if (max == 0) return -1; int left = 0, right = max - 1, selectorLength = selector.length; int mid = 0; char[] midSelector; while (left <= right) { mid = left + (right - left) /2; int compare = compare(selector, midSelector = sortedMethods[mid].selector, selectorLength, midSelector.length); if (compare < 0) { right = mid-1; } else if (compare > 0) { left = mid+1; } else { int start = mid, end = mid; // find first method with same selector while (start > left && CharOperation.equals(sortedMethods[start-1].selector, selector)){ start--; } // find last method with same selector while (end < right && CharOperation.equals(sortedMethods[end+1].selector, selector)){ end++; } return start + ((long)end<< 32); } } return -1; } /** * Compares two strings lexicographically. * The comparison is based on the Unicode value of each character in * the strings. * * @return the value 0 if the str1 is equal to str2; * a value less than 0 if str1 * is lexicographically less than str2; * and a value greater than 0 if str1 is * lexicographically greater than str2. */ static int compare(char[] str1, char[] str2, int len1, int len2) { int n= Math.min(len1, len2); int i= 0; while (n-- != 0) { char c1= str1[i]; char c2= str2[i++]; if (c1 != c2) { return c1 - c2; } } return len1 - len2; } /** * Sort the field array using a quicksort */ public static void sortFields(FieldBinding[] sortedFields, int left, int right) { Arrays.sort(sortedFields, left, right, FIELD_COMPARATOR); } /** * Sort the field array using a quicksort */ public static void sortMethods(MethodBinding[] sortedMethods, int left, int right) { Arrays.sort(sortedMethods, left, right, METHOD_COMPARATOR); } /** * Return the array of resolvable fields (resilience) */ public FieldBinding[] availableFields() { return fields(); } /** * Return the array of resolvable methods (resilience) */ public MethodBinding[] availableMethods() { return methods(); } /** * Answer true if the receiver can be instantiated */ public boolean canBeInstantiated() { return (this.modifiers & (ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation)) == 0; } /** * 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 == this.fPackage; } /** * Answer true if the receiver is visible to the receiverType and the invocationType. */ public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding invocationType) { if (isPublic()) return true; if (invocationType == this && invocationType == receiverType) return true; if (isProtected()) { // answer true if the invocationType is the declaringClass or they are in the same package // OR the invocationType is a subclass of the declaringClass // AND the invocationType is the invocationType or its subclass // OR the type is a static method accessed directly through a type // OR previous assertions are true for one of the enclosing type if (invocationType == this) return true; if (invocationType.fPackage == this.fPackage) return true; TypeBinding currentType = invocationType.erasure(); TypeBinding declaringClass = enclosingType().erasure(); // protected types always have an enclosing one if (declaringClass == invocationType) return true; if (declaringClass == null) return false; // could be null if incorrect top-level protected type //int depth = 0; do { if (currentType.findSuperTypeOriginatingFrom(declaringClass) != null) return true; //depth++; currentType = currentType.enclosingType(); } while (currentType != null); return false; } if (isPrivate()) { // answer true if the receiverType is the receiver or its enclosingType // AND the invocationType and the receiver have a common enclosingType receiverCheck: { if (!(receiverType == this || receiverType == enclosingType())) { // special tolerance for type variable direct bounds, but only if compliance <= 1.6, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622 if (receiverType.isTypeVariable()) { TypeVariableBinding typeVariable = (TypeVariableBinding) receiverType; if (typeVariable.environment.globalOptions.complianceLevel <= ClassFileConstants.JDK1_6 && (typeVariable.isErasureBoundTo(erasure()) || typeVariable.isErasureBoundTo(enclosingType().erasure()))) break receiverCheck; } return false; } } if (invocationType != this) { ReferenceBinding outerInvocationType = invocationType; ReferenceBinding temp = outerInvocationType.enclosingType(); while (temp != null) { outerInvocationType = temp; temp = temp.enclosingType(); } ReferenceBinding outerDeclaringClass = (ReferenceBinding)erasure(); temp = outerDeclaringClass.enclosingType(); while (temp != null) { outerDeclaringClass = temp; temp = temp.enclosingType(); } if (outerInvocationType != outerDeclaringClass) return false; } return true; } // isDefault() if (invocationType.fPackage != this.fPackage) return false; ReferenceBinding currentType = receiverType; TypeBinding originalDeclaringClass = (enclosingType() == null ? this : enclosingType()).original(); do { if (currentType.isCapture()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=285002 if (originalDeclaringClass == currentType.erasure().original()) return true; } else { if (originalDeclaringClass == currentType.original()) return true; } PackageBinding currentPackage = currentType.fPackage; // package could be null for wildcards/intersection types, ignore and recurse in superclass if (currentPackage != null && currentPackage != this.fPackage) return false; } while ((currentType = currentType.superclass()) != null); return false; } /** * Answer true if the receiver is visible to the type provided by the scope. */ public final boolean canBeSeenBy(Scope scope) { if (isPublic()) return true; SourceTypeBinding invocationType = scope.enclosingSourceType(); if (invocationType == this) return true; if (invocationType == null) // static import call return !isPrivate() && scope.getCurrentPackage() == this.fPackage; if (isProtected()) { // answer true if the invocationType is the declaringClass or they are in the same package // OR the invocationType is a subclass of the declaringClass // AND the invocationType is the invocationType or its subclass // OR the type is a static method accessed directly through a type // OR previous assertions are true for one of the enclosing type if (invocationType.fPackage == this.fPackage) return true; TypeBinding declaringClass = enclosingType(); // protected types always have an enclosing one if (declaringClass == null) return false; // could be null if incorrect top-level protected type declaringClass = declaringClass.erasure();// erasure cannot be null TypeBinding currentType = invocationType.erasure(); // int depth = 0; do { if (declaringClass == invocationType) return true; if (currentType.findSuperTypeOriginatingFrom(declaringClass) != null) return true; // depth++; currentType = currentType.enclosingType(); } while (currentType != null); return false; } if (isPrivate()) { // answer true if the receiver and the invocationType have a common enclosingType // already know they are not the identical type ReferenceBinding outerInvocationType = invocationType; ReferenceBinding temp = outerInvocationType.enclosingType(); while (temp != null) { outerInvocationType = temp; temp = temp.enclosingType(); } ReferenceBinding outerDeclaringClass = (ReferenceBinding)erasure(); temp = outerDeclaringClass.enclosingType(); while (temp != null) { outerDeclaringClass = temp; temp = temp.enclosingType(); } return outerInvocationType == outerDeclaringClass; } // isDefault() return invocationType.fPackage == this.fPackage; } public char[] computeGenericTypeSignature(TypeVariableBinding[] typeVariables) { boolean isMemberOfGeneric = isMemberType() && (enclosingType().modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0; if (typeVariables == Binding.NO_TYPE_VARIABLES && !isMemberOfGeneric) { return signature(); } StringBuffer sig = new StringBuffer(10); if (isMemberOfGeneric) { char[] typeSig = enclosingType().genericTypeSignature(); sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon sig.append('.'); // NOTE: cannot override trailing ';' with '.' in enclosing signature, since shared char[] sig.append(this.sourceName); } else { char[] typeSig = signature(); sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon } if (typeVariables == Binding.NO_TYPE_VARIABLES) { sig.append(';'); } else { sig.append('<'); for (int i = 0, length = typeVariables.length; i < length; i++) { sig.append(typeVariables[i].genericTypeSignature()); } sig.append(">;"); //$NON-NLS-1$ } int sigLength = sig.length(); char[] result = new char[sigLength]; sig.getChars(0, sigLength, result, 0); return result; } public void computeId() { // note that more (configurable) ids are assigned from PackageBinding#checkIfNullAnnotationType() // try to avoid multiple checks against a package/type name switch (this.compoundName.length) { case 3 : char[] packageName = this.compoundName[0]; // expect only java.*.* and javax.*.* and junit.*.* and org.junit.* switch (packageName.length) { case 3: // only one type in this group, yet: if (CharOperation.equals(TypeConstants.ORG_JUNIT_ASSERT, this.compoundName)) this.id = TypeIds.T_OrgJunitAssert; return; case 4: if (!CharOperation.equals(TypeConstants.JAVA, packageName)) return; break; // continue below ... case 5: switch (packageName[1]) { case 'a': if (CharOperation.equals(TypeConstants.JAVAX_ANNOTATION_INJECT_INJECT, this.compoundName)) this.id = TypeIds.T_JavaxInjectInject; return; case 'u': if (CharOperation.equals(TypeConstants.JUNIT_FRAMEWORK_ASSERT, this.compoundName)) this.id = TypeIds.T_JunitFrameworkAssert; return; } return; default: return; } // ... at this point we know it's java.*.* packageName = this.compoundName[1]; if (packageName.length == 0) return; // just to be safe char[] typeName = this.compoundName[2]; if (typeName.length == 0) return; // just to be safe // remaining types MUST be in java.*.* if (!CharOperation.equals(TypeConstants.LANG, this.compoundName[1])) { switch (packageName[0]) { case 'i' : if (CharOperation.equals(packageName, TypeConstants.IO)) { switch (typeName[0]) { case 'C' : if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_CLOSEABLE[2])) this.typeBits |= TypeIds.BitCloseable; // don't assign id, only typeBit (for analysis of resource leaks) return; case 'E' : if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_EXTERNALIZABLE[2])) this.id = TypeIds.T_JavaIoExternalizable; return; case 'I' : if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_IOEXCEPTION[2])) this.id = TypeIds.T_JavaIoException; return; case 'O' : if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_OBJECTSTREAMEXCEPTION[2])) this.id = TypeIds.T_JavaIoObjectStreamException; return; case 'P' : if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_PRINTSTREAM[2])) this.id = TypeIds.T_JavaIoPrintStream; return; case 'S' : if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_SERIALIZABLE[2])) this.id = TypeIds.T_JavaIoSerializable; return; } } return; case 'u' : if (CharOperation.equals(packageName, TypeConstants.UTIL)) { switch (typeName[0]) { case 'C' : if (CharOperation.equals(typeName, TypeConstants.JAVA_UTIL_COLLECTION[2])) this.id = TypeIds.T_JavaUtilCollection; return; case 'I' : if (CharOperation.equals(typeName, TypeConstants.JAVA_UTIL_ITERATOR[2])) this.id = TypeIds.T_JavaUtilIterator; return; case 'O' : if (CharOperation.equals(typeName, TypeConstants.JAVA_UTIL_OBJECTS[2])) this.id = TypeIds.T_JavaUtilObjects; return; } } return; } return; } // remaining types MUST be in java.lang.* switch (typeName[0]) { case 'A' : switch(typeName.length) { case 13 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2])) { this.id = TypeIds.T_JavaLangAutoCloseable; this.typeBits |= TypeIds.BitAutoCloseable; } return; case 14: if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ASSERTIONERROR[2])) this.id = TypeIds.T_JavaLangAssertionError; return; } return; case 'B' : switch (typeName.length) { case 4 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_BYTE[2])) this.id = TypeIds.T_JavaLangByte; return; case 7 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_BOOLEAN[2])) this.id = TypeIds.T_JavaLangBoolean; return; } return; case 'C' : switch (typeName.length) { case 5 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_CLASS[2])) this.id = TypeIds.T_JavaLangClass; return; case 9 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_CHARACTER[2])) this.id = TypeIds.T_JavaLangCharacter; else if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_CLONEABLE[2])) this.id = TypeIds.T_JavaLangCloneable; return; case 22 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_CLASSNOTFOUNDEXCEPTION[2])) this.id = TypeIds.T_JavaLangClassNotFoundException; return; } return; case 'D' : switch (typeName.length) { case 6 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_DOUBLE[2])) this.id = TypeIds.T_JavaLangDouble; return; case 10 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_DEPRECATED[2])) this.id = TypeIds.T_JavaLangDeprecated; return; } return; case 'E' : switch (typeName.length) { case 4 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ENUM[2])) this.id = TypeIds.T_JavaLangEnum; return; case 5 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ERROR[2])) this.id = TypeIds.T_JavaLangError; return; case 9 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_EXCEPTION[2])) this.id = TypeIds.T_JavaLangException; return; } return; case 'F' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_FLOAT[2])) this.id = TypeIds.T_JavaLangFloat; return; case 'I' : switch (typeName.length) { case 7 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_INTEGER[2])) this.id = TypeIds.T_JavaLangInteger; return; case 8 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ITERABLE[2])) this.id = TypeIds.T_JavaLangIterable; return; case 24 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ILLEGALARGUMENTEXCEPTION[2])) this.id = TypeIds.T_JavaLangIllegalArgumentException; return; } return; case 'L' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_LONG[2])) this.id = TypeIds.T_JavaLangLong; return; case 'N' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_NOCLASSDEFERROR[2])) this.id = TypeIds.T_JavaLangNoClassDefError; return; case 'O' : switch (typeName.length) { case 6 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_OBJECT[2])) this.id = TypeIds.T_JavaLangObject; return; case 8 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_OVERRIDE[2])) this.id = TypeIds.T_JavaLangOverride; return; } return; case 'R' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION[2])) this.id = TypeIds.T_JavaLangRuntimeException; break; case 'S' : switch (typeName.length) { case 5 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_SHORT[2])) this.id = TypeIds.T_JavaLangShort; return; case 6 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_STRING[2])) this.id = TypeIds.T_JavaLangString; else if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_SYSTEM[2])) this.id = TypeIds.T_JavaLangSystem; return; case 11 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_SAFEVARARGS[2])) this.id = TypeIds.T_JavaLangSafeVarargs; return; case 12 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_STRINGBUFFER[2])) this.id = TypeIds.T_JavaLangStringBuffer; return; case 13 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_STRINGBUILDER[2])) this.id = TypeIds.T_JavaLangStringBuilder; return; case 16 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_SUPPRESSWARNINGS[2])) this.id = TypeIds.T_JavaLangSuppressWarnings; return; } return; case 'T' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_THROWABLE[2])) this.id = TypeIds.T_JavaLangThrowable; return; case 'V' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_VOID[2])) this.id = TypeIds.T_JavaLangVoid; return; } break; case 4: // expect one type from com.*.*.*: if (CharOperation.equals(TypeConstants.COM_GOOGLE_INJECT_INJECT, this.compoundName)) { this.id = TypeIds.T_ComGoogleInjectInject; return; } // otherwise only expect java.*.*.* if (!CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) return; packageName = this.compoundName[1]; if (packageName.length == 0) return; // just to be safe packageName = this.compoundName[2]; if (packageName.length == 0) return; // just to be safe typeName = this.compoundName[3]; if (typeName.length == 0) return; // just to be safe switch (packageName[0]) { case 'a' : if (CharOperation.equals(packageName, TypeConstants.ANNOTATION)) { switch (typeName[0]) { case 'A' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION[3])) this.id = TypeIds.T_JavaLangAnnotationAnnotation; return; case 'D' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED[3])) this.id = TypeIds.T_JavaLangAnnotationDocumented; return; case 'E' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE[3])) this.id = TypeIds.T_JavaLangAnnotationElementType; return; case 'I' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_INHERITED[3])) this.id = TypeIds.T_JavaLangAnnotationInherited; return; case 'R' : switch (typeName.length) { case 9 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_RETENTION[3])) this.id = TypeIds.T_JavaLangAnnotationRetention; return; case 15 : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY[3])) this.id = TypeIds.T_JavaLangAnnotationRetentionPolicy; return; } return; case 'T' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_TARGET[3])) this.id = TypeIds.T_JavaLangAnnotationTarget; return; } } return; case 'i': if (CharOperation.equals(packageName, TypeConstants.INVOKE)) { if (typeName.length == 0) return; // just to be safe switch (typeName[0]) { case 'M' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE[3])) this.id = TypeIds.T_JavaLangInvokeMethodHandlePolymorphicSignature; return; } } return; case 'r' : if (CharOperation.equals(packageName, TypeConstants.REFLECT)) { switch (typeName[0]) { case 'C' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_REFLECT_CONSTRUCTOR[2])) this.id = TypeIds.T_JavaLangReflectConstructor; return; case 'F' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_REFLECT_FIELD[2])) this.id = TypeIds.T_JavaLangReflectField; return; case 'M' : if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_REFLECT_METHOD[2])) this.id = TypeIds.T_JavaLangReflectMethod; return; } } return; } break; case 5 : packageName = this.compoundName[0]; switch (packageName[0]) { case 'j' : if (!CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) return; packageName = this.compoundName[1]; if (packageName.length == 0) return; // just to be safe if (CharOperation.equals(TypeConstants.LANG, packageName)) { packageName = this.compoundName[2]; if (packageName.length == 0) return; // just to be safe switch (packageName[0]) { case 'i' : if (CharOperation.equals(packageName, TypeConstants.INVOKE)) { typeName = this.compoundName[3]; if (typeName.length == 0) return; // just to be safe switch (typeName[0]) { case 'M' : char[] memberTypeName = this.compoundName[4]; if (memberTypeName.length == 0) return; // just to be safe if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_POLYMORPHICSIGNATURE[3]) && CharOperation.equals(memberTypeName, TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_POLYMORPHICSIGNATURE[4])) this.id = TypeIds.T_JavaLangInvokeMethodHandlePolymorphicSignature; return; } } return; } return; } return; case 'o': if (!CharOperation.equals(TypeConstants.ORG, this.compoundName[0])) return; packageName = this.compoundName[1]; if (packageName.length == 0) return; // just to be safe switch (packageName[0]) { case 'e': if (CharOperation.equals(TypeConstants.ECLIPSE, packageName)) { packageName = this.compoundName[2]; if (packageName.length == 0) return; // just to be safe switch (packageName[0]) { case 'c' : if (CharOperation.equals(packageName, TypeConstants.CORE)) { typeName = this.compoundName[3]; if (typeName.length == 0) return; // just to be safe switch (typeName[0]) { case 'r' : char[] memberTypeName = this.compoundName[4]; if (memberTypeName.length == 0) return; // just to be safe if (CharOperation.equals(typeName, TypeConstants.ORG_ECLIPSE_CORE_RUNTIME_ASSERT[3]) && CharOperation.equals(memberTypeName, TypeConstants.ORG_ECLIPSE_CORE_RUNTIME_ASSERT[4])) this.id = TypeIds.T_OrgEclipseCoreRuntimeAssert; return; } } return; } return; } return; case 'a': if (CharOperation.equals(TypeConstants.APACHE, packageName)) { if (CharOperation.equals(TypeConstants.COMMONS, this.compoundName[2])) { if (CharOperation.equals(TypeConstants.ORG_APACHE_COMMONS_LANG_VALIDATE, this.compoundName)) this.id = TypeIds.T_OrgApacheCommonsLangValidate; else if (CharOperation.equals(TypeConstants.ORG_APACHE_COMMONS_LANG3_VALIDATE, this.compoundName)) this.id = TypeIds.T_OrgApacheCommonsLang3Validate; } } return; } return; case 'c': if (!CharOperation.equals(TypeConstants.COM, this.compoundName[0])) return; if (CharOperation.equals(TypeConstants.COM_GOOGLE_COMMON_BASE_PRECONDITIONS, this.compoundName)) this.id = TypeIds.T_ComGoogleCommonBasePreconditions; return; } break; } } /** * p.X {} -> Lp/X; */ public char[] computeUniqueKey(boolean isLeaf) { if (!isLeaf) return signature(); return genericTypeSignature(); } /** * Answer the receiver's constant pool name. * * NOTE: This method should only be used during/after code gen. */ public char[] constantPoolName() /* java/lang/Object */ { if (this.constantPoolName != null) return this.constantPoolName; return this.constantPoolName = CharOperation.concatWith(this.compoundName, '/'); } public String debugName() { return (this.compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$ } public final int depth() { int depth = 0; ReferenceBinding current = this; while ((current = current.enclosingType()) != null) depth++; return depth; } public boolean detectAnnotationCycle() { if ((this.tagBits & TagBits.EndAnnotationCheck) != 0) return false; // already checked if ((this.tagBits & TagBits.BeginAnnotationCheck) != 0) return true; // in the middle of checking its methods this.tagBits |= TagBits.BeginAnnotationCheck; MethodBinding[] currentMethods = methods(); boolean inCycle = false; // check each method before failing for (int i = 0, l = currentMethods.length; i < l; i++) { TypeBinding returnType = currentMethods[i].returnType.leafComponentType().erasure(); if (this == returnType) { if (this instanceof SourceTypeBinding) { MethodDeclaration decl = (MethodDeclaration) currentMethods[i].sourceMethod(); ((SourceTypeBinding) this).scope.problemReporter().annotationCircularity(this, this, decl != null ? decl.returnType : null); } } else if (returnType.isAnnotationType() && ((ReferenceBinding) returnType).detectAnnotationCycle()) { if (this instanceof SourceTypeBinding) { MethodDeclaration decl = (MethodDeclaration) currentMethods[i].sourceMethod(); ((SourceTypeBinding) this).scope.problemReporter().annotationCircularity(this, returnType, decl != null ? decl.returnType : null); } inCycle = true; } } if (inCycle) return true; this.tagBits |= TagBits.EndAnnotationCheck; return false; } public final ReferenceBinding enclosingTypeAt(int relativeDepth) { ReferenceBinding current = this; while (relativeDepth-- > 0 && current != null) current = current.enclosingType(); return current; } public int enumConstantCount() { int count = 0; FieldBinding[] fields = fields(); for (int i = 0, length = fields.length; i < length; i++) { if ((fields[i].modifiers & ClassFileConstants.AccEnum) != 0) count++; } return count; } public int fieldCount() { return fields().length; } public FieldBinding[] fields() { return Binding.NO_FIELDS; } public final int getAccessFlags() { return this.modifiers & ExtraCompilerModifiers.AccJustFlag; } /** * @return the JSR 175 annotations for this type. */ public AnnotationBinding[] getAnnotations() { return retrieveAnnotations(this); } /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits() */ public long getAnnotationTagBits() { return this.tagBits; } /** * @return the enclosingInstancesSlotSize */ public int getEnclosingInstancesSlotSize() { if (isStatic()) return 0; return enclosingType() == null ? 0 : 1; } public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) { return null; } public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) { return null; } public FieldBinding getField(char[] fieldName, boolean needResolve) { return null; } /** * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName() */ public char[] getFileName() { return this.fileName; } public ReferenceBinding getMemberType(char[] typeName) { ReferenceBinding[] memberTypes = memberTypes(); for (int i = memberTypes.length; --i >= 0;) if (CharOperation.equals(memberTypes[i].sourceName, typeName)) return memberTypes[i]; return null; } public MethodBinding[] getMethods(char[] selector) { return Binding.NO_METHODS; } // Answer methods named selector, which take no more than the suggestedParameterLength. // The suggested parameter length is optional and may not be guaranteed by every type. public MethodBinding[] getMethods(char[] selector, int suggestedParameterLength) { return getMethods(selector); } /** * @return the outerLocalVariablesSlotSize */ public int getOuterLocalVariablesSlotSize() { return 0; } public PackageBinding getPackage() { return this.fPackage; } 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 position 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]); } /** * Returns true if the two types have an incompatible common supertype, * e.g. List and List */ public boolean hasIncompatibleSuperType(ReferenceBinding otherType) { if (this == otherType) return false; ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; ReferenceBinding currentType = this; TypeBinding match; do { match = otherType.findSuperTypeOriginatingFrom(currentType); if (match != null && match.isProvablyDistinct(currentType)) return true; ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } while ((currentType = currentType.superclass()) != null); for (int i = 0; i < nextPosition; i++) { currentType = interfacesToVisit[i]; if (currentType == otherType) return false; match = otherType.findSuperTypeOriginatingFrom(currentType); if (match != null && match.isProvablyDistinct(currentType)) return true; ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } return false; } public boolean hasMemberTypes() { return false; } /** * Answer whether a @NonNullByDefault is applicable at the given method binding. */ boolean hasNonNullDefault() { // Note, STB overrides for correctly handling local types ReferenceBinding currentType = this; while (currentType != null) { if ((currentType.tagBits & TagBits.AnnotationNonNullByDefault) != 0) return true; if ((currentType.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) return false; currentType = currentType.enclosingType(); } // package return this.getPackage().defaultNullness == NONNULL_BY_DEFAULT; } public final boolean hasRestrictedAccess() { return (this.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0; } /** Answer an additional bit characterizing this type, like {@link TypeIds#BitAutoCloseable}. */ abstract public boolean hasTypeBit(int bit); /** 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; ReferenceBinding[] interfacesToVisit = null; int nextPosition = 0; ReferenceBinding currentType = this; do { ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { // in code assist cases when source types are added late, may not be finished connecting hierarchy if (interfacesToVisit == null) { interfacesToVisit = itsInterfaces; nextPosition = interfacesToVisit.length; } else { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } while (searchHierarchy && (currentType = currentType.superclass()) != null); for (int i = 0; i < nextPosition; i++) { currentType = interfacesToVisit[i]; if (currentType.isEquivalentTo(anInterface)) return true; ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { // in code assist cases when source types are added late, may not be finished connecting hierarchy int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } return false; } // Internal method... assume its only sent to classes NOT interfaces boolean implementsMethod(MethodBinding method) { char[] selector = method.selector; ReferenceBinding type = this; while (type != null) { MethodBinding[] methods = type.methods(); long range; if ((range = ReferenceBinding.binarySearch(selector, methods)) >= 0) { int start = (int) range, end = (int) (range >> 32); for (int i = start; i <= end; i++) { if (methods[i].areParametersEqual(method)) return true; } } type = type.superclass(); } return false; } /** * Answer true if the receiver is an abstract type */ public final boolean isAbstract() { return (this.modifiers & ClassFileConstants.AccAbstract) != 0; } public boolean isAnnotationType() { return (this.modifiers & ClassFileConstants.AccAnnotation) != 0; } public final boolean isBinaryBinding() { return (this.tagBits & TagBits.IsBinaryBinding) != 0; } public boolean isClass() { return (this.modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) == 0; } /** * Answer true if the receiver type can be assigned to the argument type (right) * In addition to improving performance, caching also ensures there is no infinite regression * since per nature, the compatibility check is recursive through parameterized type arguments (122775) */ public boolean isCompatibleWith(TypeBinding otherType, /*@Nullable*/ Scope captureScope) { if (otherType == this) return true; if (otherType.id == TypeIds.T_JavaLangObject) return true; Object result; if (this.compatibleCache == null) { this.compatibleCache = new SimpleLookupTable(3); result = null; } else { result = this.compatibleCache.get(otherType); // [dbg reset] this.compatibleCache.put(otherType,null) if (result != null) { return result == Boolean.TRUE; } } this.compatibleCache.put(otherType, Boolean.FALSE); // protect from recursive call if (isCompatibleWith0(otherType, captureScope)) { this.compatibleCache.put(otherType, Boolean.TRUE); return true; } if (captureScope == null && this instanceof TypeVariableBinding && ((TypeVariableBinding)this).firstBound instanceof ParameterizedTypeBinding) { // see https://bugs.eclipse.org/395002#c9 // in this case a subsequent check with captureScope != null may actually get // a better result, reset this info to ensure we're not blocking that re-check. this.compatibleCache.put(otherType, null); } return false; } /** * Answer true if the receiver type can be assigned to the argument type (right) */ private boolean isCompatibleWith0(TypeBinding otherType, /*@Nullable*/ Scope captureScope) { if (otherType == this) return true; if (otherType.id == TypeIds.T_JavaLangObject) return true; // equivalence may allow compatibility with array type through wildcard // bound if (isEquivalentTo(otherType)) return true; switch (otherType.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE: return false; // should have passed equivalence check above if // wildcard case Binding.TYPE_PARAMETER : // check compatibility with capture of ? super X if (otherType.isCapture()) { CaptureBinding otherCapture = (CaptureBinding) otherType; TypeBinding otherLowerBound; if ((otherLowerBound = otherCapture.lowerBound) != null) { if (otherLowerBound.isArrayType()) return false; return isCompatibleWith(otherLowerBound); } } //$FALL-THROUGH$ case Binding.GENERIC_TYPE : case Binding.TYPE : case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : switch (kind()) { case Binding.GENERIC_TYPE : case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : if (erasure() == otherType.erasure()) return false; // should have passed equivalence check // above if same erasure } ReferenceBinding otherReferenceType = (ReferenceBinding) otherType; if (otherReferenceType.isInterface()) { // could be annotation type if (implementsInterface(otherReferenceType, true)) return true; if (this instanceof TypeVariableBinding && captureScope != null) { TypeVariableBinding typeVariable = (TypeVariableBinding) this; if (typeVariable.firstBound instanceof ParameterizedTypeBinding) { TypeBinding bound = typeVariable.firstBound.capture(captureScope, -1); // no position needed as this capture will never escape this context return bound.isCompatibleWith(otherReferenceType); } } } if (isInterface()) // Explicit conversion from an interface // to a class is not allowed return false; return otherReferenceType.isSuperclassOf(this); default : return false; } } /** * Answer true if the receiver has default visibility */ public final boolean isDefault() { return (this.modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate)) == 0; } /** * Answer true if the receiver is a deprecated type */ public final boolean isDeprecated() { return (this.modifiers & ClassFileConstants.AccDeprecated) != 0; } public boolean isEnum() { return (this.modifiers & ClassFileConstants.AccEnum) != 0; } /** * Answer true if the receiver is final and cannot be subclassed */ public final boolean isFinal() { return (this.modifiers & ClassFileConstants.AccFinal) != 0; } /** * Returns true if the type hierarchy is being connected */ public boolean isHierarchyBeingConnected() { return (this.tagBits & TagBits.EndHierarchyCheck) == 0 && (this.tagBits & TagBits.BeginHierarchyCheck) != 0; } /** * Returns true if the type hierarchy is being connected "actively" i.e not paused momentatrily, * while resolving type arguments. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=294057 */ public boolean isHierarchyBeingActivelyConnected() { return (this.tagBits & TagBits.EndHierarchyCheck) == 0 && (this.tagBits & TagBits.BeginHierarchyCheck) != 0 && (this.tagBits & TagBits.PauseHierarchyCheck) == 0; } /** * Returns true if the type hierarchy is connected */ public boolean isHierarchyConnected() { return true; } public boolean isInterface() { // consider strict interfaces and annotation types return (this.modifiers & ClassFileConstants.AccInterface) != 0; } /** * Answer true if the receiver has private visibility */ public final boolean isPrivate() { return (this.modifiers & ClassFileConstants.AccPrivate) != 0; } /** * Answer true if the receiver or any of its enclosing types have private visibility */ public final boolean isOrEnclosedByPrivateType() { if (isLocalType()) return true; // catch all local types ReferenceBinding type = this; while (type != null) { if ((type.modifiers & ClassFileConstants.AccPrivate) != 0) return true; type = type.enclosingType(); } return false; } /** * Answer true if the receiver has protected visibility */ public final boolean isProtected() { return (this.modifiers & ClassFileConstants.AccProtected) != 0; } /** * Answer true if the receiver has public visibility */ public final boolean isPublic() { return (this.modifiers & ClassFileConstants.AccPublic) != 0; } /** * Answer true if the receiver is a static member type (or toplevel) */ public final boolean isStatic() { return (this.modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccInterface)) != 0 || (this.tagBits & TagBits.IsNestedType) == 0; } /** * Answer true if all float operations must adher to IEEE 754 float/double rules */ public final boolean isStrictfp() { return (this.modifiers & ClassFileConstants.AccStrictfp) != 0; } /** * Answer true if the receiver is in the superclass hierarchy of aType * NOTE: Object.isSuperclassOf(Object) -> false */ public boolean isSuperclassOf(ReferenceBinding otherType) { while ((otherType = otherType.superclass()) != null) { if (otherType.isEquivalentTo(this)) return true; } return false; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isThrowable() */ public boolean isThrowable() { ReferenceBinding current = this; do { switch (current.id) { case TypeIds.T_JavaLangThrowable : case TypeIds.T_JavaLangError : case TypeIds.T_JavaLangRuntimeException : case TypeIds.T_JavaLangException : return true; } } while ((current = current.superclass()) != null); return false; } /** * JLS 11.5 ensures that Throwable, Exception, RuntimeException and Error are directly connected. * (Throwable<- Exception <- RumtimeException, Throwable <- Error). Thus no need to check #isCompatibleWith * but rather check in type IDs so as to avoid some eager class loading for JCL writers. * When 'includeSupertype' is true, answers true if the given type can be a supertype of some unchecked exception * type (i.e. Throwable or Exception). * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isUncheckedException(boolean) */ public boolean isUncheckedException(boolean includeSupertype) { switch (this.id) { case TypeIds.T_JavaLangError : case TypeIds.T_JavaLangRuntimeException : return true; case TypeIds.T_JavaLangThrowable : case TypeIds.T_JavaLangException : return includeSupertype; } ReferenceBinding current = this; while ((current = current.superclass()) != null) { switch (current.id) { case TypeIds.T_JavaLangError : case TypeIds.T_JavaLangRuntimeException : return true; case TypeIds.T_JavaLangThrowable : case TypeIds.T_JavaLangException : return false; } } return false; } /** * Answer true if the receiver has private visibility and is used locally */ public final boolean isUsed() { return (this.modifiers & ExtraCompilerModifiers.AccLocallyUsed) != 0; } /** * Answer true if the receiver is deprecated (or any of its enclosing types) */ public final boolean isViewedAsDeprecated() { return (this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0 || getPackage().isViewedAsDeprecated(); } public ReferenceBinding[] memberTypes() { return Binding.NO_MEMBER_TYPES; } public MethodBinding[] methods() { return Binding.NO_METHODS; } public final ReferenceBinding outermostEnclosingType() { ReferenceBinding current = this; while (true) { ReferenceBinding last = current; if ((current = current.enclosingType()) == null) return last; } } /** * Answer the source name for the type. * In the case of member types, as the qualified name from its top level type. * For example, for a member type N defined inside M & A: "A.M.N". */ public char[] qualifiedSourceName() { if (isMemberType()) return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.'); return sourceName(); } /** * Answer the receiver's signature. * * NOTE: This method should only be used during/after code gen. */ public char[] readableName() /*java.lang.Object, p.X */ { char[] readableName; if (isMemberType()) { readableName = CharOperation.concat(enclosingType().readableName(), this.sourceName, '.'); } else { readableName = CharOperation.concatWith(this.compoundName, '.'); } TypeVariableBinding[] typeVars; if ((typeVars = typeVariables()) != Binding.NO_TYPE_VARIABLES) { 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 AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) { SimpleLookupTable store = storedAnnotations(forceInitialization); return store == null ? null : (AnnotationHolder) store.get(binding); } AnnotationBinding[] retrieveAnnotations(Binding binding) { AnnotationHolder holder = retrieveAnnotationHolder(binding, true); return holder == null ? Binding.NO_ANNOTATIONS : holder.getAnnotations(); } public void setAnnotations(AnnotationBinding[] annotations) { storeAnnotations(this, annotations); } public char[] shortReadableName() /*Object*/ { char[] shortReadableName; if (isMemberType()) { shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), this.sourceName, '.'); } else { shortReadableName = this.sourceName; } TypeVariableBinding[] typeVars; if ((typeVars = typeVariables()) != Binding.NO_TYPE_VARIABLES) { 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; } public char[] signature() /* Ljava/lang/Object; */ { if (this.signature != null) return this.signature; return this.signature = CharOperation.concat('L', constantPoolName(), ';'); } public char[] sourceName() { return this.sourceName; } void storeAnnotationHolder(Binding binding, AnnotationHolder holder) { if (holder == null) { SimpleLookupTable store = storedAnnotations(false); if (store != null) store.removeKey(binding); } else { SimpleLookupTable store = storedAnnotations(true); if (store != null) store.put(binding, holder); } } void storeAnnotations(Binding binding, AnnotationBinding[] annotations) { AnnotationHolder holder = null; if (annotations == null || annotations.length == 0) { SimpleLookupTable store = storedAnnotations(false); if (store != null) holder = (AnnotationHolder) store.get(binding); if (holder == null) return; // nothing to delete } else { SimpleLookupTable store = storedAnnotations(true); if (store == null) return; // not supported holder = (AnnotationHolder) store.get(binding); if (holder == null) holder = new AnnotationHolder(); } storeAnnotationHolder(binding, holder.setAnnotations(annotations)); } SimpleLookupTable storedAnnotations(boolean forceInitialize) { return null; // overrride if interested in storing annotations for the receiver, its fields and methods } public ReferenceBinding superclass() { return null; } public ReferenceBinding[] superInterfaces() { return Binding.NO_SUPERINTERFACES; } public ReferenceBinding[] syntheticEnclosingInstanceTypes() { if (isStatic()) return null; ReferenceBinding enclosingType = enclosingType(); if (enclosingType == null) return null; return new ReferenceBinding[] {enclosingType}; } 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(); } public FieldBinding[] unResolvedFields() { return Binding.NO_FIELDS; } /* * If a type - known to be a Closeable - is mentioned in one of our white lists * answer the typeBit for the white list (BitWrapperCloseable or BitResourceFreeCloseable). */ protected int applyCloseableWhitelists() { switch (this.compoundName.length) { case 3: if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) { if (CharOperation.equals(TypeConstants.IO, this.compoundName[1])) { char[] simpleName = this.compoundName[2]; int l = TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES.length; for (int i = 0; i < l; i++) { if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES[i])) return TypeIds.BitWrapperCloseable; } l = TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES.length; for (int i = 0; i < l; i++) { if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES[i])) return TypeIds.BitResourceFreeCloseable; } } } break; case 4: if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) { if (CharOperation.equals(TypeConstants.UTIL, this.compoundName[1])) { if (CharOperation.equals(TypeConstants.ZIP, this.compoundName[2])) { char[] simpleName = this.compoundName[3]; int l = TypeConstants.JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES.length; for (int i = 0; i < l; i++) { if (CharOperation.equals(simpleName, TypeConstants.JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES[i])) return TypeIds.BitWrapperCloseable; } } } } break; } int l = TypeConstants.OTHER_WRAPPER_CLOSEABLES.length; for (int i = 0; i < l; i++) { if (CharOperation.equals(this.compoundName, TypeConstants.OTHER_WRAPPER_CLOSEABLES[i])) return TypeIds.BitWrapperCloseable; } return 0; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java0000644000175000001440000020134112212041344032135 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - contributions for * bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment * bug 186342 - [compiler][null] Using annotations for null checking * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFilePool; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; 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.AbortCompilation; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; public class LookupEnvironment implements ProblemReasons, TypeConstants { /** * Map from typeBinding -> accessRestriction rule */ private Map accessRestrictions; ImportBinding[] defaultImports; public PackageBinding defaultPackage; HashtableOfPackage knownPackages; private int lastCompletedUnitIndex = -1; private int lastUnitIndex = -1; public INameEnvironment nameEnvironment; public CompilerOptions globalOptions; public ProblemReporter problemReporter; public ClassFilePool classFilePool; // 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; public ITypeRequestor typeRequestor; private ArrayBinding[][] uniqueArrayBindings; private SimpleLookupTable uniqueParameterizedTypeBindings; private SimpleLookupTable uniqueRawTypeBindings; private SimpleLookupTable uniqueWildcardBindings; private SimpleLookupTable uniqueParameterizedGenericMethodBindings; // key is a string with the method selector value is an array of method bindings private SimpleLookupTable uniquePolymorphicMethodBindings; private SimpleLookupTable uniqueGetClassMethodBinding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300734 public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units public Object missingClassFileLocation = null; // only set when resolving certain references, to help locating problems private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4]; private MethodVerifier verifier; public MethodBinding arrayClone; private ArrayList missingTypes; Set typesBeingConnected; public boolean isProcessingAnnotations = false; public boolean mayTolerateMissingType = false; PackageBinding nullableAnnotationPackage; // the package supposed to contain the Nullable annotation type PackageBinding nonnullAnnotationPackage; // the package supposed to contain the NonNull annotation type PackageBinding nonnullByDefaultAnnotationPackage; // the package supposed to contain the NonNullByDefault annotation type 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_CHAR, null, NotFound); public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) { this.typeRequestor = typeRequestor; this.globalOptions = globalOptions; this.problemReporter = problemReporter; this.defaultPackage = new PackageBinding(this); // assume the default package always exists this.defaultImports = null; this.nameEnvironment = nameEnvironment; 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.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3); this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3); this.missingTypes = null; this.accessRestrictions = new HashMap(3); this.classFilePool = ClassFilePool.newInstance(); this.typesBeingConnected = new HashSet(); } /** * 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 = this.nameEnvironment.findType(compoundName); if (answer == null) return null; if (answer.isBinaryType()) { // the type was found as a .class file this.typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName, false /* valid pkg */), answer.getAccessRestriction()); } else if (answer.isCompilationUnit()) { // the type was found as a .java file, try to build it then search the cache this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction()); } else if (answer.isSourceType()) { // the type was found as a source model this.typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName, false /* valid pkg */), answer.getAccessRestriction()); } return getCachedType(compoundName); } /* Ask the oracle for a type named name in the packageBinding. * Answer null if the name cannot be found. */ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) { if (packageBinding == null) { packageBinding = this.defaultPackage; } NameEnvironmentAnswer answer = this.nameEnvironment.findType(name, packageBinding.compoundName); if (answer == null) return null; if (answer.isBinaryType()) { // the type was found as a .class file this.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 try { this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction()); } catch (AbortCompilation abort) { if (CharOperation.equals(name, TypeConstants.PACKAGE_INFO_NAME)) return null; // silently, requestor may not be able to handle compilation units (HierarchyResolver) throw abort; } } else if (answer.isSourceType()) { // the type was found as a source model this.typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction()); } return packageBinding.getType0(name); } /* Create the initial type bindings for the compilation unit. * * See completeTypeBindings() for a description of the remaining steps * * NOTE: This method can be called multiple times as additional source files are needed */ public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) { CompilationUnitScope scope = new CompilationUnitScope(unit, this); scope.buildTypeBindings(accessRestriction); int unitsLength = this.units.length; if (++this.lastUnitIndex >= unitsLength) System.arraycopy(this.units, 0, this.units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength); this.units[this.lastUnitIndex] = unit; } /* 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, 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, 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, false /* valid pkg */), needFieldsAndMethods, accessRestriction); return null; // the type already exists & can be retrieved from the cache } public void completeTypeBindings() { this.stepCompleted = BUILD_TYPE_HIERARCHY; for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) { (this.unitBeingCompleted = this.units[i]).scope.checkAndSetImports(); } this.stepCompleted = CHECK_AND_SET_IMPORTS; for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) { (this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy(); } this.stepCompleted = CONNECT_TYPE_HIERARCHY; for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) { CompilationUnitScope unitScope = (this.unitBeingCompleted = this.units[i]).scope; unitScope.checkParameterizedTypes(); unitScope.buildFieldsAndMethods(); this.units[i] = null; // release unnecessary reference to the parsed unit } this.stepCompleted = BUILD_FIELDS_AND_METHODS; this.lastCompletedUnitIndex = this.lastUnitIndex; this.unitBeingCompleted = null; } /* * 1. Connect the type hierarchy for the type bindings created for parsedUnits. * 2. Create the field bindings * 3. Create the method bindings */ /* We know each known compilationUnit is free of errors at this point... * * Each step will create additional bindings unless a problem is detected, in which * case either the faulty import/superinterface/field/method will be skipped or a * suitable replacement will be substituted (such as Object for a missing superclass) */ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) { if (this.stepCompleted == BUILD_FIELDS_AND_METHODS) { // This can only happen because the original set of units are completely built and // are now being processed, so we want to treat all the additional units as a group // until they too are completely processed. completeTypeBindings(); } else { if (parsedUnit.scope == null) return; // parsing errors were too severe if (this.stepCompleted >= CHECK_AND_SET_IMPORTS) (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); if (this.stepCompleted >= CONNECT_TYPE_HIERARCHY) (this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy(); this.unitBeingCompleted = null; } } /* * Used by other compiler tools which do not start by calling completeTypeBindings(). * * 1. Connect the type hierarchy for the type bindings created for parsedUnits. * 2. Create the field bindings * 3. Create the method bindings */ /* * Each step will create additional bindings unless a problem is detected, in which * case either the faulty import/superinterface/field/method will be skipped or a * suitable replacement will be substituted (such as Object for a missing superclass) */ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) { if (parsedUnit.scope == null) return; // parsing errors were too severe (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); parsedUnit.scope.connectTypeHierarchy(); parsedUnit.scope.checkParameterizedTypes(); if (buildFieldsAndMethods) parsedUnit.scope.buildFieldsAndMethods(); this.unitBeingCompleted = null; } /* * Used by other compiler tools which do not start by calling completeTypeBindings() * and have more than 1 unit to complete. * * 1. Connect the type hierarchy for the type bindings created for parsedUnits. * 2. Create the field bindings * 3. Create the method bindings */ public void completeTypeBindings(CompilationUnitDeclaration[] parsedUnits, boolean[] buildFieldsAndMethods, int unitCount) { for (int i = 0; i < unitCount; i++) { CompilationUnitDeclaration parsedUnit = parsedUnits[i]; if (parsedUnit.scope != null) (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); } for (int i = 0; i < unitCount; i++) { CompilationUnitDeclaration parsedUnit = parsedUnits[i]; if (parsedUnit.scope != null) (this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy(); } for (int i = 0; i < unitCount; i++) { CompilationUnitDeclaration parsedUnit = parsedUnits[i]; if (parsedUnit.scope != null) { (this.unitBeingCompleted = parsedUnit).scope.checkParameterizedTypes(); if (buildFieldsAndMethods[i]) parsedUnit.scope.buildFieldsAndMethods(); } } this.unitBeingCompleted = null; } public MethodBinding computeArrayClone(MethodBinding objectClone) { if (this.arrayClone == null) { this.arrayClone = new MethodBinding( (objectClone.modifiers & ~ClassFileConstants.AccProtected) | ClassFileConstants.AccPublic, TypeConstants.CLONE, objectClone.returnType, Binding.NO_PARAMETERS, Binding.NO_EXCEPTIONS, // no exception for array specific method (ReferenceBinding)objectClone.returnType); } return this.arrayClone; } public TypeBinding computeBoxingType(TypeBinding type) { TypeBinding boxedType; switch (type.id) { case TypeIds.T_JavaLangBoolean : return TypeBinding.BOOLEAN; case TypeIds.T_JavaLangByte : return TypeBinding.BYTE; case TypeIds.T_JavaLangCharacter : return TypeBinding.CHAR; case TypeIds.T_JavaLangShort : return TypeBinding.SHORT; case TypeIds.T_JavaLangDouble : return TypeBinding.DOUBLE; case TypeIds.T_JavaLangFloat : return TypeBinding.FLOAT; case TypeIds.T_JavaLangInteger : return TypeBinding.INT; case TypeIds.T_JavaLangLong : return TypeBinding.LONG; case TypeIds.T_int : boxedType = getType(JAVA_LANG_INTEGER); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_INTEGER, null, NotFound); case TypeIds.T_byte : boxedType = getType(JAVA_LANG_BYTE); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_BYTE, null, NotFound); case TypeIds.T_short : boxedType = getType(JAVA_LANG_SHORT); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_SHORT, null, NotFound); case TypeIds.T_char : boxedType = getType(JAVA_LANG_CHARACTER); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_CHARACTER, null, NotFound); case TypeIds.T_long : boxedType = getType(JAVA_LANG_LONG); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_LONG, null, NotFound); case TypeIds.T_float : boxedType = getType(JAVA_LANG_FLOAT); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_FLOAT, null, NotFound); case TypeIds.T_double : boxedType = getType(JAVA_LANG_DOUBLE); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_DOUBLE, null, NotFound); case TypeIds.T_boolean : boxedType = getType(JAVA_LANG_BOOLEAN); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_BOOLEAN, null, NotFound); // case TypeIds.T_int : // return getResolvedType(JAVA_LANG_INTEGER, null); // case TypeIds.T_byte : // return getResolvedType(JAVA_LANG_BYTE, null); // case TypeIds.T_short : // return getResolvedType(JAVA_LANG_SHORT, null); // case TypeIds.T_char : // return getResolvedType(JAVA_LANG_CHARACTER, null); // case TypeIds.T_long : // return getResolvedType(JAVA_LANG_LONG, null); // case TypeIds.T_float : // return getResolvedType(JAVA_LANG_FLOAT, null); // case TypeIds.T_double : // return getResolvedType(JAVA_LANG_DOUBLE, null); // case TypeIds.T_boolean : // return getResolvedType(JAVA_LANG_BOOLEAN, null); } // allow indirect unboxing conversion for wildcards and type parameters switch (type.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : case Binding.TYPE_PARAMETER : switch (type.erasure().id) { case TypeIds.T_JavaLangBoolean : return TypeBinding.BOOLEAN; case TypeIds.T_JavaLangByte : return TypeBinding.BYTE; case TypeIds.T_JavaLangCharacter : return TypeBinding.CHAR; case TypeIds.T_JavaLangShort : return TypeBinding.SHORT; case TypeIds.T_JavaLangDouble : return TypeBinding.DOUBLE; case TypeIds.T_JavaLangFloat : return TypeBinding.FLOAT; case TypeIds.T_JavaLangInteger : return TypeBinding.INT; case TypeIds.T_JavaLangLong : return TypeBinding.LONG; } } return type; } private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isMissing) { if (constantPoolName.length == 1) return this.defaultPackage; PackageBinding packageBinding = getPackage0(constantPoolName[0]); if (packageBinding == null || packageBinding == TheNotFoundPackage) { packageBinding = new PackageBinding(constantPoolName[0], this); if (isMissing) packageBinding.tagBits |= TagBits.HasMissingType; this.knownPackages.put(constantPoolName[0], packageBinding); } for (int i = 1, length = constantPoolName.length - 1; i < length; i++) { PackageBinding parent = packageBinding; if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) { packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this); if (isMissing) { packageBinding.tagBits |= TagBits.HasMissingType; } parent.addPackage(packageBinding); } } return packageBinding; } /** * Convert a given source type into a parameterized form if generic. * generic X --> param X */ public ReferenceBinding convertToParameterizedType(ReferenceBinding originalType) { if (originalType != null) { boolean isGeneric = originalType.isGenericType(); ReferenceBinding originalEnclosingType = originalType.enclosingType(); ReferenceBinding convertedEnclosingType = originalEnclosingType; boolean needToConvert = isGeneric; if (originalEnclosingType != null) { convertedEnclosingType = originalType.isStatic() ? (ReferenceBinding) convertToRawType(originalEnclosingType, false /*do not force conversion of enclosing types*/) : convertToParameterizedType(originalEnclosingType); needToConvert |= originalEnclosingType != convertedEnclosingType; } if (needToConvert) { return createParameterizedType(originalType, isGeneric ? originalType.typeVariables() : null, convertedEnclosingType); } } return originalType; } /** * Returns the given binding's raw type binding. * @param type the TypeBinding to raw convert * @param forceRawEnclosingType forces recursive raw conversion of enclosing types (used in Javadoc references only) * @return TypeBinding the raw converted TypeBinding */ public TypeBinding convertToRawType(TypeBinding type, boolean forceRawEnclosingType) { int dimension; TypeBinding originalType; switch(type.kind()) { case Binding.BASE_TYPE : case Binding.TYPE_PARAMETER: case Binding.WILDCARD_TYPE: case Binding.INTERSECTION_TYPE: case Binding.RAW_TYPE: return type; case Binding.ARRAY_TYPE: dimension = type.dimensions(); originalType = type.leafComponentType(); break; default: if (type.id == TypeIds.T_JavaLangObject) return type; // Object is not generic dimension = 0; originalType = type; } boolean needToConvert; switch (originalType.kind()) { case Binding.BASE_TYPE : return type; case Binding.GENERIC_TYPE : needToConvert = true; break; case Binding.PARAMETERIZED_TYPE : ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType; needToConvert = paramType.genericType().isGenericType(); // only recursive call to enclosing type can find parameterizedType with arguments break; default : needToConvert = false; break; } ReferenceBinding originalEnclosing = originalType.enclosingType(); TypeBinding convertedType; if (originalEnclosing == null) { convertedType = needToConvert ? createRawType((ReferenceBinding)originalType.erasure(), null) : originalType; } else { ReferenceBinding convertedEnclosing; if (originalEnclosing.kind() == Binding.RAW_TYPE) { needToConvert |= !((ReferenceBinding)originalType).isStatic(); convertedEnclosing = originalEnclosing; } else if (forceRawEnclosingType && !needToConvert/*stop recursion when conversion occurs*/) { convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing, forceRawEnclosingType); needToConvert = originalEnclosing != convertedEnclosing; // only convert generic or parameterized types } else if (needToConvert || ((ReferenceBinding)originalType).isStatic()) { convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing, false); } else { convertedEnclosing = convertToParameterizedType(originalEnclosing); } if (needToConvert) { convertedType = createRawType((ReferenceBinding) originalType.erasure(), convertedEnclosing); } else if (originalEnclosing != convertedEnclosing) { convertedType = createParameterizedType((ReferenceBinding) originalType.erasure(), null, convertedEnclosing); } else { convertedType = originalType; } } if (originalType != convertedType) { return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType; } return type; } /** * Convert an array of types in raw forms. * Only allocate an array if anything is different. */ public ReferenceBinding[] convertToRawTypes(ReferenceBinding[] originalTypes, boolean forceErasure, boolean forceRawEnclosingType) { if (originalTypes == null) return null; ReferenceBinding[] convertedTypes = originalTypes; for (int i = 0, length = originalTypes.length; i < length; i++) { ReferenceBinding originalType = originalTypes[i]; ReferenceBinding convertedType = (ReferenceBinding) convertToRawType(forceErasure ? originalType.erasure() : originalType, forceRawEnclosingType); if (convertedType != originalType) { if (convertedTypes == originalTypes) { System.arraycopy(originalTypes, 0, convertedTypes = new ReferenceBinding[length], 0, i); } convertedTypes[i] = convertedType; } else if (convertedTypes != originalTypes) { convertedTypes[i] = originalType; } } return convertedTypes; } // variation for unresolved types in binaries (consider generic type as raw) public TypeBinding convertUnresolvedBinaryToRawType(TypeBinding type) { int dimension; TypeBinding originalType; switch(type.kind()) { case Binding.BASE_TYPE : case Binding.TYPE_PARAMETER: case Binding.WILDCARD_TYPE: case Binding.INTERSECTION_TYPE: case Binding.RAW_TYPE: return type; case Binding.ARRAY_TYPE: dimension = type.dimensions(); originalType = type.leafComponentType(); break; default: if (type.id == TypeIds.T_JavaLangObject) return type; // Object is not generic dimension = 0; originalType = type; } boolean needToConvert; switch (originalType.kind()) { case Binding.BASE_TYPE : return type; case Binding.GENERIC_TYPE : needToConvert = true; break; case Binding.PARAMETERIZED_TYPE : ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType; needToConvert = paramType.genericType().isGenericType(); // only recursive call to enclosing type can find parameterizedType with arguments break; default : needToConvert = false; break; } ReferenceBinding originalEnclosing = originalType.enclosingType(); TypeBinding convertedType; if (originalEnclosing == null) { convertedType = needToConvert ? createRawType((ReferenceBinding)originalType.erasure(), null) : originalType; } else { ReferenceBinding convertedEnclosing = (ReferenceBinding) convertUnresolvedBinaryToRawType(originalEnclosing); if (convertedEnclosing != originalEnclosing) { needToConvert |= !((ReferenceBinding)originalType).isStatic(); } if (needToConvert) { convertedType = createRawType((ReferenceBinding) originalType.erasure(), convertedEnclosing); } else if (originalEnclosing != convertedEnclosing) { convertedType = createParameterizedType((ReferenceBinding) originalType.erasure(), null, convertedEnclosing); } else { convertedType = originalType; } } if (originalType != convertedType) { return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType; } return type; } /* * Used to guarantee annotation identity. */ public AnnotationBinding createAnnotation(ReferenceBinding annotationType, ElementValuePair[] pairs) { if (pairs.length != 0) { AnnotationBinding.setMethodBindings(annotationType, pairs); } return new AnnotationBinding(annotationType, pairs); } /* * Used to guarantee array type identity. */ public ArrayBinding createArrayType(TypeBinding leafComponentType, int dimensionCount) { if (leafComponentType instanceof LocalTypeBinding) // cache local type arrays with the local type itself return ((LocalTypeBinding) leafComponentType).createArrayType(dimensionCount, this); // find the array binding cache for this dimension int dimIndex = dimensionCount - 1; int length = this.uniqueArrayBindings.length; ArrayBinding[] arrayBindings; if (dimIndex < length) { if ((arrayBindings = this.uniqueArrayBindings[dimIndex]) == null) this.uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10]; } else { System.arraycopy( this.uniqueArrayBindings, 0, this.uniqueArrayBindings = new ArrayBinding[dimensionCount][], 0, length); this.uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10]; } // find the cached array binding for this leaf component type (if any) int index = -1; length = arrayBindings.length; while (++index < length) { ArrayBinding currentBinding = arrayBindings[index]; if (currentBinding == null) // no matching array, but space left return arrayBindings[index] = new ArrayBinding(leafComponentType, dimensionCount, this); if (currentBinding.leafComponentType == leafComponentType) return currentBinding; } // no matching array, no space left System.arraycopy( arrayBindings, 0, (arrayBindings = new ArrayBinding[length * 2]), 0, length); this.uniqueArrayBindings[dimIndex] = arrayBindings; return arrayBindings[length] = new ArrayBinding(leafComponentType, dimensionCount, this); } public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) { return createBinaryTypeFrom(binaryType, packageBinding, true, accessRestriction); } 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) { // update reference to unresolved binding after having read classfile (knows whether generic for raw conversion) if (cachedType instanceof UnresolvedReferenceBinding) { ((UnresolvedReferenceBinding) cachedType).setResolvedType(binaryBinding, this); } else { if (cachedType.isBinaryBinding()) // sanity check... at this point the cache should ONLY contain unresolved types return (BinaryTypeBinding) cachedType; // it is possible with a large number of source files (exceeding AbstractImageBuilder.MAX_AT_ONCE) that a member type can be in the cache as an UnresolvedType, // but because its enclosingType is resolved while its created (call to BinaryTypeBinding constructor), its replaced with a source type return null; } } packageBinding.addType(binaryBinding); setAccessRestriction(binaryBinding, accessRestriction); // need type annotations before processing methods (for @NonNullByDefault) if (this.globalOptions.isAnnotationBasedNullAnalysisEnabled) binaryBinding.scanTypeForNullDefaultAnnotation(binaryType, packageBinding, binaryBinding); binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods); return binaryBinding; } /* * Used to create types denoting missing types. * If package is given, then reuse the package; if not then infer a package from compound name. * If the package is existing, then install the missing type in type cache */ public MissingTypeBinding createMissingType(PackageBinding packageBinding, char[][] compoundName) { // create a proxy for the missing BinaryType if (packageBinding == null) { packageBinding = computePackageFrom(compoundName, true /* missing */); if (packageBinding == TheNotFoundPackage) packageBinding = this.defaultPackage; } MissingTypeBinding missingType = new MissingTypeBinding(packageBinding, compoundName, this); if (missingType.id != TypeIds.T_JavaLangObject) { // make Object be its superclass - it could in turn be missing as well ReferenceBinding objectType = getType(TypeConstants.JAVA_LANG_OBJECT); if (objectType == null) { objectType = createMissingType(null, TypeConstants.JAVA_LANG_OBJECT); // create a proxy for the missing Object type } missingType.setMissingSuperclass(objectType); } packageBinding.addType(missingType); if (this.missingTypes == null) this.missingTypes = new ArrayList(3); this.missingTypes.add(missingType); return missingType; } /* * 1. Connect the type hierarchy for the type bindings created for parsedUnits. * 2. Create the field bindings * 3. Create the method bindings */ public PackageBinding createPackage(char[][] compoundName) { PackageBinding packageBinding = getPackage0(compoundName[0]); if (packageBinding == null || packageBinding == TheNotFoundPackage) { packageBinding = new PackageBinding(compoundName[0], this); this.knownPackages.put(compoundName[0], packageBinding); } for (int i = 1, length = compoundName.length; i < length; i++) { // check to see if it collides with a known type... // this case can only happen if the package does not exist as a directory in the file system // otherwise when the source type was defined, the correct error would have been reported // unless its an unresolved type which is referenced from an inconsistent class file // NOTE: empty packages are not packages according to changes in JLS v2, 7.4.3 // so not all types cause collision errors when they're created even though the package did exist ReferenceBinding type = packageBinding.getType0(compoundName[i]); if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding)) return null; PackageBinding parent = packageBinding; if ((packageBinding = parent.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) { // if the package is unknown, check to see if a type exists which would collide with the new package // catches the case of a package statement of: package java.lang.Object; // since the package can be added after a set of source files have already been compiled, // we need to check whenever a package is created if (this.nameEnvironment.findType(compoundName[i], parent.compoundName) != null) return null; packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this); parent.addPackage(packageBinding); } } return packageBinding; } public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, RawTypeBinding rawType) { // cached info is array of already created parameterized types for this type ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[])this.uniqueParameterizedGenericMethodBindings.get(genericMethod); boolean needToGrow = false; int index = 0; if (cachedInfo != null){ nextCachedMethod : // iterate existing parameterized for reusing one with same type arguments if any for (int max = cachedInfo.length; index < max; index++){ ParameterizedGenericMethodBinding cachedMethod = cachedInfo[index]; if (cachedMethod == null) break nextCachedMethod; if (!cachedMethod.isRaw) continue nextCachedMethod; if (cachedMethod.declaringClass != (rawType == null ? genericMethod.declaringClass : rawType)) continue nextCachedMethod; return cachedMethod; } needToGrow = true; } else { cachedInfo = new ParameterizedGenericMethodBinding[5]; this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo); } // grow cache ? int length = cachedInfo.length; if (needToGrow && index == length){ System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedGenericMethodBinding[length*2], 0, length); this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo); } // add new binding ParameterizedGenericMethodBinding parameterizedGenericMethod = new ParameterizedGenericMethodBinding(genericMethod, rawType, this); cachedInfo[index] = parameterizedGenericMethod; return parameterizedGenericMethod; } public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, TypeBinding[] typeArguments) { // cached info is array of already created parameterized types for this type ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[])this.uniqueParameterizedGenericMethodBindings.get(genericMethod); int argLength = typeArguments == null ? 0: typeArguments.length; boolean needToGrow = false; int index = 0; if (cachedInfo != null){ nextCachedMethod : // iterate existing parameterized for reusing one with same type arguments if any for (int max = cachedInfo.length; index < max; index++){ ParameterizedGenericMethodBinding cachedMethod = cachedInfo[index]; if (cachedMethod == null) break nextCachedMethod; if (cachedMethod.isRaw) continue nextCachedMethod; TypeBinding[] cachedArguments = cachedMethod.typeArguments; int cachedArgLength = cachedArguments == null ? 0 : cachedArguments.length; if (argLength != cachedArgLength) continue nextCachedMethod; for (int j = 0; j < cachedArgLength; j++){ if (typeArguments[j] != cachedArguments[j]) continue nextCachedMethod; } // all arguments match, reuse current return cachedMethod; } needToGrow = true; } else { cachedInfo = new ParameterizedGenericMethodBinding[5]; this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo); } // grow cache ? int length = cachedInfo.length; if (needToGrow && index == length){ System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedGenericMethodBinding[length*2], 0, length); this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo); } // add new binding ParameterizedGenericMethodBinding parameterizedGenericMethod = new ParameterizedGenericMethodBinding(genericMethod, typeArguments, this); cachedInfo[index] = parameterizedGenericMethod; return parameterizedGenericMethod; } public PolymorphicMethodBinding createPolymorphicMethod(MethodBinding originalPolymorphicMethod, TypeBinding[] parameters) { // cached info is array of already created polymorphic methods for this type String key = new String(originalPolymorphicMethod.selector); PolymorphicMethodBinding[] cachedInfo = (PolymorphicMethodBinding[]) this.uniquePolymorphicMethodBindings.get(key); int parametersLength = parameters == null ? 0: parameters.length; TypeBinding[] parametersTypeBinding = new TypeBinding[parametersLength]; for (int i = 0; i < parametersLength; i++) { TypeBinding parameterTypeBinding = parameters[i]; if (parameterTypeBinding.id == TypeIds.T_null) { parametersTypeBinding[i] = getType(JAVA_LANG_VOID); } else { parametersTypeBinding[i] = parameterTypeBinding.erasure(); } } boolean needToGrow = false; int index = 0; if (cachedInfo != null) { nextCachedMethod : // iterate existing polymorphic method for reusing one with same type arguments if any for (int max = cachedInfo.length; index < max; index++) { PolymorphicMethodBinding cachedMethod = cachedInfo[index]; if (cachedMethod == null) { break nextCachedMethod; } if (cachedMethod.matches(parametersTypeBinding, originalPolymorphicMethod.returnType)) { return cachedMethod; } } needToGrow = true; } else { cachedInfo = new PolymorphicMethodBinding[5]; this.uniquePolymorphicMethodBindings.put(key, cachedInfo); } // grow cache ? int length = cachedInfo.length; if (needToGrow && index == length) { System.arraycopy(cachedInfo, 0, cachedInfo = new PolymorphicMethodBinding[length*2], 0, length); this.uniquePolymorphicMethodBindings.put(key, cachedInfo); } // add new binding PolymorphicMethodBinding polymorphicMethod = new PolymorphicMethodBinding( originalPolymorphicMethod, parametersTypeBinding); cachedInfo[index] = polymorphicMethod; return polymorphicMethod; } public MethodBinding updatePolymorphicMethodReturnType(PolymorphicMethodBinding binding, TypeBinding typeBinding) { // update the return type to be the given return type, but reuse existing binding if one can match String key = new String(binding.selector); PolymorphicMethodBinding[] cachedInfo = (PolymorphicMethodBinding[]) this.uniquePolymorphicMethodBindings.get(key); boolean needToGrow = false; int index = 0; TypeBinding[] parameters = binding.parameters; if (cachedInfo != null) { nextCachedMethod : // iterate existing polymorphic method for reusing one with same type arguments if any for (int max = cachedInfo.length; index < max; index++) { PolymorphicMethodBinding cachedMethod = cachedInfo[index]; if (cachedMethod == null) { break nextCachedMethod; } if (cachedMethod.matches(parameters, typeBinding)) { return cachedMethod; } } needToGrow = true; } else { cachedInfo = new PolymorphicMethodBinding[5]; this.uniquePolymorphicMethodBindings.put(key, cachedInfo); } // grow cache ? int length = cachedInfo.length; if (needToGrow && index == length) { System.arraycopy(cachedInfo, 0, cachedInfo = new PolymorphicMethodBinding[length*2], 0, length); this.uniquePolymorphicMethodBindings.put(key, cachedInfo); } // add new binding PolymorphicMethodBinding polymorphicMethod = new PolymorphicMethodBinding( binding.original(), typeBinding, parameters); cachedInfo[index] = polymorphicMethod; return polymorphicMethod; } public ParameterizedMethodBinding createGetClassMethod(TypeBinding receiverType, MethodBinding originalMethod, Scope scope) { // see if we have already cached this method for the given receiver type. ParameterizedMethodBinding retVal = null; if (this.uniqueGetClassMethodBinding == null) { this.uniqueGetClassMethodBinding = new SimpleLookupTable(3); } else { retVal = (ParameterizedMethodBinding)this.uniqueGetClassMethodBinding.get(receiverType); } if (retVal == null) { retVal = ParameterizedMethodBinding.instantiateGetClass(receiverType, originalMethod, scope); this.uniqueGetClassMethodBinding.put(receiverType, retVal); } return retVal; } public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType) { // 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; int index = 0; if (cachedInfo != null){ nextCachedType : // iterate existing parameterized for reusing one with same type arguments if any for (int max = cachedInfo.length; index < max; index++){ ParameterizedTypeBinding cachedType = cachedInfo[index]; if (cachedType == null) break nextCachedType; if (cachedType.actualType() != 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[5]; this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo); } // grow cache ? int length = cachedInfo.length; if (needToGrow && index == length){ System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedTypeBinding[length*2], 0, length); this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo); } // add new binding ParameterizedTypeBinding parameterizedType = new ParameterizedTypeBinding(genericType,typeArguments, enclosingType, this); cachedInfo[index] = 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; int index = 0; if (cachedInfo != null){ nextCachedType : // iterate existing parameterized for reusing one with same type arguments if any for (int max = cachedInfo.length; index < max; index++){ RawTypeBinding cachedType = cachedInfo[index]; if (cachedType == null) break nextCachedType; if (cachedType.actualType() != 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 ? int length = cachedInfo.length; if (needToGrow && index == length){ System.arraycopy(cachedInfo, 0, cachedInfo = new RawTypeBinding[length*2], 0, length); this.uniqueRawTypeBindings.put(genericType, cachedInfo); } // add new binding RawTypeBinding rawType = new RawTypeBinding(genericType, enclosingType, this); cachedInfo[index] = rawType; return rawType; } public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind) { // cached info is array of already created wildcard types for this type if (genericType == null) // pseudo wildcard denoting composite bounds for lub computation genericType = ReferenceBinding.LUB_GENERIC; WildcardBinding[] cachedInfo = (WildcardBinding[])this.uniqueWildcardBindings.get(genericType); boolean needToGrow = false; int index = 0; if (cachedInfo != null){ nextCachedType : // iterate existing wildcards for reusing one with same information if any for (int max = cachedInfo.length; index < max; index++){ WildcardBinding cachedType = cachedInfo[index]; if (cachedType == null) break nextCachedType; if (cachedType.genericType != genericType) continue nextCachedType; // remain of unresolved type if (cachedType.rank != rank) continue nextCachedType; if (cachedType.boundKind != boundKind) continue nextCachedType; if (cachedType.bound != bound) continue nextCachedType; if (cachedType.otherBounds != otherBounds) { int cachedLength = cachedType.otherBounds == null ? 0 : cachedType.otherBounds.length; int length = otherBounds == null ? 0 : otherBounds.length; if (cachedLength != length) continue nextCachedType; for (int j = 0; j < length; j++) { if (cachedType.otherBounds[j] != otherBounds[j]) continue nextCachedType; } } // all match, reuse current return cachedType; } needToGrow = true; } else { cachedInfo = new WildcardBinding[10]; this.uniqueWildcardBindings.put(genericType, cachedInfo); } // grow cache ? int length = cachedInfo.length; if (needToGrow && index == length){ System.arraycopy(cachedInfo, 0, cachedInfo = new WildcardBinding[length*2], 0, length); this.uniqueWildcardBindings.put(genericType, cachedInfo); } // add new binding WildcardBinding wildcard = new WildcardBinding(genericType, rank, bound, otherBounds, boundKind, this); cachedInfo[index] = 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) { return this.defaultPackage.getType0(compoundName[0]); } PackageBinding packageBinding = getPackage0(compoundName[0]); if (packageBinding == null || packageBinding == TheNotFoundPackage) return null; for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) return null; return packageBinding.getType0(compoundName[compoundName.length - 1]); } public char[][] getNullableAnnotationName() { return this.globalOptions.nullableAnnotationName; } public char[][] getNonNullAnnotationName() { return this.globalOptions.nonNullAnnotationName; } public char[][] getNonNullByDefaultAnnotationName() { return this.globalOptions.nonNullByDefaultAnnotationName; } /* Answer the top level package named name if it exists in the cache. * Answer theNotFoundPackage if it could not be resolved the first time * it was looked up, otherwise answer null. * * NOTE: Senders must convert theNotFoundPackage into a real problem * package if its to returned. */ PackageBinding getPackage0(char[] name) { return this.knownPackages.get(name); } /* Answer the type corresponding to the compoundName. * Ask the name environment for the type if its not in the cache. * Fail with a classpath error if the type cannot be found. */ public ReferenceBinding getResolvedType(char[][] compoundName, Scope scope) { ReferenceBinding type = getType(compoundName); if (type != null) return type; // create a proxy for the missing BinaryType // report the missing class file first this.problemReporter.isClassPathCorrect( compoundName, scope == null ? this.unitBeingCompleted : scope.referenceCompilationUnit(), this.missingClassFileLocation); return createMissingType(null, compoundName); } /* Answer the top level package named name. * Ask the oracle for the package if its not in the cache. * Answer null if the package cannot be found. */ PackageBinding getTopLevelPackage(char[] name) { PackageBinding packageBinding = getPackage0(name); if (packageBinding != null) { if (packageBinding == TheNotFoundPackage) return null; return packageBinding; } if (this.nameEnvironment.isPackage(null, name)) { this.knownPackages.put(name, packageBinding = new PackageBinding(name, this)); return packageBinding; } this.knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time return null; } /* Answer the type corresponding to the compoundName. * Ask the name environment for the type if its not in the cache. * Answer null if the type cannot be found. */ public ReferenceBinding getType(char[][] compoundName) { ReferenceBinding referenceBinding; if (compoundName.length == 1) { if ((referenceBinding = this.defaultPackage.getType0(compoundName[0])) == null) { PackageBinding packageBinding = getPackage0(compoundName[0]); if (packageBinding != null && packageBinding != TheNotFoundPackage) return null; // collides with a known package... should not call this method in such a case referenceBinding = askForType(this.defaultPackage, compoundName[0]); } } else { PackageBinding packageBinding = getPackage0(compoundName[0]); if (packageBinding == TheNotFoundPackage) return null; if (packageBinding != null) { for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) { if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null) break; if (packageBinding == TheNotFoundPackage) return null; } } if (packageBinding == null) referenceBinding = askForType(compoundName); else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null) referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]); } if (referenceBinding == null || referenceBinding == TheNotFoundType) return null; referenceBinding = (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, referenceBinding, InternalNameProvided); return referenceBinding; } private TypeBinding[] getTypeArgumentsFromSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, ReferenceBinding genericType, char[][][] missingTypeNames) { java.util.ArrayList args = new java.util.ArrayList(2); int rank = 0; do { args.add(getTypeFromVariantTypeSignature(wrapper, staticVariables, enclosingType, genericType, rank++, missingTypeNames)); } 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 compound name. * 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. * * NOTE: Does NOT answer base types nor array types! */ private ReferenceBinding getTypeFromCompoundName(char[][] compoundName, boolean isParameterized, boolean wasMissingType) { ReferenceBinding binding = getCachedType(compoundName); if (binding == null) { PackageBinding packageBinding = computePackageFrom(compoundName, false /* valid pkg */); binding = new UnresolvedReferenceBinding(compoundName, packageBinding); if (wasMissingType) { binding.tagBits |= TagBits.HasMissingType; // record it was bound to a missing type } packageBinding.addType(binding); } else if (binding == TheNotFoundType) { // report the missing class file first if (!wasMissingType) { /* Since missing types have been already been complained against while producing binaries, there is no class path * misconfiguration now that did not also exist in some equivalent form while producing the class files which encode * these missing types. So no need to bark again. Note that wasMissingType == true signals a type referenced in a .class * file which could not be found when the binary was produced. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=364450 */ this.problemReporter.isClassPathCorrect(compoundName, this.unitBeingCompleted, this.missingClassFileLocation); } // create a proxy for the missing BinaryType binding = createMissingType(null, compoundName); } else if (!isParameterized) { // check raw type, only for resolved types binding = (ReferenceBinding) convertUnresolvedBinaryToRawType(binding); } return binding; } /* 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. * * NOTE: Does NOT answer base types nor array types! */ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized, char[][][] missingTypeNames) { if (end == -1) end = signature.length; char[][] compoundName = CharOperation.splitOn('/', signature, start, end); boolean wasMissingType = false; if (missingTypeNames != null) { for (int i = 0, max = missingTypeNames.length; i < max; i++) { if (CharOperation.equals(compoundName, missingTypeNames[i])) { wasMissingType = true; break; } } } return getTypeFromCompoundName(compoundName, isParameterized, wasMissingType); } /* Answer the type corresponding to the signature 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. * * NOTE: Does answer base types & array types. */ TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean isParameterized, TypeBinding enclosingType, char[][][] missingTypeNames) { int dimension = 0; while (signature[start] == '[') { start++; dimension++; } if (end == -1) end = signature.length - 1; // Just switch on signature[start] - the L case is the else TypeBinding binding = null; if (start == end) { switch (signature[start]) { case 'I' : binding = TypeBinding.INT; break; case 'Z' : binding = TypeBinding.BOOLEAN; break; case 'V' : binding = TypeBinding.VOID; break; case 'C' : binding = TypeBinding.CHAR; break; case 'D' : binding = TypeBinding.DOUBLE; break; case 'B' : binding = TypeBinding.BYTE; break; case 'F' : binding = TypeBinding.FLOAT; break; case 'J' : binding = TypeBinding.LONG; break; case 'S' : binding = TypeBinding.SHORT; break; default : this.problemReporter.corruptedSignature(enclosingType, signature, start); // will never reach here, since error will cause abort } } else { binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized, missingTypeNames); // skip leading 'L' or 'T' } if (dimension == 0) return binding; return createArrayType(binding, dimension); } public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, char[][][] missingTypeNames) { // 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 { TypeVariableBinding[] enclosingTypeVariables; if (enclosingType instanceof BinaryTypeBinding) { // compiler normal case, no eager resolution of binary variables enclosingTypeVariables = ((BinaryTypeBinding)enclosingType).typeVariables; // do not trigger resolution of variables } else { // codepath only use by codeassist for decoding signatures enclosingTypeVariables = enclosingType.typeVariables(); } for (int i = enclosingTypeVariables.length; --i >= 0;) if (CharOperation.equals(enclosingTypeVariables[i].sourceName, wrapper.signature, varStart, varEnd)) return dimension == 0 ? (TypeBinding) enclosingTypeVariables[i] : createArrayType(enclosingTypeVariables[i], dimension); } while ((enclosingType = enclosingType.enclosingType()) != null); this.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, missingTypeNames); 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; if (actualType instanceof UnresolvedReferenceBinding) if (CharOperation.indexOf('$', actualType.compoundName[actualType.compoundName.length - 1]) > 0) actualType = (ReferenceBinding) BinaryTypeBinding.resolveType(actualType, this, false /* no raw conversion */); // must resolve member types before asking for enclosingType ReferenceBinding actualEnclosing = actualType.enclosingType(); if (actualEnclosing != null) { // convert needed if read some static member type actualEnclosing = (ReferenceBinding) convertToRawType(actualEnclosing, false /*do not force conversion of enclosing types*/); } TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType, missingTypeNames); ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, actualEnclosing); while (wrapper.signature[wrapper.start] == '.') { wrapper.start++; // skip '.' int memberStart = wrapper.start; char[] memberName = wrapper.nextWord(); BinaryTypeBinding.resolveType(parameterizedType, this, false); ReferenceBinding memberType = parameterizedType.genericType().getMemberType(memberName); // need to protect against the member type being null when the signature is invalid if (memberType == null) this.problemReporter.corruptedSignature(parameterizedType, wrapper.signature, memberStart); // aborts if (wrapper.signature[wrapper.start] == '<') { wrapper.start++; // skip '<' typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType, missingTypeNames); } 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, char[][][] missingTypeNames) { // VariantTypeSignature = '-' TypeSignature // or '+' TypeSignature // or TypeSignature // or '*' switch (wrapper.signature[wrapper.start]) { case '-' : // ? super aType wrapper.start++; TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames); return createWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.SUPER); case '+' : // ? extends aType wrapper.start++; bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames); return createWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.EXTENDS); case '*' : // ? wrapper.start++; return createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND); default : return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames); } } boolean isMissingType(char[] typeName) { for (int i = this.missingTypes == null ? 0 : this.missingTypes.size(); --i >= 0;) { MissingTypeBinding missingType = (MissingTypeBinding) this.missingTypes.get(i); if (CharOperation.equals(missingType.sourceName, typeName)) return true; } return false; } /* 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 this.nameEnvironment.isPackage(null, name); return this.nameEnvironment.isPackage(compoundName, name); } // The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready. public MethodVerifier methodVerifier() { if (this.verifier == null) this.verifier = newMethodVerifier(); return this.verifier; } public MethodVerifier newMethodVerifier() { /* Always use MethodVerifier15. Even in a 1.4 project, we must internalize type variables and observe any parameterization of super class and/or super interfaces in order to be able to detect overriding in the presence of generics. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850 */ return new MethodVerifier15(this); } public void releaseClassFiles(org.eclipse.jdt.internal.compiler.ClassFile[] classFiles) { for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) this.classFilePool.release(classFiles[i]); } 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;) { ArrayBinding[] arrayBindings = this.uniqueArrayBindings[i]; if (arrayBindings != null) for (int j = arrayBindings.length; --j >= 0;) arrayBindings[j] = null; } // NOTE: remember to fix #updateCaches(...) when adding unique binding caches this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3); this.uniqueRawTypeBindings = new SimpleLookupTable(3); this.uniqueWildcardBindings = new SimpleLookupTable(3); this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3); this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3); this.uniqueGetClassMethodBinding = null; this.missingTypes = null; this.typesBeingConnected = new HashSet(); 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 this.classFilePool.reset(); // name environment has a longer life cycle, and must be reset in // the code which created it. } /** * 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 |= ExtraCompilerModifiers.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.uniqueRawTypeBindings.get(unresolvedType) != null) { // update the key Object[] keys = this.uniqueRawTypeBindings.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; } } } 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; } } } } public IQualifiedTypeResolutionListener[] resolutionListeners = new IQualifiedTypeResolutionListener[0]; public void addResolutionListener(IQualifiedTypeResolutionListener resolutionListener) { int length = this.resolutionListeners.length; for (int i = 0; i < length; i++){ if (this.resolutionListeners[i].equals(resolutionListener)) return; } System.arraycopy(this.resolutionListeners, 0, this.resolutionListeners = new IQualifiedTypeResolutionListener[length + 1], 0, length); this.resolutionListeners[length] = resolutionListener; } } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding0000644000175000001440000013007312212041344032453 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * Bug 412076 - [compiler] @NonNullByDefault doesn't work for varargs parameter when in generic interface *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.List; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.Wildcard; /** * A parameterized type encapsulates a type with type arguments, */ public class ParameterizedTypeBinding extends ReferenceBinding implements Substitution { private ReferenceBinding type; // must ensure the type is resolved 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; this.enclosingType = enclosingType; // never unresolved, never lazy per construction // if (enclosingType != null && enclosingType.isGenericType()) { // RuntimeException e = new RuntimeException("PARAM TYPE with GENERIC ENCLOSING"); // e.printStackTrace(); // throw e; // } // if (!(type instanceof UnresolvedReferenceBinding) && type.typeVariables() == Binding.NO_TYPE_VARIABLES) { // System.out.println(); // } initialize(type, arguments); if (type instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) type).addWrapper(this, environment); if (arguments != null) { for (int i = 0, l = arguments.length; i < l; i++) if (arguments[i] instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) arguments[i]).addWrapper(this, environment); } this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve() } /** * May return an UnresolvedReferenceBinding. * @see ParameterizedTypeBinding#genericType() */ protected ReferenceBinding actualType() { return this.type; } /** * Iterate type arguments, and validate them according to corresponding variable bounds. */ public void boundCheck(Scope scope, TypeReference[] argumentReferences) { if ((this.tagBits & TagBits.PassedBoundCheck) == 0) { boolean hasErrors = false; TypeVariableBinding[] typeVariables = this.type.typeVariables(); if (this.arguments != null && typeVariables != null) { // arguments may be null in error cases for (int i = 0, length = typeVariables.length; i < length; i++) { if (typeVariables[i].boundCheck(this, this.arguments[i], scope) != TypeConstants.OK) { hasErrors = true; if ((this.arguments[i].tagBits & TagBits.HasMissingType) == 0) { // do not report secondary error, if type reference already got complained against scope.problemReporter().typeMismatchError(this.arguments[i], typeVariables[i], this.type, argumentReferences[i]); } } } } if (!hasErrors) this.tagBits |= TagBits.PassedBoundCheck; // no need to recheck it in the future } } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated() */ public boolean canBeInstantiated() { return ((this.tagBits & TagBits.HasDirectWildcard) == 0) && super.canBeInstantiated(); // cannot instantiate param type with wildcard arguments } /** * Perform capture conversion for a parameterized type with wildcard arguments * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#capture(Scope,int) */ public TypeBinding capture(Scope scope, int position) { if ((this.tagBits & TagBits.HasDirectWildcard) == 0) return this; TypeBinding[] originalArguments = this.arguments; int length = originalArguments.length; TypeBinding[] capturedArguments = new TypeBinding[length]; // Retrieve the type context for capture bindingKey ReferenceBinding contextType = scope.enclosingSourceType(); if (contextType != null) contextType = contextType.outermostEnclosingType(); // maybe null when used programmatically by DOM for (int i = 0; i < length; i++) { TypeBinding argument = originalArguments[i]; if (argument.kind() == Binding.WILDCARD_TYPE) { // no capture for intersection types capturedArguments[i] = new CaptureBinding((WildcardBinding) argument, contextType, position, scope.compilationUnitScope().nextCaptureID()); } else { capturedArguments[i] = argument; } } ParameterizedTypeBinding capturedParameterizedType = this.environment.createParameterizedType(this.type, capturedArguments, enclosingType()); for (int i = 0; i < length; i++) { TypeBinding argument = capturedArguments[i]; if (argument.isCapture()) { ((CaptureBinding)argument).initializeBounds(scope, capturedParameterizedType); } } return capturedParameterizedType; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List) */ public List collectMissingTypes(List missingTypes) { if ((this.tagBits & TagBits.HasMissingType) != 0) { if (this.enclosingType != null) { missingTypes = this.enclosingType.collectMissingTypes(missingTypes); } missingTypes = genericType().collectMissingTypes(missingTypes); if (this.arguments != null) { for (int i = 0, max = this.arguments.length; i < max; i++) { missingTypes = this.arguments[i].collectMissingTypes(missingTypes); } } } return missingTypes; } /** * Collect the substitutes into a map for certain type variables inside the receiver type * e.g. Collection.collectSubstitutes(Collection>, Map), will populate Map with: T --> List * Constraints: * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1)) * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0)) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2)) */ public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { if ((this.tagBits & TagBits.HasTypeVariable) == 0) { TypeBinding actualEquivalent = actualType.findSuperTypeOriginatingFrom(this.type); if (actualEquivalent != null && actualEquivalent.isRawType()) { inferenceContext.isUnchecked = true; } return; } if (actualType == TypeBinding.NULL) return; if (!(actualType instanceof ReferenceBinding)) return; TypeBinding formalEquivalent, actualEquivalent; switch (constraint) { case TypeConstants.CONSTRAINT_EQUAL : case TypeConstants.CONSTRAINT_EXTENDS : formalEquivalent = this; actualEquivalent = actualType.findSuperTypeOriginatingFrom(this.type); if (actualEquivalent == null) return; break; case TypeConstants.CONSTRAINT_SUPER : default: formalEquivalent = this.findSuperTypeOriginatingFrom(actualType); if (formalEquivalent == null) return; actualEquivalent = actualType; break; } // collect through enclosing type ReferenceBinding formalEnclosingType = formalEquivalent.enclosingType(); if (formalEnclosingType != null) { formalEnclosingType.collectSubstitutes(scope, actualEquivalent.enclosingType(), inferenceContext, constraint); } // collect through type arguments if (this.arguments == null) return; TypeBinding[] formalArguments; switch (formalEquivalent.kind()) { case Binding.GENERIC_TYPE : formalArguments = formalEquivalent.typeVariables(); break; case Binding.PARAMETERIZED_TYPE : formalArguments = ((ParameterizedTypeBinding)formalEquivalent).arguments; break; case Binding.RAW_TYPE : if (inferenceContext.depth > 0) { inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference } return; default : return; } TypeBinding[] actualArguments; switch (actualEquivalent.kind()) { case Binding.GENERIC_TYPE : actualArguments = actualEquivalent.typeVariables(); break; case Binding.PARAMETERIZED_TYPE : actualArguments = ((ParameterizedTypeBinding)actualEquivalent).arguments; break; case Binding.RAW_TYPE : if (inferenceContext.depth > 0) { inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference } else { inferenceContext.isUnchecked = true; } return; default : return; } inferenceContext.depth++; for (int i = 0, length = formalArguments.length; i < length; i++) { TypeBinding formalArgument = formalArguments[i]; TypeBinding actualArgument = actualArguments[i]; if (formalArgument.isWildcard()) { formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, constraint); continue; } else if (actualArgument.isWildcard()){ WildcardBinding actualWildcardArgument = (WildcardBinding) actualArgument; if (actualWildcardArgument.otherBounds == null) { if (constraint == TypeConstants.CONSTRAINT_SUPER) { // JLS 15.12.7, p.459 switch(actualWildcardArgument.boundKind) { case Wildcard.EXTENDS : formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); continue; case Wildcard.SUPER : formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); continue; default : continue; // cannot infer anything further from unbound wildcard } } else { continue; // cannot infer anything further from wildcard } } } // by default, use EQUAL constraint formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); } inferenceContext.depth--; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#computeId() */ public void computeId() { this.id = TypeIds.NoId; } public char[] computeUniqueKey(boolean isLeaf) { StringBuffer sig = new StringBuffer(10); ReferenceBinding enclosing; if (isMemberType() && ((enclosing = enclosingType()).isParameterizedType() || enclosing.isRawType())) { char[] typeSig = enclosing.computeUniqueKey(false/*not a leaf*/); sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon sig.append('.').append(sourceName()); } else if(this.type.isLocalType()){ LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.type; enclosing = localTypeBinding.enclosingType(); ReferenceBinding temp; while ((temp = enclosing.enclosingType()) != null) enclosing = temp; char[] typeSig = enclosing.computeUniqueKey(false/*not a leaf*/); sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon sig.append('$'); sig.append(localTypeBinding.sourceStart); } else { char[] typeSig = this.type.computeUniqueKey(false/*not a leaf*/); sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon } ReferenceBinding captureSourceType = null; if (this.arguments != null) { sig.append('<'); for (int i = 0, length = this.arguments.length; i < length; i++) { TypeBinding typeBinding = this.arguments[i]; sig.append(typeBinding.computeUniqueKey(false/*not a leaf*/)); if (typeBinding instanceof CaptureBinding) captureSourceType = ((CaptureBinding) typeBinding).sourceType; } sig.append('>'); } sig.append(';'); if (captureSourceType != null && captureSourceType != this.type) { // contains a capture binding sig.insert(0, "&"); //$NON-NLS-1$ sig.insert(0, captureSourceType.computeUniqueKey(false/*not a leaf*/)); } int sigLength = sig.length(); char[] uniqueKey = new char[sigLength]; sig.getChars(0, sigLength, uniqueKey, 0); return uniqueKey; } /** * @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); } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName() */ public String debugName() { StringBuffer nameBuffer = new StringBuffer(10); if (this.type instanceof UnresolvedReferenceBinding) { nameBuffer.append(this.type); } 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].debugName()); } nameBuffer.append('>'); } return nameBuffer.toString(); } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#enclosingType() */ public ReferenceBinding enclosingType() { return this.enclosingType; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#environment() */ public LookupEnvironment environment() { return this.environment; } /** * @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.tagBits & TagBits.AreFieldsComplete) != 0) return this.fields; 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 = Binding.NO_FIELDS; this.tagBits |= TagBits.AreFieldsComplete; } return this.fields; } /** * Return the original generic type from which the parameterized type got instantiated from. * This will perform lazy resolution automatically if needed. * @see ParameterizedTypeBinding#actualType() if no resolution is required (unlikely) */ public ReferenceBinding genericType() { if (this.type instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) this.type).resolve(this.environment, false); return this.type; } /** * Ltype; * LY; */ public char[] genericTypeSignature() { if (this.genericTypeSignature == null) { if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) { this.genericTypeSignature = this.type.signature(); } else { StringBuffer sig = new StringBuffer(10); if (isMemberType()) { ReferenceBinding enclosing = enclosingType(); char[] typeSig = enclosing.genericTypeSignature(); sig.append(typeSig, 0, typeSig.length-1);// copy all but trailing semicolon if ((enclosing.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) { sig.append('.'); } else { sig.append('$'); } sig.append(sourceName()); } else { char[] typeSig = this.type.signature(); sig.append(typeSig, 0, typeSig.length-1);// 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('>'); } 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#getAnnotationTagBits() */ public long getAnnotationTagBits() { return this.type.getAnnotationTagBits(); } public int getEnclosingInstancesSlotSize() { return genericType().getEnclosingInstancesSlotSize(); } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactConstructor(TypeBinding[]) */ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) { int argCount = argumentTypes.length; MethodBinding match = null; if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods long range; if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) { nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; if (method.parameters.length == argCount) { TypeBinding[] toMatch = method.parameters; for (int iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) continue nextMethod; if (match != null) return null; // collision case match = method; } } } } else { MethodBinding[] matchingMethods = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods 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; } } } return match; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactMethod(char[], TypeBinding[],CompilationUnitScope) */ public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) { // sender from refScope calls recordTypeReference(this) int argCount = argumentTypes.length; boolean foundNothing = true; MethodBinding match = null; if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; 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 iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) 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 == Binding.NO_METHODS; 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) { // cannot be picked up as an exact match if its a possible anonymous case, such as: // class A { public void id(T t) {} } // class B extends A { public void id(Integer i) {} } if (match.hasSubstitutedParameters()) return null; return match; } if (foundNothing && (this.arguments == null || this.arguments.length <= 1)) { if (isInterface()) { if (superInterfaces().length == 1) { if (refScope != null) refScope.recordTypeReference(this.superInterfaces[0]); return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope); } } else if (superclass() != null) { if (refScope != null) refScope.recordTypeReference(this.superclass); return this.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 return ReferenceBinding.binarySearch(fieldName, this.fields); } /** * @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) { if (this.methods != null) { long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { int start = (int) range; int length = (int) (range >> 32) - start + 1; // cannot optimize since some clients rely on clone array // if (start == 0 && length == this.methods.length) // return this.methods; // current set is already interesting subset MethodBinding[] result; System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length); return result; } } if ((this.tagBits & TagBits.AreMethodsComplete) != 0) return Binding.NO_METHODS; // 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 Binding.NO_METHODS; 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 { int total = length + this.methods.length; MethodBinding[] temp = new MethodBinding[total]; System.arraycopy(parameterizedMethods, 0, temp, 0, length); System.arraycopy(this.methods, 0, temp, length, this.methods.length); if (total > 1) ReferenceBinding.sortMethods(temp, 0, total); // resort to ensure order is good 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 = Binding.NO_METHODS; } } public int getOuterLocalVariablesSlotSize() { return genericType().getOuterLocalVariablesSlotSize(); } public boolean hasMemberTypes() { return this.type.hasMemberTypes(); } public boolean hasTypeBit(int bit) { TypeBinding erasure = erasure(); if (erasure instanceof ReferenceBinding) return ((ReferenceBinding) erasure).hasTypeBit(bit); return false; } /** * @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 & ~ExtraCompilerModifiers.AccGenericSignature; // discard generic signature, will compute later // only set AccGenericSignature if parameterized or have enclosing type required signature if (someArguments != null) { this.modifiers |= ExtraCompilerModifiers.AccGenericSignature; } else if (this.enclosingType != null) { this.modifiers |= (this.enclosingType.modifiers & ExtraCompilerModifiers.AccGenericSignature); this.tagBits |= this.enclosingType.tagBits & (TagBits.HasTypeVariable | TagBits.HasMissingType); } if (someArguments != null) { this.arguments = someArguments; for (int i = 0, length = someArguments.length; i < length; i++) { TypeBinding someArgument = someArguments[i]; switch (someArgument.kind()) { case Binding.WILDCARD_TYPE : this.tagBits |= TagBits.HasDirectWildcard; if (((WildcardBinding) someArgument).boundKind != Wildcard.UNBOUND) { this.tagBits |= TagBits.IsBoundParameterizedType; } break; case Binding.INTERSECTION_TYPE : this.tagBits |= TagBits.HasDirectWildcard | TagBits.IsBoundParameterizedType; // Surely NOT X, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=366131 break; default : this.tagBits |= TagBits.IsBoundParameterizedType; break; } this.tagBits |= someArgument.tagBits & (TagBits.HasTypeVariable | TagBits.HasMissingType | TagBits.ContainsNestedTypeReferences); } } this.tagBits |= someType.tagBits & (TagBits.IsLocalType| TagBits.IsMemberType | TagBits.IsNestedType | TagBits.ContainsNestedTypeReferences | TagBits.HasMissingType | TagBits.AnnotationNonNullByDefault | TagBits.AnnotationNullUnspecifiedByDefault); this.tagBits &= ~(TagBits.AreFieldsComplete|TagBits.AreMethodsComplete); } protected void initializeArguments() { // do nothing for true parameterized types (only for raw types) } void initializeForStaticImports() { this.type.initializeForStaticImports(); } public boolean isEquivalentTo(TypeBinding otherType) { if (this == otherType) return true; if (otherType == null) return false; switch(otherType.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE: return ((WildcardBinding) otherType).boundCheck(this); case Binding.PARAMETERIZED_TYPE : 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) { ReferenceBinding otherEnclosing = otherParamType.enclosingType(); if (otherEnclosing == null) return false; if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) { if (enclosing != otherEnclosing) return false; } else { if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false; } } } if (this.arguments == null) { return otherParamType.arguments == null; } int length = this.arguments.length; TypeBinding[] otherArguments = otherParamType.arguments; if (otherArguments == null || otherArguments.length != 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(); } /* With the hybrid 1.4/1.5+ projects modes, while establishing type equivalence, we need to be prepared for a type such as Map appearing in one of three forms: As (a) a ParameterizedTypeBinding e.g Map, (b) as RawTypeBinding Map#RAW and finally (c) as a BinaryTypeBinding When the usage of a type lacks type parameters, whether we land up with the raw form or not depends on whether the underlying type was "seen to be" a generic type in the particular build environment or not. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=328827 */ if (erasure() == otherType) { return true; } return false; } public boolean isHierarchyConnected() { return this.superclass != null && this.superInterfaces != null; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#isRawSubstitution() */ public boolean isRawSubstitution() { return isRawType(); } public int kind() { return PARAMETERIZED_TYPE; } /** * @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]; // boolean isRaw = this.isRawType(); for (int i = 0; i < length; i++) // substitute all member types, so as to get updated enclosing types parameterizedMemberTypes[i] = /*isRaw && originalMemberTypes[i].isGenericType() ? this.environment.createRawType(originalMemberTypes[i], this) : */ 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 = Binding.NO_MEMBER_TYPES; } } return this.memberTypes; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#methods() */ public MethodBinding[] methods() { if ((this.tagBits & TagBits.AreMethodsComplete) != 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 = Binding.NO_METHODS; this.tagBits |= TagBits.AreMethodsComplete; } return this.methods; } /** * Define to be able to get the computeId() for the inner type binding. * * @see org.eclipse.jdt.internal.compiler.lookup.Binding#problemId() */ public int problemId() { return this.type.problemId(); } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedPackageName() */ public char[] qualifiedPackageName() { return this.type.qualifiedPackageName(); } /** * @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 (isMemberType()) { nameBuffer.append(CharOperation.concat(enclosingType().readableName(), this.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() { if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0) return this; this.tagBits &= ~TagBits.HasUnresolvedTypeVariables; // can be recursive so only want to call once ReferenceBinding resolvedType = (ReferenceBinding) BinaryTypeBinding.resolveType(this.type, this.environment, false /* no raw conversion */); // still part of parameterized type ref this.tagBits |= resolvedType.tagBits & TagBits.ContainsNestedTypeReferences; if (this.arguments != null) { int argLength = this.arguments.length; for (int i = 0; i < argLength; i++) { TypeBinding resolveType = BinaryTypeBinding.resolveType(this.arguments[i], this.environment, true /* raw conversion */); this.arguments[i] = resolveType; this.tagBits |= resolvedType.tagBits & TagBits.ContainsNestedTypeReferences; } /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=186565, Removed generic check and arity check since we are dealing with binary types here and the fact that the compiler produced class files for these types at all is proof positive that the generic check and the arity check passed in the build environment that produced these class files. Otherwise we don't handle mixed 1.5 and 1.4 projects correctly. Just as with bounds check below, incremental build will propagate the change and detect problems in source. */ // // arity check // TypeVariableBinding[] refTypeVariables = resolvedType.typeVariables(); // if (refTypeVariables == Binding.NO_TYPE_VARIABLES) { // check generic // // Below 1.5, we should have already complained about the use of type parameters. // boolean isCompliant15 = this.environment.globalOptions.originalSourceLevel >= ClassFileConstants.JDK1_5; // if (isCompliant15 && (resolvedType.tagBits & TagBits.HasMissingType) == 0) { // this.environment.problemReporter.nonGenericTypeCannotBeParameterized(0, null, resolvedType, this.arguments); // } // return this; // } 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... REMOVED for now since incremental build will propagate change & detect in source // for (int i = 0; i < argLength; i++) { // TypeBinding resolvedArgument = this.arguments[i]; // if (refTypeVariables[i].boundCheck(this, resolvedArgument) != TypeConstants.OK) { // 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 (isMemberType()) { nameBuffer.append(CharOperation.concat(enclosingType().shortReadableName(), this.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(); } /** * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#substitute(org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding) */ public TypeBinding substitute(TypeVariableBinding originalVariable) { 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(); // only for raw types if (currentType.arguments != null) { if (currentType.arguments.length == 0) { // diamond type return originalVariable; } return currentType.arguments[originalVariable.rank]; } } // recurse on enclosing type, as it may hold more substitutions to perform if (currentType.isStatic()) break; ReferenceBinding enclosing = currentType.enclosingType(); if (!(enclosing instanceof ParameterizedTypeBinding)) break; currentType = (ParameterizedTypeBinding) enclosing; } return originalVariable; } /** * @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) Scope.substitute(this, genericSuperclass); } return this.superclass; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces() */ public ReferenceBinding[] superInterfaces() { if (this.superInterfaces == null) { if (this.type.isHierarchyBeingConnected()) return Binding.NO_SUPERINTERFACES; // prevent superinterfaces from being assigned before they are connected 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; ReferenceBinding enclosing = resolvedType.enclosingType(); if (enclosing != null) { this.enclosingType = (ReferenceBinding) env.convertUnresolvedBinaryToRawType(enclosing); // needed when binding unresolved member type } } if (this.arguments != null) { for (int i = 0, l = this.arguments.length; i < l; i++) { if (this.arguments[i] == unresolvedType) { this.arguments[i] = env.convertUnresolvedBinaryToRawType(resolvedType); update = true; } } } if (update) initialize(this.type, this.arguments); } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticEnclosingInstanceTypes() */ public ReferenceBinding[] syntheticEnclosingInstanceTypes() { return genericType().syntheticEnclosingInstanceTypes(); } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticOuterLocalVariables() */ public SyntheticArgumentBinding[] syntheticOuterLocalVariables() { return genericType().syntheticOuterLocalVariables(); } /** * @see java.lang.Object#toString() */ public String toString() { StringBuffer buffer = new StringBuffer(30); if (this.type instanceof UnresolvedReferenceBinding) { buffer.append(debugName()); } else { 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$ if (isEnum()) buffer.append("enum "); //$NON-NLS-1$ else if (isAnnotationType()) buffer.append("@interface "); //$NON-NLS-1$ else if (isClass()) buffer.append("class "); //$NON-NLS-1$ else buffer.append("interface "); //$NON-NLS-1$ buffer.append(debugName()); buffer.append("\n\textends "); //$NON-NLS-1$ buffer.append((this.superclass != null) ? this.superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$ if (this.superInterfaces != null) { if (this.superInterfaces != Binding.NO_SUPERINTERFACES) { buffer.append("\n\timplements : "); //$NON-NLS-1$ for (int i = 0, length = this.superInterfaces.length; i < length; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append((this.superInterfaces[i] != null) ? this.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 (this.fields != null) { if (this.fields != Binding.NO_FIELDS) { buffer.append("\n/* fields */"); //$NON-NLS-1$ for (int i = 0, length = this.fields.length; i < length; i++) buffer.append('\n').append((this.fields[i] != null) ? this.fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$ } } else { buffer.append("NULL FIELDS"); //$NON-NLS-1$ } if (this.methods != null) { if (this.methods != Binding.NO_METHODS) { buffer.append("\n/* methods */"); //$NON-NLS-1$ for (int i = 0, length = this.methods.length; i < length; i++) buffer.append('\n').append((this.methods[i] != null) ? this.methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ } } else { buffer.append("NULL METHODS"); //$NON-NLS-1$ } // if (memberTypes != null) { // if (memberTypes != NoMemberTypes) { // buffer.append("\n/* members */"); // for (int i = 0, length = memberTypes.length; i < length; i++) // buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE"); // } // } else { // buffer.append("NULL MEMBER TYPES"); // } 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 Binding.NO_TYPE_VARIABLES; } public FieldBinding[] unResolvedFields() { return this.fields; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/Substitution.java0000644000175000001440000000200712212041344031151 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; /* * Encapsulates aspects related to type variable substitution */ public interface Substitution { /** * Returns the type substitute for a given type variable, or itself * if no substitution got performed. */ TypeBinding substitute(TypeVariableBinding typeVariable); /** * Returns the lookup environment */ LookupEnvironment environment(); /** * Returns true for raw substitution */ boolean isRawSubstitution(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java0000644000175000001440000017233012212041344032025 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 364890 - BinaryTypeBinding should use char constants from Util * bug 365387 - [compiler][null] bug 186342: Issues to follow up post review and verification. * bug 358903 - Filter practically unimportant resource leak warnings * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 331649 - [compiler][null] consider null annotations for fields *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.ArrayList; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.*; import org.eclipse.jdt.internal.compiler.impl.BooleanConstant; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.Util; /* Not all fields defined by this type are initialized when it is created. Some are initialized only when needed. Accessors have been provided for some public fields so all TypeBindings have the same API... but access public fields directly whenever possible. Non-public fields have accessors which should be used everywhere you expect the field to be initialized. null is NOT a valid value for a non-public field... it just means the field is not initialized. */ public class BinaryTypeBinding extends ReferenceBinding { // all of these fields are ONLY guaranteed to be initialized if accessed using their public accessor method protected ReferenceBinding superclass; protected ReferenceBinding enclosingType; protected ReferenceBinding[] superInterfaces; protected FieldBinding[] fields; protected MethodBinding[] methods; protected ReferenceBinding[] memberTypes; protected TypeVariableBinding[] typeVariables; // For the link with the principle structure protected LookupEnvironment environment; protected SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder static Object convertMemberValue(Object binaryValue, LookupEnvironment env, char[][][] missingTypeNames) { if (binaryValue == null) return null; if (binaryValue instanceof Constant) return binaryValue; if (binaryValue instanceof ClassSignature) return env.getTypeFromSignature(((ClassSignature) binaryValue).getTypeName(), 0, -1, false, null, missingTypeNames); if (binaryValue instanceof IBinaryAnnotation) return createAnnotation((IBinaryAnnotation) binaryValue, env, missingTypeNames); if (binaryValue instanceof EnumConstantSignature) { EnumConstantSignature ref = (EnumConstantSignature) binaryValue; ReferenceBinding enumType = (ReferenceBinding) env.getTypeFromSignature(ref.getTypeName(), 0, -1, false, null, missingTypeNames); enumType = (ReferenceBinding) resolveType(enumType, env, false /* no raw conversion */); return enumType.getField(ref.getEnumConstantName(), false); } if (binaryValue instanceof Object[]) { Object[] objects = (Object[]) binaryValue; int length = objects.length; if (length == 0) return objects; Object[] values = new Object[length]; for (int i = 0; i < length; i++) values[i] = convertMemberValue(objects[i], env, missingTypeNames); return values; } // should never reach here. throw new IllegalStateException(); } static AnnotationBinding createAnnotation(IBinaryAnnotation annotationInfo, LookupEnvironment env, char[][][] missingTypeNames) { IBinaryElementValuePair[] binaryPairs = annotationInfo.getElementValuePairs(); int length = binaryPairs == null ? 0 : binaryPairs.length; ElementValuePair[] pairs = length == 0 ? Binding.NO_ELEMENT_VALUE_PAIRS : new ElementValuePair[length]; for (int i = 0; i < length; i++) pairs[i] = new ElementValuePair(binaryPairs[i].getName(), convertMemberValue(binaryPairs[i].getValue(), env, missingTypeNames), null); char[] typeName = annotationInfo.getTypeName(); ReferenceBinding annotationType = env.getTypeFromConstantPoolName(typeName, 1, typeName.length - 1, false, missingTypeNames); return new UnresolvedAnnotationBinding(annotationType, pairs, env); } public static AnnotationBinding[] createAnnotations(IBinaryAnnotation[] annotationInfos, LookupEnvironment env, char[][][] missingTypeNames) { int length = annotationInfos == null ? 0 : annotationInfos.length; AnnotationBinding[] result = length == 0 ? Binding.NO_ANNOTATIONS : new AnnotationBinding[length]; for (int i = 0; i < length; i++) result[i] = createAnnotation(annotationInfos[i], env, missingTypeNames); return result; } public static TypeBinding resolveType(TypeBinding type, LookupEnvironment environment, boolean convertGenericToRawType) { switch (type.kind()) { case Binding.PARAMETERIZED_TYPE : ((ParameterizedTypeBinding) type).resolve(); break; case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : return ((WildcardBinding) type).resolve(); case Binding.ARRAY_TYPE : resolveType(((ArrayBinding) type).leafComponentType, environment, convertGenericToRawType); break; case Binding.TYPE_PARAMETER : ((TypeVariableBinding) type).resolve(); break; case Binding.GENERIC_TYPE : if (convertGenericToRawType) // raw reference to generic ? return environment.convertUnresolvedBinaryToRawType(type); break; default: if (type instanceof UnresolvedReferenceBinding) return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType); if (convertGenericToRawType) // raw reference to generic ? return environment.convertUnresolvedBinaryToRawType(type); break; } return type; } /** * Default empty constructor for subclasses only. */ protected BinaryTypeBinding() { // only for subclasses } /** * Standard constructor for creating binary type bindings from binary models (classfiles) * @param packageBinding * @param binaryType * @param environment */ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) { this.compoundName = CharOperation.splitOn('/', binaryType.getName()); computeId(); this.tagBits |= TagBits.IsBinaryBinding; this.environment = environment; this.fPackage = packageBinding; this.fileName = binaryType.getFileName(); /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, even in a 1.4 project, we must internalize type variables and observe any parameterization of super class and/or super interfaces in order to be able to detect overriding in the presence of generics. */ char[] typeSignature = binaryType.getGenericSignature(); this.typeVariables = typeSignature != null && typeSignature.length > 0 && typeSignature[0] == Util.C_GENERIC_START ? null // is initialized in cachePartsFrom (called from LookupEnvironment.createBinaryTypeFrom())... must set to null so isGenericType() answers true : Binding.NO_TYPE_VARIABLES; this.sourceName = binaryType.getSourceName(); this.modifiers = binaryType.getModifiers(); if ((binaryType.getTagBits() & TagBits.HierarchyHasProblems) != 0) this.tagBits |= TagBits.HierarchyHasProblems; if (binaryType.isAnonymous()) { this.tagBits |= TagBits.AnonymousTypeMask; } else if (binaryType.isLocal()) { this.tagBits |= TagBits.LocalTypeMask; } else if (binaryType.isMember()) { this.tagBits |= TagBits.MemberTypeMask; } // 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, true, null /* could not be missing */); // pretend parameterized to avoid raw this.tagBits |= TagBits.MemberTypeMask; // must be a member type not a top-level or local type this.tagBits |= TagBits.HasUnresolvedEnclosingType; if (enclosingType().isStrictfp()) this.modifiers |= ClassFileConstants.AccStrictfp; if (enclosingType().isDeprecated()) this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; } } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#availableMethods() */ public FieldBinding[] availableFields() { if ((this.tagBits & TagBits.AreFieldsComplete) != 0) return this.fields; // lazily sort fields if ((this.tagBits & TagBits.AreFieldsSorted) == 0) { int length = this.fields.length; if (length > 1) ReferenceBinding.sortFields(this.fields, 0, length); this.tagBits |= TagBits.AreFieldsSorted; } FieldBinding[] availableFields = new FieldBinding[this.fields.length]; int count = 0; for (int i = 0; i < this.fields.length; i++) { try { availableFields[count] = resolveTypeFor(this.fields[i]); count++; } catch (AbortCompilation a){ // silent abort } } if (count < availableFields.length) System.arraycopy(availableFields, 0, availableFields = new FieldBinding[count], 0, count); return availableFields; } private TypeVariableBinding[] addMethodTypeVariables(TypeVariableBinding[] methodTypeVars) { if (this.typeVariables == null || this.typeVariables == Binding.NO_TYPE_VARIABLES) { return methodTypeVars; } if (methodTypeVars == null || methodTypeVars == Binding.NO_TYPE_VARIABLES) { return this.typeVariables; } // uniq-merge both the arrays int total = this.typeVariables.length + methodTypeVars.length; TypeVariableBinding[] combinedTypeVars = new TypeVariableBinding[total]; System.arraycopy(this.typeVariables, 0, combinedTypeVars, 0, this.typeVariables.length); int size = this.typeVariables.length; loop: for (int i = 0, len = methodTypeVars.length; i < len; i++) { for (int j = this.typeVariables.length -1 ; j >= 0; j--) { if (CharOperation.equals(methodTypeVars[i].sourceName, this.typeVariables[j].sourceName)) continue loop; } combinedTypeVars[size++] = methodTypeVars[i]; } if (size != total) { System.arraycopy(combinedTypeVars, 0, combinedTypeVars = new TypeVariableBinding[size], 0, size); } return combinedTypeVars; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#availableMethods() */ public MethodBinding[] availableMethods() { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) return this.methods; // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } MethodBinding[] availableMethods = new MethodBinding[this.methods.length]; int count = 0; for (int i = 0; i < this.methods.length; i++) { try { availableMethods[count] = resolveTypesFor(this.methods[i]); count++; } catch (AbortCompilation a){ // silent abort } } if (count < availableMethods.length) System.arraycopy(availableMethods, 0, availableMethods = new MethodBinding[count], 0, count); return availableMethods; } void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) { try { // 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 = Binding.NO_TYPE_VARIABLES; this.superInterfaces = Binding.NO_SUPERINTERFACES; // must retrieve member types in case superclass/interfaces need them this.memberTypes = Binding.NO_MEMBER_TYPES; IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes(); if (memberTypeStructures != null) { int size = memberTypeStructures.length; if (size > 0) { 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] = this.environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false, null /* could not be missing */); } this.tagBits |= TagBits.HasUnresolvedMemberTypes; } } long sourceLevel = this.environment.globalOptions.originalSourceLevel; /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, even in a 1.4 project, we must internalize type variables and observe any parameterization of super class and/or super interfaces in order to be able to detect overriding in the presence of generics. */ char[] typeSignature = binaryType.getGenericSignature(); // use generic signature even in 1.4 this.tagBits |= binaryType.getTagBits(); char[][][] missingTypeNames = binaryType.getMissingTypeNames(); SignatureWrapper wrapper = null; if (typeSignature != null) { // ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature wrapper = new SignatureWrapper(typeSignature); if (wrapper.signature[wrapper.start] == Util.C_GENERIC_START) { // ParameterPart = '<' ParameterSignature(s) '>' wrapper.start++; // skip '<' this.typeVariables = createTypeVariables(wrapper, true, missingTypeNames); wrapper.start++; // skip '>' this.tagBits |= TagBits.HasUnresolvedTypeVariables; this.modifiers |= ExtraCompilerModifiers.AccGenericSignature; } } TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES; char[] methodDescriptor = binaryType.getEnclosingMethod(); if (methodDescriptor != null) { MethodBinding enclosingMethod = findMethod(methodDescriptor, missingTypeNames); if (enclosingMethod != null) { typeVars = enclosingMethod.typeVariables; this.typeVariables = addMethodTypeVariables(typeVars); } } 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 = this.environment.getTypeFromConstantPoolName(superclassName, 0, -1, false, missingTypeNames); this.tagBits |= TagBits.HasUnresolvedSuperclass; } this.superInterfaces = Binding.NO_SUPERINTERFACES; 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] = this.environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false, missingTypeNames); this.tagBits |= TagBits.HasUnresolvedSuperinterfaces; } } } else { // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested) this.superclass = (ReferenceBinding) this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames); this.tagBits |= TagBits.HasUnresolvedSuperclass; this.superInterfaces = Binding.NO_SUPERINTERFACES; 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(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames)); } while (!wrapper.atEnd()); this.superInterfaces = new ReferenceBinding[types.size()]; types.toArray(this.superInterfaces); this.tagBits |= TagBits.HasUnresolvedSuperinterfaces; } } if (needFieldsAndMethods) { createFields(binaryType.getFields(), sourceLevel, missingTypeNames); createMethods(binaryType.getMethods(), sourceLevel, missingTypeNames); boolean isViewedAsDeprecated = isViewedAsDeprecated(); if (isViewedAsDeprecated) { for (int i = 0, max = this.fields.length; i < max; i++) { FieldBinding field = this.fields[i]; if (!field.isDeprecated()) { field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; } } for (int i = 0, max = this.methods.length; i < max; i++) { MethodBinding method = this.methods[i]; if (!method.isDeprecated()) { method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; } } } } if (this.environment.globalOptions.storeAnnotations) setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames)); } finally { // protect against incorrect use of the needFieldsAndMethods flag, see 48459 if (this.fields == null) this.fields = Binding.NO_FIELDS; if (this.methods == null) this.methods = Binding.NO_METHODS; } } private void createFields(IBinaryField[] iFields, long sourceLevel, char[][][] missingTypeNames) { this.fields = Binding.NO_FIELDS; if (iFields != null) { int size = iFields.length; if (size > 0) { this.fields = new FieldBinding[size]; boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5; boolean hasRestrictedAccess = hasRestrictedAccess(); int firstAnnotatedFieldIndex = -1; for (int i = 0; i < size; i++) { IBinaryField binaryField = iFields[i]; char[] fieldSignature = use15specifics ? binaryField.getGenericSignature() : null; TypeBinding type = fieldSignature == null ? this.environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this, missingTypeNames) : this.environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), Binding.NO_TYPE_VARIABLES, this, missingTypeNames); FieldBinding field = new FieldBinding( binaryField.getName(), type, binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved, this, binaryField.getConstant()); if (firstAnnotatedFieldIndex < 0 && this.environment.globalOptions.storeAnnotations && binaryField.getAnnotations() != null) { firstAnnotatedFieldIndex = i; } field.id = i; // ordinal if (use15specifics) field.tagBits |= binaryField.getTagBits(); if (hasRestrictedAccess) field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; if (fieldSignature != null) field.modifiers |= ExtraCompilerModifiers.AccGenericSignature; this.fields[i] = field; } // second pass for reifying annotations, since may refer to fields being constructed (147875) if (firstAnnotatedFieldIndex >= 0) { for (int i = firstAnnotatedFieldIndex; i = ClassFileConstants.JDK1_5; /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, Since a 1.4 project can have a 1.5 type as a super type and the 1.5 type could be generic, we must internalize usages of type variables properly in order to be able to apply substitutions and thus be able to detect overriding in the presence of generics. Seeing the erased form is not good enough. */ char[] methodSignature = method.getGenericSignature(); // always use generic signature, even in 1.4 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]) != Util.C_PARAM_END) { if (nextChar != Util.C_ARRAY) { numOfParams++; if (nextChar == Util.C_RESOLVED) while ((nextChar = methodDescriptor[++index]) != Util.C_NAME_END){/*empty*/} } } // Ignore synthetic argument for member types or enum types. int startIndex = 0; if (method.isConstructor()) { if (isMemberType() && !isStatic()) { // enclosing type startIndex++; } if (isEnum()) { // synthetic arguments (String, int) startIndex += 2; } } int size = numOfParams - startIndex; if (size > 0) { parameters = new TypeBinding[size]; if (this.environment.globalOptions.storeAnnotations) paramAnnotations = new AnnotationBinding[size][]; index = 1; int end = 0; // first character is always '(' so skip it for (int i = 0; i < numOfParams; i++) { while ((nextChar = methodDescriptor[++end]) == Util.C_ARRAY){/*empty*/} if (nextChar == Util.C_RESOLVED) while ((nextChar = methodDescriptor[++end]) != Util.C_NAME_END){/*empty*/} if (i >= startIndex) { // skip the synthetic arg if necessary parameters[i - startIndex] = this.environment.getTypeFromSignature(methodDescriptor, index, end, false, this, missingTypeNames); // 'paramAnnotations' line up with 'parameters' // int parameter to method.getParameterAnnotations() include the synthetic arg if (paramAnnotations != null) paramAnnotations[i - startIndex] = createAnnotations(method.getParameterAnnotations(i - startIndex), this.environment, missingTypeNames); } index = end + 1; } } 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] = this.environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false, missingTypeNames); } } if (!method.isConstructor()) returnType = this.environment.getTypeFromSignature(methodDescriptor, index + 1, -1, false, this, missingTypeNames); // index is currently pointing at the ')' } else { methodModifiers |= ExtraCompilerModifiers.AccGenericSignature; // MethodTypeSignature = ParameterPart(optional) '(' TypeSignatures ')' return_typeSignature ['^' TypeSignature (optional)] SignatureWrapper wrapper = new SignatureWrapper(methodSignature, use15specifics); if (wrapper.signature[wrapper.start] == Util.C_GENERIC_START) { // (Ljava/lang/Class;)TA; // ParameterPart = '<' ParameterSignature(s) '>' wrapper.start++; // skip '<' typeVars = createTypeVariables(wrapper, false, missingTypeNames); wrapper.start++; // skip '>' } if (wrapper.signature[wrapper.start] == Util.C_PARAM_START) { wrapper.start++; // skip '(' if (wrapper.signature[wrapper.start] == Util.C_PARAM_END) { wrapper.start++; // skip ')' } else { java.util.ArrayList types = new java.util.ArrayList(2); while (wrapper.signature[wrapper.start] != Util.C_PARAM_END) types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames)); wrapper.start++; // skip ')' int numParam = types.size(); parameters = new TypeBinding[numParam]; types.toArray(parameters); if (this.environment.globalOptions.storeAnnotations) { paramAnnotations = new AnnotationBinding[numParam][]; for (int i = 0; i < numParam; i++) paramAnnotations[i] = createAnnotations(method.getParameterAnnotations(i), this.environment, missingTypeNames); } } } // always retrieve return type (for constructors, its V for void - will be ignored) returnType = this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames); if (!wrapper.atEnd() && wrapper.signature[wrapper.start] == Util.C_EXCEPTION_START) { // attempt to find each exception 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(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames)); } while (!wrapper.atEnd() && wrapper.signature[wrapper.start] == Util.C_EXCEPTION_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] = this.environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false, missingTypeNames); } } } } MethodBinding result = method.isConstructor() ? new MethodBinding(methodModifiers, parameters, exceptions, this) : new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this); if (this.environment.globalOptions.storeAnnotations) result.setAnnotations( createAnnotations(method.getAnnotations(), this.environment, missingTypeNames), paramAnnotations, isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames) : null, this.environment); 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; scanMethodForNullAnnotation(method, result); return result; } /** * Create method bindings for binary type, filtering out and synthetics */ private void createMethods(IBinaryMethod[] iMethods, long sourceLevel, char[][][] missingTypeNames) { int total = 0, initialTotal = 0, iClinit = -1; int[] toSkip = null; if (iMethods != null) { total = initialTotal = iMethods.length; boolean keepBridgeMethods = sourceLevel < ClassFileConstants.JDK1_5; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=330347 for (int i = total; --i >= 0;) { IBinaryMethod method = iMethods[i]; if ((method.getModifiers() & ClassFileConstants.AccSynthetic) != 0) { if (keepBridgeMethods && (method.getModifiers() & ClassFileConstants.AccBridge) != 0) continue; // want to see bridge methods as real methods // discard synthetics methods if (toSkip == null) toSkip = new int[iMethods.length]; toSkip[i] = -1; total--; } else if (iClinit == -1) { char[] methodName = method.getSelector(); if (methodName.length == 8 && methodName[0] == Util.C_GENERIC_START) { // discard iClinit = i; total--; } } } } if (total == 0) { this.methods = Binding.NO_METHODS; return; } boolean hasRestrictedAccess = hasRestrictedAccess(); this.methods = new MethodBinding[total]; if (total == initialTotal) { for (int i = 0; i < initialTotal; i++) { MethodBinding method = createMethod(iMethods[i], sourceLevel, missingTypeNames); if (hasRestrictedAccess) method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; this.methods[i] = method; } } else { for (int i = 0, index = 0; i < initialTotal; i++) { if (iClinit != i && (toSkip == null || toSkip[i] != -1)) { MethodBinding method = createMethod(iMethods[i], sourceLevel, missingTypeNames); if (hasRestrictedAccess) method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; this.methods[index++] = method; } } } } private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, boolean assignVariables, char[][][] missingTypeNames) { // 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 Util.C_GENERIC_START : depth++; break; case Util.C_GENERIC_END : if (--depth < 0) break createVariables; break; case Util.C_NAME_END : if ((depth == 0) && (i +1 < length) && (typeSignature[i+1] != Util.C_COLON)) pendingVariable = true; break; default: if (pendingVariable) { pendingVariable = false; int colon = CharOperation.indexOf(Util.C_COLON, typeSignature, i); char[] variableName = CharOperation.subarray(typeSignature, i, colon); variables.add(new TypeVariableBinding(variableName, this, rank++, this.environment)); } } } } // initialize type variable bounds - may refer to forward variables TypeVariableBinding[] result; variables.toArray(result = new TypeVariableBinding[rank]); // when creating the type variables for a type, the type must remember them before initializing each variable // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=163680 if (assignVariables) this.typeVariables = result; for (int i = 0; i < rank; i++) { initializeTypeVariable(result[i], result, wrapper, missingTypeNames); } 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 ((this.tagBits & TagBits.HasUnresolvedEnclosingType) == 0) return this.enclosingType; // finish resolving the type this.enclosingType = (ReferenceBinding) resolveType(this.enclosingType, this.environment, false /* no raw conversion */); this.tagBits &= ~TagBits.HasUnresolvedEnclosingType; return this.enclosingType; } // NOTE: the type of each field of a binary type is resolved when needed public FieldBinding[] fields() { if ((this.tagBits & TagBits.AreFieldsComplete) != 0) return this.fields; // lazily sort fields if ((this.tagBits & TagBits.AreFieldsSorted) == 0) { int length = this.fields.length; if (length > 1) ReferenceBinding.sortFields(this.fields, 0, length); this.tagBits |= TagBits.AreFieldsSorted; } for (int i = this.fields.length; --i >= 0;) resolveTypeFor(this.fields[i]); this.tagBits |= TagBits.AreFieldsComplete; return this.fields; } private MethodBinding findMethod(char[] methodDescriptor, char[][][] missingTypeNames) { int index = -1; while (methodDescriptor[++index] != Util.C_PARAM_START) { // empty } char[] selector = new char[index]; System.arraycopy(methodDescriptor, 0, selector, 0, index); TypeBinding[] parameters = Binding.NO_PARAMETERS; int numOfParams = 0; char nextChar; int paramStart = index; while ((nextChar = methodDescriptor[++index]) != Util.C_PARAM_END) { if (nextChar != Util.C_ARRAY) { numOfParams++; if (nextChar == Util.C_RESOLVED) while ((nextChar = methodDescriptor[++index]) != Util.C_NAME_END){/*empty*/} } } if (numOfParams > 0) { parameters = new TypeBinding[numOfParams]; index = paramStart + 1; int end = paramStart; // first character is always '(' so skip it for (int i = 0; i < numOfParams; i++) { while ((nextChar = methodDescriptor[++end]) == Util.C_ARRAY){/*empty*/} if (nextChar == Util.C_RESOLVED) while ((nextChar = methodDescriptor[++end]) != Util.C_NAME_END){/*empty*/} TypeBinding param = this.environment.getTypeFromSignature(methodDescriptor, index, end, false, this, missingTypeNames); if (param instanceof UnresolvedReferenceBinding) { param = resolveType(param, this.environment, true /* raw conversion */); } parameters[i] = param; index = end + 1; } } int parameterLength = parameters.length; MethodBinding[] methods2 = this.enclosingType.getMethods(selector, parameterLength); // find matching method using parameters loop: for (int i = 0, max = methods2.length; i < max; i++) { MethodBinding currentMethod = methods2[i]; TypeBinding[] parameters2 = currentMethod.parameters; int currentMethodParameterLength = parameters2.length; if (parameterLength == currentMethodParameterLength) { for (int j = 0; j < currentMethodParameterLength; j++) { if (parameters[j] != parameters2[j] && parameters[j].erasure() != parameters2[j].erasure()) { continue loop; } } return currentMethod; } } return null; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature() */ public char[] genericTypeSignature() { return computeGenericTypeSignature(this.typeVariables); } //NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) { // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } int argCount = argumentTypes.length; long range; if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) { nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; if (method.parameters.length == argCount) { resolveTypesFor(method); TypeBinding[] toMatch = method.parameters; for (int iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) continue nextMethod; return method; } } } return null; } //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, CompilationUnitScope refScope) { // sender from refScope calls recordTypeReference(this) // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } int argCount = argumentTypes.length; boolean foundNothing = true; long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; foundNothing = false; // inner type lookups must know that a method with this name exists if (method.parameters.length == argCount) { resolveTypesFor(method); TypeBinding[] toMatch = method.parameters; for (int iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) continue nextMethod; return method; } } } if (foundNothing) { if (isInterface()) { if (superInterfaces().length == 1) { // ensure superinterfaces are resolved before checking if (refScope != null) refScope.recordTypeReference(this.superInterfaces[0]); return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope); } } else if (superclass() != null) { // ensure superclass is resolved before checking if (refScope != null) refScope.recordTypeReference(this.superclass); return this.superclass.getExactMethod(selector, argumentTypes, refScope); } } return null; } //NOTE: the type of a field of a binary type is resolved when needed public FieldBinding getField(char[] fieldName, boolean needResolve) { // lazily sort fields if ((this.tagBits & TagBits.AreFieldsSorted) == 0) { int length = this.fields.length; if (length > 1) ReferenceBinding.sortFields(this.fields, 0, length); this.tagBits |= TagBits.AreFieldsSorted; } FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields); return needResolve && field != null ? resolveTypeFor(field) : field; } /** * Rewrite of default getMemberType to avoid resolving eagerly all member types when one is requested */ public ReferenceBinding getMemberType(char[] typeName) { for (int i = this.memberTypes.length; --i >= 0;) { ReferenceBinding memberType = this.memberTypes[i]; if (memberType instanceof UnresolvedReferenceBinding) { char[] name = memberType.sourceName; // source name is qualified with enclosing type name 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] = (ReferenceBinding) resolveType(memberType, this.environment, false /* no raw conversion for now */); } else if (CharOperation.equals(typeName, memberType.sourceName)) { return memberType; } } return null; } // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed public MethodBinding[] getMethods(char[] selector) { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { int start = (int) range, end = (int) (range >> 32); int length = end - start + 1; if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // simply clone method subset MethodBinding[] result; System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length); return result; } } return Binding.NO_METHODS; } // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { int start = (int) range, end = (int) (range >> 32); int length = end - start + 1; MethodBinding[] result = new MethodBinding[length]; // iterate methods to resolve them for (int i = start, index = 0; i <= end; i++, index++) result[index] = resolveTypesFor(this.methods[i]); return result; } return Binding.NO_METHODS; } // Answer methods named selector, which take no more than the suggestedParameterLength. // The suggested parameter length is optional and may not be guaranteed by every type. public MethodBinding[] getMethods(char[] selector, int suggestedParameterLength) { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) return getMethods(selector); // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { int start = (int) range, end = (int) (range >> 32); int length = end - start + 1; int count = 0; for (int i = start; i <= end; i++) { int len = this.methods[i].parameters.length; if (len <= suggestedParameterLength || (this.methods[i].isVarargs() && len == suggestedParameterLength + 1)) count++; } if (count == 0) { MethodBinding[] result = new MethodBinding[length]; // iterate methods to resolve them for (int i = start, index = 0; i <= end; i++) result[index++] = resolveTypesFor(this.methods[i]); return result; } else { MethodBinding[] result = new MethodBinding[count]; // iterate methods to resolve them for (int i = start, index = 0; i <= end; i++) { int len = this.methods[i].parameters.length; if (len <= suggestedParameterLength || (this.methods[i].isVarargs() && len == suggestedParameterLength + 1)) result[index++] = resolveTypesFor(this.methods[i]); } return result; } } return Binding.NO_METHODS; } public boolean hasMemberTypes() { return this.memberTypes.length > 0; } // NOTE: member types of binary types are resolved when needed public TypeVariableBinding getTypeVariable(char[] variableName) { TypeVariableBinding variable = super.getTypeVariable(variableName); variable.resolve(); return variable; } public boolean hasTypeBit(int bit) { // ensure hierarchy is resolved, which will propagate bits down to us boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType; this.environment.mayTolerateMissingType = true; try { superclass(); superInterfaces(); } finally { this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; } return (this.typeBits & bit) != 0; } private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames) { // ParameterSignature = Identifier ':' TypeSignature // or Identifier ':' TypeSignature(optional) InterfaceBound(s) // InterfaceBound = ':' TypeSignature int colon = CharOperation.indexOf(Util.C_COLON, wrapper.signature, wrapper.start); wrapper.start = colon + 1; // skip name + ':' ReferenceBinding type, firstBound = null; if (wrapper.signature[wrapper.start] == Util.C_COLON) { type = this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); } else { TypeBinding typeFromTypeSignature = this.environment.getTypeFromTypeSignature(wrapper, existingVariables, this, missingTypeNames); if (typeFromTypeSignature instanceof ReferenceBinding) { type = (ReferenceBinding) typeFromTypeSignature; } else { // this should only happen if the signature is corrupted (332423) type = this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); } firstBound = type; } // variable is visible to its bounds variable.modifiers |= ExtraCompilerModifiers.AccUnresolved; variable.superclass = type; ReferenceBinding[] bounds = null; if (wrapper.signature[wrapper.start] == Util.C_COLON) { java.util.ArrayList types = new java.util.ArrayList(2); do { wrapper.start++; // skip ':' types.add(this.environment.getTypeFromTypeSignature(wrapper, existingVariables, this, missingTypeNames)); } while (wrapper.signature[wrapper.start] == Util.C_COLON); bounds = new ReferenceBinding[types.size()]; types.toArray(bounds); } variable.superInterfaces = bounds == null ? Binding.NO_SUPERINTERFACES : bounds; if (firstBound == null) { firstBound = variable.superInterfaces.length == 0 ? null : variable.superInterfaces[0]; } 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 : case Binding.INTERSECTION_TYPE : return ((WildcardBinding) otherType).boundCheck(this); case Binding.PARAMETERIZED_TYPE: /* With the hybrid 1.4/1.5+ projects modes, while establishing type equivalence, we need to be prepared for a type such as Map appearing in one of three forms: As (a) a ParameterizedTypeBinding e.g Map, (b) as RawTypeBinding Map#RAW and finally (c) as a BinaryTypeBinding When the usage of a type lacks type parameters, whether we land up with the raw form or not depends on whether the underlying type was "seen to be" a generic type in the particular build environment or not. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=186565 && https://bugs.eclipse.org/bugs/show_bug.cgi?id=328827 */ case Binding.RAW_TYPE : return otherType.erasure() == this; } return false; } public boolean isGenericType() { return this.typeVariables != Binding.NO_TYPE_VARIABLES; } public boolean isHierarchyConnected() { return (this.tagBits & (TagBits.HasUnresolvedSuperclass | TagBits.HasUnresolvedSuperinterfaces)) == 0; } public int kind() { if (this.typeVariables != Binding.NO_TYPE_VARIABLES) return Binding.GENERIC_TYPE; return Binding.TYPE; } // NOTE: member types of binary types are resolved when needed public ReferenceBinding[] memberTypes() { if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0) return this.memberTypes; for (int i = this.memberTypes.length; --i >= 0;) this.memberTypes[i] = (ReferenceBinding) resolveType(this.memberTypes[i], this.environment, false /* no raw conversion for now */); this.tagBits &= ~TagBits.HasUnresolvedMemberTypes; return this.memberTypes; } // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed public MethodBinding[] methods() { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) return this.methods; // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } for (int i = this.methods.length; --i >= 0;) resolveTypesFor(this.methods[i]); this.tagBits |= TagBits.AreMethodsComplete; return this.methods; } private FieldBinding resolveTypeFor(FieldBinding field) { if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return field; TypeBinding resolvedType = resolveType(field.type, this.environment, true /* raw conversion */); field.type = resolvedType; if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { field.tagBits |= TagBits.HasMissingType; } field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; return field; } MethodBinding resolveTypesFor(MethodBinding method) { if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return method; if (!method.isConstructor()) { TypeBinding resolvedType = resolveType(method.returnType, this.environment, true /* raw conversion */); method.returnType = resolvedType; if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } } for (int i = method.parameters.length; --i >= 0;) { TypeBinding resolvedType = resolveType(method.parameters[i], this.environment, true /* raw conversion */); method.parameters[i] = resolvedType; if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } } for (int i = method.thrownExceptions.length; --i >= 0;) { ReferenceBinding resolvedType = (ReferenceBinding) resolveType(method.thrownExceptions[i], this.environment, true /* raw conversion */); method.thrownExceptions[i] = resolvedType; if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } } for (int i = method.typeVariables.length; --i >= 0;) { method.typeVariables[i].resolve(); } method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; return method; } AnnotationBinding[] retrieveAnnotations(Binding binding) { return AnnotationBinding.addStandardAnnotations(super.retrieveAnnotations(binding), binding.getAnnotationTagBits(), this.environment); } SimpleLookupTable storedAnnotations(boolean forceInitialize) { if (forceInitialize && this.storedAnnotations == null) { if (!this.environment.globalOptions.storeAnnotations) return null; // not supported during this compile this.storedAnnotations = new SimpleLookupTable(3); } return this.storedAnnotations; } void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBinding) { // global option is checked by caller char[][] nullableAnnotationName = this.environment.getNullableAnnotationName(); char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName(); if (nullableAnnotationName == null || nonNullAnnotationName == null) return; // not well-configured to use null annotations if (fieldBinding.type == null || fieldBinding.type.isBaseType()) return; // null annotations are only applied to reference types boolean explicitNullness = false; IBinaryAnnotation[] annotations = field.getAnnotations(); if (annotations != null) { for (int i = 0; i < annotations.length; i++) { char[] annotationTypeName = annotations[i].getTypeName(); if (annotationTypeName[0] != Util.C_RESOLVED) continue; char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';' if (CharOperation.equals(typeName, nonNullAnnotationName)) { fieldBinding.tagBits |= TagBits.AnnotationNonNull; explicitNullness = true; break; } if (CharOperation.equals(typeName, nullableAnnotationName)) { fieldBinding.tagBits |= TagBits.AnnotationNullable; explicitNullness = true; break; } } } if (!explicitNullness && (this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) { fieldBinding.tagBits |= TagBits.AnnotationNonNull; } } void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding) { if (!this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) return; char[][] nullableAnnotationName = this.environment.getNullableAnnotationName(); char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName(); char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName(); if (nullableAnnotationName == null || nonNullAnnotationName == null || nonNullByDefaultAnnotationName == null) return; // not well-configured to use null annotations // return: IBinaryAnnotation[] annotations = method.getAnnotations(); boolean explicitNullness = false; if (annotations != null) { for (int i = 0; i < annotations.length; i++) { char[] annotationTypeName = annotations[i].getTypeName(); if (annotationTypeName[0] != Util.C_RESOLVED) continue; char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';' if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) { methodBinding.tagBits |= TagBits.AnnotationNonNullByDefault; } if (!explicitNullness && CharOperation.equals(typeName, nonNullAnnotationName)) { methodBinding.tagBits |= TagBits.AnnotationNonNull; explicitNullness = true; } if (!explicitNullness && CharOperation.equals(typeName, nullableAnnotationName)) { methodBinding.tagBits |= TagBits.AnnotationNullable; explicitNullness = true; } } } // parameters: TypeBinding[] parameters = methodBinding.parameters; int numVisibleParams = parameters.length; int numParamAnnotations = method.getAnnotatedParametersCount(); if (numParamAnnotations > 0) { for (int j = 0; j < numVisibleParams; j++) { if (numParamAnnotations > 0) { int startIndex = numParamAnnotations - numVisibleParams; IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j+startIndex); if (paramAnnotations != null) { for (int i = 0; i < paramAnnotations.length; i++) { char[] annotationTypeName = paramAnnotations[i].getTypeName(); if (annotationTypeName[0] != Util.C_RESOLVED) continue; char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';' if (CharOperation.equals(typeName, nonNullAnnotationName)) { if (methodBinding.parameterNonNullness == null) methodBinding.parameterNonNullness = new Boolean[numVisibleParams]; methodBinding.parameterNonNullness[j] = Boolean.TRUE; break; } else if (CharOperation.equals(typeName, nullableAnnotationName)) { if (methodBinding.parameterNonNullness == null) methodBinding.parameterNonNullness = new Boolean[numVisibleParams]; methodBinding.parameterNonNullness[j] = Boolean.FALSE; break; } } } } } } } void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBinding packageBinding, BinaryTypeBinding binaryBinding) { char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName(); if (nonNullByDefaultAnnotationName == null) return; // not well-configured to use null annotations IBinaryAnnotation[] annotations = binaryType.getAnnotations(); boolean isPackageInfo = CharOperation.equals(binaryBinding.sourceName(), TypeConstants.PACKAGE_INFO_NAME); if (annotations != null) { long annotationBit = 0L; int nullness = NO_NULL_DEFAULT; int length = annotations.length; for (int i = 0; i < length; i++) { char[] annotationTypeName = annotations[i].getTypeName(); if (annotationTypeName[0] != Util.C_RESOLVED) continue; char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';' if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) { IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs(); if (elementValuePairs != null && elementValuePairs.length == 1) { Object value = elementValuePairs[0].getValue(); if (value instanceof BooleanConstant && !((BooleanConstant)value).booleanValue()) { // parameter is 'false': this means we cancel defaults from outer scopes: annotationBit = TagBits.AnnotationNullUnspecifiedByDefault; nullness = NULL_UNSPECIFIED_BY_DEFAULT; break; } } annotationBit = TagBits.AnnotationNonNullByDefault; nullness = NONNULL_BY_DEFAULT; break; } } if (annotationBit != 0L) { binaryBinding.tagBits |= annotationBit; if (isPackageInfo) packageBinding.defaultNullness = nullness; return; } } if (isPackageInfo) { // no default annotations found in package-info packageBinding.defaultNullness = Binding.NULL_UNSPECIFIED_BY_DEFAULT; return; } ReferenceBinding enclosingTypeBinding = binaryBinding.enclosingType; if (enclosingTypeBinding != null) { if ((enclosingTypeBinding.tagBits & TagBits.AnnotationNonNullByDefault) != 0) { binaryBinding.tagBits |= TagBits.AnnotationNonNullByDefault; return; } else if ((enclosingTypeBinding.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) { binaryBinding.tagBits |= TagBits.AnnotationNullUnspecifiedByDefault; return; } } // no annotation found on the type or its enclosing types // check the package-info for default annotation if not already done before if (packageBinding.defaultNullness == Binding.NO_NULL_DEFAULT && !isPackageInfo) { // this will scan the annotations in package-info ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME); if (packageInfo == null) { packageBinding.defaultNullness = Binding.NULL_UNSPECIFIED_BY_DEFAULT; } } // no @NonNullByDefault at type level, check containing package: switch (packageBinding.defaultNullness) { case Binding.NONNULL_BY_DEFAULT : binaryBinding.tagBits |= TagBits.AnnotationNonNullByDefault; break; case Binding.NULL_UNSPECIFIED_BY_DEFAULT : binaryBinding.tagBits |= TagBits.AnnotationNullUnspecifiedByDefault; break; } } /* 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 ((this.tagBits & TagBits.HasUnresolvedSuperclass) == 0) return this.superclass; // finish resolving the type this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true /* raw conversion */); this.tagBits &= ~TagBits.HasUnresolvedSuperclass; if (this.superclass.problemId() == ProblemReasons.NotFound) { this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency } else { // make super-type resolving recursive for propagating typeBits downwards boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType; this.environment.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164 try { this.superclass.superclass(); this.superclass.superInterfaces(); } finally { this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; } } this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! this.typeBits |= applyCloseableWhitelists(); return this.superclass; } // NOTE: superInterfaces of binary types are resolved when needed public ReferenceBinding[] superInterfaces() { if ((this.tagBits & TagBits.HasUnresolvedSuperinterfaces) == 0) return this.superInterfaces; for (int i = this.superInterfaces.length; --i >= 0;) { this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */); if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) { this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency } else { // make super-type resolving recursive for propagating typeBits downwards boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType; this.environment.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164 try { this.superInterfaces[i].superclass(); this.superInterfaces[i].superInterfaces(); } finally { this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; } } this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); } this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces; return this.superInterfaces; } public TypeVariableBinding[] typeVariables() { if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0) return this.typeVariables; for (int i = this.typeVariables.length; --i >= 0;) this.typeVariables[i].resolve(); this.tagBits &= ~TagBits.HasUnresolvedTypeVariables; return this.typeVariables; } public String toString() { StringBuffer buffer = new StringBuffer(); 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$ if (isEnum()) buffer.append("enum "); //$NON-NLS-1$ else if (isAnnotationType()) buffer.append("@interface "); //$NON-NLS-1$ else if (isClass()) buffer.append("class "); //$NON-NLS-1$ else buffer.append("interface "); //$NON-NLS-1$ buffer.append((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$ if (this.typeVariables == null) { buffer.append(""); //$NON-NLS-1$ } else if (this.typeVariables != Binding.NO_TYPE_VARIABLES) { buffer.append("<"); //$NON-NLS-1$ for (int i = 0, length = this.typeVariables.length; i < length; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ if (this.typeVariables[i] == null) { buffer.append("NULL TYPE VARIABLE"); //$NON-NLS-1$ continue; } char[] varChars = this.typeVariables[i].toString().toCharArray(); buffer.append(varChars, 1, varChars.length - 2); } buffer.append(">"); //$NON-NLS-1$ } buffer.append("\n\textends "); //$NON-NLS-1$ buffer.append((this.superclass != null) ? this.superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$ if (this.superInterfaces != null) { if (this.superInterfaces != Binding.NO_SUPERINTERFACES) { buffer.append("\n\timplements : "); //$NON-NLS-1$ for (int i = 0, length = this.superInterfaces.length; i < length; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append((this.superInterfaces[i] != null) ? this.superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$ } } } else { buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$ } if (this.enclosingType != null) { buffer.append("\n\tenclosing type : "); //$NON-NLS-1$ buffer.append(this.enclosingType.debugName()); } if (this.fields != null) { if (this.fields != Binding.NO_FIELDS) { buffer.append("\n/* fields */"); //$NON-NLS-1$ for (int i = 0, length = this.fields.length; i < length; i++) buffer.append((this.fields[i] != null) ? "\n" + this.fields[i].toString() : "\nNULL FIELD"); //$NON-NLS-1$ //$NON-NLS-2$ } } else { buffer.append("NULL FIELDS"); //$NON-NLS-1$ } if (this.methods != null) { if (this.methods != Binding.NO_METHODS) { buffer.append("\n/* methods */"); //$NON-NLS-1$ for (int i = 0, length = this.methods.length; i < length; i++) buffer.append((this.methods[i] != null) ? "\n" + this.methods[i].toString() : "\nNULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$ } } else { buffer.append("NULL METHODS"); //$NON-NLS-1$ } if (this.memberTypes != null) { if (this.memberTypes != Binding.NO_MEMBER_TYPES) { buffer.append("\n/* members */"); //$NON-NLS-1$ for (int i = 0, length = this.memberTypes.length; i < length; i++) buffer.append((this.memberTypes[i] != null) ? "\n" + this.memberTypes[i].toString() : "\nNULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$ } } else { buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$ } buffer.append("\n\n\n"); //$NON-NLS-1$ return buffer.toString(); } MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types return this.methods; } public FieldBinding[] unResolvedFields() { return this.fields; } } ././@LongLink0000644000000000000000000000015512251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBind0000644000175000001440000000472212212041344032501 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; public class UnresolvedAnnotationBinding extends AnnotationBinding { private LookupEnvironment env; private boolean typeUnresolved = true; UnresolvedAnnotationBinding(ReferenceBinding type, ElementValuePair[] pairs, LookupEnvironment env) { super(type, pairs); this.env = env; } public ReferenceBinding getAnnotationType() { if (this.typeUnresolved) { // the type is resolved when requested boolean wasToleratingMissingTypeProcessingAnnotations = this.env.mayTolerateMissingType; this.env.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=388042 try { this.type = (ReferenceBinding) BinaryTypeBinding.resolveType(this.type, this.env, false /* no raw conversion for now */); // annotation types are never parameterized } finally { this.env.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; } this.typeUnresolved = false; } return this.type; } public ElementValuePair[] getElementValuePairs() { if (this.env != null) { if (this.typeUnresolved) { getAnnotationType(); // resolve the annotation type } // resolve method binding and value type (if unresolved) for each pair for (int i = this.pairs.length; --i >= 0;) { ElementValuePair pair = this.pairs[i]; MethodBinding[] methods = this.type.getMethods(pair.getName()); // there should be exactly one since the type is an annotation type. if (methods != null && methods.length == 1) { pair.setMethodBinding(methods[0]); } // else silently leave a null there Object value = pair.getValue(); if (value instanceof UnresolvedReferenceBinding) { pair.setValue(((UnresolvedReferenceBinding) value). resolve(this.env, false)); // no parameterized types in annotation values } // do nothing for UnresolvedAnnotationBinding-s, since their // content is only accessed through get* methods } this.env = null; } return this.pairs; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java0000644000175000001440000002404712212041344031016 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.List; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; public final class ArrayBinding extends TypeBinding { // creation and initialization of the length field // the declaringClass of this field is intentionally set to null so it can be distinguished. public static final FieldBinding ArrayLength = new FieldBinding(TypeConstants.LENGTH, TypeBinding.INT, ClassFileConstants.AccPublic | ClassFileConstants.AccFinal, null, Constant.NotAConstant); public TypeBinding leafComponentType; public int dimensions; LookupEnvironment environment; char[] constantPoolName; char[] genericTypeSignature; public ArrayBinding(TypeBinding type, int dimensions, LookupEnvironment environment) { this.tagBits |= TagBits.IsArrayType; this.leafComponentType = type; this.dimensions = dimensions; this.environment = environment; if (type instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) type).addWrapper(this, environment); else this.tagBits |= type.tagBits & (TagBits.HasTypeVariable | TagBits.HasDirectWildcard | TagBits.HasMissingType | TagBits.ContainsNestedTypeReferences); } public TypeBinding closestMatch() { if (isValidBinding()) { return this; } TypeBinding leafClosestMatch = this.leafComponentType.closestMatch(); if (leafClosestMatch == null) { return null; } return this.environment.createArrayType(this.leafComponentType.closestMatch(), this.dimensions); } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List) */ public List collectMissingTypes(List missingTypes) { if ((this.tagBits & TagBits.HasMissingType) != 0) { missingTypes = this.leafComponentType.collectMissingTypes(missingTypes); } return missingTypes; } /** * Collect the substitutes into a map for certain type variables inside the receiver type * e.g. Collection.collectSubstitutes(Collection>, Map), will populate Map with: T --> List * Constraints: * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1)) * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0)) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2)) */ public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { if ((this.tagBits & TagBits.HasTypeVariable) == 0) return; if (actualType == TypeBinding.NULL) return; switch(actualType.kind()) { case Binding.ARRAY_TYPE : int actualDim = actualType.dimensions(); if (actualDim == this.dimensions) { this.leafComponentType.collectSubstitutes(scope, actualType.leafComponentType(), inferenceContext, constraint); } else if (actualDim > this.dimensions) { ArrayBinding actualReducedType = this.environment.createArrayType(actualType.leafComponentType(), actualDim - this.dimensions); this.leafComponentType.collectSubstitutes(scope, actualReducedType, inferenceContext, constraint); } break; case Binding.TYPE_PARAMETER : //TypeVariableBinding variable = (TypeVariableBinding) otherType; // TODO (philippe) should consider array bounds, and recurse break; } } /* * brakets leafUniqueKey * p.X[][] --> [[Lp/X; */ public char[] computeUniqueKey(boolean isLeaf) { char[] brackets = new char[this.dimensions]; for (int i = this.dimensions - 1; i >= 0; i--) brackets[i] = '['; return CharOperation.concat(brackets, this.leafComponentType.computeUniqueKey(isLeaf)); } /** * 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 (this.constantPoolName != null) return this.constantPoolName; char[] brackets = new char[this.dimensions]; for (int i = this.dimensions - 1; i >= 0; i--) brackets[i] = '['; return this.constantPoolName = CharOperation.concat(brackets, this.leafComponentType.signature()); } public String debugName() { StringBuffer brackets = new StringBuffer(this.dimensions * 2); for (int i = this.dimensions; --i >= 0;) brackets.append("[]"); //$NON-NLS-1$ return this.leafComponentType.debugName() + brackets.toString(); } public int dimensions() { return this.dimensions; } /* Answer an array whose dimension size is one less than the receiver. * * When the receiver's dimension size is one then answer the leaf component type. */ 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[this.dimensions]; for (int i = this.dimensions - 1; i >= 0; i--) brackets[i] = '['; this.genericTypeSignature = CharOperation.concat(brackets, this.leafComponentType.genericTypeSignature()); } return this.genericTypeSignature; } public PackageBinding getPackage() { return this.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 otherType, Scope captureScope) { if (this == otherType) return true; switch (otherType.kind()) { case Binding.ARRAY_TYPE : ArrayBinding otherArray = (ArrayBinding) otherType; if (otherArray.leafComponentType.isBaseType()) return false; // relying on the fact that all equal arrays are identical if (this.dimensions == otherArray.dimensions) return this.leafComponentType.isCompatibleWith(otherArray.leafComponentType); if (this.dimensions < otherArray.dimensions) return false; // cannot assign 'String[]' into 'Object[][]' but can assign 'byte[][]' into 'Object[]' break; case Binding.BASE_TYPE : return false; case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : return ((WildcardBinding) otherType).boundCheck(this); case Binding.TYPE_PARAMETER : // check compatibility with capture of ? super X if (otherType.isCapture()) { CaptureBinding otherCapture = (CaptureBinding) otherType; TypeBinding otherLowerBound; if ((otherLowerBound = otherCapture.lowerBound) != null) { if (!otherLowerBound.isArrayType()) return false; return isCompatibleWith(otherLowerBound, captureScope); } } return false; } //Check dimensions - Java does not support explicitly sized dimensions for types. //However, if it did, the type checking support would go here. switch (otherType.leafComponentType().id) { case TypeIds.T_JavaLangObject : case TypeIds.T_JavaLangCloneable : case TypeIds.T_JavaIoSerializable : return true; } return false; } public int kind() { return ARRAY_TYPE; } public TypeBinding leafComponentType(){ return this.leafComponentType; } /* API * Answer the problem id associated with the receiver. * NoError if the receiver is a valid binding. */ public int problemId() { return this.leafComponentType.problemId(); } /** * Answer the source name for the type. * In the case of member types, as the qualified name from its top level type. * For example, for a member type N defined inside M & A: "A.M.N". */ public char[] qualifiedSourceName() { char[] brackets = new char[this.dimensions * 2]; for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) { brackets[i] = ']'; brackets[i - 1] = '['; } return CharOperation.concat(this.leafComponentType.qualifiedSourceName(), brackets); } public char[] readableName() /* java.lang.Object[] */ { char[] brackets = new char[this.dimensions * 2]; for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) { brackets[i] = ']'; brackets[i - 1] = '['; } return CharOperation.concat(this.leafComponentType.readableName(), brackets); } public char[] shortReadableName(){ char[] brackets = new char[this.dimensions * 2]; for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) { brackets[i] = ']'; brackets[i - 1] = '['; } return CharOperation.concat(this.leafComponentType.shortReadableName(), brackets); } public char[] sourceName() { char[] brackets = new char[this.dimensions * 2]; for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) { brackets[i] = ']'; brackets[i - 1] = '['; } return CharOperation.concat(this.leafComponentType.sourceName(), brackets); } public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) { if (this.leafComponentType == unresolvedType) { this.leafComponentType = env.convertUnresolvedBinaryToRawType(resolvedType); this.tagBits |= this.leafComponentType.tagBits & (TagBits.HasTypeVariable | TagBits.HasDirectWildcard | TagBits.HasMissingType); } } public String toString() { return this.leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$ } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java0000644000175000001440000024332312212041344032042 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 328281 - visibility leaks not detected when analyzing unused field in private class * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 365836 - [compiler][null] Incomplete propagation of null defaults. * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 365662 - [compiler][null] warn on contradictory and redundant null annotations * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults * bug 366063 - Compiler should not add synthetic @NonNull annotations * bug 384663 - Package Based Annotation Compilation Error in JDT 3.8/4.2 (works in 3.7.2) * bug 386356 - Type mismatch error with annotations and generics * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 331649 - [compiler][null] consider null annotations for fields * bug 380896 - [compiler][null] Enum constants not recognised as being NonNull. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.HashMap; import java.util.Iterator; 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.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; 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.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.Util; public class SourceTypeBinding extends ReferenceBinding { public ReferenceBinding superclass; public ReferenceBinding[] superInterfaces; private FieldBinding[] fields; private MethodBinding[] methods; public ReferenceBinding[] memberTypes; public TypeVariableBinding[] typeVariables; public ClassScope scope; // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods // if a new category is added, also increment MAX_SYNTHETICS private final static int METHOD_EMUL = 0; private final static int FIELD_EMUL = 1; private final static int CLASS_LITERAL_EMUL = 2; private final static int MAX_SYNTHETICS = 3; HashMap[] synthetics; char[] genericReferenceTypeSignature; private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder private int defaultNullness; private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) { this.compoundName = compoundName; this.fPackage = fPackage; this.fileName = scope.referenceCompilationUnit().getFileName(); this.modifiers = scope.referenceContext.modifiers; this.sourceName = scope.referenceContext.name; this.scope = scope; // expect the fields & methods to be initialized correctly later this.fields = Binding.UNINITIALIZED_FIELDS; this.methods = Binding.UNINITIALIZED_METHODS; computeId(); } private void addDefaultAbstractMethods() { if ((this.tagBits & TagBits.KnowsDefaultAbstractMethods) != 0) return; this.tagBits |= TagBits.KnowsDefaultAbstractMethods; if (isClass() && isAbstract()) { if (this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_2) return; // no longer added for post 1.2 targets ReferenceBinding[] itsInterfaces = superInterfaces(); if (itsInterfaces != Binding.NO_SUPERINTERFACES) { MethodBinding[] defaultAbstracts = null; int defaultAbstractsCount = 0; ReferenceBinding[] interfacesToVisit = itsInterfaces; int nextPosition = interfacesToVisit.length; for (int i = 0; i < nextPosition; i++) { ReferenceBinding superType = interfacesToVisit[i]; if (superType.isValidBinding()) { MethodBinding[] superMethods = superType.methods(); nextAbstractMethod: for (int m = superMethods.length; --m >= 0;) { MethodBinding method = superMethods[m]; // explicitly implemented ? if (implementsMethod(method)) continue nextAbstractMethod; if (defaultAbstractsCount == 0) { defaultAbstracts = new MethodBinding[5]; } else { // already added as default abstract ? for (int k = 0; k < defaultAbstractsCount; k++) { MethodBinding alreadyAdded = defaultAbstracts[k]; if (CharOperation.equals(alreadyAdded.selector, method.selector) && alreadyAdded.areParametersEqual(method)) continue nextAbstractMethod; } } MethodBinding defaultAbstract = new MethodBinding( method.modifiers | ExtraCompilerModifiers.AccDefaultAbstract | ClassFileConstants.AccSynthetic, method.selector, method.returnType, method.parameters, method.thrownExceptions, this); if (defaultAbstractsCount == defaultAbstracts.length) System.arraycopy(defaultAbstracts, 0, defaultAbstracts = new MethodBinding[2 * defaultAbstractsCount], 0, defaultAbstractsCount); defaultAbstracts[defaultAbstractsCount++] = defaultAbstract; } if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { int itsLength = itsInterfaces.length; if (nextPosition + itsLength >= interfacesToVisit.length) System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); nextInterface : for (int a = 0; a < itsLength; a++) { ReferenceBinding next = itsInterfaces[a]; for (int b = 0; b < nextPosition; b++) if (next == interfacesToVisit[b]) continue nextInterface; interfacesToVisit[nextPosition++] = next; } } } } if (defaultAbstractsCount > 0) { int length = this.methods.length; System.arraycopy(this.methods, 0, this.methods = new MethodBinding[length + defaultAbstractsCount], 0, length); System.arraycopy(defaultAbstracts, 0, this.methods, length, defaultAbstractsCount); // re-sort methods length = length + defaultAbstractsCount; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); // this.tagBits |= TagBits.AreMethodsSorted; -- already set in #methods() } } } } /* Add a new synthetic field for . * Answer the new field or the existing field if one already existed. */ public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOuterLocalVariable) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5); FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(actualOuterLocalVariable); if (synthField == null) { synthField = new SyntheticFieldBinding( CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name), actualOuterLocalVariable.type, ClassFileConstants.AccPrivate | ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic, this, Constant.NotAConstant, this.synthetics[SourceTypeBinding.FIELD_EMUL].size()); this.synthetics[SourceTypeBinding.FIELD_EMUL].put(actualOuterLocalVariable, synthField); } // ensure there is not already such a field defined by the user boolean needRecheck; int index = 1; do { needRecheck = false; FieldBinding existingField; if ((existingField = getField(synthField.name, true /*resolve*/)) != null) { TypeDeclaration typeDecl = this.scope.referenceContext; FieldDeclaration[] fieldDeclarations = typeDecl.fields; int max = fieldDeclarations == null ? 0 : fieldDeclarations.length; for (int i = 0; i < max; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; if (fieldDecl.binding == existingField) { synthField.name = CharOperation.concat( TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name, ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$ needRecheck = true; break; } } } } while (needRecheck); return synthField; } /* Add a new synthetic field for . * Answer the new field or the existing field if one already existed. */ public FieldBinding addSyntheticFieldForInnerclass(ReferenceBinding enclosingType) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5); FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(enclosingType); if (synthField == null) { synthField = new SyntheticFieldBinding( CharOperation.concat( TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, String.valueOf(enclosingType.depth()).toCharArray()), enclosingType, ClassFileConstants.AccDefault | ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic, this, Constant.NotAConstant, this.synthetics[SourceTypeBinding.FIELD_EMUL].size()); this.synthetics[SourceTypeBinding.FIELD_EMUL].put(enclosingType, synthField); } // ensure there is not already such a field defined by the user boolean needRecheck; do { needRecheck = false; FieldBinding existingField; if ((existingField = getField(synthField.name, true /*resolve*/)) != null) { TypeDeclaration typeDecl = this.scope.referenceContext; FieldDeclaration[] fieldDeclarations = typeDecl.fields; int max = fieldDeclarations == null ? 0 : fieldDeclarations.length; for (int i = 0; i < max; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; if (fieldDecl.binding == existingField) { if (this.scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) { synthField.name = CharOperation.concat( synthField.name, "$".toCharArray()); //$NON-NLS-1$ needRecheck = true; } else { this.scope.problemReporter().duplicateFieldInType(this, fieldDecl); } break; } } } } while (needRecheck); return synthField; } /* Add a new synthetic field for a class literal access. * Answer the new field or the existing field if one already existed. */ public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, BlockScope blockScope) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null) this.synthetics[SourceTypeBinding.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) this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].get(targetType); if (synthField == null) { synthField = new SyntheticFieldBinding( CharOperation.concat( TypeConstants.SYNTHETIC_CLASS, String.valueOf(this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size()).toCharArray()), blockScope.getJavaLangClass(), ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic, this, Constant.NotAConstant, this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size()); this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].put(targetType, synthField); } // ensure there is not already such a field defined by the user FieldBinding existingField; if ((existingField = getField(synthField.name, true /*resolve*/)) != null) { TypeDeclaration typeDecl = blockScope.referenceType(); FieldDeclaration[] typeDeclarationFields = typeDecl.fields; int max = typeDeclarationFields == null ? 0 : typeDeclarationFields.length; for (int i = 0; i < max; i++) { FieldDeclaration fieldDecl = typeDeclarationFields[i]; if (fieldDecl.binding == existingField) { blockScope.problemReporter().duplicateFieldInType(this, fieldDecl); break; } } } return synthField; } /* 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 addSyntheticFieldForAssert(BlockScope blockScope) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5); FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$ if (synthField == null) { synthField = new SyntheticFieldBinding( TypeConstants.SYNTHETIC_ASSERT_DISABLED, TypeBinding.BOOLEAN, ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic | ClassFileConstants.AccFinal, this, Constant.NotAConstant, this.synthetics[SourceTypeBinding.FIELD_EMUL].size()); this.synthetics[SourceTypeBinding.FIELD_EMUL].put("assertionEmulation", 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 = getField(synthField.name, true /*resolve*/)) != null) { TypeDeclaration typeDecl = this.scope.referenceContext; int max = (typeDecl.fields == null) ? 0 : typeDecl.fields.length; for (int i = 0; i < max; i++) { FieldDeclaration fieldDecl = typeDecl.fields[i]; if (fieldDecl.binding == existingField) { synthField.name = CharOperation.concat( 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 (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5); FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get("enumConstantValues"); //$NON-NLS-1$ if (synthField == null) { synthField = new SyntheticFieldBinding( TypeConstants.SYNTHETIC_ENUM_VALUES, this.scope.createArrayType(this,1), ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic | ClassFileConstants.AccFinal, this, Constant.NotAConstant, this.synthetics[SourceTypeBinding.FIELD_EMUL].size()); this.synthetics[SourceTypeBinding.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 = getField(synthField.name, true /*resolve*/)) != null) { TypeDeclaration typeDecl = this.scope.referenceContext; FieldDeclaration[] fieldDeclarations = typeDecl.fields; int max = fieldDeclarations == null ? 0 : fieldDeclarations.length; for (int i = 0; i < max; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; if (fieldDecl.binding == existingField) { synthField.name = CharOperation.concat( TypeConstants.SYNTHETIC_ENUM_VALUES, ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$ needRecheck = true; break; } } } } while (needRecheck); return synthField; } /* Add a new synthetic access method for read/write access to . Answer the new method or the existing method if one already existed. */ public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess, boolean isSuperAccess) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); SyntheticMethodBinding accessMethod = null; SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(targetField); if (accessors == null) { accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, isSuperAccess, this); this.synthetics[SourceTypeBinding.METHOD_EMUL].put(targetField, accessors = new SyntheticMethodBinding[2]); accessors[isReadAccess ? 0 : 1] = accessMethod; } else { if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) { accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, isSuperAccess, 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 (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); SyntheticMethodBinding accessMethod = null; SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(selector); if (accessors == null) { accessMethod = new SyntheticMethodBinding(this, selector); this.synthetics[SourceTypeBinding.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 synthetic field to handle the cache of the switch translation table for the corresponding enum type */ public SyntheticFieldBinding addSyntheticFieldForSwitchEnum(char[] fieldName, String key) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5); SyntheticFieldBinding synthField = (SyntheticFieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(key); if (synthField == null) { synthField = new SyntheticFieldBinding( fieldName, this.scope.createArrayType(TypeBinding.INT,1), ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic, this, Constant.NotAConstant, this.synthetics[SourceTypeBinding.FIELD_EMUL].size()); this.synthetics[SourceTypeBinding.FIELD_EMUL].put(key, synthField); } // ensure there is not already such a field defined by the user boolean needRecheck; int index = 0; do { needRecheck = false; FieldBinding existingField; if ((existingField = getField(synthField.name, true /*resolve*/)) != null) { TypeDeclaration typeDecl = this.scope.referenceContext; FieldDeclaration[] fieldDeclarations = typeDecl.fields; int max = fieldDeclarations == null ? 0 : fieldDeclarations.length; for (int i = 0; i < max; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; if (fieldDecl.binding == existingField) { synthField.name = CharOperation.concat( fieldName, ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$ needRecheck = true; break; } } } } while (needRecheck); return synthField; } /* 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 addSyntheticMethodForSwitchEnum(TypeBinding enumBinding) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); SyntheticMethodBinding accessMethod = null; char[] selector = CharOperation.concat(TypeConstants.SYNTHETIC_SWITCH_ENUM_TABLE, enumBinding.constantPoolName()); CharOperation.replace(selector, '/', '$'); final String key = new String(selector); SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(key); // first add the corresponding synthetic field if (accessors == null) { // then create the synthetic method final SyntheticFieldBinding fieldBinding = addSyntheticFieldForSwitchEnum(selector, key); accessMethod = new SyntheticMethodBinding(fieldBinding, this, enumBinding, selector); this.synthetics[SourceTypeBinding.METHOD_EMUL].put(key, accessors = new SyntheticMethodBinding[2]); accessors[0] = accessMethod; } else { if ((accessMethod = accessors[0]) == null) { final SyntheticFieldBinding fieldBinding = addSyntheticFieldForSwitchEnum(selector, key); accessMethod = new SyntheticMethodBinding(fieldBinding, this, enumBinding, selector); accessors[0] = accessMethod; } } return accessMethod; } public SyntheticMethodBinding addSyntheticMethodForEnumInitialization(int begin, int end) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); SyntheticMethodBinding accessMethod = new SyntheticMethodBinding(this, begin, end); SyntheticMethodBinding[] accessors = new SyntheticMethodBinding[2]; this.synthetics[SourceTypeBinding.METHOD_EMUL].put(accessMethod.selector, accessors); 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 SyntheticMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); SyntheticMethodBinding accessMethod = null; SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(targetMethod); if (accessors == null) { accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this); this.synthetics[SourceTypeBinding.METHOD_EMUL].put(targetMethod, accessors = new SyntheticMethodBinding[2]); accessors[isSuperAccess ? 0 : 1] = accessMethod; } else { if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) { accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this); accessors[isSuperAccess ? 0 : 1] = accessMethod; } } if (targetMethod.declaringClass.isStatic()) { if ((targetMethod.isConstructor() && targetMethod.parameters.length >= 0xFE) || targetMethod.parameters.length >= 0xFF) { this.scope.problemReporter().tooManyParametersForSyntheticMethod(targetMethod.sourceMethod()); } } else if ((targetMethod.isConstructor() && targetMethod.parameters.length >= 0xFD) || targetMethod.parameters.length >= 0xFE) { this.scope.problemReporter().tooManyParametersForSyntheticMethod(targetMethod.sourceMethod()); } return accessMethod; } /* * Record the fact that bridge methods need to be generated to override certain inherited methods */ public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding targetMethod) { if (isInterface()) return null; // only classes & enums get bridge methods // targetMethod may be inherited if (inheritedMethodToBridge.returnType.erasure() == targetMethod.returnType.erasure() && inheritedMethodToBridge.areParameterErasuresEqual(targetMethod)) { return null; // do not need bridge method } if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) { this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); } else { // check to see if there is another equivalent inheritedMethod already added Iterator synthMethods = this.synthetics[SourceTypeBinding.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; } } } } SyntheticMethodBinding accessMethod = null; SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge); if (accessors == null) { accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this); this.synthetics[SourceTypeBinding.METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]); accessors[1] = accessMethod; } else { if ((accessMethod = accessors[1]) == null) { accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this); accessors[1] = accessMethod; } } return accessMethod; } /* * https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658. Generate a bridge method if a public method is inherited * from a non-public class into a public class (only in 1.6 or greater) */ public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) { if (this.scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_5) { return null; } if (isInterface()) return null; if (inheritedMethodToBridge.isAbstract() || inheritedMethodToBridge.isFinal() || inheritedMethodToBridge.isStatic()) { return null; } if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) { this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); } else { // check to see if there is another equivalent inheritedMethod already added Iterator synthMethods = this.synthetics[SourceTypeBinding.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; } } } } SyntheticMethodBinding accessMethod = null; SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge); if (accessors == null) { accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, this); this.synthetics[SourceTypeBinding.METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]); accessors[0] = accessMethod; } else { if ((accessMethod = accessors[0]) == null) { accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, this); accessors[0] = accessMethod; } } return accessMethod; } boolean areFieldsInitialized() { return this.fields != Binding.UNINITIALIZED_FIELDS; } boolean areMethodsInitialized() { return this.methods != Binding.UNINITIALIZED_METHODS; } public int kind() { if (this.typeVariables != Binding.NO_TYPE_VARIABLES) return Binding.GENERIC_TYPE; return Binding.TYPE; } public char[] computeUniqueKey(boolean isLeaf) { char[] uniqueKey = super.computeUniqueKey(isLeaf); if (uniqueKey.length == 2) return uniqueKey; // problem type's unique key is "L;" if (Util.isClassFileName(this.fileName)) return uniqueKey; // no need to insert compilation unit name for a .class file // insert compilation unit name if the type name is not the main type name int end = CharOperation.lastIndexOf('.', this.fileName); if (end != -1) { int start = CharOperation.lastIndexOf('/', this.fileName) + 1; char[] mainTypeName = CharOperation.subarray(this.fileName, start, end); start = CharOperation.lastIndexOf('/', uniqueKey) + 1; if (start == 0) start = 1; // start after L if (this.isMemberType()) { end = CharOperation.indexOf('$', uniqueKey, start); } else { // '$' is part of the type name end = -1; } if (end == -1) end = CharOperation.indexOf('<', uniqueKey, start); if (end == -1) end = CharOperation.indexOf(';', uniqueKey, start); char[] topLevelType = CharOperation.subarray(uniqueKey, start, end); if (!CharOperation.equals(topLevelType, mainTypeName)) { StringBuffer buffer = new StringBuffer(); buffer.append(uniqueKey, 0, start); buffer.append(mainTypeName); buffer.append('~'); buffer.append(topLevelType); buffer.append(uniqueKey, end, uniqueKey.length - end); int length = buffer.length(); uniqueKey = new char[length]; buffer.getChars(0, length, uniqueKey, 0); return uniqueKey; } } return uniqueKey; } void faultInTypesForFieldsAndMethods() { // check @Deprecated annotation getAnnotationTagBits(); // marks as deprecated by side effect ReferenceBinding enclosingType = enclosingType(); if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !isDeprecated()) this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; fields(); methods(); for (int i = 0, length = this.memberTypes.length; i < length; i++) ((SourceTypeBinding) this.memberTypes[i]).faultInTypesForFieldsAndMethods(); } // NOTE: the type of each field of a source type is resolved when needed public FieldBinding[] fields() { if ((this.tagBits & TagBits.AreFieldsComplete) != 0) return this.fields; int failed = 0; FieldBinding[] resolvedFields = this.fields; try { // lazily sort fields if ((this.tagBits & TagBits.AreFieldsSorted) == 0) { int length = this.fields.length; if (length > 1) ReferenceBinding.sortFields(this.fields, 0, length); this.tagBits |= TagBits.AreFieldsSorted; } for (int i = 0, length = this.fields.length; i < length; i++) { if (resolveTypeFor(this.fields[i]) == null) { // do not alter original field array until resolution is over, due to reentrance (143259) if (resolvedFields == this.fields) { System.arraycopy(this.fields, 0, resolvedFields = new FieldBinding[length], 0, length); } resolvedFields[i] = null; failed++; } } } finally { if (failed > 0) { // ensure fields are consistent reqardless of the error int newSize = resolvedFields.length - failed; if (newSize == 0) return this.fields = Binding.NO_FIELDS; FieldBinding[] newFields = new FieldBinding[newSize]; for (int i = 0, j = 0, length = resolvedFields.length; i < length; i++) { if (resolvedFields[i] != null) newFields[j++] = resolvedFields[i]; } this.fields = newFields; } } this.tagBits |= TagBits.AreFieldsComplete; return this.fields; } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature() */ public char[] genericTypeSignature() { if (this.genericReferenceTypeSignature == null) this.genericReferenceTypeSignature = computeGenericTypeSignature(this.typeVariables); 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 != Binding.NO_TYPE_VARIABLES) { 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(this.scope.getJavaLangObject().genericTypeSignature()); for (int i = 0, length = this.superInterfaces.length; i < length; i++) sig.append(this.superInterfaces[i].genericTypeSignature()); return sig.toString().toCharArray(); } /** * Compute the tagbits for standard annotations. For source types, these could require * lazily resolving corresponding annotation nodes, in case of forward references. * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits() */ public long getAnnotationTagBits() { if ((this.tagBits & TagBits.AnnotationResolved) == 0 && this.scope != null) { TypeDeclaration typeDecl = this.scope.referenceContext; boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation; try { typeDecl.staticInitializerScope.insideTypeAnnotation = true; ASTNode.resolveAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this); } finally { typeDecl.staticInitializerScope.insideTypeAnnotation = old; } if ((this.tagBits & TagBits.AnnotationDeprecated) != 0) this.modifiers |= ClassFileConstants.AccDeprecated; evaluateNullAnnotations(this.tagBits); } return this.tagBits; } public MethodBinding[] getDefaultAbstractMethods() { int count = 0; for (int i = this.methods.length; --i >= 0;) if (this.methods[i].isDefaultAbstract()) count++; if (count == 0) return Binding.NO_METHODS; MethodBinding[] result = new MethodBinding[count]; count = 0; for (int i = this.methods.length; --i >= 0;) if (this.methods[i].isDefaultAbstract()) result[count++] = this.methods[i]; return result; } // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) { int argCount = argumentTypes.length; if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods long range; if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) { nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; if (method.parameters.length == argCount) { TypeBinding[] toMatch = method.parameters; for (int iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) continue nextMethod; return method; } } } } else { // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } long range; if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) { nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; if (resolveTypesFor(method) == null || method.returnType == null) { methods(); return getExactConstructor(argumentTypes); // try again since the problem methods have been removed } if (method.parameters.length == argCount) { TypeBinding[] toMatch = method.parameters; for (int iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) continue nextMethod; return method; } } } } return null; } //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, CompilationUnitScope refScope) { // sender from refScope calls recordTypeReference(this) int argCount = argumentTypes.length; boolean foundNothing = true; if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; 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 iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) continue nextMethod; return method; } } } } else { // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { // check unresolved method int start = (int) range, end = (int) (range >> 32); for (int imethod = start; imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; if (resolveTypesFor(method) == null || method.returnType == null) { methods(); return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed } } // check dup collisions boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; for (int i = start; i <= end; i++) { MethodBinding method1 = this.methods[i]; for (int j = end; j > i; j--) { MethodBinding method2 = this.methods[j]; boolean paramsMatch = isSource15 ? method1.areParameterErasuresEqual(method2) : method1.areParametersEqual(method2); if (paramsMatch) { methods(); return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed } } } nextMethod: for (int imethod = start; imethod <= end; imethod++) { MethodBinding method = this.methods[imethod]; TypeBinding[] toMatch = method.parameters; if (toMatch.length == argCount) { for (int iarg = 0; iarg < argCount; iarg++) if (toMatch[iarg] != argumentTypes[iarg]) continue nextMethod; return method; } } } } if (foundNothing) { if (isInterface()) { if (this.superInterfaces.length == 1) { if (refScope != null) refScope.recordTypeReference(this.superInterfaces[0]); return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope); } } else if (this.superclass != null) { if (refScope != null) refScope.recordTypeReference(this.superclass); return this.superclass.getExactMethod(selector, argumentTypes, refScope); } } return null; } //NOTE: the type of a field of a source type is resolved when needed public FieldBinding getField(char[] fieldName, boolean needResolve) { if ((this.tagBits & TagBits.AreFieldsComplete) != 0) return ReferenceBinding.binarySearch(fieldName, this.fields); // lazily sort fields if ((this.tagBits & TagBits.AreFieldsSorted) == 0) { int length = this.fields.length; if (length > 1) ReferenceBinding.sortFields(this.fields, 0, length); this.tagBits |= TagBits.AreFieldsSorted; } // always resolve anyway on source types FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields); if (field != null) { FieldBinding result = null; try { result = resolveTypeFor(field); return result; } finally { if (result == null) { // ensure fields are consistent reqardless of the error int newSize = this.fields.length - 1; if (newSize == 0) { this.fields = Binding.NO_FIELDS; } else { FieldBinding[] newFields = new FieldBinding[newSize]; int index = 0; for (int i = 0, length = this.fields.length; i < length; i++) { FieldBinding f = this.fields[i]; if (f == field) continue; newFields[index++] = f; } this.fields = newFields; } } } } return null; } // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed public MethodBinding[] getMethods(char[] selector) { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { int start = (int) range, end = (int) (range >> 32); int length = end - start + 1; MethodBinding[] result; System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length); return result; } else { return Binding.NO_METHODS; } } // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } MethodBinding[] result; long range; if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { int start = (int) range, end = (int) (range >> 32); for (int i = start; i <= end; i++) { MethodBinding method = this.methods[i]; if (resolveTypesFor(method) == null || method.returnType == null) { methods(); return getMethods(selector); // try again since the problem methods have been removed } } int length = end - start + 1; System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length); } else { return Binding.NO_METHODS; } boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; for (int i = 0, length = result.length - 1; i < length; i++) { MethodBinding method = result[i]; for (int j = length; j > i; j--) { boolean paramsMatch = isSource15 ? method.areParameterErasuresEqual(result[j]) : method.areParametersEqual(result[j]); if (paramsMatch) { methods(); return getMethods(selector); // try again since the duplicate methods have been removed } } } return result; } /* Answer the synthetic field for * or null if one does not exist. */ public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) { if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null; return (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(actualOuterLocalVariable); } /* Answer the synthetic field for * or null if one does not exist. */ public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) { if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null; FieldBinding field = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(targetEnclosingType); if (field != null) return field; // type compatibility : to handle cases such as // 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){ Iterator accessFields = this.synthetics[SourceTypeBinding.FIELD_EMUL].values().iterator(); while (accessFields.hasNext()) { field = (FieldBinding) accessFields.next(); if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, field.name) && field.type.findSuperTypeOriginatingFrom(targetEnclosingType) != null) return field; } } return null; } /* * Answer the bridge method associated for an inherited methods or null if one does not exist */ public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) { if (this.synthetics == null) return null; if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) return null; SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge); if (accessors == null) return null; return accessors[1]; } public boolean hasTypeBit(int bit) { // source types initialize type bits during connectSuperclass/interfaces() return (this.typeBits & bit) != 0; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits() */ public void initializeDeprecatedAnnotationTagBits() { if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) { TypeDeclaration typeDecl = this.scope.referenceContext; boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation; try { typeDecl.staticInitializerScope.insideTypeAnnotation = true; ASTNode.resolveDeprecatedAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this); this.tagBits |= TagBits.DeprecatedAnnotationResolved; } finally { typeDecl.staticInitializerScope.insideTypeAnnotation = old; } if ((this.tagBits & TagBits.AnnotationDeprecated) != 0) { this.modifiers |= ClassFileConstants.AccDeprecated; } } } // ensure the receiver knows its hierarchy & fields/methods so static imports can be resolved correctly // see bug 230026 void initializeForStaticImports() { if (this.scope == null) return; // already initialized if (this.superInterfaces == null) this.scope.connectTypeHierarchy(); this.scope.buildFields(); this.scope.buildMethods(); } private void initializeNullDefault() { // ensure nullness defaults are initialized at all enclosing levels: switch (this.nullnessDefaultInitialized) { case 0: getAnnotationTagBits(); // initialize //$FALL-THROUGH$ case 1: getPackage().isViewedAsDeprecated(); // initialize annotations this.nullnessDefaultInitialized = 2; } } /** * 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 : case Binding.INTERSECTION_TYPE: return ((WildcardBinding) otherType).boundCheck(this); case Binding.PARAMETERIZED_TYPE : if ((otherType.tagBits & TagBits.HasDirectWildcard) == 0 && (!isMemberType() || !otherType.isMemberType())) return false; // should have been identical ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType; if (this != otherParamType.genericType()) return false; if (!isStatic()) { // static member types do not compare their enclosing ReferenceBinding enclosing = enclosingType(); if (enclosing != null) { ReferenceBinding otherEnclosing = otherParamType.enclosingType(); if (otherEnclosing == null) return false; if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) { if (enclosing != otherEnclosing) return false; } else { if (!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 != Binding.NO_TYPE_VARIABLES; } public boolean isHierarchyConnected() { return (this.tagBits & TagBits.EndHierarchyCheck) != 0; } public ReferenceBinding[] memberTypes() { return this.memberTypes; } public boolean hasMemberTypes() { return this.memberTypes.length > 0; } // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed public MethodBinding[] methods() { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) return this.methods; if (!areMethodsInitialized()) { // https://bugs.eclipse.org/384663 this.scope.buildMethods(); } // lazily sort methods if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { int length = this.methods.length; if (length > 1) ReferenceBinding.sortMethods(this.methods, 0, length); this.tagBits |= TagBits.AreMethodsSorted; } int failed = 0; MethodBinding[] resolvedMethods = this.methods; try { for (int i = 0, length = this.methods.length; i < length; i++) { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // recursive call to methods() from resolveTypesFor(..) resolved the methods return this.methods; } if (resolveTypesFor(this.methods[i]) == null) { // do not alter original method array until resolution is over, due to reentrance (143259) if (resolvedMethods == this.methods) { System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length); } resolvedMethods[i] = null; // unable to resolve parameters failed++; } } // find & report collision cases boolean complyTo15OrAbove = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; boolean compliance16 = this.scope.compilerOptions().complianceLevel == ClassFileConstants.JDK1_6; for (int i = 0, length = this.methods.length; i < length; i++) { int severity = ProblemSeverities.Error; MethodBinding method = resolvedMethods[i]; if (method == null) continue; char[] selector = method.selector; AbstractMethodDeclaration methodDecl = null; nextSibling: for (int j = i + 1; j < length; j++) { MethodBinding method2 = resolvedMethods[j]; if (method2 == null) continue nextSibling; if (!CharOperation.equals(selector, method2.selector)) break nextSibling; // methods with same selector are contiguous if (complyTo15OrAbove) { if (method.areParameterErasuresEqual(method2)) { // we now ignore return types in 1.7 when detecting duplicates, just as we did before 1.5 // Only in 1.6, we have to make sure even return types are different // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317719 if (compliance16 && method.returnType != null && method2.returnType != null) { if (method.returnType.erasure() != method2.returnType.erasure()) { // check to see if the erasure of either method is equal to the other // if not, then change severity to WARNING TypeBinding[] params1 = method.parameters; TypeBinding[] params2 = method2.parameters; int pLength = params1.length; TypeVariableBinding[] vars = method.typeVariables; TypeVariableBinding[] vars2 = method2.typeVariables; boolean equalTypeVars = vars == vars2; MethodBinding subMethod = method2; if (!equalTypeVars) { MethodBinding temp = method.computeSubstitutedMethod(method2, this.scope.environment()); if (temp != null) { equalTypeVars = true; subMethod = temp; } } boolean equalParams = method.areParametersEqual(subMethod); if (equalParams && equalTypeVars) { // duplicates regardless of return types } else if (vars != Binding.NO_TYPE_VARIABLES && vars2 != Binding.NO_TYPE_VARIABLES) { // both have type arguments. Erasure of signature of one cannot be equal to signature of other severity = ProblemSeverities.Warning; } else if (pLength > 0) { int index = pLength; // is erasure of signature of m2 same as signature of m1? for (; --index >= 0;) { if (params1[index] != params2[index].erasure()) { // If one of them is a raw type if (params1[index] instanceof RawTypeBinding) { if (params2[index].erasure() != ((RawTypeBinding)params1[index]).actualType()) { break; } } else { break; } } if (params1[index] == params2[index]) { TypeBinding type = params1[index].leafComponentType(); if (type instanceof SourceTypeBinding && type.typeVariables() != Binding.NO_TYPE_VARIABLES) { index = pLength; // handle comparing identical source types like X... its erasure is itself BUT we need to answer false break; } } } if (index >= 0 && index < pLength) { // is erasure of signature of m1 same as signature of m2? for (index = pLength; --index >= 0;) if (params1[index].erasure() != params2[index]) { // If one of them is a raw type if (params2[index] instanceof RawTypeBinding) { if (params1[index].erasure() != ((RawTypeBinding)params2[index]).actualType()) { break; } } else { break; } } } if (index >= 0) { // erasure of neither is equal to signature of other severity = ProblemSeverities.Warning; } } else if (pLength != 0){ severity = ProblemSeverities.Warning; } // pLength = 0 automatically makes erasure of arguments one equal to arguments of other. } // else return types also equal. All conditions satisfied // to give error in 1.6 compliance as well. } } else { continue nextSibling; } } else if (!method.areParametersEqual(method2)) { // prior to 1.5, parameters identical meant a collision case continue nextSibling; } // otherwise duplicates / name clash boolean isEnumSpecialMethod = isEnum() && (CharOperation.equals(selector,TypeConstants.VALUEOF) || CharOperation.equals(selector,TypeConstants.VALUES)); // report duplicate boolean removeMethod2 = (severity == ProblemSeverities.Error) ? true : false; // do not remove if in 1.6 and just a warning given if (methodDecl == 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 boolean removeMethod = method.returnType == null && method2.returnType != null; if (isEnumSpecialMethod) { this.scope.problemReporter().duplicateEnumSpecialMethod(this, methodDecl); // remove user defined methods & keep the synthetic removeMethod = true; } else { this.scope.problemReporter().duplicateMethodInType(this, methodDecl, method.areParametersEqual(method2), severity); } if (removeMethod) { removeMethod2 = false; methodDecl.binding = null; // do not alter original method array until resolution is over, due to reentrance (143259) if (resolvedMethods == this.methods) System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length); resolvedMethods[i] = null; failed++; } } } AbstractMethodDeclaration method2Decl = method2.sourceMethod(); if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method if (isEnumSpecialMethod) { this.scope.problemReporter().duplicateEnumSpecialMethod(this, method2Decl); removeMethod2 = true; } else { this.scope.problemReporter().duplicateMethodInType(this, method2Decl, method.areParametersEqual(method2), severity); } if (removeMethod2) { method2Decl.binding = null; // do not alter original method array until resolution is over, due to reentrance (143259) if (resolvedMethods == this.methods) System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length); resolvedMethods[j] = null; failed++; } } } if (method.returnType == null && resolvedMethods[i] != null) { // forget method with invalid return type... was kept to detect possible collisions methodDecl = method.sourceMethod(); if (methodDecl != null) methodDecl.binding = null; // do not alter original method array until resolution is over, due to reentrance (143259) if (resolvedMethods == this.methods) System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length); resolvedMethods[i] = null; failed++; } } } finally { if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // recursive call to methods() from resolveTypesFor(..) resolved the methods return this.methods; } if (failed > 0) { int newSize = resolvedMethods.length - failed; if (newSize == 0) { this.methods = Binding.NO_METHODS; } else { MethodBinding[] newMethods = new MethodBinding[newSize]; for (int i = 0, j = 0, length = resolvedMethods.length; i < length; i++) if (resolvedMethods[i] != null) newMethods[j++] = resolvedMethods[i]; this.methods = newMethods; } } // handle forward references to potential default abstract methods addDefaultAbstractMethods(); this.tagBits |= TagBits.AreMethodsComplete; } return this.methods; } public FieldBinding resolveTypeFor(FieldBinding field) { if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return field; if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { if ((field.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0) field.modifiers |= ClassFileConstants.AccDeprecated; } if (isViewedAsDeprecated() && !field.isDeprecated()) field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; if (hasRestrictedAccess()) field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; FieldDeclaration[] fieldDecls = this.scope.referenceContext.fields; int length = fieldDecls == null ? 0 : fieldDecls.length; for (int f = 0; f < length; f++) { if (fieldDecls[f].binding != field) continue; MethodScope initializationScope = field.isStatic() ? this.scope.referenceContext.staticInitializerScope : this.scope.referenceContext.initializerScope; FieldBinding previousField = initializationScope.initializedField; try { initializationScope.initializedField = field; FieldDeclaration fieldDecl = fieldDecls[f]; TypeBinding fieldType = fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT ? initializationScope.environment().convertToRawType(this, false /*do not force conversion of enclosing types*/) // enum constant is implicitly of declaring enum type : fieldDecl.type.resolveType(initializationScope, true /* check bounds*/); field.type = fieldType; field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; if (fieldType == null) { fieldDecl.binding = null; return null; } if (fieldType == TypeBinding.VOID) { this.scope.problemReporter().variableTypeCannotBeVoid(fieldDecl); fieldDecl.binding = null; return null; } if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == TypeBinding.VOID) { this.scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecl); fieldDecl.binding = null; return null; } if ((fieldType.tagBits & TagBits.HasMissingType) != 0) { field.tagBits |= TagBits.HasMissingType; } TypeBinding leafType = fieldType.leafComponentType(); if (leafType instanceof ReferenceBinding && (((ReferenceBinding)leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) { field.modifiers |= ExtraCompilerModifiers.AccGenericSignature; } // apply null default: LookupEnvironment environment = this.scope.environment(); if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) { if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { // enum constants neither have a type declaration nor can they be null field.tagBits |= TagBits.AnnotationNonNull; } else { initializeNullDefault(); if (hasNonNullDefault()) { field.fillInDefaultNonNullness(fieldDecl, initializationScope); } // validate null annotation: this.scope.validateNullAnnotation(field.tagBits, fieldDecl.type, fieldDecl.annotations); } } } finally { initializationScope.initializedField = previousField; } return field; } return null; // should never reach this point } public MethodBinding resolveTypesFor(MethodBinding method) { if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return method; if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { if ((method.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0) method.modifiers |= ClassFileConstants.AccDeprecated; } if (isViewedAsDeprecated() && !method.isDeprecated()) method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; if (hasRestrictedAccess()) method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; 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, true); // 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; method.thrownExceptions = new ReferenceBinding[size]; int count = 0; ReferenceBinding resolvedExceptionType; for (int i = 0; i < size; i++) { resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/); if (resolvedExceptionType == null) continue; if (resolvedExceptionType.isBoundParameterizedType()) { methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]); continue; } if (resolvedExceptionType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null) { if (resolvedExceptionType.isValidBinding()) { methodDecl.scope.problemReporter().cannotThrowType(exceptionTypes[i], resolvedExceptionType); continue; } } if ((resolvedExceptionType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } method.modifiers |= (resolvedExceptionType.modifiers & ExtraCompilerModifiers.AccGenericSignature); method.thrownExceptions[count++] = resolvedExceptionType; } if (count < size) System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count); } final boolean reportUnavoidableGenericTypeProblems = this.scope.compilerOptions().reportUnavoidableGenericTypeProblems; boolean foundArgProblem = false; Argument[] arguments = methodDecl.arguments; if (arguments != null) { int size = arguments.length; method.parameters = Binding.NO_PARAMETERS; TypeBinding[] newParameters = new TypeBinding[size]; for (int i = 0; i < size; i++) { Argument arg = arguments[i]; if (arg.annotations != null) { method.tagBits |= TagBits.HasParameterAnnotations; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=322817 boolean deferRawTypeCheck = !reportUnavoidableGenericTypeProblems && !method.isConstructor() && (arg.type.bits & ASTNode.IgnoreRawTypeCheck) == 0; TypeBinding parameterType; if (deferRawTypeCheck) { arg.type.bits |= ASTNode.IgnoreRawTypeCheck; } try { parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/); } finally { if (deferRawTypeCheck) { arg.type.bits &= ~ASTNode.IgnoreRawTypeCheck; } } if (parameterType == null) { foundArgProblem = true; } else if (parameterType == TypeBinding.VOID) { methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg); foundArgProblem = true; } else { if ((parameterType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } TypeBinding leafType = parameterType.leafComponentType(); if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) method.modifiers |= ExtraCompilerModifiers.AccGenericSignature; newParameters[i] = parameterType; arg.binding = new LocalVariableBinding(arg, parameterType, arg.modifiers, true /*isArgument*/); } } // only assign parameters if no problems are found if (!foundArgProblem) { method.parameters = newParameters; } } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=337799 if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7) { if ((method.tagBits & TagBits.AnnotationSafeVarargs) != 0) { if (!method.isVarargs()) { methodDecl.scope.problemReporter().safeVarargsOnFixedArityMethod(method); } else if (!method.isStatic() && !method.isFinal() && !method.isConstructor()) { methodDecl.scope.problemReporter().safeVarargsOnNonFinalInstanceMethod(method); } } else if (method.parameters != null && method.parameters.length > 0 && method.isVarargs()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=337795 if (!method.parameters[method.parameters.length - 1].isReifiable()) { methodDecl.scope.problemReporter().possibleHeapPollutionFromVararg(methodDecl.arguments[methodDecl.arguments.length - 1]); } } } boolean foundReturnTypeProblem = false; if (!method.isConstructor()) { TypeReference returnType = methodDecl instanceof MethodDeclaration ? ((MethodDeclaration) methodDecl).returnType : null; if (returnType == null) { methodDecl.scope.problemReporter().missingReturnType(methodDecl); method.returnType = null; foundReturnTypeProblem = true; } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=322817 boolean deferRawTypeCheck = !reportUnavoidableGenericTypeProblems && (returnType.bits & ASTNode.IgnoreRawTypeCheck) == 0; TypeBinding methodType; if (deferRawTypeCheck) { returnType.bits |= ASTNode.IgnoreRawTypeCheck; } try { methodType = returnType.resolveType(methodDecl.scope, true /* check bounds*/); } finally { if (deferRawTypeCheck) { returnType.bits &= ~ASTNode.IgnoreRawTypeCheck; } } if (methodType == null) { foundReturnTypeProblem = true; } else { if ((methodType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } method.returnType = methodType; TypeBinding leafType = methodType.leafComponentType(); if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) method.modifiers |= ExtraCompilerModifiers.AccGenericSignature; } } } if (foundArgProblem) { methodDecl.binding = null; method.parameters = Binding.NO_PARAMETERS; // see 107004 // 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++) typeParameters[i].binding = null; return null; } CompilerOptions compilerOptions = this.scope.compilerOptions(); if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) { createArgumentBindings(method, compilerOptions); // need annotations resolved already at this point } if (foundReturnTypeProblem) return method; // but its still unresolved with a null return type & is still connected to its method declaration method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; return method; } private void createArgumentBindings(MethodBinding method, CompilerOptions compilerOptions) { initializeNullDefault(); AbstractMethodDeclaration methodDecl = method.sourceMethod(); if (methodDecl != null) { // while creating argument bindings we also collect explicit null annotations: if (method.parameters != Binding.NO_PARAMETERS) methodDecl.createArgumentBindings(); // add implicit annotations (inherited(?) & default): if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) { new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations).checkImplicitNullAnnotations(method, methodDecl, true, this.scope); } } } private void evaluateNullAnnotations(long annotationTagBits) { if (this.nullnessDefaultInitialized > 0 || !this.scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) return; boolean isPackageInfo = CharOperation.equals(this.sourceName, TypeConstants.PACKAGE_INFO_NAME); PackageBinding pkg = getPackage(); boolean isInDefaultPkg = (pkg.compoundName == CharOperation.NO_CHAR_CHAR); if (!isPackageInfo) { boolean isInNullnessAnnotationPackage = pkg == this.scope.environment().nonnullAnnotationPackage || pkg == this.scope.environment().nullableAnnotationPackage || pkg == this.scope.environment().nonnullByDefaultAnnotationPackage; if (pkg.defaultNullness == NO_NULL_DEFAULT && !isInDefaultPkg && !isInNullnessAnnotationPackage && !(this instanceof NestedTypeBinding)) { ReferenceBinding packageInfo = pkg.getType(TypeConstants.PACKAGE_INFO_NAME); if (packageInfo == null) { // no pkgInfo - complain this.scope.problemReporter().missingNonNullByDefaultAnnotation(this.scope.referenceContext); pkg.defaultNullness = NULL_UNSPECIFIED_BY_DEFAULT; } else { // if pkgInfo has no default annot. - complain packageInfo.getAnnotationTagBits(); } } } this.nullnessDefaultInitialized = 1; // transfer nullness info from tagBits to this.nullnessDefaultAnnotation int newDefaultNullness = NO_NULL_DEFAULT; if ((annotationTagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) newDefaultNullness = NULL_UNSPECIFIED_BY_DEFAULT; else if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0) newDefaultNullness = NONNULL_BY_DEFAULT; if (newDefaultNullness != NO_NULL_DEFAULT) { if (isPackageInfo) { pkg.defaultNullness = newDefaultNullness; } else { this.defaultNullness = newDefaultNullness; TypeDeclaration typeDecl = this.scope.referenceContext; long nullDefaultBits = annotationTagBits & (TagBits.AnnotationNullUnspecifiedByDefault|TagBits.AnnotationNonNullByDefault); checkRedundantNullnessDefaultRecurse(typeDecl, typeDecl.annotations, nullDefaultBits); } } else if (isPackageInfo || (isInDefaultPkg && !(this instanceof NestedTypeBinding))) { this.scope.problemReporter().missingNonNullByDefaultAnnotation(this.scope.referenceContext); if (!isInDefaultPkg) pkg.defaultNullness = NULL_UNSPECIFIED_BY_DEFAULT; } } protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) { if (this.fPackage.defaultNullness != NO_NULL_DEFAULT) { if ((this.fPackage.defaultNullness == NONNULL_BY_DEFAULT && ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0))) { this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this.fPackage); } return; } } // return: should caller continue searching? protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[] annotations, long annotationTagBits) { int thisDefault = this.defaultNullness; if (thisDefault == NONNULL_BY_DEFAULT) { if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0) { this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this); } return false; // different default means inner default is not redundant -> we're done } return true; } boolean hasNonNullDefault() { // find the applicable default inside->out: SourceTypeBinding currentType = null; Scope currentScope = this.scope; while (currentScope != null) { switch (currentScope.kind) { case Scope.METHOD_SCOPE: AbstractMethodDeclaration referenceMethod = ((MethodScope)currentScope).referenceMethod(); if (referenceMethod != null && referenceMethod.binding != null) { long methodTagBits = referenceMethod.binding.tagBits; if ((methodTagBits & TagBits.AnnotationNonNullByDefault) != 0) return true; if ((methodTagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) return false; } break; case Scope.CLASS_SCOPE: currentType = ((ClassScope)currentScope).referenceContext.binding; if (currentType != null) { int foundDefaultNullness = currentType.defaultNullness; if (foundDefaultNullness != NO_NULL_DEFAULT) { return foundDefaultNullness == NONNULL_BY_DEFAULT; } } break; } currentScope = currentScope.parent; } // package if (currentType != null) { return currentType.getPackage().defaultNullness == NONNULL_BY_DEFAULT; } return false; } public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) { if (forceInitialization) binding.getAnnotationTagBits(); // ensure annotations are up to date return super.retrieveAnnotationHolder(binding, false); } public void setFields(FieldBinding[] fields) { this.fields = fields; } public void setMethods(MethodBinding[] methods) { this.methods = methods; } public final int sourceEnd() { return this.scope.referenceContext.sourceEnd; } public final int sourceStart() { return this.scope.referenceContext.sourceStart; } SimpleLookupTable storedAnnotations(boolean forceInitialize) { if (forceInitialize && this.storedAnnotations == null && this.scope != null) { // scope null when no annotation cached, and type got processed fully (159631) this.scope.referenceCompilationUnit().compilationResult.hasAnnotations = true; if (!this.scope.environment().globalOptions.storeAnnotations) return null; // not supported during this compile this.storedAnnotations = new SimpleLookupTable(3); } return this.storedAnnotations; } public ReferenceBinding superclass() { return this.superclass; } public ReferenceBinding[] superInterfaces() { return this.superInterfaces; } public SyntheticMethodBinding[] syntheticMethods() { if (this.synthetics == null || this.synthetics[SourceTypeBinding.METHOD_EMUL] == null || this.synthetics[SourceTypeBinding.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; SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1]; Iterator methodArrayIterator = this.synthetics[SourceTypeBinding.METHOD_EMUL].values().iterator(); while (methodArrayIterator.hasNext()) { SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) methodArrayIterator.next(); for (int i = 0, max = methodAccessors.length; i < max; i++) { if (methodAccessors[i] != null) { if (index+1 > bindings.length) { System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + 1]), 0, index); } bindings[index++] = methodAccessors[i]; } } } // sort them in according to their own indexes int length; SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length]; for (int i = 0; i < length; i++){ SyntheticMethodBinding binding = bindings[i]; sortedBindings[binding.index] = binding; } return sortedBindings; } /** * Answer the collection of synthetic fields to append into the classfile */ public FieldBinding[] syntheticFields() { if (this.synthetics == null) return null; int fieldSize = this.synthetics[SourceTypeBinding.FIELD_EMUL] == null ? 0 : this.synthetics[SourceTypeBinding.FIELD_EMUL].size(); int literalSize = this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null ? 0 :this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size(); int totalSize = fieldSize + literalSize; if (totalSize == 0) return null; FieldBinding[] bindings = new FieldBinding[totalSize]; // add innerclass synthetics if (this.synthetics[SourceTypeBinding.FIELD_EMUL] != null){ Iterator elements = this.synthetics[SourceTypeBinding.FIELD_EMUL].values().iterator(); for (int i = 0; i < fieldSize; i++) { SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next(); bindings[synthBinding.index] = synthBinding; } } // add class literal synthetics if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] != null){ Iterator elements = this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].values().iterator(); for (int i = 0; i < literalSize; i++) { SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next(); bindings[fieldSize+synthBinding.index] = synthBinding; } } return bindings; } public String toString() { StringBuffer buffer = new StringBuffer(30); buffer.append("(id="); //$NON-NLS-1$ if (this.id == TypeIds.NoId) buffer.append("NoId"); //$NON-NLS-1$ else buffer.append(this.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$ if (isEnum()) buffer.append("enum "); //$NON-NLS-1$ else if (isAnnotationType()) buffer.append("@interface "); //$NON-NLS-1$ else if (isClass()) buffer.append("class "); //$NON-NLS-1$ else buffer.append("interface "); //$NON-NLS-1$ buffer.append((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$ if (this.typeVariables == null) { buffer.append(""); //$NON-NLS-1$ } else if (this.typeVariables != Binding.NO_TYPE_VARIABLES) { buffer.append("<"); //$NON-NLS-1$ for (int i = 0, length = this.typeVariables.length; i < length; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ if (this.typeVariables[i] == null) { buffer.append("NULL TYPE VARIABLE"); //$NON-NLS-1$ continue; } char[] varChars = this.typeVariables[i].toString().toCharArray(); buffer.append(varChars, 1, varChars.length - 2); } buffer.append(">"); //$NON-NLS-1$ } buffer.append("\n\textends "); //$NON-NLS-1$ buffer.append((this.superclass != null) ? this.superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$ if (this.superInterfaces != null) { if (this.superInterfaces != Binding.NO_SUPERINTERFACES) { buffer.append("\n\timplements : "); //$NON-NLS-1$ for (int i = 0, length = this.superInterfaces.length; i < length; i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append((this.superInterfaces[i] != null) ? this.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 (this.fields != null) { if (this.fields != Binding.NO_FIELDS) { buffer.append("\n/* fields */"); //$NON-NLS-1$ for (int i = 0, length = this.fields.length; i < length; i++) buffer.append('\n').append((this.fields[i] != null) ? this.fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$ } } else { buffer.append("NULL FIELDS"); //$NON-NLS-1$ } if (this.methods != null) { if (this.methods != Binding.NO_METHODS) { buffer.append("\n/* methods */"); //$NON-NLS-1$ for (int i = 0, length = this.methods.length; i < length; i++) buffer.append('\n').append((this.methods[i] != null) ? this.methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ } } else { buffer.append("NULL METHODS"); //$NON-NLS-1$ } if (this.memberTypes != null) { if (this.memberTypes != Binding.NO_MEMBER_TYPES) { buffer.append("\n/* members */"); //$NON-NLS-1$ for (int i = 0, length = this.memberTypes.length; i < length; i++) buffer.append('\n').append((this.memberTypes[i] != null) ? this.memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$ } } else { buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$ } buffer.append("\n\n"); //$NON-NLS-1$ return buffer.toString(); } public TypeVariableBinding[] typeVariables() { return this.typeVariables != null ? this.typeVariables : Binding.NO_TYPE_VARIABLES; } void verifyMethods(MethodVerifier verifier) { verifier.verify(this); for (int i = this.memberTypes.length; --i >= 0;) ((SourceTypeBinding) this.memberTypes[i]).verifyMethods(verifier); } public FieldBinding[] unResolvedFields() { return this.fields; } public void tagIndirectlyAccessibleMembers() { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=328281 for (int i = 0; i < this.fields.length; i++) { if (!this.fields[i].isPrivate()) this.fields[i].modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } for (int i = 0; i < this.memberTypes.length; i++) { if (!this.memberTypes[i].isPrivate()) this.memberTypes[i].modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } if (this.superclass.isPrivate()) if (this.superclass instanceof SourceTypeBinding) // should always be true because private super type can only be accessed in same CU ((SourceTypeBinding) this.superclass).tagIndirectlyAccessibleMembers(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java0000644000175000001440000002521512212041344031632 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 365662 - [compiler][null] warn on contradictory and redundant null annotations *******************************************************************************/ 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.Annotation; import org.eclipse.jdt.internal.compiler.ast.CaseStatement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; public final class LocalTypeBinding extends NestedTypeBinding { final static char[] LocalTypePrefix = { '$', 'L', 'o', 'c', 'a', 'l', '$' }; private InnerEmulationDependency[] dependents; public ArrayBinding[] localArrayBindings; // used to cache array bindings of various dimensions for this local type public CaseStatement enclosingCase; // from 1.4 on, local types should not be accessed across switch case blocks (52221) public int sourceStart; // used by computeUniqueKey to uniquely identify this binding public MethodBinding enclosingMethod; public LocalTypeBinding(ClassScope scope, SourceTypeBinding enclosingType, CaseStatement switchCase) { super( new char[][] {CharOperation.concat(LocalTypeBinding.LocalTypePrefix, scope.referenceContext.name)}, scope, enclosingType); TypeDeclaration typeDeclaration = scope.referenceContext; if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) { this.tagBits |= TagBits.AnonymousTypeMask; } else { this.tagBits |= TagBits.LocalTypeMask; } this.enclosingCase = switchCase; this.sourceStart = typeDeclaration.sourceStart; MethodScope methodScope = scope.enclosingMethodScope(); AbstractMethodDeclaration methodDeclaration = methodScope.referenceMethod(); if (methodDeclaration != null) { this.enclosingMethod = methodDeclaration.binding; } } /* Record a dependency onto a source target type which may be altered * by the end of the innerclass emulation. Later on, we will revisit * all its dependents so as to update them (see updateInnerEmulationDependents()). */ public void addInnerEmulationDependent(BlockScope dependentScope, boolean wasEnclosingInstanceSupplied) { int index; if (this.dependents == null) { index = 0; this.dependents = new InnerEmulationDependency[1]; } else { index = this.dependents.length; for (int i = 0; i < index; i++) if (this.dependents[i].scope == dependentScope) return; // already stored System.arraycopy(this.dependents, 0, (this.dependents = new InnerEmulationDependency[index + 1]), 0, index); } this.dependents[index] = new InnerEmulationDependency(dependentScope, wasEnclosingInstanceSupplied); // System.out.println("Adding dependency: "+ new String(scope.enclosingType().readableName()) + " --> " + new String(this.readableName())); } /* * Returns the anonymous original super type (in some error cases, superclass may get substituted with Object) */ public ReferenceBinding anonymousOriginalSuperType() { if (this.superInterfaces != Binding.NO_SUPERINTERFACES) { return this.superInterfaces[0]; } if ((this.tagBits & TagBits.HierarchyHasProblems) == 0) { return this.superclass; } if (this.scope != null) { TypeReference typeReference = this.scope.referenceContext.allocation.type; if (typeReference != null) { return (ReferenceBinding) typeReference.resolvedType; } } return this.superclass; // default answer } protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) { long outerDefault = this.enclosingMethod != null ? this.enclosingMethod.tagBits & ((TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault)) : 0; if (outerDefault != 0) { if (outerDefault == annotationTagBits) { this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this.enclosingMethod); } return; } super.checkRedundantNullnessDefaultRecurse(location, annotations, annotationTagBits); } public char[] computeUniqueKey(boolean isLeaf) { char[] outerKey = outermostEnclosingType().computeUniqueKey(isLeaf); int semicolon = CharOperation.lastIndexOf(';', outerKey); StringBuffer sig = new StringBuffer(); sig.append(outerKey, 0, semicolon); // insert $sourceStart sig.append('$'); sig.append(String.valueOf(this.sourceStart)); // insert $LocalName if local if (!isAnonymousType()) { sig.append('$'); sig.append(this.sourceName); } // insert remaining from outer key sig.append(outerKey, semicolon, outerKey.length-semicolon); int sigLength = sig.length(); char[] uniqueKey = new char[sigLength]; sig.getChars(0, sigLength, uniqueKey, 0); return uniqueKey; } public char[] constantPoolName() /* java/lang/Object */ { if (this.constantPoolName == null && this.scope != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=322154, we do have some // cases where the left hand does not know what the right is doing. this.constantPoolName = this.scope.compilationUnitScope().computeConstantPoolName(this); } return this.constantPoolName; } ArrayBinding createArrayType(int dimensionCount, LookupEnvironment lookupEnvironment) { if (this.localArrayBindings == null) { this.localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount, lookupEnvironment)}; return this.localArrayBindings[0]; } // find the cached array binding for this dimensionCount (if any) int length = this.localArrayBindings.length; for (int i = 0; i < length; i++) if (this.localArrayBindings[i].dimensions == dimensionCount) return this.localArrayBindings[i]; // no matching array System.arraycopy(this.localArrayBindings, 0, this.localArrayBindings = new ArrayBinding[length + 1], 0, length); return this.localArrayBindings[length] = new ArrayBinding(this, dimensionCount, lookupEnvironment); } /* * Overriden for code assist. In this case, the constantPoolName() has not been computed yet. * Slam the source name so that the signature is syntactically correct. * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=99686) */ public char[] genericTypeSignature() { if (this.genericReferenceTypeSignature == null && this.constantPoolName == null) { if (isAnonymousType()) setConstantPoolName(superclass().sourceName()); else setConstantPoolName(sourceName()); } return super.genericTypeSignature(); } public char[] readableName() /*java.lang.Object, p.X */ { char[] readableName; if (isAnonymousType()) { readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, anonymousOriginalSuperType().readableName(), TypeConstants.ANONYM_SUFFIX); } else if (isMemberType()) { readableName = CharOperation.concat(enclosingType().readableName(), this.sourceName, '.'); } else { readableName = this.sourceName; } TypeVariableBinding[] typeVars; if ((typeVars = typeVariables()) != Binding.NO_TYPE_VARIABLES) { 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*/ { char[] shortReadableName; if (isAnonymousType()) { shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, anonymousOriginalSuperType().shortReadableName(), TypeConstants.ANONYM_SUFFIX); } else if (isMemberType()) { shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), this.sourceName, '.'); } else { shortReadableName = this.sourceName; } TypeVariableBinding[] typeVars; if ((typeVars = typeVariables()) != Binding.NO_TYPE_VARIABLES) { 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 public void setAsMemberType() { this.tagBits |= TagBits.MemberTypeMask; } public void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Object */ { this.constantPoolName = computedConstantPoolName; } /* * Overriden for code assist. In this case, the constantPoolName() has not been computed yet. * Slam the source name so that the signature is syntactically correct. * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=102284) */ public char[] signature() { if (this.signature == null && this.constantPoolName == null) { if (isAnonymousType()) setConstantPoolName(superclass().sourceName()); else setConstantPoolName(sourceName()); } return super.signature(); } public char[] sourceName() { if (isAnonymousType()) { return CharOperation.concat(TypeConstants.ANONYM_PREFIX, anonymousOriginalSuperType().sourceName(), TypeConstants.ANONYM_SUFFIX); } else return this.sourceName; } public String toString() { if (isAnonymousType()) return "Anonymous type : " + super.toString(); //$NON-NLS-1$ if (isMemberType()) return "Local member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$ return "Local type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$ } /* Trigger the dependency mechanism forcing the innerclass emulation * to be propagated to all dependent source types. */ public void updateInnerEmulationDependents() { if (this.dependents != null) { for (int i = 0; i < this.dependents.length; i++) { InnerEmulationDependency dependency = this.dependents[i]; // System.out.println("Updating " + new String(this.readableName()) + " --> " + new String(dependency.scope.enclosingType().readableName())); dependency.scope.propagateInnerEmulation(this, dependency.wasEnclosingInstanceSupplied); } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java0000644000175000001440000001662412212041344031335 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.core.compiler.CharOperation; /** * 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); this.tagBits &= ~TagBits.HasMissingType; if ((type.tagBits & TagBits.HasMissingType) != 0) { if (type instanceof MissingTypeBinding) { this.tagBits |= TagBits.HasMissingType; } else if (type instanceof ParameterizedTypeBinding) { ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) type; if (parameterizedTypeBinding.genericType() instanceof MissingTypeBinding) { this.tagBits |= TagBits.HasMissingType; } } } if (enclosingType != null && (enclosingType.tagBits & TagBits.HasMissingType) != 0) { if (enclosingType instanceof MissingTypeBinding) { this.tagBits |= TagBits.HasMissingType; } else if (enclosingType instanceof ParameterizedTypeBinding) { ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) enclosingType; if (parameterizedTypeBinding.genericType() instanceof MissingTypeBinding) { this.tagBits |= TagBits.HasMissingType; } } } if (enclosingType == null || (enclosingType.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) { this.modifiers &= ~ExtraCompilerModifiers.AccGenericSignature; // only need signature if enclosing needs one } } public char[] computeUniqueKey(boolean isLeaf) { StringBuffer sig = new StringBuffer(10); if (isMemberType() && enclosingType().isParameterizedType()) { char[] typeSig = enclosingType().computeUniqueKey(false/*not a leaf*/); sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon sig.append('.').append(sourceName()).append('<').append('>').append(';'); } else { sig.append(genericType().computeUniqueKey(false/*not a leaf*/)); sig.insert(sig.length()-1, "<>"); //$NON-NLS-1$ } int sigLength = sig.length(); char[] uniqueKey = new char[sigLength]; sig.getChars(0, sigLength, uniqueKey, 0); return uniqueKey; } /** * @see org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding#createParameterizedMethod(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) */ public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) { if (originalMethod.typeVariables == Binding.NO_TYPE_VARIABLES || originalMethod.isStatic()) { return super.createParameterizedMethod(originalMethod); } return this.environment.createParameterizedGenericMethod(originalMethod, this); } 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(actualType().sourceName()).append("#RAW"); //$NON-NLS-1$ return nameBuffer.toString(); } /** * Ltype; * LY; */ public char[] genericTypeSignature() { if (this.genericTypeSignature == null) { if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) { this.genericTypeSignature = genericType().signature(); } else { StringBuffer sig = new StringBuffer(10); if (isMemberType()) { ReferenceBinding enclosing = enclosingType(); char[] typeSig = enclosing.genericTypeSignature(); sig.append(typeSig, 0, typeSig.length-1);// copy all but trailing semicolon if ((enclosing.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) { sig.append('.'); } else { sig.append('$'); } sig.append(sourceName()); } else { char[] typeSig = genericType().signature(); sig.append(typeSig, 0, typeSig.length-1);// copy all but trailing semicolon } sig.append(';'); int sigLength = sig.length(); this.genericTypeSignature = new char[sigLength]; sig.getChars(0, sigLength, this.genericTypeSignature, 0); } } return this.genericTypeSignature; } public boolean isEquivalentTo(TypeBinding otherType) { if (this == otherType || erasure() == otherType) return true; if (otherType == null) return false; switch(otherType.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE: return ((WildcardBinding) otherType).boundCheck(this); case Binding.GENERIC_TYPE : case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : return erasure() == otherType.erasure(); } return false; } public boolean isProvablyDistinct(TypeBinding otherType) { if (this == otherType || erasure() == otherType) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=329588 return false; if (otherType == null) return true; switch(otherType.kind()) { case Binding.GENERIC_TYPE : case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : return erasure() != otherType.erasure(); } return true; } protected void initializeArguments() { TypeVariableBinding[] typeVariables = genericType().typeVariables(); int length = typeVariables.length; TypeBinding[] typeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { // perform raw conversion on variable upper bound - could cause infinite regression if arguments were initialized lazily typeArguments[i] = this.environment.convertToRawType(typeVariables[i].erasure(), false /*do not force conversion of enclosing types*/); } 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(), this.sourceName, '.'); } else { readableName = CharOperation.concatWith(actualType().compoundName, '.'); } return readableName; } /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName() */ public char[] shortReadableName() /*Object*/ { char[] shortReadableName; if (isMemberType()) { shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), this.sourceName, '.'); } else { shortReadableName = actualType().sourceName; } return shortReadableName; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java0000644000175000001440000002377312212041344032031 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 365662 - [compiler][null] warn on contradictory and redundant null annotations * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Annotation; public class NestedTypeBinding extends SourceTypeBinding { public SourceTypeBinding enclosingType; public SyntheticArgumentBinding[] enclosingInstances; private ReferenceBinding[] enclosingTypes = Binding.UNINITIALIZED_REFERENCE_TYPES; public SyntheticArgumentBinding[] outerLocalVariables; private int outerLocalVariablesSlotSize = -1; // amount of slots used by synthetic outer local variables public NestedTypeBinding(char[][] typeName, ClassScope scope, SourceTypeBinding enclosingType) { super(typeName, enclosingType.fPackage, scope); this.tagBits |= (TagBits.IsNestedType | TagBits.ContainsNestedTypeReferences); this.enclosingType = enclosingType; } /* Add a new synthetic argument for . * Answer the new argument or the existing argument if one already existed. */ public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) { SyntheticArgumentBinding synthLocal = null; if (this.outerLocalVariables == null) { synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable); this.outerLocalVariables = new SyntheticArgumentBinding[] {synthLocal}; } else { int size = this.outerLocalVariables.length; int newArgIndex = size; for (int i = size; --i >= 0;) { // must search backwards if (this.outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable) return this.outerLocalVariables[i]; // already exists if (this.outerLocalVariables[i].id > actualOuterLocalVariable.id) newArgIndex = i; } SyntheticArgumentBinding[] synthLocals = new SyntheticArgumentBinding[size + 1]; System.arraycopy(this.outerLocalVariables, 0, synthLocals, 0, newArgIndex); synthLocals[newArgIndex] = synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable); System.arraycopy(this.outerLocalVariables, newArgIndex, synthLocals, newArgIndex + 1, size - newArgIndex); this.outerLocalVariables = synthLocals; } //System.out.println("Adding synth arg for local var: " + new String(actualOuterLocalVariable.name) + " to: " + new String(this.readableName())); if (this.scope.referenceCompilationUnit().isPropagatingInnerClassEmulation) updateInnerEmulationDependents(); return synthLocal; } /* Add a new synthetic argument for . * Answer the new argument or the existing argument if one already existed. */ public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding targetEnclosingType) { SyntheticArgumentBinding synthLocal = null; if (this.enclosingInstances == null) { synthLocal = new SyntheticArgumentBinding(targetEnclosingType); this.enclosingInstances = new SyntheticArgumentBinding[] {synthLocal}; } else { int size = this.enclosingInstances.length; int newArgIndex = size; if (enclosingType() == targetEnclosingType) newArgIndex = 0; SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1]; System.arraycopy(this.enclosingInstances, 0, newInstances, newArgIndex == 0 ? 1 : 0, size); newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(targetEnclosingType); this.enclosingInstances = newInstances; } //System.out.println("Adding synth arg for enclosing type: " + new String(enclosingType.readableName()) + " to: " + new String(this.readableName())); if (this.scope.referenceCompilationUnit().isPropagatingInnerClassEmulation) updateInnerEmulationDependents(); return synthLocal; } /* Add a new synthetic argument and field for . * Answer the new argument or the existing argument if one already existed. */ public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBinding actualOuterLocalVariable) { SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable); if (synthLocal == null) return null; if (synthLocal.matchingField == null) synthLocal.matchingField = addSyntheticFieldForInnerclass(actualOuterLocalVariable); return synthLocal; } /* Add a new synthetic argument and field for . * Answer the new argument or the existing argument if one already existed. */ public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding targetEnclosingType) { SyntheticArgumentBinding synthLocal = addSyntheticArgument(targetEnclosingType); if (synthLocal == null) return null; if (synthLocal.matchingField == null) synthLocal.matchingField = addSyntheticFieldForInnerclass(targetEnclosingType); return synthLocal; } protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) { ReferenceBinding currentType = this.enclosingType; do { if (!((SourceTypeBinding)currentType).checkRedundantNullnessDefaultOne(location, annotations, annotationTagBits)) { return; } currentType = currentType.enclosingType(); } while (currentType instanceof SourceTypeBinding); super.checkRedundantNullnessDefaultRecurse(location, annotations, annotationTagBits); } /* Answer the receiver's enclosing type... null if the receiver is a top level type. */ public ReferenceBinding enclosingType() { return this.enclosingType; } /** * @return the enclosingInstancesSlotSize */ public int getEnclosingInstancesSlotSize() { return this.enclosingInstances == null ? 0 : this.enclosingInstances.length; } /** * @return the outerLocalVariablesSlotSize */ public int getOuterLocalVariablesSlotSize() { if (this.outerLocalVariablesSlotSize < 0) { this.outerLocalVariablesSlotSize = 0; int outerLocalsCount = this.outerLocalVariables == null ? 0 : this.outerLocalVariables.length; for (int i = 0; i < outerLocalsCount; i++){ SyntheticArgumentBinding argument = this.outerLocalVariables[i]; switch (argument.type.id) { case TypeIds.T_long : case TypeIds.T_double : this.outerLocalVariablesSlotSize += 2; break; default : this.outerLocalVariablesSlotSize ++; break; } } } return this.outerLocalVariablesSlotSize; } /* Answer the synthetic argument for or null if one does not exist. */ public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) { if (this.outerLocalVariables == null) return null; // is null if no outer local variables are known for (int i = this.outerLocalVariables.length; --i >= 0;) if (this.outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable) return this.outerLocalVariables[i]; return null; } /* Answer the synthetic argument for or null if one does not exist. */ public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, boolean onlyExactMatch, boolean scopeIsConstructorCall) { if (this.enclosingInstances == null) return null; // is null if no enclosing instances are known // exact match // firstly, during allocation, check and use the leftmost one (if possible) // to handle cases involving two instances of same type, such as // class X { // class Inner extends X {} // void f(){ // new X().new Inner(){} // // here the result of (new X()) is passed as the first (synthetic) arg for ctor of new Inner(){} // // (and (this) as the second, of course) // } // } if (scopeIsConstructorCall && this.enclosingInstances.length > 0) if (this.enclosingInstances[0].type == targetEnclosingType) if (this.enclosingInstances[0].actualOuterLocalVariable == null) return this.enclosingInstances[0]; // then check other possibility for (int i = this.enclosingInstances.length; --i >= 0;) if (this.enclosingInstances[i].type == targetEnclosingType) if (this.enclosingInstances[i].actualOuterLocalVariable == null) return this.enclosingInstances[i]; // type compatibility : to handle cases such as // 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){ for (int i = this.enclosingInstances.length; --i >= 0;) if (this.enclosingInstances[i].actualOuterLocalVariable == null) if (this.enclosingInstances[i].type.findSuperTypeOriginatingFrom(targetEnclosingType) != null) return this.enclosingInstances[i]; } return null; } public SyntheticArgumentBinding[] syntheticEnclosingInstances() { return this.enclosingInstances; // is null if no enclosing instances are required } public ReferenceBinding[] syntheticEnclosingInstanceTypes() { if (this.enclosingTypes == UNINITIALIZED_REFERENCE_TYPES) { if (this.enclosingInstances == null) { this.enclosingTypes = null; } else { int length = this.enclosingInstances.length; this.enclosingTypes = new ReferenceBinding[length]; for (int i = 0; i < length; i++) { this.enclosingTypes[i] = (ReferenceBinding) this.enclosingInstances[i].type; } } } return this.enclosingTypes; } public SyntheticArgumentBinding[] syntheticOuterLocalVariables() { return this.outerLocalVariables; // is null if no outer locals are required } /* * Trigger the dependency mechanism forcing the innerclass emulation * to be propagated to all dependent source types. */ public void updateInnerEmulationDependents() { // nothing to do in general, only local types are doing anything } } ././@LongLink0000644000000000000000000000016012251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVe0000644000175000001440000004670712212041344032467 0ustar dokousers/******************************************************************************* * Copyright (c) 2012, 2013 GK Software AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stephan Herrmann - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; /** * Extracted slice from MethodVerifier15, which is responsible only for implicit null annotations. * First, if enabled, it detects overridden methods from which null annotations are inherited. * Next, also default nullness is filled into remaining empty slots. * After all implicit annotations have been filled in compatibility is checked and problems are complained. */ public class ImplicitNullAnnotationVerifier { /** * Simple record to store nullness info for one argument or return type * while iterating over a set of overridden methods. */ static class InheritedNonNullnessInfo { Boolean inheritedNonNullness; MethodBinding annotationOrigin; boolean complained; } // delegate which to ask for recursive analysis of super methods // can be 'this', but is never a MethodVerifier (to avoid infinite recursion). ImplicitNullAnnotationVerifier buddyImplicitNullAnnotationsVerifier; private boolean inheritNullAnnotations; public ImplicitNullAnnotationVerifier(boolean inheritNullAnnotations) { this.buddyImplicitNullAnnotationsVerifier = this; this.inheritNullAnnotations = inheritNullAnnotations; } // for sub-classes: ImplicitNullAnnotationVerifier(CompilerOptions options) { this.buddyImplicitNullAnnotationsVerifier = new ImplicitNullAnnotationVerifier(options.inheritNullAnnotations); this.inheritNullAnnotations = options.inheritNullAnnotations; } /** * Check and fill in implicit annotations from overridden methods and from default. * Precondition: caller has checked whether annotation-based null analysis is enabled. */ public void checkImplicitNullAnnotations(MethodBinding currentMethod, AbstractMethodDeclaration srcMethod, boolean complain, Scope scope) { // check inherited nullness from superclass and superInterfaces try { ReferenceBinding currentType = currentMethod.declaringClass; if (currentType.id == TypeIds.T_JavaLangObject) { return; } boolean needToApplyNonNullDefault = currentMethod.hasNonNullDefault(); // compatibility & inheritance do not consider constructors / static methods: boolean isInstanceMethod = !currentMethod.isConstructor() && !currentMethod.isStatic(); complain &= isInstanceMethod; if (!needToApplyNonNullDefault && !complain && !(this.inheritNullAnnotations && isInstanceMethod)) { return; // short cut, no work to be done } if (isInstanceMethod) { List superMethodList = new ArrayList(); int paramLen = currentMethod.parameters.length; findAllOverriddenMethods(currentMethod.original(), currentMethod.selector, paramLen, currentType, new HashSet(), superMethodList); // prepare interim storage for nullness info so we don't pollute currentMethod before we know its conflict-free: InheritedNonNullnessInfo[] inheritedNonNullnessInfos = new InheritedNonNullnessInfo[paramLen+1]; // index 0 is for the return type for (int i=0; i= 0;) { MethodBinding currentSuper = (MethodBinding) superMethodList.get(i); if ((currentSuper.tagBits & TagBits.IsNullnessKnown) == 0) { // recurse to prepare currentSuper checkImplicitNullAnnotations(currentSuper, null, false, scope); // TODO (stephan) complain=true if currentSuper is source method?? } checkNullSpecInheritance(currentMethod, srcMethod, needToApplyNonNullDefault, complain, currentSuper, scope, inheritedNonNullnessInfos); needToApplyNonNullDefault = false; } // transfer collected information into currentMethod: InheritedNonNullnessInfo info = inheritedNonNullnessInfos[0]; if (!info.complained) { if (info.inheritedNonNullness == Boolean.TRUE) { currentMethod.tagBits |= TagBits.AnnotationNonNull; } else if (info.inheritedNonNullness == Boolean.FALSE) { currentMethod.tagBits |= TagBits.AnnotationNullable; } } for (int i=0; i and X as the same 'type' if (one.isParameterizedType() && two.isParameterizedType()) return one.isEquivalentTo(two) && two.isEquivalentTo(one); // 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 } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java0000644000175000001440000004436012212041344031263 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 358903 - Filter practically unimportant resource leak warnings * bug 381445 - [compiler][resource] Can the resource leak check be made aware of Closeables.closeQuietly? * bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account * bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; // TODO should rename into TypeNames (once extracted last non name constants) public interface TypeConstants { char[] JAVA = "java".toCharArray(); //$NON-NLS-1$ char[] JAVAX = "javax".toCharArray(); //$NON-NLS-1$ char[] LANG = "lang".toCharArray(); //$NON-NLS-1$ char[] IO = "io".toCharArray(); //$NON-NLS-1$ char[] UTIL = "util".toCharArray(); //$NON-NLS-1$ char[] ZIP = "zip".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[] EQUALS = "equals".toCharArray(); //$NON-NLS-1$ char[] GETCLASS = "getClass".toCharArray(); //$NON-NLS-1$ char[] HASHCODE = "hashCode".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[] WILDCARD_CAPTURE_NAME_PREFIX = "capture#".toCharArray(); //$NON-NLS-1$ char[] WILDCARD_CAPTURE_NAME_SUFFIX = "-of ".toCharArray(); //$NON-NLS-1$ char[] WILDCARD_CAPTURE = { '!' }; 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$ // common 3rd party package components: char[] ORG = "org".toCharArray(); //$NON-NLS-1$ char[] ECLIPSE = "eclipse".toCharArray(); //$NON-NLS-1$ char[] CORE = "core".toCharArray(); //$NON-NLS-1$ char[] RUNTIME = "runtime".toCharArray(); //$NON-NLS-1$ char[] APACHE = "apache".toCharArray(); //$NON-NLS-1$ char[] COMMONS = "commons".toCharArray(); //$NON-NLS-1$ char[] LANG3 = "lang3".toCharArray(); //$NON-NLS-1$ char[] COM = "com".toCharArray(); //$NON-NLS-1$ char[] GOOGLE = "google".toCharArray(); //$NON-NLS-1$ // Constant compound names 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_COLLECTION = {JAVA, UTIL, "Collection".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_UTIL_ITERATOR = {JAVA, UTIL, "Iterator".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_UTIL_OBJECTS = {JAVA, UTIL, "Objects".toCharArray()}; //$NON-NLS-1$ 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$ char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {JAVA, LANG, REFLECT, "Field".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {JAVA, LANG, REFLECT, "Method".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_IO_CLOSEABLE = new char[][] { JAVA, IO, "Closeable".toCharArray()};//$NON-NLS-1$ char[][] JAVA_IO_OBJECTSTREAMEXCEPTION = new char[][] { JAVA, IO, "ObjectStreamException".toCharArray()};//$NON-NLS-1$ char[][] JAVA_IO_EXTERNALIZABLE = {JAVA, IO, "Externalizable".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_IO_IOEXCEPTION = new char[][] { JAVA, IO, "IOException".toCharArray()};//$NON-NLS-1$ char[][] JAVA_IO_OBJECTOUTPUTSTREAM = new char[][] { JAVA, IO, "ObjectOutputStream".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_IO_OBJECTINPUTSTREAM = new char[][] { JAVA, IO, "ObjectInputStream".toCharArray()}; //$NON-NLS-1$ // javax.rmi.CORBA.Stub char[][] JAVAX_RMI_CORBA_STUB = new char[][] { JAVAX, "rmi".toCharArray(), //$NON-NLS-1$ "CORBA".toCharArray(), //$NON-NLS-1$ "Stub".toCharArray(), //$NON-NLS-1$ }; char[][] JAVA_LANG_SAFEVARARGS = {JAVA, LANG, "SafeVarargs".toCharArray()}; //$NON-NLS-1$ char[] INVOKE = "invoke".toCharArray(); //$NON-NLS-1$ char[][] JAVA_LANG_INVOKE_METHODHANDLE_POLYMORPHICSIGNATURE = { // Signature while parsing binary file JAVA, LANG, INVOKE, "MethodHandle".toCharArray(), //$NON-NLS-1$ "PolymorphicSignature".toCharArray() //$NON-NLS-1$ }; char[][] JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE = { // Signature while parsing source file JAVA, LANG, INVOKE, "MethodHandle$PolymorphicSignature".toCharArray() //$NON-NLS-1$ }; char[][] JAVA_LANG_AUTOCLOSEABLE = {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$ char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$ // known helper functions for closing a Closeable (all receive a Closeable as their first argument): public static class CloseMethodRecord { public char[][] typeName; public char[] selector; public CloseMethodRecord(char[][] typeName, char[] selector) { this.typeName = typeName; this.selector = selector; } } char[][] GUAVA_CLOSEABLES = { COM, GOOGLE, "common".toCharArray(), IO, "Closeables".toCharArray() }; //$NON-NLS-1$ //$NON-NLS-2$ char[][] APACHE_IOUTILS = { ORG, APACHE, COMMONS, IO, "IOUtils".toCharArray() }; //$NON-NLS-1$ char[] CLOSE_QUIETLY = "closeQuietly".toCharArray(); //$NON-NLS-1$ CloseMethodRecord[] closeMethods = new CloseMethodRecord[] { new CloseMethodRecord(GUAVA_CLOSEABLES, CLOSE_QUIETLY), new CloseMethodRecord(GUAVA_CLOSEABLES, CLOSE), new CloseMethodRecord(APACHE_IOUTILS, CLOSE_QUIETLY) }; // white lists of closeables: char[][] JAVA_IO_WRAPPER_CLOSEABLES = new char[][] { "BufferedInputStream".toCharArray(), //$NON-NLS-1$ "BufferedOutputStream".toCharArray(), //$NON-NLS-1$ "BufferedReader".toCharArray(), //$NON-NLS-1$ "BufferedWriter".toCharArray(), //$NON-NLS-1$ "InputStreamReader".toCharArray(), //$NON-NLS-1$ "PrintWriter".toCharArray(), //$NON-NLS-1$ "LineNumberReader".toCharArray(), //$NON-NLS-1$ "DataInputStream".toCharArray(), //$NON-NLS-1$ "DataOutputStream".toCharArray(), //$NON-NLS-1$ "ObjectInputStream".toCharArray(), //$NON-NLS-1$ "ObjectOutputStream".toCharArray(), //$NON-NLS-1$ "FilterInputStream".toCharArray(), //$NON-NLS-1$ "FilterOutputStream".toCharArray(), //$NON-NLS-1$ "DataInputStream".toCharArray(), //$NON-NLS-1$ "DataOutputStream".toCharArray(), //$NON-NLS-1$ "PushbackInputStream".toCharArray(), //$NON-NLS-1$ "SequenceInputStream".toCharArray(), //$NON-NLS-1$ "PrintStream".toCharArray(), //$NON-NLS-1$ "PushbackReader".toCharArray(), //$NON-NLS-1$ "OutputStreamWriter".toCharArray(), //$NON-NLS-1$ }; char[][] JAVA_UTIL_ZIP_WRAPPER_CLOSEABLES = new char[][] { "GZIPInputStream".toCharArray(), //$NON-NLS-1$ "InflaterInputStream".toCharArray(), //$NON-NLS-1$ "DeflaterInputStream".toCharArray(), //$NON-NLS-1$ "CheckedInputStream".toCharArray(), //$NON-NLS-1$ "ZipInputStream".toCharArray(), //$NON-NLS-1$ "JarInputStream".toCharArray(), //$NON-NLS-1$ "GZIPOutputStream".toCharArray(), //$NON-NLS-1$ "InflaterOutputStream".toCharArray(), //$NON-NLS-1$ "DeflaterOutputStream".toCharArray(), //$NON-NLS-1$ "CheckedOutputStream".toCharArray(), //$NON-NLS-1$ "ZipOutputStream".toCharArray(), //$NON-NLS-1$ "JarOutputStream".toCharArray(), //$NON-NLS-1$ }; char[][][] OTHER_WRAPPER_CLOSEABLES = new char[][][] { {JAVA, "security".toCharArray(), "DigestInputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ {JAVA, "security".toCharArray(), "DigestOutputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ {JAVA, "beans".toCharArray(), "XMLEncoder".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ {JAVA, "beans".toCharArray(), "XMLDecoder".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ {JAVAX, "sound".toCharArray(), "sampled".toCharArray(), "AudioInputStream".toCharArray()}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ }; char[][] JAVA_IO_RESOURCE_FREE_CLOSEABLES = new char[][] { "StringReader".toCharArray(), //$NON-NLS-1$ "StringWriter".toCharArray(), //$NON-NLS-1$ "ByteArrayInputStream".toCharArray(), //$NON-NLS-1$ "ByteArrayOutputStream".toCharArray(), //$NON-NLS-1$ "CharArrayReader".toCharArray(), //$NON-NLS-1$ "CharArrayWriter".toCharArray(), //$NON-NLS-1$ "StringBufferInputStream".toCharArray(), //$NON-NLS-1$ }; // different assertion utilities: char[] ASSERT_CLASS = "Assert".toCharArray(); //$NON-NLS-1$ char[][] ORG_ECLIPSE_CORE_RUNTIME_ASSERT = new char[][] { ORG, ECLIPSE, CORE, RUNTIME, ASSERT_CLASS }; // ... methods: char[] IS_NOTNULL = "isNotNull".toCharArray(); //$NON-NLS-1$ char[] JUNIT = "junit".toCharArray(); //$NON-NLS-1$ char[] FRAMEWORK = "framework".toCharArray(); //$NON-NLS-1$ char[][] JUNIT_FRAMEWORK_ASSERT = new char[][] { JUNIT, FRAMEWORK, ASSERT_CLASS }; char[][] ORG_JUNIT_ASSERT = new char[][] { ORG, JUNIT, ASSERT_CLASS }; // ... methods: char[] ASSERT_NULL = "assertNull".toCharArray(); //$NON-NLS-1$ char[] ASSERT_NOTNULL = "assertNotNull".toCharArray(); //$NON-NLS-1$ char[] ASSERT_TRUE = "assertTrue".toCharArray(); //$NON-NLS-1$ char[] ASSERT_FALSE = "assertFalse".toCharArray(); //$NON-NLS-1$ char[] VALIDATE_CLASS = "Validate".toCharArray(); //$NON-NLS-1$ char[][] ORG_APACHE_COMMONS_LANG_VALIDATE = new char[][] { ORG, APACHE, COMMONS, LANG, VALIDATE_CLASS }; char[][] ORG_APACHE_COMMONS_LANG3_VALIDATE = new char[][] { ORG, APACHE, COMMONS, LANG3, VALIDATE_CLASS }; // ... methods: char[] IS_TRUE = "isTrue".toCharArray(); //$NON-NLS-1$ char[] NOT_NULL = "notNull".toCharArray(); //$NON-NLS-1$ char[][] COM_GOOGLE_COMMON_BASE_PRECONDITIONS = new char[][] { COM, GOOGLE, "common".toCharArray(), "base".toCharArray(), "Preconditions".toCharArray() }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // ... methods: char[] CHECK_NOT_NULL = "checkNotNull".toCharArray(); //$NON-NLS-1$ char[] CHECK_ARGUMENT = "checkArgument".toCharArray(); //$NON-NLS-1$ char[] CHECK_STATE = "checkState".toCharArray(); //$NON-NLS-1$ // ... methods in java.util.Objects: char[] REQUIRE_NON_NULL = "requireNonNull".toCharArray(); //$NON-NLS-1$ // different @Inject annotations are relevant for @NonNull fields char[] INJECT_PACKAGE = "inject".toCharArray(); //$NON-NLS-1$ char[] INJECT_TYPE = "Inject".toCharArray(); //$NON-NLS-1$ char[][] JAVAX_ANNOTATION_INJECT_INJECT = new char[][] { JAVAX, INJECT_PACKAGE, INJECT_TYPE }; char[][] COM_GOOGLE_INJECT_INJECT = new char[][] {COM, GOOGLE, INJECT_PACKAGE, INJECT_TYPE }; // detail for the above: char[] OPTIONAL = "optional".toCharArray(); //$NON-NLS-1$ // Constraints for generic type argument inference int CONSTRAINT_EQUAL = 0; // Actual = Formal int CONSTRAINT_EXTENDS = 1; // Actual << Formal int CONSTRAINT_SUPER = 2; // Actual >> Formal // Constants used to perform bound checks int OK = 0; int UNCHECKED = 1; int MISMATCH = 2; // Synthetics char[] INIT = "".toCharArray(); //$NON-NLS-1$ char[] CLINIT = "".toCharArray(); //$NON-NLS-1$ char[] SYNTHETIC_SWITCH_ENUM_TABLE = "$SWITCH_TABLE$".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$ char[] SYNTHETIC_ENUM_CONSTANT_INITIALIZATION_METHOD_PREFIX = " enum constant initialization$".toCharArray(); //$NON-NLS-1$ char[] SYNTHETIC_STATIC_FACTORY = "".toCharArray(); //$NON-NLS-1$ // synthetic package-info name public static final char[] PACKAGE_INFO_NAME = "package-info".toCharArray(); //$NON-NLS-1$ } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/PolymorphicMethodBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/PolymorphicMethodBinding0000644000175000001440000000512412212041344032461 0ustar dokousers/******************************************************************************* * Copyright (c) 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; /** * Binding denoting a polymorphic method */ public class PolymorphicMethodBinding extends MethodBinding { protected MethodBinding polymorphicMethod; public PolymorphicMethodBinding(MethodBinding polymorphicMethod, TypeBinding[] parameterTypes) { super( polymorphicMethod.modifiers, polymorphicMethod.selector, polymorphicMethod.returnType, parameterTypes, polymorphicMethod.thrownExceptions, polymorphicMethod.declaringClass); this.polymorphicMethod = polymorphicMethod; this.tagBits = polymorphicMethod.tagBits; } public PolymorphicMethodBinding(MethodBinding polymorphicMethod, TypeBinding returnType, TypeBinding[] parameterTypes) { super( polymorphicMethod.modifiers, polymorphicMethod.selector, returnType, parameterTypes, polymorphicMethod.thrownExceptions, polymorphicMethod.declaringClass); this.polymorphicMethod = polymorphicMethod; this.tagBits = polymorphicMethod.tagBits; } public MethodBinding original() { return this.polymorphicMethod; } public boolean isPolymorphic() { return true; } public boolean matches(TypeBinding[] matchingParameters, TypeBinding matchingReturnType) { int cachedParametersLength = this.parameters == null ? 0 : this.parameters.length; int matchingParametersLength = matchingParameters == null ? 0 : matchingParameters.length; if (matchingParametersLength != cachedParametersLength) { return false; } for (int j = 0; j < cachedParametersLength; j++){ if (this.parameters[j] != matchingParameters[j]) { return false; } } TypeBinding cachedReturnType = this.returnType; if (matchingReturnType == null) { if (cachedReturnType != null) { return false; } } else if (cachedReturnType == null) { return false; } else if (matchingReturnType != cachedReturnType) { return false; } // all arguments match return true; } /* * Even if polymorphic methods are varargs method, we don't want them to be treated as varargs method */ public boolean isVarargs() { return false; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java0000644000175000001440000000371512212041344031402 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 384380 - False positive on a « Potential null pointer access » after a continue *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.internal.compiler.ast.ASTNode; public interface InvocationSite { TypeBinding[] genericTypeArguments(); boolean isSuperAccess(); boolean isTypeAccess(); // in case the receiver type does not match the actual receiver type // e.g. pkg.Type.C (receiver type of C is type of source context, // but actual receiver type is pkg.Type) // e.g2. in presence of implicit access to enclosing type void setActualReceiverType(ReferenceBinding receiverType); void setDepth(int depth); void setFieldIndex(int depth); int sourceEnd(); int sourceStart(); TypeBinding expectedType(); static class EmptyWithAstNode implements InvocationSite { ASTNode node; public EmptyWithAstNode(ASTNode node) { this.node = node; } public TypeBinding[] genericTypeArguments() { return null;} public boolean isSuperAccess() {return false;} public boolean isTypeAccess() {return false;} public void setActualReceiverType(ReferenceBinding receiverType) {/* empty */} public void setDepth(int depth) {/* empty */ } public void setFieldIndex(int depth) {/* empty */ } public int sourceEnd() {return this.node.sourceEnd; } public int sourceStart() {return this.node.sourceStart; } public TypeBinding expectedType() { return null; } } } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.j0000644000175000001440000005027112212041344032361 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 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 TypeBinding targetEnumType; // enum type public int purpose; // fields used to generate enum constants when too many public int startIndex; public int endIndex; public final static int FieldReadAccess = 1; // field read public final static int FieldWriteAccess = 2; // field write public final static int SuperFieldReadAccess = 3; // super field read public final static int SuperFieldWriteAccess = 4; // super field write public final static int MethodAccess = 5; // normal method public final static int ConstructorAccess = 6; // constructor public final static int SuperMethodAccess = 7; // super method public final static int BridgeMethod = 8; // bridge method public final static int EnumValues = 9; // enum #values() public final static int EnumValueOf = 10; // enum #valueOf(String) public final static int SwitchTable = 11; // switch table method public final static int TooManyEnumsConstants = 12; // too many enum constants public int sourceStart = 0; // start position of the matching declaration public int index; // used for sorting access methods in the class file public SyntheticMethodBinding(FieldBinding targetField, boolean isReadAccess, boolean isSuperAccess, ReferenceBinding declaringClass) { this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass; SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods(); int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; this.index = methodId; this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray()); if (isReadAccess) { this.returnType = targetField.type; if (targetField.isStatic()) { this.parameters = Binding.NO_PARAMETERS; } else { this.parameters = new TypeBinding[1]; this.parameters[0] = declaringSourceType; } this.targetReadField = targetField; this.purpose = isSuperAccess ? SyntheticMethodBinding.SuperFieldReadAccess : SyntheticMethodBinding.FieldReadAccess; } else { this.returnType = TypeBinding.VOID; if (targetField.isStatic()) { this.parameters = new TypeBinding[1]; this.parameters[0] = targetField.type; } else { this.parameters = new TypeBinding[2]; this.parameters[0] = declaringSourceType; this.parameters[1] = targetField.type; } this.targetWriteField = targetField; this.purpose = isSuperAccess ? SyntheticMethodBinding.SuperFieldWriteAccess : SyntheticMethodBinding.FieldWriteAccess; } this.thrownExceptions = Binding.NO_EXCEPTIONS; this.declaringClass = declaringSourceType; // check for method collision boolean needRename; do { check : { needRename = false; // check for collision with known methods long range; MethodBinding[] methods = declaringSourceType.methods(); if ((range = ReferenceBinding.binarySearch(this.selector, methods)) >= 0) { int paramCount = this.parameters.length; nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = methods[imethod]; if (method.parameters.length == paramCount) { TypeBinding[] toMatch = method.parameters; for (int i = 0; i < paramCount; i++) { if (toMatch[i] != this.parameters[i]) { continue nextMethod; } } needRename = true; break check; } } } // check for collision with synthetic accessors if (knownAccessMethods != null) { for (int i = 0, length = knownAccessMethods.length; i < length; i++) { if (knownAccessMethods[i] == null) continue; if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && areParametersEqual(methods[i])) { needRename = true; break check; } } } } if (needRename) { // retry with a selector postfixed by a growing methodId setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray())); } } while (needRename); // retrieve sourceStart position for the target field for line number attributes FieldDeclaration[] fieldDecls = declaringSourceType.scope.referenceContext.fields; if (fieldDecls != null) { for (int i = 0, max = fieldDecls.length; i < max; i++) { if (fieldDecls[i].binding == targetField) { this.sourceStart = fieldDecls[i].sourceStart; return; } } } /* did not find the target field declaration - it is a synthetic one public class A { public class B { public class C { void foo() { System.out.println("A.this = " + A.this); } } } public static void main(String args[]) { new A().new B().new C().foo(); } } */ // We now at this point - per construction - it is for sure an enclosing instance, we are going to // show the target field type declaration location. this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; // use the target declaring class name position instead } public SyntheticMethodBinding(FieldBinding targetField, ReferenceBinding declaringClass, TypeBinding enumBinding, char[] selector) { this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass; SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods(); int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; this.index = methodId; this.selector = selector; this.returnType = declaringSourceType.scope.createArrayType(TypeBinding.INT, 1); this.parameters = Binding.NO_PARAMETERS; this.targetReadField = targetField; this.targetEnumType = enumBinding; this.purpose = SyntheticMethodBinding.SwitchTable; this.thrownExceptions = Binding.NO_EXCEPTIONS; this.declaringClass = declaringSourceType; if (declaringSourceType.isStrictfp()) { this.modifiers |= ClassFileConstants.AccStrictfp; } // check for method collision boolean needRename; do { check : { needRename = false; // check for collision with known methods long range; MethodBinding[] methods = declaringSourceType.methods(); if ((range = ReferenceBinding.binarySearch(this.selector, methods)) >= 0) { int paramCount = this.parameters.length; nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { MethodBinding method = methods[imethod]; if (method.parameters.length == paramCount) { TypeBinding[] toMatch = method.parameters; for (int i = 0; i < paramCount; i++) { if (toMatch[i] != this.parameters[i]) { continue nextMethod; } } needRename = true; break check; } } } // check for collision with synthetic accessors if (knownAccessMethods != null) { for (int i = 0, length = knownAccessMethods.length; i < length; i++) { if (knownAccessMethods[i] == null) continue; if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && areParametersEqual(methods[i])) { needRename = true; break check; } } } } if (needRename) { // retry with a selector postfixed by a growing methodId setSelector(CharOperation.concat(selector, String.valueOf(++methodId).toCharArray())); } } while (needRename); // We now at this point - per construction - it is for sure an enclosing instance, we are going to // show the target field type declaration location. this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; // use the target declaring class name position instead } public SyntheticMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding declaringClass) { if (targetMethod.isConstructor()) { initializeConstructorAccessor(targetMethod); } else { initializeMethodAccessor(targetMethod, isSuperAccess, declaringClass); } } /** * Construct a bridge method */ public SyntheticMethodBinding(MethodBinding overridenMethodToBridge, MethodBinding targetMethod, SourceTypeBinding declaringClass) { this.declaringClass = declaringClass; this.selector = overridenMethodToBridge.selector; // amongst other, clear the AccGenericSignature, so as to ensure no remains of original inherited persist (101794) // also use the modifiers from the target method, as opposed to inherited one (147690) this.modifiers = (targetMethod.modifiers | ClassFileConstants.AccBridge | ClassFileConstants.AccSynthetic) & ~(ClassFileConstants.AccSynchronized | ClassFileConstants.AccAbstract | ClassFileConstants.AccNative | ClassFileConstants.AccFinal | ExtraCompilerModifiers.AccGenericSignature); this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); this.returnType = overridenMethodToBridge.returnType; this.parameters = overridenMethodToBridge.parameters; this.thrownExceptions = overridenMethodToBridge.thrownExceptions; this.targetMethod = targetMethod; this.purpose = SyntheticMethodBinding.BridgeMethod; SyntheticMethodBinding[] knownAccessMethods = 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) { this.declaringClass = declaringEnum; this.selector = selector; this.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic; this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); LookupEnvironment environment = declaringEnum.scope.environment(); this.thrownExceptions = Binding.NO_EXCEPTIONS; if (selector == TypeConstants.VALUES) { this.returnType = environment.createArrayType(environment.convertToParameterizedType(declaringEnum), 1); this.parameters = Binding.NO_PARAMETERS; this.purpose = SyntheticMethodBinding.EnumValues; } else if (selector == TypeConstants.VALUEOF) { this.returnType = environment.convertToParameterizedType(declaringEnum); this.parameters = new TypeBinding[]{ declaringEnum.scope.getJavaLangString() }; this.purpose = SyntheticMethodBinding.EnumValueOf; } SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods(); int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; this.index = methodId; if (declaringEnum.isStrictfp()) { this.modifiers |= ClassFileConstants.AccStrictfp; } } /** * Construct enum special methods: values or valueOf methods */ public SyntheticMethodBinding(SourceTypeBinding declaringEnum, int startIndex, int endIndex) { this.declaringClass = declaringEnum; SyntheticMethodBinding[] knownAccessMethods = declaringEnum.syntheticMethods(); this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length; StringBuffer buffer = new StringBuffer(); buffer.append(TypeConstants.SYNTHETIC_ENUM_CONSTANT_INITIALIZATION_METHOD_PREFIX).append(this.index); this.selector = String.valueOf(buffer).toCharArray(); this.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic; this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); this.purpose = SyntheticMethodBinding.TooManyEnumsConstants; this.thrownExceptions = Binding.NO_EXCEPTIONS; this.returnType = TypeBinding.VOID; this.parameters = Binding.NO_PARAMETERS; this.startIndex = startIndex; this.endIndex = endIndex; } // Create a synthetic method that will simply call the super classes method. // Used when a public method is inherited from a non-public class into a public class. // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658 public SyntheticMethodBinding(MethodBinding overridenMethodToBridge, SourceTypeBinding declaringClass) { this.declaringClass = declaringClass; this.selector = overridenMethodToBridge.selector; // amongst other, clear the AccGenericSignature, so as to ensure no remains of original inherited persist (101794) // also use the modifiers from the target method, as opposed to inherited one (147690) this.modifiers = (overridenMethodToBridge.modifiers | ClassFileConstants.AccBridge | ClassFileConstants.AccSynthetic) & ~(ClassFileConstants.AccSynchronized | ClassFileConstants.AccAbstract | ClassFileConstants.AccNative | ClassFileConstants.AccFinal | ExtraCompilerModifiers.AccGenericSignature); this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); this.returnType = overridenMethodToBridge.returnType; this.parameters = overridenMethodToBridge.parameters; this.thrownExceptions = overridenMethodToBridge.thrownExceptions; this.targetMethod = overridenMethodToBridge; this.purpose = SyntheticMethodBinding.SuperMethodAccess; SyntheticMethodBinding[] knownAccessMethods = 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). */ public void initializeConstructorAccessor(MethodBinding accessedConstructor) { this.targetMethod = accessedConstructor; this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccSynthetic; this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); SourceTypeBinding sourceType = (SourceTypeBinding) accessedConstructor.declaringClass; SyntheticMethodBinding[] knownSyntheticMethods = sourceType.syntheticMethods(); this.index = knownSyntheticMethods == null ? 0 : knownSyntheticMethods.length; this.selector = accessedConstructor.selector; this.returnType = accessedConstructor.returnType; this.purpose = SyntheticMethodBinding.ConstructorAccess; final int parametersLength = accessedConstructor.parameters.length; this.parameters = new TypeBinding[parametersLength + 1]; System.arraycopy( accessedConstructor.parameters, 0, this.parameters, 0, parametersLength); this.parameters[parametersLength] = accessedConstructor.declaringClass; this.thrownExceptions = accessedConstructor.thrownExceptions; this.declaringClass = sourceType; // check for method collision boolean needRename; do { check : { needRename = false; // check for collision with known methods MethodBinding[] methods = sourceType.methods(); for (int i = 0, length = methods.length; i < length; i++) { if (CharOperation.equals(this.selector, methods[i].selector) && areParameterErasuresEqual(methods[i])) { needRename = true; break check; } } // check for collision with synthetic accessors if (knownSyntheticMethods != null) { for (int i = 0, length = knownSyntheticMethods.length; i < length; i++) { if (knownSyntheticMethods[i] == null) continue; if (CharOperation.equals(this.selector, knownSyntheticMethods[i].selector) && areParameterErasuresEqual(knownSyntheticMethods[i])) { needRename = true; break check; } } } } if (needRename) { // retry with a new extra argument int length = this.parameters.length; System.arraycopy( this.parameters, 0, this.parameters = new TypeBinding[length + 1], 0, length); this.parameters[length] = this.declaringClass; } } while (needRename); // retrieve sourceStart position for the target method for line number attributes AbstractMethodDeclaration[] methodDecls = sourceType.scope.referenceContext.methods; if (methodDecls != null) { for (int i = 0, length = methodDecls.length; i < length; i++) { if (methodDecls[i].binding == accessedConstructor) { this.sourceStart = methodDecls[i].sourceStart; return; } } } } /** * An method accessor is a method with an access$N selector, where N is incremented in case of collisions. */ public void initializeMethodAccessor(MethodBinding accessedMethod, boolean isSuperAccess, ReferenceBinding receiverType) { this.targetMethod = accessedMethod; this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType; SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods(); int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; this.index = methodId; this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray()); this.returnType = accessedMethod.returnType; this.purpose = isSuperAccess ? SyntheticMethodBinding.SuperMethodAccess : SyntheticMethodBinding.MethodAccess; if (accessedMethod.isStatic()) { this.parameters = accessedMethod.parameters; } else { this.parameters = new TypeBinding[accessedMethod.parameters.length + 1]; this.parameters[0] = declaringSourceType; System.arraycopy(accessedMethod.parameters, 0, this.parameters, 1, accessedMethod.parameters.length); } this.thrownExceptions = accessedMethod.thrownExceptions; this.declaringClass = declaringSourceType; // check for method collision boolean needRename; do { check : { needRename = false; // check for collision with known methods MethodBinding[] methods = declaringSourceType.methods(); for (int i = 0, length = methods.length; i < length; i++) { if (CharOperation.equals(this.selector, methods[i].selector) && areParameterErasuresEqual(methods[i])) { needRename = true; break check; } } // check for collision with synthetic accessors if (knownAccessMethods != null) { for (int i = 0, length = knownAccessMethods.length; i < length; i++) { if (knownAccessMethods[i] == null) continue; if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && areParameterErasuresEqual(knownAccessMethods[i])) { needRename = true; break check; } } } } if (needRename) { // retry with a selector & a growing methodId setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray())); } } while (needRename); // retrieve sourceStart position for the target method for line number attributes AbstractMethodDeclaration[] methodDecls = declaringSourceType.scope.referenceContext.methods; if (methodDecls != null) { for (int i = 0, length = methodDecls.length; i < length; i++) { if (methodDecls[i].binding == accessedMethod) { this.sourceStart = methodDecls[i].sourceStart; return; } } } } protected boolean isConstructorRelated() { return this.purpose == SyntheticMethodBinding.ConstructorAccess; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java0000644000175000001440000013704112212041344030470 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points * bug 358903 - Filter practically unimportant resource leak warnings * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 379784 - [compiler] "Method can be static" is not getting reported * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional * Jesper S Moller - Contributions for * bug 378674 - "The method can be declared as static" is wrong * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; 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.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; public class BlockScope extends Scope { // Local variable management public LocalVariableBinding[] locals; public int localIndex; // position for next variable public int startIndex; // start position in this scope - for ordering scopes vs. variables public int offset; // for variable allocation throughout scopes public int maxOffset; // for variable allocation throughout scopes // finally scopes must be shifted behind respective try&catch scope(s) so as to avoid // collisions of secret variables (return address, save value). public BlockScope[] shiftScopes; public Scope[] subscopes = new Scope[1]; // need access from code assist public int subscopeCount = 0; // need access from code assist // record the current case statement being processed (for entire switch case block). public CaseStatement enclosingCase; // from 1.4 on, local types should not be accessed across switch case blocks (52221) public final static VariableBinding[] EmulationPathToImplicitThis = {}; public final static VariableBinding[] NoEnclosingInstanceInConstructorCall = {}; public final static VariableBinding[] NoEnclosingInstanceInStaticContext = {}; public BlockScope(BlockScope parent) { this(parent, true); } public BlockScope(BlockScope parent, boolean addToParentScope) { this(Scope.BLOCK_SCOPE, parent); this.locals = new LocalVariableBinding[5]; if (addToParentScope) parent.addSubscope(this); this.startIndex = parent.localIndex; } public BlockScope(BlockScope parent, int variableCount) { this(Scope.BLOCK_SCOPE, parent); this.locals = new LocalVariableBinding[variableCount]; parent.addSubscope(this); this.startIndex = parent.localIndex; } protected BlockScope(int kind, Scope parent) { super(kind, parent); } /* Create the class scope & binding for the anonymous type. */ public final void addAnonymousType(TypeDeclaration anonymousType, ReferenceBinding superBinding) { ClassScope anonymousClassScope = new ClassScope(this, anonymousType); anonymousClassScope.buildAnonymousTypeBinding( enclosingSourceType(), superBinding); } /* Create the class scope & binding for the local type. */ public final void addLocalType(TypeDeclaration localType) { ClassScope localTypeScope = new ClassScope(this, localType); addSubscope(localTypeScope); localTypeScope.buildLocalTypeBinding(enclosingSourceType()); } /* Insert a local variable into a given scope, updating its position * and checking there are not too many locals or arguments allocated. */ public final void addLocalVariable(LocalVariableBinding binding) { checkAndSetModifiersForVariable(binding); // insert local in scope if (this.localIndex == this.locals.length) System.arraycopy( this.locals, 0, (this.locals = new LocalVariableBinding[this.localIndex * 2]), 0, this.localIndex); this.locals[this.localIndex++] = binding; // update local variable binding binding.declaringScope = this; binding.id = outerMostMethodScope().analysisIndex++; // share the outermost method scope analysisIndex } public void addSubscope(Scope childScope) { if (this.subscopeCount == this.subscopes.length) System.arraycopy( this.subscopes, 0, (this.subscopes = new Scope[this.subscopeCount * 2]), 0, this.subscopeCount); this.subscopes[this.subscopeCount++] = childScope; } /** * Answer true if the receiver is suitable for assigning final blank fields. * in other words, it is inside an initializer, a constructor or a clinit */ public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) { if (enclosingReceiverType() != binding.declaringClass) return false; MethodScope methodScope = methodScope(); if (methodScope.isStatic != binding.isStatic()) return false; return methodScope.isInsideInitializer() // inside initializer || ((AbstractMethodDeclaration) methodScope.referenceContext).isInitializationMethod(); // inside constructor or clinit } String basicToString(int tab) { String newLine = "\n"; //$NON-NLS-1$ for (int i = tab; --i >= 0;) newLine += "\t"; //$NON-NLS-1$ String s = newLine + "--- Block Scope ---"; //$NON-NLS-1$ newLine += "\t"; //$NON-NLS-1$ s += newLine + "locals:"; //$NON-NLS-1$ for (int i = 0; i < this.localIndex; i++) s += newLine + "\t" + this.locals[i].toString(); //$NON-NLS-1$ s += newLine + "startIndex = " + this.startIndex; //$NON-NLS-1$ return s; } private void checkAndSetModifiersForVariable(LocalVariableBinding varBinding) { int modifiers = varBinding.modifiers; if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0 && varBinding.declaration != null){ problemReporter().duplicateModifierForVariable(varBinding.declaration, this instanceof MethodScope); } int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; int unexpectedModifiers = ~ClassFileConstants.AccFinal; if ((realModifiers & unexpectedModifiers) != 0 && varBinding.declaration != null){ problemReporter().illegalModifierForVariable(varBinding.declaration, this instanceof MethodScope); } varBinding.modifiers = modifiers; } /* Compute variable positions in scopes given an initial position offset * ignoring unused local variables. * * No argument is expected here (ilocal is the first non-argument local of the outermost scope) * Arguments are managed by the MethodScope method */ void computeLocalVariablePositions(int ilocal, int initOffset, CodeStream codeStream) { this.offset = initOffset; this.maxOffset = initOffset; // local variable init int maxLocals = this.localIndex; boolean hasMoreVariables = ilocal < maxLocals; // scope init int iscope = 0, maxScopes = this.subscopeCount; boolean hasMoreScopes = maxScopes > 0; // iterate scopes and variables in parallel while (hasMoreVariables || hasMoreScopes) { if (hasMoreScopes && (!hasMoreVariables || (this.subscopes[iscope].startIndex() <= ilocal))) { // consider subscope first if (this.subscopes[iscope] instanceof BlockScope) { BlockScope subscope = (BlockScope) this.subscopes[iscope]; int subOffset = subscope.shiftScopes == null ? this.offset : subscope.maxShiftedOffset(); subscope.computeLocalVariablePositions(0, subOffset, codeStream); if (subscope.maxOffset > this.maxOffset) this.maxOffset = subscope.maxOffset; } hasMoreScopes = ++iscope < maxScopes; } else { // consider variable first LocalVariableBinding local = this.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.UNUSED && local.constant() == Constant.NotAConstant); // do not report fake used variable if (local.useFlag == LocalVariableBinding.UNUSED && (local.declaration != null) // unused (and non secret) local && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable if (!(local.declaration instanceof Argument)) // do not report unused catch arguments problemReporter().unusedLocalVariable(local.declaration); } // could be optimized out, but does need to preserve unread variables ? if (!generateCurrentLocalVar) { if (local.declaration != null && compilerOptions().preserveAllLocalVariables) { generateCurrentLocalVar = true; // force it to be preserved in the generated code if (local.useFlag == LocalVariableBinding.UNUSED) local.useFlag = LocalVariableBinding.USED; } } // allocate variable if (generateCurrentLocalVar) { if (local.declaration != null) { codeStream.record(local); // record user-defined local variables for attribute generation } // assign variable position local.resolvedPosition = this.offset; if ((local.type == TypeBinding.LONG) || (local.type == TypeBinding.DOUBLE)) { this.offset += 2; } else { this.offset++; } if (this.offset > 0xFFFF) { // no more than 65535 words of locals problemReporter().noMoreAvailableSpaceForLocal( local, local.declaration == null ? (ASTNode)methodScope().referenceContext : local.declaration); } } else { local.resolvedPosition = -1; // not generated } hasMoreVariables = ++ilocal < maxLocals; } } if (this.offset > this.maxOffset) this.maxOffset = this.offset; } /* * Record the suitable binding denoting a synthetic field or constructor argument, * mapping to the actual outer local variable in the scope context. * Note that this may not need any effect, in case the outer local variable does not * need to be emulated and can directly be used as is (using its back pointer to its * declaring scope). */ public void emulateOuterAccess(LocalVariableBinding outerLocalVariable) { BlockScope outerVariableScope = outerLocalVariable.declaringScope; if (outerVariableScope == null) return; // no need to further emulate as already inserted (val$this$0) MethodScope currentMethodScope = methodScope(); if (outerVariableScope.methodScope() != currentMethodScope) { NestedTypeBinding currentType = (NestedTypeBinding) enclosingSourceType(); //do nothing for member types, pre emulation was performed already if (!currentType.isLocalType()) { return; } // must also add a synthetic field if we're not inside a constructor if (!currentMethodScope.isInsideInitializerOrConstructor()) { currentType.addSyntheticArgumentAndField(outerLocalVariable); } else { currentType.addSyntheticArgument(outerLocalVariable); } } } /* Note that it must never produce a direct access to the targetEnclosingType, * but instead a field sequence (this$2.this$1.this$0) so as to handle such a test case: * * class XX { * void foo() { * class A { * class B { * class C { * boolean foo() { * return (Object) A.this == (Object) B.this; * } * } * } * } * new A().new B().new C(); * } * } * where we only want to deal with ONE enclosing instance for C (could not figure out an A for C) */ public final ReferenceBinding findLocalType(char[] name) { long compliance = compilerOptions().complianceLevel; for (int i = this.subscopeCount-1; i >= 0; i--) { if (this.subscopes[i] instanceof ClassScope) { LocalTypeBinding sourceType = (LocalTypeBinding)((ClassScope) this.subscopes[i]).referenceContext.binding; // from 1.4 on, local types should not be accessed across switch case blocks (52221) if (compliance >= ClassFileConstants.JDK1_4 && sourceType.enclosingCase != null) { if (!isInsideCase(sourceType.enclosingCase)) { continue; } } if (CharOperation.equals(sourceType.sourceName(), name)) return sourceType; } } return null; } /** * Returns all declarations of most specific locals containing a given position in their source range. * This code does not recurse in nested types. * Returned array may have null values at trailing indexes. */ public LocalDeclaration[] findLocalVariableDeclarations(int position) { // local variable init int ilocal = 0, maxLocals = this.localIndex; boolean hasMoreVariables = maxLocals > 0; LocalDeclaration[] localDeclarations = null; int declPtr = 0; // scope init int iscope = 0, maxScopes = this.subscopeCount; boolean hasMoreScopes = maxScopes > 0; // iterate scopes and variables in parallel while (hasMoreVariables || hasMoreScopes) { if (hasMoreScopes && (!hasMoreVariables || (this.subscopes[iscope].startIndex() <= ilocal))) { // consider subscope first Scope subscope = this.subscopes[iscope]; if (subscope.kind == Scope.BLOCK_SCOPE) { // do not dive in nested types localDeclarations = ((BlockScope)subscope).findLocalVariableDeclarations(position); if (localDeclarations != null) { return localDeclarations; } } hasMoreScopes = ++iscope < maxScopes; } else { // consider variable first LocalVariableBinding local = this.locals[ilocal]; // if no local at all, will be locals[ilocal]==null if (local != null) { LocalDeclaration localDecl = local.declaration; if (localDecl != null) { if (localDecl.declarationSourceStart <= position) { if (position <= localDecl.declarationSourceEnd) { if (localDeclarations == null) { localDeclarations = new LocalDeclaration[maxLocals]; } localDeclarations[declPtr++] = localDecl; } } else { return localDeclarations; } } } hasMoreVariables = ++ilocal < maxLocals; if (!hasMoreVariables && localDeclarations != null) { return localDeclarations; } } } return null; } public LocalVariableBinding findVariable(char[] variableName) { int varLength = variableName.length; for (int i = this.localIndex-1; i >= 0; i--) { // lookup backward to reach latest additions first LocalVariableBinding local; char[] localName; if ((localName = (local = this.locals[i]).name).length == varLength && CharOperation.equals(localName, variableName)) return local; } return null; } /* API * flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE. * Only bindings corresponding to the mask will be answered. * * if the VARIABLE mask is set then * If the first name provided is a field (or local) then the field (or local) is answered * Otherwise, package names and type names are consumed until a field is found. * In this case, the field is answered. * * if the TYPE mask is set, * package names and type names are consumed until the end of the input. * Only if all of the input is consumed is the type answered * * All other conditions are errors, and a problem binding is returned. * * 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. * * The VARIABLE mask has precedence over the TYPE mask. * * InvocationSite implements * isSuperAccess(); this is used to determine if the discovered field is visible. * setFieldIndex(int); this is used to record the number of names that were consumed. * * For example, getBinding({"foo","y","q", VARIABLE, site) will answer * the binding for the field or local named "foo" (or an error binding if none exists). * In addition, setFieldIndex(1) will be sent to the invocation site. * If a type named "foo" exists, it will not be detected (and an error binding will be answered) * * IMPORTANT NOTE: This method is written under the assumption that compoundName is longer than length 1. */ public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, boolean needResolve) { Binding binding = getBinding(compoundName[0], mask | Binding.TYPE | Binding.PACKAGE, invocationSite, needResolve); invocationSite.setFieldIndex(1); if (binding instanceof VariableBinding) return binding; CompilationUnitScope unitScope = compilationUnitScope(); // in the problem case, we want to ensure we record the qualified dependency in case a type is added // and we do not know that its package was also added (can happen with CompilationParticipants) unitScope.recordQualifiedReference(compoundName); if (!binding.isValidBinding()) return binding; int length = compoundName.length; int currentIndex = 1; foundType : if (binding instanceof PackageBinding) { PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < length) { unitScope.recordReference(packageBinding.compoundName, compoundName[currentIndex]); binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); invocationSite.setFieldIndex(currentIndex); if (binding == null) { if (currentIndex == length) { // must be a type if its the last name, otherwise we have no idea if its a package or type return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound); } return new ProblemBinding( CharOperation.subarray(compoundName, 0, currentIndex), ProblemReasons.NotFound); } if (binding instanceof ReferenceBinding) { if (!binding.isValidBinding()) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding)((ReferenceBinding)binding).closestMatch(), binding.problemId()); if (!((ReferenceBinding) binding).canBeSeenBy(this)) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding) binding, ProblemReasons.NotVisible); break foundType; } packageBinding = (PackageBinding) binding; } // It is illegal to request a PACKAGE from this method. return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound); } // know binding is now a ReferenceBinding ReferenceBinding referenceBinding = (ReferenceBinding) binding; binding = environment().convertToRawType(referenceBinding, false /*do not force conversion of enclosing types*/); if (invocationSite instanceof ASTNode) { ASTNode invocationNode = (ASTNode) invocationSite; if (invocationNode.isTypeUseDeprecated(referenceBinding, this)) { problemReporter().deprecatedType(referenceBinding, invocationNode); } } Binding problemFieldBinding = null; while (currentIndex < length) { referenceBinding = (ReferenceBinding) binding; char[] nextName = compoundName[currentIndex++]; invocationSite.setFieldIndex(currentIndex); invocationSite.setActualReceiverType(referenceBinding); if ((mask & Binding.FIELD) != 0 && (binding = findField(referenceBinding, nextName, invocationSite, true /*resolve*/)) != null) { if (binding.isValidBinding()) { break; // binding is now a field } problemFieldBinding = new ProblemFieldBinding( ((ProblemFieldBinding)binding).closestMatch, ((ProblemFieldBinding)binding).declaringClass, CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'), binding.problemId()); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317858 : If field is inaccessible, // don't give up yet, continue to look for a visible member type if (binding.problemId() != ProblemReasons.NotVisible) { return problemFieldBinding; } } if ((binding = findMemberType(nextName, referenceBinding)) == null) { if (problemFieldBinding != null) { return problemFieldBinding; } if ((mask & Binding.FIELD) != 0) { return new ProblemFieldBinding( null, referenceBinding, nextName, ProblemReasons.NotFound); } else if ((mask & Binding.VARIABLE) != 0) { return new ProblemBinding( CharOperation.subarray(compoundName, 0, currentIndex), referenceBinding, ProblemReasons.NotFound); } return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), referenceBinding, ProblemReasons.NotFound); } // binding is a ReferenceBinding if (!binding.isValidBinding()) { if (problemFieldBinding != null) { return problemFieldBinding; } return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding)((ReferenceBinding)binding).closestMatch(), binding.problemId()); } if (invocationSite instanceof ASTNode) { referenceBinding = (ReferenceBinding) binding; ASTNode invocationNode = (ASTNode) invocationSite; if (invocationNode.isTypeUseDeprecated(referenceBinding, this)) { problemReporter().deprecatedType(referenceBinding, invocationNode); } } } if ((mask & Binding.FIELD) != 0 && (binding instanceof FieldBinding)) { // was looking for a field and found a field FieldBinding field = (FieldBinding) binding; if (!field.isStatic()) return new ProblemFieldBinding( field, field.declaringClass, CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'), ProblemReasons.NonStaticReferenceInStaticContext); // Since a qualified reference must be for a static member, it won't affect static-ness of the enclosing method, // so we don't have to call resetEnclosingMethodStaticFlag() in this case return binding; } if ((mask & Binding.TYPE) != 0 && (binding instanceof ReferenceBinding)) { // was looking for a type and found a type return binding; } // handle the case when a field or type was asked for but we resolved the compoundName to a type or field return new ProblemBinding( CharOperation.subarray(compoundName, 0, currentIndex), ProblemReasons.NotFound); } // Added for code assist... NOT Public API public final Binding getBinding(char[][] compoundName, InvocationSite invocationSite) { int currentIndex = 0; int length = compoundName.length; Binding binding = getBinding( compoundName[currentIndex++], Binding.VARIABLE | Binding.TYPE | Binding.PACKAGE, invocationSite, true /*resolve*/); if (!binding.isValidBinding()) return binding; foundType : if (binding instanceof PackageBinding) { while (currentIndex < length) { PackageBinding packageBinding = (PackageBinding) binding; binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); if (binding == null) { if (currentIndex == length) { // must be a type if its the last name, otherwise we have no idea if its a package or type return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound); } return new ProblemBinding( CharOperation.subarray(compoundName, 0, currentIndex), ProblemReasons.NotFound); } if (binding instanceof ReferenceBinding) { if (!binding.isValidBinding()) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding)((ReferenceBinding)binding).closestMatch(), binding.problemId()); if (!((ReferenceBinding) binding).canBeSeenBy(this)) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding) binding, ProblemReasons.NotVisible); break foundType; } } return binding; } foundField : if (binding instanceof ReferenceBinding) { while (currentIndex < length) { ReferenceBinding typeBinding = (ReferenceBinding) binding; char[] nextName = compoundName[currentIndex++]; TypeBinding receiverType = typeBinding.capture(this, invocationSite.sourceEnd()); if ((binding = findField(receiverType, nextName, invocationSite, true /*resolve*/)) != null) { if (!binding.isValidBinding()) { return new ProblemFieldBinding( (FieldBinding) binding, ((FieldBinding) binding).declaringClass, CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'), binding.problemId()); } if (!((FieldBinding) binding).isStatic()) return new ProblemFieldBinding( (FieldBinding) binding, ((FieldBinding) binding).declaringClass, CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'), ProblemReasons.NonStaticReferenceInStaticContext); break foundField; // binding is now a field } if ((binding = findMemberType(nextName, typeBinding)) == null) { return new ProblemBinding( CharOperation.subarray(compoundName, 0, currentIndex), typeBinding, ProblemReasons.NotFound); } if (!binding.isValidBinding()) { return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding)((ReferenceBinding)binding).closestMatch(), binding.problemId()); } } return binding; } VariableBinding variableBinding = (VariableBinding) binding; while (currentIndex < length) { TypeBinding typeBinding = variableBinding.type; if (typeBinding == null) { return new ProblemFieldBinding( null, null, CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'), ProblemReasons.NotFound); } TypeBinding receiverType = typeBinding.capture(this, invocationSite.sourceEnd()); variableBinding = findField(receiverType, compoundName[currentIndex++], invocationSite, true /*resolve*/); if (variableBinding == null) { return new ProblemFieldBinding( null, receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null, CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'), ProblemReasons.NotFound); } if (!variableBinding.isValidBinding()) return variableBinding; } return variableBinding; } /* * This retrieves the argument that maps to an enclosing instance of the suitable type, * if not found then answers nil -- do not create one * * #implicitThis : the implicit this will be ok * #((arg) this$n) : available as a constructor arg * #((arg) this$n ... this$p) : available as as a constructor arg + a sequence of fields * #((fieldDescr) this$n ... this$p) : available as a sequence of fields * nil : not found * * Note that this algorithm should answer the shortest possible sequence when * shortcuts are available: * this$0 . this$0 . this$0 * instead of * this$2 . this$1 . this$0 . this$1 . this$0 * thus the code generation will be more compact and runtime faster */ public VariableBinding[] getEmulationPath(LocalVariableBinding outerLocalVariable) { MethodScope currentMethodScope = methodScope(); SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType(); // identity check BlockScope variableScope = outerLocalVariable.declaringScope; if (variableScope == null /*val$this$0*/ || currentMethodScope == variableScope.methodScope()) { return new VariableBinding[] { outerLocalVariable }; // implicit this is good enough } // use synthetic constructor arguments if possible if (currentMethodScope.isInsideInitializerOrConstructor() && (sourceType.isNestedType())) { SyntheticArgumentBinding syntheticArg; if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(outerLocalVariable)) != null) { return new VariableBinding[] { syntheticArg }; } } // use a synthetic field then if (!currentMethodScope.isStatic) { FieldBinding syntheticField; if ((syntheticField = sourceType.getSyntheticField(outerLocalVariable)) != null) { return new VariableBinding[] { syntheticField }; } } return null; } /* * This retrieves the argument that maps to an enclosing instance of the suitable type, * if not found then answers nil -- do not create one * * #implicitThis : the implicit this will be ok * #((arg) this$n) : available as a constructor arg * #((arg) this$n access$m... access$p) : available as as a constructor arg + a sequence of synthetic accessors to synthetic fields * #((fieldDescr) this$n access#m... access$p) : available as a first synthetic field + a sequence of synthetic accessors to synthetic fields * null : not found * jls 15.9.2 + http://www.ergnosis.com/java-spec-report/java-language/jls-8.8.5.1-d.html */ public Object[] getEmulationPath(ReferenceBinding targetEnclosingType, boolean onlyExactMatch, boolean denyEnclosingArgInConstructorCall) { MethodScope currentMethodScope = methodScope(); SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType(); // use 'this' if possible if (!currentMethodScope.isStatic && !currentMethodScope.isConstructorCall) { if (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeOriginatingFrom(targetEnclosingType) != null)) { return BlockScope.EmulationPathToImplicitThis; // implicit this is good enough } } if (!sourceType.isNestedType() || sourceType.isStatic()) { // no emulation from within non-inner types if (currentMethodScope.isConstructorCall) { return BlockScope.NoEnclosingInstanceInConstructorCall; } else if (currentMethodScope.isStatic){ return BlockScope.NoEnclosingInstanceInStaticContext; } return null; } boolean insideConstructor = currentMethodScope.isInsideInitializerOrConstructor(); // use synthetic constructor arguments if possible if (insideConstructor) { SyntheticArgumentBinding syntheticArg; if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, onlyExactMatch, currentMethodScope.isConstructorCall)) != null) { boolean isAnonymousAndHasEnclosing = sourceType.isAnonymousType() && sourceType.scope.referenceContext.allocation.enclosingInstance != null; // reject allocation and super constructor call if (denyEnclosingArgInConstructorCall && currentMethodScope.isConstructorCall && !isAnonymousAndHasEnclosing && (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeOriginatingFrom(targetEnclosingType) != null))) { return BlockScope.NoEnclosingInstanceInConstructorCall; } return new Object[] { syntheticArg }; } } // use a direct synthetic field then if (currentMethodScope.isStatic) { return BlockScope.NoEnclosingInstanceInStaticContext; } if (sourceType.isAnonymousType()) { ReferenceBinding enclosingType = sourceType.enclosingType(); if (enclosingType.isNestedType()) { NestedTypeBinding nestedEnclosingType = (NestedTypeBinding) enclosingType; SyntheticArgumentBinding enclosingArgument = nestedEnclosingType.getSyntheticArgument(nestedEnclosingType.enclosingType(), onlyExactMatch, currentMethodScope.isConstructorCall); if (enclosingArgument != null) { FieldBinding syntheticField = sourceType.getSyntheticField(enclosingArgument); if (syntheticField != null) { if (syntheticField.type == targetEnclosingType || (!onlyExactMatch && ((ReferenceBinding)syntheticField.type).findSuperTypeOriginatingFrom(targetEnclosingType) != null)) return new Object[] { syntheticField }; } } } } FieldBinding syntheticField = sourceType.getSyntheticField(targetEnclosingType, onlyExactMatch); if (syntheticField != null) { if (currentMethodScope.isConstructorCall){ return BlockScope.NoEnclosingInstanceInConstructorCall; } return new Object[] { syntheticField }; } // could be reached through a sequence of enclosing instance link (nested members) Object[] path = new Object[2]; // probably at least 2 of them ReferenceBinding currentType = sourceType.enclosingType(); if (insideConstructor) { path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument(currentType, onlyExactMatch, currentMethodScope.isConstructorCall); } else { if (currentMethodScope.isConstructorCall){ return BlockScope.NoEnclosingInstanceInConstructorCall; } path[0] = sourceType.getSyntheticField(currentType, onlyExactMatch); } if (path[0] != null) { // keep accumulating int count = 1; ReferenceBinding currentEnclosingType; while ((currentEnclosingType = currentType.enclosingType()) != null) { //done? if (currentType == targetEnclosingType || (!onlyExactMatch && currentType.findSuperTypeOriginatingFrom(targetEnclosingType) != null)) break; if (currentMethodScope != null) { currentMethodScope = currentMethodScope.enclosingMethodScope(); if (currentMethodScope != null && currentMethodScope.isConstructorCall){ return BlockScope.NoEnclosingInstanceInConstructorCall; } if (currentMethodScope != null && currentMethodScope.isStatic){ return BlockScope.NoEnclosingInstanceInStaticContext; } } syntheticField = ((NestedTypeBinding) currentType).getSyntheticField(currentEnclosingType, onlyExactMatch); if (syntheticField == null) break; // append inside the path if (count == path.length) { System.arraycopy(path, 0, (path = new Object[count + 1]), 0, count); } // private access emulation is necessary since synthetic field is private path[count++] = ((SourceTypeBinding) syntheticField.declaringClass).addSyntheticMethod(syntheticField, true/*read*/, false /*not super access*/); currentType = currentEnclosingType; } if (currentType == targetEnclosingType || (!onlyExactMatch && currentType.findSuperTypeOriginatingFrom(targetEnclosingType) != null)) { return path; } } return null; } /* Answer true if the variable name already exists within the receiver's scope. */ public final boolean isDuplicateLocalVariable(char[] name) { BlockScope current = this; while (true) { for (int i = 0; i < this.localIndex; i++) { if (CharOperation.equals(name, current.locals[i].name)) return true; } if (current.kind != Scope.BLOCK_SCOPE) return false; current = (BlockScope)current.parent; } } public int maxShiftedOffset() { int max = -1; if (this.shiftScopes != null){ for (int i = 0, length = this.shiftScopes.length; i < length; i++){ if (this.shiftScopes[i] != null) { int subMaxOffset = this.shiftScopes[i].maxOffset; if (subMaxOffset > max) max = subMaxOffset; } } } return max; } /** * Returns true if the context requires to check initialization of final blank fields. * in other words, it is inside an initializer, a constructor or a clinit */ public final boolean needBlankFinalFieldInitializationCheck(FieldBinding binding) { boolean isStatic = binding.isStatic(); ReferenceBinding fieldDeclaringClass = binding.declaringClass; // loop in enclosing context, until reaching the field declaring context MethodScope methodScope = methodScope(); while (methodScope != null) { if (methodScope.isStatic != isStatic) return false; if (!methodScope.isInsideInitializer() // inside initializer && !((AbstractMethodDeclaration) methodScope.referenceContext).isInitializationMethod()) { // inside constructor or clinit return false; // found some non-initializer context } ReferenceBinding enclosingType = methodScope.enclosingReceiverType(); if (enclosingType == fieldDeclaringClass) { return true; // found the field context, no need to check any further } if (!enclosingType.erasure().isAnonymousType()) { return false; // only check inside anonymous type } methodScope = methodScope.enclosingMethodScope(); } return false; } /* Answer the problem reporter to use for raising new problems. * * Note that as a side-effect, this updates the current reference context * (unit, type or method) in case the problem handler decides it is necessary * to abort. */ public ProblemReporter problemReporter() { return methodScope().problemReporter(); } /* * Code responsible to request some more emulation work inside the invocation type, so as to supply * correct synthetic arguments to any allocation of the target type. */ public void propagateInnerEmulation(ReferenceBinding targetType, boolean isEnclosingInstanceSupplied) { // no need to propagate enclosing instances, they got eagerly allocated already. SyntheticArgumentBinding[] syntheticArguments; if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) { for (int i = 0, max = syntheticArguments.length; i < max; i++) { SyntheticArgumentBinding syntheticArg = syntheticArguments[i]; // need to filter out the one that could match a supplied enclosing instance if (!(isEnclosingInstanceSupplied && (syntheticArg.type == targetType.enclosingType()))) { emulateOuterAccess(syntheticArg.actualOuterLocalVariable); } } } } /* Answer the reference type of this scope. * * It is the nearest enclosing type of this scope. */ public TypeDeclaration referenceType() { return methodScope().referenceType(); } /* * Answer the index of this scope relatively to its parent. * For method scope, answers -1 (not a classScope relative position) */ public int scopeIndex() { if (this instanceof MethodScope) return -1; BlockScope parentScope = (BlockScope)this.parent; Scope[] parentSubscopes = parentScope.subscopes; for (int i = 0, max = parentScope.subscopeCount; i < max; i++) { if (parentSubscopes[i] == this) return i; } return -1; } // start position in this scope - for ordering scopes vs. variables int startIndex() { return this.startIndex; } public String toString() { return toString(0); } public String toString(int tab) { String s = basicToString(tab); for (int i = 0; i < this.subscopeCount; i++) if (this.subscopes[i] instanceof BlockScope) s += ((BlockScope) this.subscopes[i]).toString(tab + 1) + "\n"; //$NON-NLS-1$ return s; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682 /** * This method is used to reset the CanBeStatic the enclosing method of the current block */ public void resetEnclosingMethodStaticFlag() { MethodScope methodScope = methodScope(); if (methodScope != null) { if (methodScope.referenceContext instanceof MethodDeclaration) { MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext; methodDeclaration.bits &= ~ASTNode.CanBeStatic; } else if (methodScope.referenceContext instanceof TypeDeclaration) { // anonymous type, find enclosing method methodScope = methodScope.enclosingMethodScope(); if (methodScope != null && methodScope.referenceContext instanceof MethodDeclaration) { MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext; methodDeclaration.bits &= ~ASTNode.CanBeStatic; } } } } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376550 /** * This method is used to reset the CanBeStatic on all enclosing methods until the method * belonging to the enclosingInstanceType * @param enclosingInstanceType type of which an enclosing instance is required in the code. */ public void resetDeclaringClassMethodStaticFlag(TypeBinding enclosingInstanceType) { MethodScope methodScope = methodScope(); if (methodScope != null && methodScope.referenceContext instanceof TypeDeclaration) { if (!methodScope.enclosingReceiverType().isCompatibleWith(enclosingInstanceType)) { // unless invoking a method of the local type ... // anonymous type, find enclosing method methodScope = methodScope.enclosingMethodScope(); } } while (methodScope != null && methodScope.referenceContext instanceof MethodDeclaration) { MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext; methodDeclaration.bits &= ~ASTNode.CanBeStatic; ClassScope enclosingClassScope = methodScope.enclosingClassScope(); if (enclosingClassScope != null) { TypeDeclaration type = enclosingClassScope.referenceContext; if (type != null && type.binding != null && enclosingInstanceType != null && !type.binding.isCompatibleWith(enclosingInstanceType.original())) { methodScope = enclosingClassScope.enclosingMethodScope(); continue; } } break; } } private List trackingVariables; // can be null if no resources are tracked /** Used only during analyseCode and only for checking if a resource was closed in a finallyBlock. */ public FlowInfo finallyInfo; /** * Register a tracking variable and compute its id. */ public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) { if (this.trackingVariables == null) this.trackingVariables = new ArrayList(3); this.trackingVariables.add(fakedTrackingVariable); MethodScope outerMethodScope = outerMostMethodScope(); return outerMethodScope.analysisIndex++; } /** When are no longer interested in this tracking variable - remove it. */ public void removeTrackingVar(FakedTrackingVariable trackingVariable) { if (trackingVariable.innerTracker != null) { removeTrackingVar(trackingVariable.innerTracker); trackingVariable.innerTracker = null; } if (this.trackingVariables != null) if (this.trackingVariables.remove(trackingVariable)) return; if (this.parent instanceof BlockScope) ((BlockScope)this.parent).removeTrackingVar(trackingVariable); } /** Unregister a wrapper resource without affecting its inner. */ public void pruneWrapperTrackingVar(FakedTrackingVariable trackingVariable) { this.trackingVariables.remove(trackingVariable); } /** * At the end of a block check the closing-status of all tracked closeables that are declared in this block. * Also invoked when entering unreachable code. */ public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext, ASTNode location, BlockScope locationScope) { if (!compilerOptions().analyseResourceLeaks) return; if (this.trackingVariables == null) { // at a method return we also consider enclosing scopes if (location != null && this.parent instanceof BlockScope) ((BlockScope) this.parent).checkUnclosedCloseables(flowInfo, flowContext, location, locationScope); return; } if (location != null && flowInfo.reachMode() != 0) return; FakedTrackingVariable returnVar = (location instanceof ReturnStatement) ? FakedTrackingVariable.getCloseTrackingVariable(((ReturnStatement)location).expression, flowInfo, flowContext) : null; Set varSet = new HashSet(this.trackingVariables); FakedTrackingVariable trackingVar; // pick one outer-most variable from the set at a time while ((trackingVar = FakedTrackingVariable.pickVarForReporting(varSet, this, location != null)) != null) { if (returnVar != null && trackingVar.isResourceBeingReturned(returnVar)) { continue; } if (location != null && trackingVar.hasDefinitelyNoResource(flowInfo)) { continue; // reporting against a specific location, there is no resource at this flow, don't complain } if (location != null && flowContext != null && flowContext.recordExitAgainstResource(this, flowInfo, trackingVar, location)) { continue; // handled by the flow context } // compute the most specific null status for this resource, int status = trackingVar.findMostSpecificStatus(flowInfo, this, locationScope); if (status == FlowInfo.NULL) { // definitely unclosed: highest priority reportResourceLeak(trackingVar, location, status); continue; } if (location == null) // at end of block and not definitely unclosed { // problems at specific locations: medium priority if (trackingVar.reportRecordedErrors(this, status)) // ... report previously recorded errors continue; } if (status == FlowInfo.POTENTIALLY_NULL) { // potentially unclosed: lower priority reportResourceLeak(trackingVar, location, status); } else if (status == FlowInfo.NON_NULL) { // properly closed but not managed by t-w-r: lowest priority if (environment().globalOptions.complianceLevel >= ClassFileConstants.JDK1_7) trackingVar.reportExplicitClosing(problemReporter()); } } if (location == null) { // when leaving this block dispose off all tracking variables: for (int i=0; i always closed } else if ( elseFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in else branch && thenFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in then branch { thenFlowInfo.markAsDefinitelyNonNull(trackingVar.binding); // -> always closed } else { if (thenFlowInfo == FlowInfo.DEAD_END || elseFlowInfo == FlowInfo.DEAD_END) continue; // short cut for (int j=i+1; j !*123; (Lp/X; in declaring type except if leaf) * p.X { capture of ? extends p.Y } --> !+Lp/Y;123; (Lp/X; in declaring type except if leaf) */ public char[] computeUniqueKey(boolean isLeaf) { StringBuffer buffer = new StringBuffer(); if (isLeaf) { buffer.append(this.sourceType.computeUniqueKey(false/*not a leaf*/)); buffer.append('&'); } buffer.append(TypeConstants.WILDCARD_CAPTURE); buffer.append(this.wildcard.computeUniqueKey(false/*not a leaf*/)); buffer.append(this.position); buffer.append(';'); int length = buffer.length(); char[] uniqueKey = new char[length]; buffer.getChars(0, length, uniqueKey, 0); return uniqueKey; } public String debugName() { if (this.wildcard != null) { StringBuffer buffer = new StringBuffer(10); buffer .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX) .append(this.captureID) .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX) .append(this.wildcard.debugName()); return buffer.toString(); } return super.debugName(); } public char[] genericTypeSignature() { if (this.genericTypeSignature == null) { this.genericTypeSignature = CharOperation.concat(TypeConstants.WILDCARD_CAPTURE, this.wildcard.genericTypeSignature()); } return this.genericTypeSignature; } /** * Initialize capture bounds using substituted supertypes * e.g. given X>, capture(X) = X, where capture extends X */ public void initializeBounds(Scope scope, ParameterizedTypeBinding capturedParameterizedType) { TypeVariableBinding wildcardVariable = this.wildcard.typeVariable(); if (wildcardVariable == null) { // error resilience when capturing Zork // no substitution for wildcard bound (only formal bounds from type variables are to be substituted: 104082) TypeBinding originalWildcardBound = this.wildcard.bound; switch (this.wildcard.boundKind) { case Wildcard.EXTENDS : // still need to capture bound supertype as well so as not to expose wildcards to the outside (111208) TypeBinding capturedWildcardBound = originalWildcardBound.capture(scope, this.position); if (originalWildcardBound.isInterface()) { this.superclass = scope.getJavaLangObject(); this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) capturedWildcardBound }; } else { // the wildcard bound should be a subtype of variable superclass // it may occur that the bound is less specific, then consider glb (202404) if (capturedWildcardBound.isArrayType() || capturedWildcardBound == this) { this.superclass = scope.getJavaLangObject(); } else { this.superclass = (ReferenceBinding) capturedWildcardBound; } this.superInterfaces = Binding.NO_SUPERINTERFACES; } this.firstBound = capturedWildcardBound; if ((capturedWildcardBound.tagBits & TagBits.HasTypeVariable) == 0) this.tagBits &= ~TagBits.HasTypeVariable; break; case Wildcard.UNBOUND : this.superclass = scope.getJavaLangObject(); this.superInterfaces = Binding.NO_SUPERINTERFACES; this.tagBits &= ~TagBits.HasTypeVariable; break; case Wildcard.SUPER : this.superclass = scope.getJavaLangObject(); this.superInterfaces = Binding.NO_SUPERINTERFACES; this.lowerBound = this.wildcard.bound; if ((originalWildcardBound.tagBits & TagBits.HasTypeVariable) == 0) this.tagBits &= ~TagBits.HasTypeVariable; break; } return; } ReferenceBinding originalVariableSuperclass = wildcardVariable.superclass; ReferenceBinding substitutedVariableSuperclass = (ReferenceBinding) Scope.substitute(capturedParameterizedType, originalVariableSuperclass); // prevent cyclic capture: given X, capture(X could yield a circular type if (substitutedVariableSuperclass == this) substitutedVariableSuperclass = originalVariableSuperclass; ReferenceBinding[] originalVariableInterfaces = wildcardVariable.superInterfaces(); ReferenceBinding[] substitutedVariableInterfaces = Scope.substitute(capturedParameterizedType, originalVariableInterfaces); if (substitutedVariableInterfaces != originalVariableInterfaces) { // prevent cyclic capture: given X, capture(X could yield a circular type for (int i = 0, length = substitutedVariableInterfaces.length; i < length; i++) { if (substitutedVariableInterfaces[i] == this) substitutedVariableInterfaces[i] = originalVariableInterfaces[i]; } } // no substitution for wildcard bound (only formal bounds from type variables are to be substituted: 104082) TypeBinding originalWildcardBound = this.wildcard.bound; switch (this.wildcard.boundKind) { case Wildcard.EXTENDS : // still need to capture bound supertype as well so as not to expose wildcards to the outside (111208) TypeBinding capturedWildcardBound = originalWildcardBound.capture(scope, this.position); if (originalWildcardBound.isInterface()) { this.superclass = substitutedVariableSuperclass; // merge wildcard bound into variable superinterfaces using glb if (substitutedVariableInterfaces == Binding.NO_SUPERINTERFACES) { this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) capturedWildcardBound }; } else { int length = substitutedVariableInterfaces.length; System.arraycopy(substitutedVariableInterfaces, 0, substitutedVariableInterfaces = new ReferenceBinding[length+1], 1, length); substitutedVariableInterfaces[0] = (ReferenceBinding) capturedWildcardBound; this.superInterfaces = Scope.greaterLowerBound(substitutedVariableInterfaces); } } else { // the wildcard bound should be a subtype of variable superclass // it may occur that the bound is less specific, then consider glb (202404) if (capturedWildcardBound.isArrayType() || capturedWildcardBound == this) { this.superclass = substitutedVariableSuperclass; } else { this.superclass = (ReferenceBinding) capturedWildcardBound; if (this.superclass.isSuperclassOf(substitutedVariableSuperclass)) { this.superclass = substitutedVariableSuperclass; } } this.superInterfaces = substitutedVariableInterfaces; } this.firstBound = capturedWildcardBound; if ((capturedWildcardBound.tagBits & TagBits.HasTypeVariable) == 0) this.tagBits &= ~TagBits.HasTypeVariable; break; case Wildcard.UNBOUND : this.superclass = substitutedVariableSuperclass; this.superInterfaces = substitutedVariableInterfaces; this.tagBits &= ~TagBits.HasTypeVariable; break; case Wildcard.SUPER : this.superclass = substitutedVariableSuperclass; if (wildcardVariable.firstBound == substitutedVariableSuperclass || originalWildcardBound == substitutedVariableSuperclass) { this.firstBound = substitutedVariableSuperclass; } this.superInterfaces = substitutedVariableInterfaces; this.lowerBound = originalWildcardBound; if ((originalWildcardBound.tagBits & TagBits.HasTypeVariable) == 0) this.tagBits &= ~TagBits.HasTypeVariable; break; } } /** * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isCapture() */ public boolean isCapture() { return true; } /** * @see TypeBinding#isEquivalentTo(TypeBinding) */ public boolean isEquivalentTo(TypeBinding otherType) { if (this == otherType) return true; if (otherType == null) return false; // capture of ? extends X[] if (this.firstBound != null && this.firstBound.isArrayType()) { if (this.firstBound.isCompatibleWith(otherType)) return true; } switch (otherType.kind()) { case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : return ((WildcardBinding) otherType).boundCheck(this); } return false; } public char[] readableName() { if (this.wildcard != null) { StringBuffer buffer = new StringBuffer(10); buffer .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX) .append(this.captureID) .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX) .append(this.wildcard.readableName()); int length = buffer.length(); char[] name = new char[length]; buffer.getChars(0, length, name, 0); return name; } return super.readableName(); } public char[] shortReadableName() { if (this.wildcard != null) { StringBuffer buffer = new StringBuffer(10); buffer .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX) .append(this.captureID) .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX) .append(this.wildcard.shortReadableName()); int length = buffer.length(); char[] name = new char[length]; buffer.getChars(0, length, name, 0); return name; } return super.shortReadableName(); } public String toString() { if (this.wildcard != null) { StringBuffer buffer = new StringBuffer(10); buffer .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX) .append(this.captureID) .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX) .append(this.wildcard); return buffer.toString(); } return super.toString(); } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.jav0000644000175000001440000011577712212041344032427 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Erling Ellingsen - patch for bug 125570 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; 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.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.util.*; public class CompilationUnitScope extends Scope { public LookupEnvironment environment; public CompilationUnitDeclaration referenceContext; public char[][] currentPackageName; public PackageBinding fPackage; public ImportBinding[] imports; public int importPtr; public HashtableOfObject typeOrPackageCache; // used in Scope.getTypeOrPackage() public SourceTypeBinding[] topLevelTypes; private CompoundNameVector qualifiedReferences; private SimpleNameVector simpleNameReferences; private SimpleNameVector rootReferences; private ObjectVector referencedTypes; private ObjectVector referencedSuperTypes; HashtableOfType constantPoolNameUsage; private int captureID = 1; private ImportBinding[] tempImports; // to keep a record of resolved imports while traversing all in faultInImports() public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment environment) { super(COMPILATION_UNIT_SCOPE, null); this.environment = environment; this.referenceContext = unit; unit.scope = this; this.currentPackageName = unit.currentPackage == null ? CharOperation.NO_CHAR_CHAR : unit.currentPackage.tokens; if (compilerOptions().produceReferenceInfo) { this.qualifiedReferences = new CompoundNameVector(); this.simpleNameReferences = new SimpleNameVector(); this.rootReferences = 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.rootReferences = null; this.referencedTypes = null; this.referencedSuperTypes = null; } } void buildFieldsAndMethods() { for (int i = 0, length = this.topLevelTypes.length; i < length; i++) this.topLevelTypes[i].scope.buildFieldsAndMethods(); } void buildTypeBindings(AccessRestriction accessRestriction) { this.topLevelTypes = new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved boolean firstIsSynthetic = false; if (this.referenceContext.compilationResult.compilationUnit != null) { char[][] expectedPackageName = this.referenceContext.compilationResult.compilationUnit.getPackageName(); if (expectedPackageName != null && !CharOperation.equals(this.currentPackageName, expectedPackageName)) { // only report if the unit isn't structurally empty if (this.referenceContext.currentPackage != null || this.referenceContext.types != null || this.referenceContext.imports != null) { problemReporter().packageIsNotExpectedPackage(this.referenceContext); } this.currentPackageName = expectedPackageName.length == 0 ? CharOperation.NO_CHAR_CHAR : expectedPackageName; } } if (this.currentPackageName == CharOperation.NO_CHAR_CHAR) { // environment default package is never null this.fPackage = this.environment.defaultPackage; } else { if ((this.fPackage = this.environment.createPackage(this.currentPackageName)) == null) { if (this.referenceContext.currentPackage != null) { problemReporter().packageCollidesWithType(this.referenceContext); // only report when the unit has a package statement } // ensure fPackage is not null this.fPackage = this.environment.defaultPackage; return; } else if (this.referenceContext.isPackageInfo()) { // resolve package annotations now if this is "package-info.java". if (this.referenceContext.types == null || this.referenceContext.types.length == 0) { this.referenceContext.types = new TypeDeclaration[1]; this.referenceContext.createPackageInfoType(); firstIsSynthetic = true; } // ensure the package annotations are copied over before resolution if (this.referenceContext.currentPackage != null && this.referenceContext.currentPackage.annotations != null) { this.referenceContext.types[0].annotations = this.referenceContext.currentPackage.annotations; } } recordQualifiedReference(this.currentPackageName); // always dependent on your own package } // Skip typeDeclarations which know of previously reported errors TypeDeclaration[] types = this.referenceContext.types; int typeLength = (types == null) ? 0 : types.length; this.topLevelTypes = new SourceTypeBinding[typeLength]; int count = 0; nextType: for (int i = 0; i < typeLength; i++) { TypeDeclaration typeDecl = types[i]; if (this.environment.isProcessingAnnotations && this.environment.isMissingType(typeDecl.name)) throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type ReferenceBinding typeBinding = this.fPackage.getType0(typeDecl.name); recordSimpleReference(typeDecl.name); // needed to detect collision cases if (typeBinding != null && typeBinding.isValidBinding() && !(typeBinding instanceof UnresolvedReferenceBinding)) { // if its an unresolved binding - its fixed up whenever its needed, see UnresolvedReferenceBinding.resolve() if (this.environment.isProcessingAnnotations) throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type // if a type exists, check that its a valid type // it can be a NotFound problem type if its a secondary type referenced before its primary type found in additional units // and it can be an unresolved type which is now being defined problemReporter().duplicateTypes(this.referenceContext, typeDecl); continue nextType; } if (this.fPackage != this.environment.defaultPackage && this.fPackage.getPackage(typeDecl.name) != null) { // if a package exists, it must be a valid package - cannot be a NotFound problem package // this is now a warning since a package does not really 'exist' until it contains a type, see JLS v2, 7.4.3 problemReporter().typeCollidesWithPackage(this.referenceContext, typeDecl); } if ((typeDecl.modifiers & ClassFileConstants.AccPublic) != 0) { char[] mainTypeName; if ((mainTypeName = this.referenceContext.getMainTypeName()) != null // mainTypeName == null means that implementor of ICompilationUnit decided to return null && !CharOperation.equals(mainTypeName, typeDecl.name)) { problemReporter().publicClassMustMatchFileName(this.referenceContext, typeDecl); // tolerate faulty main type name (91091), allow to proceed into type construction } } ClassScope child = new ClassScope(this, typeDecl); SourceTypeBinding type = child.buildType(null, this.fPackage, accessRestriction); if (firstIsSynthetic && i == 0) type.modifiers |= ClassFileConstants.AccSynthetic; if (type != null) this.topLevelTypes[count++] = type; } // shrink topLevelTypes... only happens if an error was reported if (count != this.topLevelTypes.length) System.arraycopy(this.topLevelTypes, 0, this.topLevelTypes = new SourceTypeBinding[count], 0, count); } void checkAndSetImports() { if (this.referenceContext.imports == null) { this.imports = getDefaultImports(); return; } // allocate the import array, add java.lang.* by default int numberOfStatements = this.referenceContext.imports.length; int numberOfImports = numberOfStatements + 1; for (int i = 0; i < numberOfStatements; i++) { ImportReference importReference = this.referenceContext.imports[i]; if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(TypeConstants.JAVA_LANG, importReference.tokens) && !importReference.isStatic()) { numberOfImports--; break; } } ImportBinding[] resolvedImports = new ImportBinding[numberOfImports]; resolvedImports[0] = getDefaultImports()[0]; int index = 1; nextImport : for (int i = 0; i < numberOfStatements; i++) { ImportReference importReference = this.referenceContext.imports[i]; char[][] compoundName = importReference.tokens; // skip duplicates or imports of the current package for (int j = 0; j < index; j++) { ImportBinding resolved = resolvedImports[j]; if (resolved.onDemand == ((importReference.bits & ASTNode.OnDemand) != 0) && resolved.isStatic() == importReference.isStatic()) if (CharOperation.equals(compoundName, resolvedImports[j].compoundName)) continue nextImport; } if ((importReference.bits & ASTNode.OnDemand) != 0) { if (CharOperation.equals(compoundName, this.currentPackageName)) continue nextImport; 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); } } // shrink resolvedImports... only happens if an error was reported if (resolvedImports.length > index) System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index); this.imports = resolvedImports; } /** * Perform deferred check specific to parameterized types: bound checks, supertype collisions */ void checkParameterizedTypes() { if (compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) return; for (int i = 0, length = this.topLevelTypes.length; i < length; i++) { ClassScope scope = this.topLevelTypes[i].scope; scope.checkParameterizedTypeBounds(); scope.checkParameterizedSuperTypeCollisions(); } } /* * INTERNAL USE-ONLY * Innerclasses get their name computed as they are generated, since some may not * be actually outputed if sitting inside unreachable code. */ public char[] computeConstantPoolName(LocalTypeBinding localType) { if (localType.constantPoolName != null) { return localType.constantPoolName; } // delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes. if (this.constantPoolNameUsage == null) this.constantPoolNameUsage = new HashtableOfType(); ReferenceBinding outerMostEnclosingType = localType.scope.outerMostClassScope().enclosingSourceType(); // ensure there is not already such a local type name defined by the user int index = 0; char[] candidateName; boolean isCompliant15 = compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5; while(true) { if (localType.isMemberType()){ if (index == 0){ candidateName = CharOperation.concat( localType.enclosingType().constantPoolName(), localType.sourceName, '$'); } else { // in case of collision, then member name gets extra $1 inserted // e.g. class X { { class L{} new X(){ class L{} } } } candidateName = CharOperation.concat( localType.enclosingType().constantPoolName(), '$', String.valueOf(index).toCharArray(), '$', localType.sourceName); } } else if (localType.isAnonymousType()){ if (isCompliant15) { // from 1.5 on, use immediately enclosing type name candidateName = CharOperation.concat( localType.enclosingType.constantPoolName(), String.valueOf(index+1).toCharArray(), '$'); } else { candidateName = CharOperation.concat( outerMostEnclosingType.constantPoolName(), String.valueOf(index+1).toCharArray(), '$'); } } else { // local type if (isCompliant15) { candidateName = CharOperation.concat( CharOperation.concat( localType.enclosingType().constantPoolName(), String.valueOf(index+1).toCharArray(), '$'), localType.sourceName); } else { candidateName = CharOperation.concat( outerMostEnclosingType.constantPoolName(), '$', String.valueOf(index+1).toCharArray(), '$', localType.sourceName); } } if (this.constantPoolNameUsage.get(candidateName) != null) { index ++; } else { this.constantPoolNameUsage.put(candidateName, localType); break; } } return candidateName; } void connectTypeHierarchy() { for (int i = 0, length = this.topLevelTypes.length; i < length; i++) this.topLevelTypes[i].scope.connectTypeHierarchy(); } void faultInImports() { if (this.typeOrPackageCache != null) return; // can be called when a field constant is resolved before static imports if (this.referenceContext.imports == null) { this.typeOrPackageCache = new HashtableOfObject(1); return; } // collect the top level type names if a single type import exists int numberOfStatements = this.referenceContext.imports.length; HashtableOfType typesBySimpleNames = null; for (int i = 0; i < numberOfStatements; i++) { if ((this.referenceContext.imports[i].bits & ASTNode.OnDemand) == 0) { typesBySimpleNames = new HashtableOfType(this.topLevelTypes.length + numberOfStatements); for (int j = 0, length = this.topLevelTypes.length; j < length; j++) typesBySimpleNames.put(this.topLevelTypes[j].sourceName, this.topLevelTypes[j]); break; } } // allocate the import array, add java.lang.* by default int numberOfImports = numberOfStatements + 1; for (int i = 0; i < numberOfStatements; i++) { ImportReference importReference = this.referenceContext.imports[i]; if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(TypeConstants.JAVA_LANG, importReference.tokens) && !importReference.isStatic()) { numberOfImports--; break; } } this.tempImports = new ImportBinding[numberOfImports]; this.tempImports[0] = getDefaultImports()[0]; this.importPtr = 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 = this.referenceContext.imports[i]; char[][] compoundName = importReference.tokens; // skip duplicates or imports of the current package for (int j = 0; j < this.importPtr; j++) { ImportBinding resolved = this.tempImports[j]; if (resolved.onDemand == ((importReference.bits & ASTNode.OnDemand) != 0) && resolved.isStatic() == importReference.isStatic()) { if (CharOperation.equals(compoundName, resolved.compoundName)) { problemReporter().unusedImport(importReference); // since skipped, must be reported now continue nextImport; } } } if ((importReference.bits & ASTNode.OnDemand) != 0) { if (CharOperation.equals(compoundName, this.currentPackageName)) { problemReporter().unusedImport(importReference); // since skipped, must be reported now continue nextImport; } 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; } recordImportBinding(new ImportBinding(compoundName, true, importBinding, importReference)); } else { Binding importBinding = findSingleImport(compoundName, Binding.TYPE | Binding.FIELD | Binding.METHOD, importReference.isStatic()); if (!importBinding.isValidBinding()) { if (importBinding.problemId() == ProblemReasons.Ambiguous) { // keep it unless a duplicate can be found below } else { problemReporter().importProblem(importReference, importBinding); continue nextImport; } } if (importBinding instanceof PackageBinding) { problemReporter().cannotImportPackage(importReference); continue nextImport; } // all the code here which checks for valid bindings have been moved to the method // checkAndRecordImportBinding() since bug 361327 if(checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName) == -1) continue nextImport; if (importReference.isStatic()) { // look for more static bindings being imported by single static import(bug 361327). // findSingleImport() finds fields first, followed by method and then type // So if a type is found, no fields and methods are available anyway // similarly when method is found, type may be available but no field available for sure if (importBinding.kind() == Binding.FIELD) { checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE | Binding.METHOD, importReference); } else if (importBinding.kind() == Binding.METHOD) { checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE, importReference); } } } } // shrink resolvedImports... only happens if an error was reported if (this.tempImports.length > this.importPtr) System.arraycopy(this.tempImports, 0, this.tempImports = new ImportBinding[this.importPtr], 0, this.importPtr); this.imports = this.tempImports; int length = this.imports.length; this.typeOrPackageCache = new HashtableOfObject(length); for (int i = 0; i < length; i++) { ImportBinding binding = this.imports[i]; if (!binding.onDemand && binding.resolvedImport instanceof ReferenceBinding || binding instanceof ImportConflictBinding) this.typeOrPackageCache.put(binding.compoundName[binding.compoundName.length - 1], binding); } } public void faultInTypes() { faultInImports(); for (int i = 0, length = this.topLevelTypes.length; i < length; i++) this.topLevelTypes[i].faultInTypesForFieldsAndMethods(); } // this API is for code assist purpose public Binding findImport(char[][] compoundName, boolean findStaticImports, boolean onDemand) { if(onDemand) { return findImport(compoundName, compoundName.length); } else { return findSingleImport(compoundName, Binding.TYPE | Binding.FIELD | Binding.METHOD, findStaticImports); } } private Binding findImport(char[][] compoundName, int length) { recordQualifiedReference(compoundName); Binding binding = this.environment.getTopLevelPackage(compoundName[0]); int i = 1; foundNothingOrType: if (binding != null) { PackageBinding packageBinding = (PackageBinding) binding; while (i < length) { binding = packageBinding.getTypeOrPackage(compoundName[i++]); if (binding == null || !binding.isValidBinding()) { binding = null; break foundNothingOrType; } if (!(binding instanceof PackageBinding)) break foundNothingOrType; packageBinding = (PackageBinding) binding; } return packageBinding; } ReferenceBinding type; if (binding == null) { if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound); type = findType(compoundName[0], this.environment.defaultPackage, this.environment.defaultPackage); if (type == null || !type.isValidBinding()) return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound); i = 1; // reset to look for member types inside the default package type } else { type = (ReferenceBinding) binding; } while (i < length) { type = (ReferenceBinding)this.environment.convertToRawType(type, false /*do not force conversion of enclosing types*/); // type imports are necessarily raw for all except last if (!type.canBeSeenBy(this.fPackage)) return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, ProblemReasons.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), null, ProblemReasons.NotFound); } if (!type.canBeSeenBy(this.fPackage)) return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotVisible); return type; } private Binding findSingleImport(char[][] compoundName, int mask, boolean findStaticImports) { if (compoundName.length == 1) { // findType records the reference // the name cannot be a package if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound); ReferenceBinding typeBinding = findType(compoundName[0], this.environment.defaultPackage, this.fPackage); if (typeBinding == null) return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound); return typeBinding; } if (findStaticImports) return findSingleStaticImport(compoundName, mask); return findImport(compoundName, compoundName.length); } private Binding findSingleStaticImport(char[][] compoundName, int mask) { 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, (ReferenceBinding) temp, ProblemReasons.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 = (mask & Binding.FIELD) != 0 ? findField(type, name, null, true) : null; if (field != null) { if (field.problemId() == ProblemReasons.Ambiguous && ((ProblemFieldBinding) field).closestMatch.isStatic()) return field; // keep the ambiguous field instead of a possible method match if (field.isValidBinding() && field.isStatic() && field.canBeSeenBy(type, null, this)) return field; } // look to see if there is a static method with the same selector MethodBinding method = (mask & Binding.METHOD) != 0 ? findStaticMethod(type, name) : null; if (method != null) return method; type = findMemberType(name, type); if (type == null || !type.isStatic()) { if (field != null && !field.isValidBinding() && field.problemId() != ProblemReasons.NotFound) return field; return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotFound); } if (type.isValidBinding() && !type.canBeSeenBy(this.fPackage)) return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotVisible); if (type.problemId() == ProblemReasons.NotVisible) // ensure compoundName is correct return new ProblemReferenceBinding(compoundName, ((ProblemReferenceBinding) type).closestMatch, ProblemReasons.NotVisible); return type; } // helper method for findSingleStaticImport() private MethodBinding findStaticMethod(ReferenceBinding currentType, char[] selector) { if (!currentType.canBeSeenBy(this)) return null; do { currentType.initializeForStaticImports(); MethodBinding[] methods = currentType.getMethods(selector); if (methods != Binding.NO_METHODS) { for (int i = methods.length; --i >= 0;) { MethodBinding method = methods[i]; if (method.isStatic() && method.canBeSeenBy(this.fPackage)) return method; } } } while ((currentType = currentType.superclass()) != null); return null; } ImportBinding[] getDefaultImports() { // initialize the default imports if necessary... share the default java.lang.* import if (this.environment.defaultImports != null) return this.environment.defaultImports; Binding importBinding = this.environment.getTopLevelPackage(TypeConstants.JAVA); if (importBinding != null) importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1]); if (importBinding == null || !importBinding.isValidBinding()) { // create a proxy for the missing BinaryType problemReporter().isClassPathCorrect( TypeConstants.JAVA_LANG_OBJECT, this.referenceContext, this.environment.missingClassFileLocation); BinaryTypeBinding missingObject = this.environment.createMissingType(null, TypeConstants.JAVA_LANG_OBJECT); importBinding = missingObject.fPackage; } return this.environment.defaultImports = new ImportBinding[] {new ImportBinding(TypeConstants.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, Binding.TYPE | Binding.FIELD | Binding.METHOD, isStaticImport); } public int nextCaptureID() { return this.captureID++; } /* Answer the problem reporter to use for raising new problems. * * Note that as a side-effect, this updates the current reference context * (unit, type or method) in case the problem handler decides it is necessary * to abort. */ public ProblemReporter problemReporter() { ProblemReporter problemReporter = this.referenceContext.problemReporter; problemReporter.referenceContext = this.referenceContext; return problemReporter; } /* What do we hold onto: 1. when we resolve 'a.b.c', say we keep only 'a.b.c' & when we fail to resolve 'c' in 'a.b', lets keep 'a.b.c' THEN when we come across a new/changed/removed item named 'a.b.c', we would find all references to 'a.b.c' -> This approach fails because every type is resolved in every onDemand import to detect collision cases... so the references could be 10 times bigger than necessary. 2. when we resolve 'a.b.c', lets keep 'a.b' & 'c' & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'c' THEN when we come across a new/changed/removed item named 'a.b.c', we would find all references to 'a.b' & 'c' -> This approach does not have a space problem but fails to handle collision cases. What happens if a type is added named 'a.b'? We would search for 'a' & 'b' but would not find a match. 3. when we resolve 'a.b.c', lets keep 'a', 'a.b' & 'a', 'b', 'c' & when we fail to resolve 'c' in 'a.b', lets keep 'a', 'a.b' & 'a', 'b', 'c' THEN when we come across a new/changed/removed item named 'a.b.c', we would find all references to 'a.b' & 'c' OR 'a.b' -> 'a' & 'b' OR 'a' -> '' & 'a' -> As long as each single char[] is interned, we should not have a space problem and can handle collision cases. 4. when we resolve 'a.b.c', lets keep 'a.b' & 'a', 'b', 'c' & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'a', 'b', 'c' THEN when we come across a new/changed/removed item named 'a.b.c', we would find all references to 'a.b' & 'c' OR 'a.b' -> 'a' & 'b' in the simple name collection OR 'a' -> 'a' in the simple name collection -> As long as each single char[] is interned, we should not have a space problem and can handle collision cases. */ void recordQualifiedReference(char[][] qualifiedName) { if (this.qualifiedReferences == null) return; // not recording dependencies int length = qualifiedName.length; if (length > 1) { recordRootReference(qualifiedName[0]); while (!this.qualifiedReferences.contains(qualifiedName)) { this.qualifiedReferences.add(qualifiedName); if (length == 2) { recordSimpleReference(qualifiedName[0]); recordSimpleReference(qualifiedName[1]); return; } length--; recordSimpleReference(qualifiedName[length]); System.arraycopy(qualifiedName, 0, qualifiedName = new char[length][], 0, length); } } else if (length == 1) { recordRootReference(qualifiedName[0]); recordSimpleReference(qualifiedName[0]); } } void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) { recordQualifiedReference(qualifiedEnclosingName); if (qualifiedEnclosingName.length == 0) recordRootReference(simpleName); recordSimpleReference(simpleName); } void recordReference(ReferenceBinding type, char[] simpleName) { ReferenceBinding actualType = typeToRecord(type); if (actualType != null) recordReference(actualType.compoundName, simpleName); } void recordRootReference(char[] simpleName) { if (this.rootReferences == null) return; // not recording dependencies if (!this.rootReferences.contains(simpleName)) this.rootReferences.add(simpleName); } void recordSimpleReference(char[] simpleName) { if (this.simpleNameReferences == null) return; // not recording dependencies if (!this.simpleNameReferences.contains(simpleName)) this.simpleNameReferences.add(simpleName); } void recordSuperTypeReference(TypeBinding type) { if (this.referencedSuperTypes == null) return; // not recording dependencies ReferenceBinding actualType = typeToRecord(type); if (actualType != null && !this.referencedSuperTypes.containsIdentical(actualType)) this.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 (this.referencedTypes == null) return; // not recording dependencies ReferenceBinding actualType = typeToRecord(type); if (actualType != null && !this.referencedTypes.containsIdentical(actualType)) this.referencedTypes.add(actualType); } void recordTypeReferences(TypeBinding[] types) { if (this.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 ReferenceBinding actualType = typeToRecord(types[i]); if (actualType != null && !this.referencedTypes.containsIdentical(actualType)) this.referencedTypes.add(actualType); } } Binding resolveSingleImport(ImportBinding importBinding, int mask) { if (importBinding.resolvedImport == null) { importBinding.resolvedImport = findSingleImport(importBinding.compoundName, mask, importBinding.isStatic()); if (!importBinding.resolvedImport.isValidBinding() || importBinding.resolvedImport instanceof PackageBinding) { if (importBinding.resolvedImport.problemId() == ProblemReasons.Ambiguous) return importBinding.resolvedImport; if (this.imports != null) { ImportBinding[] newImports = new ImportBinding[this.imports.length - 1]; for (int i = 0, n = 0, max = this.imports.length; i < max; i++) if (this.imports[i] != importBinding) newImports[n++] = this.imports[i]; this.imports = newImports; } return null; } } return importBinding.resolvedImport; } public void storeDependencyInfo() { // add the type hierarchy of each referenced supertype // cannot do early since the hierarchy may not be fully resolved for (int i = 0; i < this.referencedSuperTypes.size; i++) { // grows as more types are added ReferenceBinding type = (ReferenceBinding) this.referencedSuperTypes.elementAt(i); if (!this.referencedTypes.containsIdentical(type)) this.referencedTypes.add(type); if (!type.isLocalType()) { ReferenceBinding enclosing = type.enclosingType(); if (enclosing != null) recordSuperTypeReference(enclosing); } ReferenceBinding superclass = type.superclass(); if (superclass != null) recordSuperTypeReference(superclass); ReferenceBinding[] interfaces = type.superInterfaces(); if (interfaces != null) for (int j = 0, length = interfaces.length; j < length; j++) recordSuperTypeReference(interfaces[j]); } for (int i = 0, l = this.referencedTypes.size; i < l; i++) { ReferenceBinding type = (ReferenceBinding) this.referencedTypes.elementAt(i); if (!type.isLocalType()) recordQualifiedReference(type.isMemberType() ? CharOperation.splitOn('.', type.readableName()) : type.compoundName); } int size = this.qualifiedReferences.size; char[][][] qualifiedRefs = new char[size][][]; for (int i = 0; i < size; i++) qualifiedRefs[i] = this.qualifiedReferences.elementAt(i); this.referenceContext.compilationResult.qualifiedReferences = qualifiedRefs; size = this.simpleNameReferences.size; char[][] simpleRefs = new char[size][]; for (int i = 0; i < size; i++) simpleRefs[i] = this.simpleNameReferences.elementAt(i); this.referenceContext.compilationResult.simpleNameReferences = simpleRefs; size = this.rootReferences.size; char[][] rootRefs = new char[size][]; for (int i = 0; i < size; i++) rootRefs[i] = this.rootReferences.elementAt(i); this.referenceContext.compilationResult.rootReferences = rootRefs; } public String toString() { return "--- CompilationUnit Scope : " + new String(this.referenceContext.getFileName()); //$NON-NLS-1$ } private ReferenceBinding typeToRecord(TypeBinding type) { if (type.isArrayType()) type = ((ArrayBinding) type).leafComponentType; switch (type.kind()) { case Binding.BASE_TYPE : case Binding.TYPE_PARAMETER : case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : return null; case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : type = type.erasure(); } ReferenceBinding refType = (ReferenceBinding) type; if (refType.isLocalType()) return null; return refType; } public void verifyMethods(MethodVerifier verifier) { for (int i = 0, length = this.topLevelTypes.length; i < length; i++) this.topLevelTypes[i].verifyMethods(verifier); } private void recordImportBinding(ImportBinding bindingToAdd) { if (this.tempImports.length == this.importPtr) { System.arraycopy(this.tempImports, 0, (this.tempImports = new ImportBinding[this.importPtr + 1]), 0, this.importPtr); } this.tempImports[this.importPtr++] = bindingToAdd; } /** * Checks additional bindings (methods or types) imported from a single static import. * Method is tried first, followed by type. If found, records them. * If in the process, import is flagged as duplicate, -1 is returned. * @param compoundName * @param typesBySimpleNames * @param mask * @param importReference */ private void checkMoreStaticBindings( char[][] compoundName, HashtableOfType typesBySimpleNames, int mask, ImportReference importReference) { Binding importBinding = findSingleStaticImport(compoundName, mask); if (!importBinding.isValidBinding()) { // only continue if the same kind's ambiguous binding is returned // may have found an ambiguous type when looking for field or method. Don't continue in that case if (importBinding.problemId() == ProblemReasons.Ambiguous) { // keep it unless a duplicate can be found below checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); } } else { checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); } if (((mask & Binding.METHOD) != 0) && (importBinding.kind() == Binding.METHOD)) { // found method // type is left to be looked for // reset METHOD bit to enable lookup for only type mask &= ~Binding.METHOD; // now search for a type binding checkMoreStaticBindings(compoundName, typesBySimpleNames, mask, importReference); } } /** * Checks for duplicates. If all ok, records the importBinding * returns -1 when this import is flagged as duplicate. * @param importBinding * @param typesBySimpleNames * @param importReference * @param compoundName * @return -1 when this import is flagged as duplicate, importPtr otherwise. */ private int checkAndRecordImportBinding( Binding importBinding, HashtableOfType typesBySimpleNames, ImportReference importReference, char[][] compoundName) { ReferenceBinding conflictingType = null; if (importBinding instanceof MethodBinding) { conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length); if (!conflictingType.isValidBinding() || (importReference.isStatic() && !conflictingType.isStatic())) conflictingType = null; } // collisions between an imported static field & a type should be checked according to spec... but currently not by javac if (importBinding instanceof ReferenceBinding || conflictingType != null) { ReferenceBinding referenceBinding = conflictingType == null ? (ReferenceBinding) importBinding : conflictingType; ReferenceBinding typeToCheck = referenceBinding.problemId() == ProblemReasons.Ambiguous ? ((ProblemReferenceBinding) referenceBinding).closestMatch : referenceBinding; if (importReference.isTypeUseDeprecated(typeToCheck, this)) problemReporter().deprecatedType(typeToCheck, 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) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=302865 // Check all resolved imports to see if this import qualifies as a duplicate for (int j = 0; j < this.importPtr; j++) { ImportBinding resolved = this.tempImports[j]; if (resolved instanceof ImportConflictBinding) { ImportConflictBinding importConflictBinding = (ImportConflictBinding) resolved; if (importConflictBinding.conflictingTypeBinding == referenceBinding) { if (!importReference.isStatic()) { // resolved is implicitly static problemReporter().duplicateImport(importReference); recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); } } } else if (resolved.resolvedImport == referenceBinding) { if (importReference.isStatic() != resolved.isStatic()) { problemReporter().duplicateImport(importReference); recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); } } } return -1; } // either the type collides with a top level type or another imported type for (int j = 0, length = this.topLevelTypes.length; j < length; j++) { if (CharOperation.equals(this.topLevelTypes[j].sourceName, existingType.sourceName)) { problemReporter().conflictingImport(importReference); return -1; } } problemReporter().duplicateImport(importReference); return -1; } typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding); } else if (importBinding instanceof FieldBinding) { for (int j = 0; j < this.importPtr; j++) { ImportBinding resolved = this.tempImports[j]; // find other static fields with the same name if (resolved.isStatic() && resolved.resolvedImport instanceof FieldBinding && importBinding != resolved.resolvedImport) { if (CharOperation.equals(compoundName[compoundName.length - 1], resolved.compoundName[resolved.compoundName.length - 1])) { problemReporter().duplicateImport(importReference); return -1; } } } } if (conflictingType == null) { recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); } else { recordImportBinding(new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference)); } return this.importPtr; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/0000755000175000001440000000000012212041344025051 5ustar dokousers././@LongLink0000644000000000000000000000015112251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.0000644000175000001440000000525512212041344032212 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; public class JavadocSingleNameReference extends SingleNameReference { public int tagSourceStart, tagSourceEnd; public JavadocSingleNameReference(char[] source, long pos, int tagStart, int tagEnd) { super(source, pos); this.tagSourceStart = tagStart; this.tagSourceEnd = tagEnd; this.bits |= InsideJavadoc; } public void resolve(BlockScope scope) { resolve(scope, true, scope.compilerOptions().reportUnusedParameterIncludeDocCommentReference); } /** * Resolve without warnings */ public void resolve(BlockScope scope, boolean warn, boolean considerParamRefAsUsage) { LocalVariableBinding variableBinding = scope.findVariable(this.token); if (variableBinding != null && variableBinding.isValidBinding() && ((variableBinding.tagBits & TagBits.IsArgument) != 0)) { this.binding = variableBinding; if (considerParamRefAsUsage) { variableBinding.useFlag = LocalVariableBinding.USED; } return; } if (warn) { try { MethodScope methScope = (MethodScope) scope; scope.problemReporter().javadocUndeclaredParamTagName(this.token, this.sourceStart, this.sourceEnd, methScope.referenceMethod().modifiers); } catch (Exception e) { scope.problemReporter().javadocUndeclaredParamTagName(this.token, this.sourceStart, this.sourceEnd, -1); } } } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000015112251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.0000644000175000001440000001076712212041344032257 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class JavadocSingleTypeReference extends SingleTypeReference { public int tagSourceStart, tagSourceEnd; public PackageBinding packageBinding; public JavadocSingleTypeReference(char[] source, long pos, int tagStart, int tagEnd) { super(source, pos); this.tagSourceStart = tagStart; this.tagSourceEnd = tagEnd; this.bits |= ASTNode.InsideJavadoc; } /* * We need to modify resolving behavior to handle package references */ protected TypeBinding internalResolveType(Scope scope) { // handle the error here this.constant = Constant.NotAConstant; if (this.resolvedType != null) { // is a shared type reference which was already resolved if (this.resolvedType.isValidBinding()) { return this.resolvedType; } else { switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : case ProblemReasons.InheritedNameHidesEnclosingName : TypeBinding type = this.resolvedType.closestMatch(); return type; default : return null; } } } this.resolvedType = getTypeBinding(scope); // End resolution when getTypeBinding(scope) returns null. This may happen in // certain circumstances, typically when an illegal access is done on a type // variable (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=204749) if (this.resolvedType == null) return null; if (!this.resolvedType.isValidBinding()) { char[][] tokens = { this.token }; Binding binding = scope.getTypeOrPackage(tokens); if (binding instanceof PackageBinding) { this.packageBinding = (PackageBinding) binding; // Valid package references are allowed in Javadoc (https://bugs.eclipse.org/bugs/show_bug.cgi?id=281609) } else { if (this.resolvedType.problemId() == ProblemReasons.NonStaticReferenceInStaticContext) { TypeBinding closestMatch = this.resolvedType.closestMatch(); if (closestMatch != null && closestMatch.isTypeVariable()) { this.resolvedType = closestMatch; // ignore problem as we want report specific javadoc one instead return this.resolvedType; } } reportInvalidType(scope); } return null; } if (isTypeUseDeprecated(this.resolvedType, scope)) reportDeprecatedType(this.resolvedType, scope); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=209936 // raw convert all enclosing types when dealing with Javadoc references if (this.resolvedType.isGenericType() || this.resolvedType.isParameterizedType()) { this.resolvedType = scope.environment().convertToRawType(this.resolvedType, true /*force the conversion of enclosing types*/); } return this.resolvedType; } protected void reportDeprecatedType(TypeBinding type, Scope scope) { scope.problemReporter().javadocDeprecatedType(type, this, scope.getDeclarationModifiers()); } protected void reportInvalidType(Scope scope) { scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers()); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java0000644000175000001440000001216412212041344031424 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class ClassLiteralAccess extends Expression { public TypeReference type; public TypeBinding targetType; FieldBinding syntheticField; public ClassLiteralAccess(int sourceEnd, TypeReference type) { this.type = type; type.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage this.sourceStart = type.sourceStart; this.sourceEnd = sourceEnd; } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // if reachable, request the addition of a synthetic field for caching the class descriptor SourceTypeBinding sourceType = currentScope.outerMostClassScope().enclosingSourceType(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=22334 if (!sourceType.isInterface() && !this.targetType.isBaseType() && currentScope.compilerOptions().targetJDK < ClassFileConstants.JDK1_5) { this.syntheticField = sourceType.addSyntheticFieldForClassLiteral(this.targetType, currentScope); } return flowInfo; } /** * MessageSendDotClass 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) { int pc = codeStream.position; // in interface case, no caching occurs, since cannot make a cache field for interface if (valueRequired) { codeStream.generateClassLiteralAccessForType(this.type.resolvedType, this.syntheticField); codeStream.generateImplicitConversion(this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printExpression(int indent, StringBuffer output) { return this.type.print(0, output).append(".class"); //$NON-NLS-1$ } public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; if ((this.targetType = this.type.resolveType(scope, true /* check bounds*/)) == null) return null; /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=320463 https://bugs.eclipse.org/bugs/show_bug.cgi?id=312076 JLS3 15.8.2 forbids the type named in the class literal expression from being a parameterized type. And the grammar in 18.1 disallows (where X and Y are some concrete types) constructs of the form Outer.class, Outer.Inner.class, Outer.Inner.class, Outer.Inner.class etc. Corollary wise, we should resolve the type of the class literal expression to be a raw type as class literals exist only for the raw underlying type. */ this.targetType = scope.environment().convertToRawType(this.targetType, true /* force conversion of enclosing types*/); if (this.targetType.isArrayType()) { ArrayBinding arrayBinding = (ArrayBinding) this.targetType; TypeBinding leafComponentType = arrayBinding.leafComponentType; if (leafComponentType == TypeBinding.VOID) { scope.problemReporter().cannotAllocateVoidArray(this); return null; } else if (leafComponentType.isTypeVariable()) { scope.problemReporter().illegalClassLiteralForTypeVariable((TypeVariableBinding)leafComponentType, this); } } else if (this.targetType.isTypeVariable()) { scope.problemReporter().illegalClassLiteralForTypeVariable((TypeVariableBinding)this.targetType, this); } ReferenceBinding classType = scope.getJavaLangClass(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=328689 if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // Integer.class --> Class, perform boxing of base types (int.class --> Class) TypeBinding boxedType = null; if (this.targetType.id == T_void) { boxedType = scope.environment().getResolvedType(JAVA_LANG_VOID, scope); } else { boxedType = scope.boxing(this.targetType); } this.resolvedType = scope.environment().createParameterizedType(classType, new TypeBinding[]{ boxedType }, null/*not a member*/); } else { this.resolvedType = classType; } return this.resolvedType; } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.type.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java0000644000175000001440000002650112212041344031223 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; //dedicated treatment for the && public class AND_AND_Expression extends BinaryExpression { int rightInitStateIndex = -1; int mergedInitStateIndex = -1; public AND_AND_Expression(Expression left, Expression right, int operator) { super(left, right, operator); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { Constant cst = this.left.optimizedBooleanConstant(); boolean isLeftOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isLeftOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; if (isLeftOptimizedTrue) { // TRUE && anything // need to be careful of scenario: // (x && y) && !z, if passing the left info to the right, it would // be swapped by the ! FlowInfo mergedInfo = this.left.analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); mergedInfo = this.right.analyseCode(currentScope, flowContext, mergedInfo); this.mergedInitStateIndex = currentScope.methodScope() .recordInitializationStates(mergedInfo); return mergedInfo; } FlowInfo leftInfo = this.left.analyseCode(currentScope, flowContext, flowInfo); if ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) != 0) flowContext.expireNullCheckedFieldInfo(); // need to be careful of scenario: // (x && y) && !z, if passing the left info to the right, it would be // swapped by the ! FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalCopy(); this.rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo); int previousMode = rightInfo.reachMode(); if (isLeftOptimizedFalse) { if ((rightInfo.reachMode() & FlowInfo.UNREACHABLE) == 0) { currentScope.problemReporter().fakeReachable(this.right); rightInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } } rightInfo = this.right.analyseCode(currentScope, flowContext, rightInfo); if ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) != 0) flowContext.expireNullCheckedFieldInfo(); this.left.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); this.right.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); FlowInfo mergedInfo = FlowInfo.conditional( rightInfo.safeInitsWhenTrue(), leftInfo.initsWhenFalse().unconditionalInits().mergedWith( rightInfo.initsWhenFalse().setReachMode(previousMode).unconditionalInits())); // reset after trueMergedInfo got extracted this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } /** * Code generation for a binary operation */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { // inlined value if (valueRequired) codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); return; } Constant cst = this.right.constant; if (cst != Constant.NotAConstant) { // && true --> if (cst.booleanValue() == true) { this.left.generateCode(currentScope, codeStream, valueRequired); } else { // && false --> false this.left.generateCode(currentScope, codeStream, false); if (valueRequired) codeStream.iconst_0(); } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); return; } BranchLabel falseLabel = new BranchLabel(codeStream), endLabel; cst = this.left.optimizedBooleanConstant(); boolean leftIsConst = cst != Constant.NotAConstant; boolean leftIsTrue = leftIsConst && cst.booleanValue() == true; cst = this.right.optimizedBooleanConstant(); boolean rightIsConst = cst != Constant.NotAConstant; boolean rightIsTrue = rightIsConst && cst.booleanValue() == true; generateOperands : { if (leftIsConst) { this.left.generateCode(currentScope, codeStream, false); if (!leftIsTrue) { break generateOperands; // no need to generate right operand } } else { this.left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true); // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1 } if (this.rightInitStateIndex != -1) { codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } if (rightIsConst) { this.right.generateCode(currentScope, codeStream, false); } else { this.right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired); } } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } /* * improving code gen for such a case: boolean b = i < 0 && false since * the label has never been used, we have the inlined value on the * stack. */ if (valueRequired) { if (leftIsConst && !leftIsTrue) { codeStream.iconst_0(); } else { if (rightIsConst && !rightIsTrue) { codeStream.iconst_0(); } else { codeStream.iconst_1(); } if (falseLabel.forwardReferenceCount() > 0) { if ((this.bits & IsReturnedValue) != 0) { codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); falseLabel.place(); codeStream.iconst_0(); } else { codeStream.goto_(endLabel = new BranchLabel(codeStream)); codeStream.decrStackSize(1); falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } else { falseLabel.place(); } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } else { falseLabel.place(); } } /** * Boolean operator code generation Optimized operations are: && */ public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { if (this.constant != Constant.NotAConstant) { super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } // && true --> Constant cst = this.right.constant; if (cst != Constant.NotAConstant && cst.booleanValue() == true) { int pc = codeStream.position; this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } cst = this.left.optimizedBooleanConstant(); boolean leftIsConst = cst != Constant.NotAConstant; boolean leftIsTrue = leftIsConst && cst.booleanValue() == true; cst = this.right.optimizedBooleanConstant(); boolean rightIsConst = cst != Constant.NotAConstant; boolean rightIsTrue = rightIsConst && cst.booleanValue() == true; // default case generateOperands : { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case BranchLabel internalFalseLabel = new BranchLabel(codeStream); this.left.generateOptimizedBoolean(currentScope, codeStream, null, internalFalseLabel, !leftIsConst); // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1 if (leftIsConst && !leftIsTrue) { internalFalseLabel.place(); break generateOperands; // no need to generate right operand } if (this.rightInitStateIndex != -1) { codeStream .addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } this.right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired && !rightIsConst); if (valueRequired && rightIsConst && rightIsTrue) { codeStream.goto_(trueLabel); codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } internalFalseLabel.place(); } } else { // implicit falling through the TRUE case if (trueLabel == null) { this.left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, !leftIsConst); // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1 int pc = codeStream.position; if (leftIsConst && !leftIsTrue) { if (valueRequired) { codeStream.goto_(falseLabel); } codeStream.recordPositionsFrom(pc, this.sourceEnd); break generateOperands; // no need to generate right operand } if (this.rightInitStateIndex != -1) { codeStream .addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } this.right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired && !rightIsConst); if (valueRequired && rightIsConst && !rightIsTrue) { codeStream.goto_(falseLabel); codeStream.recordPositionsFrom(pc, this.sourceEnd); } } else { // no implicit fall through TRUE/FALSE --> should never occur } } } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } } public boolean isCompactableOperation() { return false; } /** * @see org.eclipse.jdt.internal.compiler.ast.BinaryExpression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public TypeBinding resolveType(BlockScope scope) { TypeBinding result = super.resolveType(scope); // check whether comparing identical expressions Binding leftDirect = Expression.getDirectBinding(this.left); if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) { if (!(this.right instanceof Assignment)) scope.problemReporter().comparingIdenticalExpressions(this); } return result; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.left.traverse(visitor, scope); this.right.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java0000644000175000001440000002762412212041344031127 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 292478 - Report potentially null across variable assignment * bug 335093 - [compiler][null] minimal hook for future null annotation support * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 358903 - Filter practically unimportant resource leak warnings * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 400761 - [compiler][null] null may be return as boolean without a diagnostic * Jesper S Moller - Contributions for * Bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.*; public class LocalDeclaration extends AbstractVariableDeclaration { public LocalVariableBinding binding; public LocalDeclaration( char[] name, int sourceStart, int sourceEnd) { this.name = name; this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; this.declarationEnd = sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // record variable initialization if any if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.bits |= ASTNode.IsLocalDeclarationReachable; // only set if actually reached } if (this.initialization == null) { return flowInfo; } this.initialization.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); FlowInfo preInitInfo = null; boolean shouldAnalyseResource = this.binding != null && flowInfo.reachMode() == FlowInfo.REACHABLE && currentScope.compilerOptions().analyseResourceLeaks && FakedTrackingVariable.isAnyCloseable(this.initialization.resolvedType); if (shouldAnalyseResource) { preInitInfo = flowInfo.unconditionalCopy(); // analysis of resource leaks needs additional context while analyzing the RHS: FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, this.binding, this.initialization, flowInfo); } flowInfo = this.initialization .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); if (shouldAnalyseResource) FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, flowContext, this, this.initialization, this.binding); else FakedTrackingVariable.cleanUpAfterAssignment(currentScope, Binding.LOCAL, this.initialization); int nullStatus = this.initialization.nullStatus(flowInfo, flowContext); if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes this.bits |= FirstAssignmentToLocal; } else { this.bits &= ~FirstAssignmentToLocal; // int i = (i = 0); } flowInfo.markAsDefinitelyAssigned(this.binding); nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, this.binding, nullStatus, this.initialization, this.initialization.resolvedType); if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) { flowInfo.markNullStatus(this.binding, nullStatus); // no need to inform enclosing try block since its locals won't get // known by the finally block } return flowInfo; } public void checkModifiers() { //only potential valid modifier is <> if (((this.modifiers & ExtraCompilerModifiers.AccJustFlag) & ~ClassFileConstants.AccFinal) != 0) //AccModifierProblem -> other (non-visibility problem) //AccAlternateModifierProblem -> duplicate modifier //AccModifierProblem | AccAlternateModifierProblem -> visibility problem" this.modifiers = (this.modifiers & ~ExtraCompilerModifiers.AccAlternateModifierProblem) | ExtraCompilerModifiers.AccModifierProblem; } /** * Code generation for a local declaration: * i.e. normal assignment to a local variable + unused variable handling */ public void generateCode(BlockScope currentScope, CodeStream codeStream) { // even if not reachable, variable must be added to visible if allocated (28298) if (this.binding.resolvedPosition != -1) { codeStream.addVisibleLocalVariable(this.binding); } if ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; // something to initialize? generateInit: { if (this.initialization == null) break generateInit; // forget initializing unused or final locals set to constant value (final ones are inlined) if (this.binding.resolvedPosition < 0) { if (this.initialization.constant != Constant.NotAConstant) break generateInit; // if binding unused generate then discard the value this.initialization.generateCode(currentScope, codeStream, false); break generateInit; } this.initialization.generateCode(currentScope, codeStream, true); // 26903, need extra cast to store null in array local var if (this.binding.type.isArrayType() && ((this.initialization instanceof CastExpression) // arrayLoc = (type[])null && (((CastExpression)this.initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL))){ codeStream.checkcast(this.binding.type); } codeStream.store(this.binding, false); if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) { /* Variable may have been initialized during the code initializing it e.g. int i = (i = 1); */ this.binding.recordInitializationStartPC(codeStream.position); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind() */ public int getKind() { return LOCAL_VARIABLE; } public void resolve(BlockScope scope) { // create a binding and add it to the scope TypeBinding variableType = this.type.resolveType(scope, true /* check bounds*/); checkModifiers(); if (variableType != null) { if (variableType == TypeBinding.VOID) { scope.problemReporter().variableTypeCannotBeVoid(this); return; } if (variableType.isArrayType() && ((ArrayBinding) variableType).leafComponentType == TypeBinding.VOID) { scope.problemReporter().variableTypeCannotBeVoidArray(this); return; } } Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/); if (existingVariable != null && existingVariable.isValidBinding()){ if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) { scope.problemReporter().redefineLocal(this); } else { scope.problemReporter().localVariableHiding(this, existingVariable, false); } } if ((this.modifiers & ClassFileConstants.AccFinal)!= 0 && this.initialization == null) { this.modifiers |= ExtraCompilerModifiers.AccBlankFinal; } this.binding = new LocalVariableBinding(this, variableType, this.modifiers, false /*isArgument*/); scope.addLocalVariable(this.binding); this.binding.setConstant(Constant.NotAConstant); // allow to recursivelly target the binding.... // the correct constant is harmed if correctly computed at the end of this method if (variableType == null) { if (this.initialization != null) this.initialization.resolveType(scope); // want to report all possible errors return; } // store the constant for final locals if (this.initialization != null) { if (this.initialization instanceof ArrayInitializer) { TypeBinding initializationType = this.initialization.resolveTypeExpecting(scope, variableType); if (initializationType != null) { ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType; this.initialization.computeConversion(scope, variableType, initializationType); } } else { this.initialization.setExpectedType(variableType); TypeBinding initializationType = this.initialization.resolveType(scope); if (initializationType != null) { if (variableType != initializationType) // must call before computeConversion() and typeMismatchError() scope.compilationUnitScope().recordTypeConversion(variableType, initializationType); if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, variableType) || initializationType.isCompatibleWith(variableType, scope)) { this.initialization.computeConversion(scope, variableType, initializationType); if (initializationType.needsUncheckedConversion(variableType)) { scope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, variableType); } if (this.initialization instanceof CastExpression && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) { CastExpression.checkNeedForAssignedCast(scope, variableType, (CastExpression) this.initialization); } } else if (isBoxingCompatible(initializationType, variableType, this.initialization, scope)) { this.initialization.computeConversion(scope, variableType, initializationType); if (this.initialization instanceof CastExpression && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) { CastExpression.checkNeedForAssignedCast(scope, variableType, (CastExpression) this.initialization); } } else { if ((variableType.tagBits & TagBits.HasMissingType) == 0) { // if problem already got signaled on type, do not report secondary problem scope.problemReporter().typeMismatchError(initializationType, variableType, this.initialization, null); } } } } // check for assignment with no effect if (this.binding == Expression.getDirectBinding(this.initialization)) { scope.problemReporter().assignmentHasNoEffect(this, this.name); } // change the constant in the binding when it is final // (the optimization of the constant propagation will be done later on) // cast from constant actual type to variable type this.binding.setConstant( this.binding.isFinal() ? this.initialization.constant.castTo((variableType.id << 4) + this.initialization.constant.typeID()) : Constant.NotAConstant); } // only resolve annotation at the end, for constant to be positioned before (96991) resolveAnnotations(scope, this.annotations, this.binding); scope.validateNullAnnotation(this.binding.tagBits, this.type, this.annotations); } public void traverse(ASTVisitor visitor, BlockScope scope) { if (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); } this.type.traverse(visitor, scope); if (this.initialization != null) this.initialization.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/NameReference.java0000644000175000001440000000551212212041344030416 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 331649 - [compiler][null] consider null annotations for fields *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.lookup.*; public abstract class NameReference extends Reference implements InvocationSite { public Binding binding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding public TypeBinding actualReceiverType; // modified receiver type - actual one according to namelookup //the error printing //some name reference are build as name reference but //only used as type reference. When it happens, instead of //creating a new object (aTypeReference) we just flag a boolean //This concesion is valuable while there are cases when the NameReference //will be a TypeReference (static message sends.....) and there is //no changeClass in java. public NameReference() { this.bits |= Binding.TYPE | Binding.VARIABLE; // restrictiveFlag } /** * Use this method only when sure that the current reference is not * a chain of several fields (QualifiedNameReference with more than one field). * Otherwise use {@link #lastFieldBinding()}. */ public FieldBinding fieldBinding() { //this method should be sent ONLY after a check against isFieldReference() //check its use doing senders......... return (FieldBinding) this.binding ; } public FieldBinding lastFieldBinding() { if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD) return fieldBinding(); // most subclasses only refer to one field anyway return null; } public boolean isSuperAccess() { return false; } public boolean isTypeAccess() { // null is acceptable when we are resolving the first part of a reference return this.binding == null || this.binding instanceof ReferenceBinding; } public boolean isTypeReference() { return this.binding instanceof ReferenceBinding; } public void setActualReceiverType(ReferenceBinding receiverType) { if (receiverType == null) return; // error scenario only this.actualReceiverType = receiverType; } public void setDepth(int depth) { this.bits &= ~DepthMASK; // flush previous depth if any if (depth > 0) { this.bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits } } public void setFieldIndex(int index){ // ignored } public abstract String unboundReferenceErrorName(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java0000644000175000001440000014403312212041344032244 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 185682 - Increment/decrement operators mark local variables as read * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check * Jesper S Moller - Contributions for * bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class QualifiedNameReference extends NameReference { public char[][] tokens; public long[] sourcePositions; public FieldBinding[] otherBindings; int[] otherDepths; public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding public SyntheticMethodBinding syntheticWriteAccessor; public SyntheticMethodBinding[] syntheticReadAccessors; public TypeBinding genericCast; public TypeBinding[] otherGenericCasts; public QualifiedNameReference(char[][] tokens, long[] positions, int sourceStart, int sourceEnd) { this.tokens = tokens; this.sourcePositions = positions; this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; } public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { // determine the rank until which we now we do not need any actual value for the field access int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; FieldBinding lastFieldBinding = null; switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field lastFieldBinding = (FieldBinding) this.binding; if (needValue || complyTo14) { manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, 0, flowInfo); } // check if final blank field if (lastFieldBinding.isBlankFinal() && this.otherBindings != null // the last field binding is only assigned && currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(lastFieldBinding.declaringClass.original(), flowInfo); if (!fieldInits.isDefinitelyAssigned(lastFieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this); } } break; case Binding.LOCAL : // first binding is a local variable LocalVariableBinding localBinding; if (!flowInfo .isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); } if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { localBinding.useFlag = LocalVariableBinding.USED; } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { localBinding.useFlag = LocalVariableBinding.FAKE_USED; } if (needValue) { checkInternalNPE(currentScope, flowContext, flowInfo, true); } } if (needValue) { manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); // only for first binding } // all intermediate field accesses are read accesses if (this.otherBindings != null) { for (int i = 0; i < otherBindingsCount-1; i++) { lastFieldBinding = this.otherBindings[i]; needValue = !this.otherBindings[i+1].isStatic(); if (needValue || complyTo14) { manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, i + 1, flowInfo); } } lastFieldBinding = this.otherBindings[otherBindingsCount-1]; } if (isCompound) { if (otherBindingsCount == 0 && lastFieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(lastFieldBinding.declaringClass, flowInfo); if (!fieldInits.isDefinitelyAssigned(lastFieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this); } } manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, otherBindingsCount, flowInfo); } if (assignment.expression != null) { flowInfo = assignment .expression .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); } // the last field access is a write access if (lastFieldBinding.isFinal()) { // in a context where it can be assigned? if (otherBindingsCount == 0 && this.indexOfFirstFieldBinding == 1 && lastFieldBinding.isBlankFinal() && !isCompound && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { if (flowInfo.isPotentiallyAssigned(lastFieldBinding)) { currentScope.problemReporter().duplicateInitializationOfBlankFinalField(lastFieldBinding, this); } else { flowContext.recordSettingFinal(lastFieldBinding, this, flowInfo); } flowInfo.markAsDefinitelyAssigned(lastFieldBinding); } else { currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this); if (otherBindingsCount == 0 && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { // pretend it got assigned flowInfo.markAsDefinitelyAssigned(lastFieldBinding); } } } // note: not covering def.assign for @NonNull: QNR cannot provably refer to a variable of the current object manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, -1 /*write-access*/, flowInfo); return flowInfo; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return analyseCode(currentScope, flowContext, flowInfo, true); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { // determine the rank until which we now we do not need any actual value for the field access int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; boolean needValue = otherBindingsCount == 0 ? valueRequired : !this.otherBindings[0].isStatic(); boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field if (needValue || complyTo14) { manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, 0, flowInfo); } FieldBinding fieldBinding = (FieldBinding) this.binding; if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding // check if reading a final blank field if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo); if (!fieldInits.isDefinitelyAssigned(fieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); } } } break; case Binding.LOCAL : // reading a local variable LocalVariableBinding localBinding; if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); } if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { localBinding.useFlag = LocalVariableBinding.USED; } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { localBinding.useFlag = LocalVariableBinding.FAKE_USED; } } if (needValue) { checkInternalNPE(currentScope, flowContext, flowInfo, true); } if (needValue) { manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); // only for first binding (if value needed only) } if (this.otherBindings != null) { for (int i = 0; i < otherBindingsCount; i++) { needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired; if (needValue || complyTo14) { manageSyntheticAccessIfNecessary(currentScope, this.otherBindings[i], i + 1, flowInfo); } } } return flowInfo; } /* check if any dot in this QNR may trigger an NPE. */ private void checkInternalNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, boolean checkString) { if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) { LocalVariableBinding local = (LocalVariableBinding) this.binding; if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0 && (checkString || local.type.id != TypeIds.T_JavaLangString)) { if ((this.bits & ASTNode.IsNonNull) == 0) { flowContext.recordUsingNullReference(scope, local, this, FlowContext.MAY_NULL, flowInfo); } flowInfo.markAsComparedEqualToNonNull(local); // from thereon it is set flowContext.markFinallyNullStatus(local, FlowInfo.NON_NULL); } } if (this.otherBindings != null) { if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD) { // is the first field dereferenced annotated Nullable? If so, report immediately checkNullableFieldDereference(scope, (FieldBinding) this.binding, this.sourcePositions[0]); } // look for annotated fields, they do not depend on flow context -> check immediately: int length = this.otherBindings.length - 1; // don't check the last binding for (int i = 0; i < length; i++) { checkNullableFieldDereference(scope, this.otherBindings[i], this.sourcePositions[i+1]); } } } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { if (super.checkNPE(scope, flowContext, flowInfo)) { return true; } FieldBinding fieldBinding = null; long position = 0L; if (this.otherBindings == null) { if ((this.bits & RestrictiveFlagMASK) == Binding.FIELD) { fieldBinding = (FieldBinding) this.binding; position = this.sourcePositions[0]; } } else { fieldBinding = this.otherBindings[this.otherBindings.length - 1]; position = this.sourcePositions[this.sourcePositions.length - 1]; } if (fieldBinding != null) { return checkNullableFieldDereference(scope, fieldBinding, position); } return false; } /** * @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(); TypeBinding originalType = originalBinding.type; // extra cast needed if field type is type variable if (originalType.leafComponentType().isTypeVariable()) { TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) ? compileTimeType // unboxing: checkcast before conversion : runtimeTimeType; TypeBinding typeCast = originalType.genericCast(targetType); setGenericCast(length, typeCast); if (typeCast instanceof ReferenceBinding) { ReferenceBinding referenceCast = (ReferenceBinding) typeCast; if (!referenceCast.canBeSeenBy(scope)) { scope.problemReporter().invalidType(this, new ProblemReferenceBinding( CharOperation.splitOn('.', referenceCast.shortReadableName()), referenceCast, ProblemReasons.NotVisible)); } } } } super.computeConversion(scope, runtimeTimeType, compileTimeType); } public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { int pc = codeStream.position; FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); codeStream.recordPositionsFrom(pc , this.sourceStart); assignment.expression.generateCode(currentScope, codeStream, true); fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, valueRequired); // equivalent to valuesRequired[maxOtherBindings] if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { if (valueRequired) { codeStream.generateConstant(this.constant, this.implicitConversion); } } else { FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); if (lastFieldBinding != null) { boolean isStatic = lastFieldBinding.isStatic(); Constant fieldConstant = lastFieldBinding.constant(); if (fieldConstant != Constant.NotAConstant) { if (!isStatic){ codeStream.invokeObjectGetClass(); codeStream.pop(); } if (valueRequired) { // inline the last field constant codeStream.generateConstant(fieldConstant, this.implicitConversion); } } else { boolean isFirst = lastFieldBinding == this.binding && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) && this.otherBindings == null; // could be dup: next.next.next TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); if (valueRequired || (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) || ((this.implicitConversion & TypeIds.UNBOXING) != 0) || requiredGenericCast != null) { int lastFieldPc = codeStream.position; if (lastFieldBinding.declaringClass == null) { // array length codeStream.arraylength(); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { // could occur if !valueRequired but compliance >= 1.4 codeStream.pop(); } } else { SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; if (accessor == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); if (isStatic) { codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); } } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; // conversion only generated if unboxing if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); switch (isUnboxing ? postConversionType(currentScope).id : lastFieldBinding.type.id) { case T_long : case T_double : codeStream.pop2(); break; default : codeStream.pop(); break; } } } int fieldPosition = (int) (this.sourcePositions[this.sourcePositions.length - 1] >>> 32); codeStream.recordPositionsFrom(lastFieldPc, fieldPosition); } else { if (!isStatic){ codeStream.invokeObjectGetClass(); // perform null check codeStream.pop(); } } } } } codeStream.recordPositionsFrom(pc, this.sourceStart); } public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); // check if compound assignment is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, lastFieldBinding, valueRequired); boolean isFirst = lastFieldBinding == this.binding && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) && this.otherBindings == null; // could be dup: next.next.next TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; if (lastFieldBinding.isStatic()) { if (accessor == null) { codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } } else { codeStream.dup(); if (accessor == null) { codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } } // the last field access is a write access // perform the actual compound operation int operationTypeID; switch(operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) { case T_JavaLangString : case T_JavaLangObject : case T_undefined : codeStream.generateStringConcatenationAppend(currentScope, null, expression); break; default : TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); // promote the array reference to the suitable operation type codeStream.generateImplicitConversion(this.implicitConversion); // generate the increment value (will by itself be promoted to the operation value) if (expression == IntLiteral.One) { // prefix operation codeStream.generateConstant(expression.constant, this.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(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, valueRequired); // equivalent to valuesRequired[maxOtherBindings] } public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); // check if this post increment is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, lastFieldBinding, valueRequired); boolean isFirst = lastFieldBinding == this.binding && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) && this.otherBindings == null; // could be dup: next.next.next TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; if (lastFieldBinding.isStatic()) { if (accessor == null) { codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, constantPoolDeclaringClass); } } else { codeStream.dup(); if (accessor == null) { codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, null /* default declaringClass */); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } } TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); TypeBinding operandType; if (requiredGenericCast != null) { codeStream.checkcast(requiredGenericCast); operandType = requiredGenericCast; } else { operandType = lastFieldBinding.type; } // duplicate the old field value if (valueRequired) { if (lastFieldBinding.isStatic()) { switch (operandType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2(); break; default: codeStream.dup(); break; } } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] switch (operandType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2_x1(); break; default: codeStream.dup_x1(); break; } } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateConstant( postIncrement.expression.constant, this.implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion( postIncrement.preAssignImplicitConversion); fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, false); } /* * 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 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.otherBindings == null ? 0 : this.otherBindings.length; boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); FieldBinding lastFieldBinding; TypeBinding lastGenericCast; TypeBinding lastReceiverType; boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : lastFieldBinding = ((FieldBinding) this.binding).original(); lastGenericCast = this.genericCast; lastReceiverType = this.actualReceiverType; // if first field is actually constant, we can inline it if (lastFieldBinding.constant() != Constant.NotAConstant) { break; } if ((needValue && !lastFieldBinding.isStatic()) || lastGenericCast != null) { int pc = codeStream.position; if ((this.bits & ASTNode.DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { generateReceiver(codeStream); } codeStream.recordPositionsFrom(pc, this.sourceStart); } break; case Binding.LOCAL : // reading the first local variable lastFieldBinding = null; lastGenericCast = null; LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; lastReceiverType = localBinding.type; if (!needValue) break; // no value needed // regular local variable read Constant localConstant = localBinding.constant(); if (localConstant != Constant.NotAConstant) { codeStream.generateConstant(localConstant, 0); // no implicit conversion } else { // outer local? if ((this.bits & ASTNode.DepthMASK) != 0) { // outer local can be reached either through a synthetic arg or a synthetic field VariableBinding[] path = currentScope.getEmulationPath(localBinding); codeStream.generateOuterAccess(path, this, localBinding, currentScope); } else { codeStream.load(localBinding); } } break; default : // should not occur return null; } // all intermediate field accesses are read accesses // only the last field binding is a write access int positionsLength = this.sourcePositions.length; FieldBinding initialFieldBinding = lastFieldBinding; // can be null if initial was a local binding if (this.otherBindings != null) { for (int i = 0; i < otherBindingsCount; i++) { int pc = codeStream.position; FieldBinding nextField = this.otherBindings[i].original(); TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i]; if (lastFieldBinding != null) { needValue = !nextField.isStatic(); Constant fieldConstant = lastFieldBinding.constant(); if (fieldConstant != Constant.NotAConstant) { if (i > 0 && !lastFieldBinding.isStatic()) { codeStream.invokeObjectGetClass(); // perform null check codeStream.pop(); } if (needValue) { codeStream.generateConstant(fieldConstant, 0); } } else { if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) { MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; if (accessor == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1); if (lastFieldBinding.isStatic()) { codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); } } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } if (lastGenericCast != null) { codeStream.checkcast(lastGenericCast); lastReceiverType = lastGenericCast; } else { lastReceiverType = lastFieldBinding.type; } if (!needValue) codeStream.pop(); } else { if (lastFieldBinding == initialFieldBinding) { if (lastFieldBinding.isStatic()){ // if no valueRequired, still need possible side-effects of invocation, if field belongs to different class if (initialFieldBinding.declaringClass != this.actualReceiverType.erasure()) { MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; if (accessor == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1); codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } codeStream.pop(); } } } else if (!lastFieldBinding.isStatic()){ codeStream.invokeObjectGetClass(); // perform null check codeStream.pop(); } lastReceiverType = lastFieldBinding.type; } if ((positionsLength - otherBindingsCount + i - 1) >= 0) { int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32); codeStream.recordPositionsFrom(pc, fieldPosition); } } } 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; } protected FieldBinding getCodegenBinding(int index) { if (index == 0){ return ((FieldBinding)this.binding).original(); } else { return this.otherBindings[index-1].original(); } } /** * Returns the receiver type for the final field in sequence (i.e. the return type of the previous binding) * @return receiver type for the final field in sequence */ protected TypeBinding getFinalReceiverType() { int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; switch (otherBindingsCount) { case 0 : return this.actualReceiverType; case 1 : return this.genericCast != null ? this.genericCast : ((VariableBinding)this.binding).type; default: TypeBinding previousGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[otherBindingsCount-2]; return previousGenericCast != null ? previousGenericCast : this.otherBindings[otherBindingsCount-2].type; } } // 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 = this.tokens.length; FieldBinding field = ((this.bits & Binding.FIELD) != 0) ? (FieldBinding) this.binding : null; TypeBinding type = ((VariableBinding) this.binding).type; int index = this.indexOfFirstFieldBinding; if (index == length) { // restrictiveFlag == FIELD this.constant = ((FieldBinding) this.binding).constant(); // perform capture conversion if read access return (type != null && (this.bits & ASTNode.IsStrictlyAssigned) == 0) ? type.capture(scope, this.sourceEnd) : type; } // allocation of the fieldBindings array and its respective constants int otherBindingsLength = length - index; this.otherBindings = new FieldBinding[otherBindingsLength]; this.otherDepths = new int[otherBindingsLength]; // fill the first constant (the one of the binding) this.constant = ((VariableBinding) this.binding).constant(); // save first depth, since will be updated by visibility checks of other bindings int firstDepth = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT; // iteration on each field while (index < length) { char[] token = this.tokens[index]; if (type == null) return null; // could not resolve type prior to this point this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any FieldBinding previousField = field; field = scope.getField(type.capture(scope, (int)this.sourcePositions[index]), token, this); int place = index - this.indexOfFirstFieldBinding; this.otherBindings[place] = field; this.otherDepths[place] = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT; if (field.isValidBinding()) { // set generic cast of for previous field (if any) if (previousField != null) { TypeBinding fieldReceiverType = type; TypeBinding oldReceiverType = fieldReceiverType; fieldReceiverType = fieldReceiverType.getErasureCompatibleType(field.declaringClass);// handle indirect inheritance thru variable secondary bound FieldBinding originalBinding = previousField.original(); if (fieldReceiverType != oldReceiverType || originalBinding.type.leafComponentType().isTypeVariable()) { // record need for explicit cast at codegen setGenericCast(index-1,originalBinding.type.genericCast(fieldReceiverType)); // type cannot be base-type even in boxing case } } // only last field is actually a write access if any if (isFieldUseDeprecated(field, scope, index+1 == length ? this.bits : 0)) { scope.problemReporter().deprecatedField(field, this); } // constant propagation can only be performed as long as the previous one is a constant too. if (this.constant != Constant.NotAConstant) { this.constant = field.constant(); } if (field.isStatic()) { if ((field.modifiers & ClassFileConstants.AccEnum) != 0) { // enum constants are checked even when qualified) ReferenceBinding declaringClass = field.original().declaringClass; MethodScope methodScope = scope.methodScope(); SourceTypeBinding sourceType = methodScope.enclosingSourceType(); if ((this.bits & ASTNode.IsStrictlyAssigned) == 0 && sourceType == declaringClass && methodScope.lastVisibleFieldID >= 0 && field.id >= methodScope.lastVisibleFieldID && (!field.isStatic() || methodScope.isStatic)) { scope.problemReporter().forwardReference(this, index, field); } // check if accessing enum static field in initializer if ((sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body && field.constant() == Constant.NotAConstant && !methodScope.isStatic && methodScope.isInsideInitializerOrConstructor()) { scope.problemReporter().enumStaticFieldUsedDuringInitialization(field, this); } } // static field accessed through receiver? legal but unoptimal (optional warning) scope.problemReporter().nonStaticAccessToStaticField(this, field, index); // indirect static reference ? if (field.declaringClass != type) { scope.problemReporter().indirectAccessToStaticField(this, field); } } type = field.type; index++; } else { this.constant = Constant.NotAConstant; //don't fill other constants slots... scope.problemReporter().invalidField(this, field, index, type); setDepth(firstDepth); return null; } } setDepth(firstDepth); type = (this.otherBindings[otherBindingsLength - 1]).type; // perform capture conversion if read access return (type != null && (this.bits & ASTNode.IsStrictlyAssigned) == 0) ? type.capture(scope, this.sourceEnd) : type; } public boolean isEquivalent(Reference reference) { if (reference instanceof FieldReference) { return reference.isEquivalent(this); // comparison FR <-> QNR is implemented only once } if (!(reference instanceof QualifiedNameReference)) return false; // straight-forward test of equality of two QNRs: QualifiedNameReference qualifiedReference = (QualifiedNameReference) reference; if (this.tokens.length != qualifiedReference.tokens.length) return false; if (this.binding != qualifiedReference.binding) return false; if (this.otherBindings != null) { if (qualifiedReference.otherBindings == null) return false; int len = this.otherBindings.length; if (len != qualifiedReference.otherBindings.length) return false; for (int i=0; i 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding) if (fieldBinding.constant() != Constant.NotAConstant) return; if (fieldBinding.isPrivate()) { // private access FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); ReferenceBinding declaringClass = codegenField.declaringClass; if (declaringClass != currentScope.enclosingSourceType()) { setSyntheticAccessor(fieldBinding, index, ((SourceTypeBinding) declaringClass).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/, false /*not super access*/)); currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/); return; } } else if (fieldBinding.isProtected()){ int depth = (index == 0 || (index < 0 && this.otherDepths == null)) ? (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT : this.otherDepths[index < 0 ? this.otherDepths.length-1 : index-1]; // implicit protected access if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) { FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); setSyntheticAccessor(fieldBinding, index, ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/, false /*not super access*/)); currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/); return; } } } public Constant optimizedBooleanConstant() { switch (this.resolvedType.id) { case T_boolean : case T_JavaLangBoolean : if (this.constant != Constant.NotAConstant) return this.constant; switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field if (this.otherBindings == null) return ((FieldBinding)this.binding).constant(); //$FALL-THROUGH$ case Binding.LOCAL : // reading a local variable return this.otherBindings[this.otherBindings.length-1].constant(); } } return Constant.NotAConstant; } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope) */ public TypeBinding postConversionType(Scope scope) { TypeBinding convertedType = this.resolvedType; TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); if (requiredGenericCast != null) convertedType = requiredGenericCast; int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; switch (runtimeType) { case T_boolean : convertedType = TypeBinding.BOOLEAN; break; case T_byte : convertedType = TypeBinding.BYTE; break; case T_short : convertedType = TypeBinding.SHORT; break; case T_char : convertedType = TypeBinding.CHAR; break; case T_int : convertedType = TypeBinding.INT; break; case T_float : convertedType = TypeBinding.FLOAT; break; case T_long : convertedType = TypeBinding.LONG; break; case T_double : convertedType = TypeBinding.DOUBLE; break; default : } if ((this.implicitConversion & TypeIds.BOXING) != 0) { convertedType = scope.environment().computeBoxingType(convertedType); } return convertedType; } public StringBuffer printExpression(int indent, StringBuffer output) { for (int i = 0; i < this.tokens.length; i++) { if (i > 0) output.append('.'); output.append(this.tokens[i]); } return output; } /** * Normal field binding did not work, try to bind to a field of the delegate receiver. */ public TypeBinding reportError(BlockScope scope) { if (this.binding instanceof ProblemFieldBinding) { scope.problemReporter().invalidField(this, (FieldBinding) this.binding); } else if (this.binding instanceof ProblemReferenceBinding || this.binding instanceof MissingTypeBinding) { scope.problemReporter().invalidType(this, (TypeBinding) this.binding); } else { scope.problemReporter().unresolvableReference(this, this.binding); } return null; } public TypeBinding resolveType(BlockScope scope) { // 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 = scope.enclosingReceiverType(); this.constant = Constant.NotAConstant; if ((this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.VARIABLE : //============only variable=========== case Binding.TYPE | Binding.VARIABLE : if (this.binding instanceof LocalVariableBinding) { this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits this.bits |= Binding.LOCAL; LocalVariableBinding local = (LocalVariableBinding) this.binding; if (!local.isFinal() && ((this.bits & ASTNode.DepthMASK) != 0)) { scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding) this.binding, this); } if (local.type != null && (local.type.tagBits & TagBits.HasMissingType) != 0) { // only complain if field reference (for local, its type got flagged already) return null; } this.resolvedType = getOtherFieldBindings(scope); if (this.resolvedType != null && (this.resolvedType.tagBits & TagBits.HasMissingType) != 0) { FieldBinding lastField = this.otherBindings[this.otherBindings.length - 1]; scope.problemReporter().invalidField(this, new ProblemFieldBinding(lastField.declaringClass, lastField.name, ProblemReasons.NotFound), this.tokens.length, this.resolvedType.leafComponentType()); return null; } return this.resolvedType; } if (this.binding instanceof FieldBinding) { this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits this.bits |= Binding.FIELD; FieldBinding fieldBinding = (FieldBinding) this.binding; MethodScope methodScope = scope.methodScope(); ReferenceBinding declaringClass = fieldBinding.original().declaringClass; SourceTypeBinding sourceType = methodScope.enclosingSourceType(); // check for forward references if ((this.indexOfFirstFieldBinding == 1 || (fieldBinding.modifiers & ClassFileConstants.AccEnum) != 0 || (!fieldBinding.isFinal() && declaringClass.isEnum())) // enum constants are checked even when qualified && sourceType == declaringClass && methodScope.lastVisibleFieldID >= 0 && fieldBinding.id >= methodScope.lastVisibleFieldID && (!fieldBinding.isStatic() || methodScope.isStatic)) { if (methodScope.insideTypeAnnotation && fieldBinding.id == methodScope.lastVisibleFieldID) { // false alarm, location is NOT a field initializer but the value in a memberValuePair } else { scope.problemReporter().forwardReference(this, this.indexOfFirstFieldBinding-1, fieldBinding); } } if (isFieldUseDeprecated(fieldBinding, scope, this.indexOfFirstFieldBinding == this.tokens.length ? this.bits : 0)) { scope.problemReporter().deprecatedField(fieldBinding, this); } if (fieldBinding.isStatic()) { // only last field is actually a write access if any // check if accessing enum static field in initializer if (declaringClass.isEnum()) { if ((sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body && fieldBinding.constant() == Constant.NotAConstant && !methodScope.isStatic && methodScope.isInsideInitializerOrConstructor()) { scope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this); } } if (this.indexOfFirstFieldBinding > 1 && fieldBinding.declaringClass != this.actualReceiverType && fieldBinding.declaringClass.canBeSeenBy(scope)) { scope.problemReporter().indirectAccessToStaticField(this, fieldBinding); } } else { if (this.indexOfFirstFieldBinding == 1 && scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) { scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding); } //must check for the static status.... if (this.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); return null; } } this.resolvedType = getOtherFieldBindings(scope); if (this.resolvedType != null && (this.resolvedType.tagBits & TagBits.HasMissingType) != 0) { FieldBinding lastField = this.indexOfFirstFieldBinding == this.tokens.length ? (FieldBinding)this.binding : this.otherBindings[this.otherBindings.length - 1]; scope.problemReporter().invalidField(this, new ProblemFieldBinding(lastField.declaringClass, lastField.name, ProblemReasons.NotFound), this.tokens.length, this.resolvedType.leafComponentType()); return null; } return this.resolvedType; } // thus it was a type this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits this.bits |= Binding.TYPE; //$FALL-THROUGH$ case Binding.TYPE : //=============only type ============== TypeBinding type = (TypeBinding) this.binding; // if (isTypeUseDeprecated(type, scope)) // scope.problemReporter().deprecatedType(type, this); type = scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/); return this.resolvedType = type; } } //========error cases=============== return this.resolvedType = reportError(scope); } public void setFieldIndex(int index) { this.indexOfFirstFieldBinding = index; } // set the matching codegenBinding and generic cast protected void setGenericCast(int index, TypeBinding someGenericCast) { if (someGenericCast == null) return; 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 ? this.syntheticWriteAccessor = syntheticAccessor; } else { if (this.syntheticReadAccessors == null) { this.syntheticReadAccessors = new SyntheticMethodBinding[this.otherBindings == null ? 1 : this.otherBindings.length + 1]; } this.syntheticReadAccessors[index] = syntheticAccessor; } } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public String unboundReferenceErrorName() { return new String(this.tokens[0]); } public VariableBinding nullAnnotatedVariableBinding() { if (this.binding != null && isFieldAccess()) { FieldBinding fieldBinding; if (this.otherBindings == null) { fieldBinding = (FieldBinding) this.binding; } else { fieldBinding = this.otherBindings[this.otherBindings.length - 1]; } if (fieldBinding.isNullable() || fieldBinding.isNonNull()) { return fieldBinding; } } return null; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java0000644000175000001440000000606212212041344030112 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.*; import org.eclipse.jdt.internal.compiler.codegen.*; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; public class CharLiteral extends NumberLiteral { char value; public CharLiteral(char[] token, int s, int e) { super(token, s, e); computeValue(); } public void computeConstant() { //The source is a char[3] first and last char are ' //This is true for both regular char AND unicode char //BUT not for escape char like '\b' which are char[4].... this.constant = CharConstant.fromValue(this.value); } private void computeValue() { //The source is a char[3] first and last char are ' //This is true for both regular char AND unicode char //BUT not for escape char like '\b' which are char[4].... if ((this.value = this.source[1]) != '\\') return; char digit; switch (digit = this.source[2]) { case 'b' : this.value = '\b'; break; case 't' : this.value = '\t'; break; case 'n' : this.value = '\n'; break; case 'f' : this.value = '\f'; break; case 'r' : this.value = '\r'; break; case '\"' : this.value = '\"'; break; case '\'' : this.value = '\''; break; case '\\' : this.value = '\\'; break; default : //octal (well-formed: ended by a ' ) int number = ScannerHelper.getNumericValue(digit); if ((digit = this.source[3]) != '\'') number = (number * 8) + ScannerHelper.getNumericValue(digit); else { this.constant = CharConstant.fromValue(this.value = (char) number); break; } if ((digit = this.source[4]) != '\'') number = (number * 8) + ScannerHelper.getNumericValue(digit); this.value = (char) number; break; } } /** * CharLiteral 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) { int pc = codeStream.position; if (valueRequired) { codeStream.generateConstant(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.CHAR; } public void traverse(ASTVisitor visitor, BlockScope blockScope) { visitor.visit(this, blockScope); visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java0000644000175000001440000000543712212041344032361 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; public class JavadocReturnStatement extends ReturnStatement { public JavadocReturnStatement(int s, int e) { super(null, s, e); this.bits |= (ASTNode.InsideJavadoc | ASTNode.Empty); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.Statement#resolve(org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void resolve(BlockScope scope) { MethodScope methodScope = scope.methodScope(); MethodBinding methodBinding = null; TypeBinding methodType = (methodScope.referenceContext instanceof AbstractMethodDeclaration) ? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null ? null : methodBinding.returnType) : TypeBinding.VOID; if (methodType == null || methodType == TypeBinding.VOID) { scope.problemReporter().javadocUnexpectedTag(this.sourceStart, this.sourceEnd); } else if ((this.bits & ASTNode.Empty) != 0) { scope.problemReporter().javadocEmptyReturnTag(this.sourceStart, this.sourceEnd, scope.getDeclarationModifiers()); } } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.Statement#printStatement(int, java.lang.StringBuffer) */ public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output).append("return"); //$NON-NLS-1$ if ((this.bits & ASTNode.Empty) == 0) output.append(' ').append(" "); //$NON-NLS-1$ return output; } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java0000644000175000001440000002335612212041344031103 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields *******************************************************************************/ 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.*; public class UnaryExpression extends OperatorExpression { public Expression expression; public Constant optimizedBooleanConstant; public UnaryExpression(Expression expression, int operator) { this.expression = expression; this.bits |= operator << OperatorSHIFT; // encode operator } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.expression.checkNPE(currentScope, flowContext, flowInfo); if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) { flowContext.tagBits ^= FlowContext.INSIDE_NEGATION; flowInfo = this.expression. analyseCode(currentScope, flowContext, flowInfo). asNegatedCondition(); flowContext.tagBits ^= FlowContext.INSIDE_NEGATION; return flowInfo; } else { return this.expression. analyseCode(currentScope, flowContext, flowInfo); } } public Constant optimizedBooleanConstant() { return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant; } /** * Code generation for an unary operation * * @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; BranchLabel falseLabel, endifLabel; if (this.constant != Constant.NotAConstant) { // inlined value if (valueRequired) { codeStream.generateConstant(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } switch ((this.bits & OperatorMASK) >> OperatorSHIFT) { case NOT : switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) /* runtime type */ { case T_boolean : // ! // Generate code for the condition this.expression.generateOptimizedBoolean( currentScope, codeStream, null, (falseLabel = new BranchLabel(codeStream)), valueRequired); if (valueRequired) { codeStream.iconst_0(); if (falseLabel.forwardReferenceCount() > 0) { codeStream.goto_(endifLabel = new BranchLabel(codeStream)); codeStream.decrStackSize(1); falseLabel.place(); codeStream.iconst_1(); endifLabel.place(); } } else { // 6596: if (!(a && b)){} - must still place falseLabel falseLabel.place(); } break; } break; case TWIDDLE : switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4 /* runtime */) { case T_int : // ~int this.expression.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.iconst_m1(); codeStream.ixor(); } break; case T_long : this.expression.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.ldc2_w(-1L); codeStream.lxor(); } } break; case MINUS : // - if (this.constant != Constant.NotAConstant) { if (valueRequired) { switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime */ case T_int : codeStream.generateInlinedValue(this.constant.intValue() * -1); break; case T_float : codeStream.generateInlinedValue(this.constant.floatValue() * -1.0f); break; case T_long : codeStream.generateInlinedValue(this.constant.longValue() * -1L); break; case T_double : codeStream.generateInlinedValue(this.constant.doubleValue() * -1.0); } } } else { this.expression.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime type */ case T_int : codeStream.ineg(); break; case T_float : codeStream.fneg(); break; case T_long : codeStream.lneg(); break; case T_double : codeStream.dneg(); } } } break; case PLUS : this.expression.generateCode(currentScope, codeStream, valueRequired); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * Boolean operator code generation * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^ */ public void generateOptimizedBoolean( BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == T_boolean)) { super.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) { this.expression.generateOptimizedBoolean( currentScope, codeStream, falseLabel, trueLabel, valueRequired); } else { super.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); } } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { output.append(operatorToString()).append(' '); return this.expression.printExpression(0, output); } public TypeBinding resolveType(BlockScope scope) { boolean expressionIsCast; if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= DisableUnnecessaryCastCheck; // will check later on TypeBinding expressionType = this.expression.resolveType(scope); if (expressionType == null) { this.constant = Constant.NotAConstant; return null; } int expressionTypeID = expressionType.id; // autoboxing support boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; if (use15specifics) { if (!expressionType.isBaseType()) { expressionTypeID = scope.environment().computeBoxingType(expressionType).id; } } if (expressionTypeID > 15) { this.constant = Constant.NotAConstant; scope.problemReporter().invalidOperator(this, expressionType); return null; } int tableId; switch ((this.bits & OperatorMASK) >> OperatorSHIFT) { case NOT : tableId = AND_AND; break; case TWIDDLE : tableId = LEFT_SHIFT; break; default : tableId = MINUS; } //+ and - cases // the code is an int // (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.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 : this.resolvedType = TypeBinding.BOOLEAN; break; case T_byte : this.resolvedType = TypeBinding.BYTE; break; case T_char : this.resolvedType = TypeBinding.CHAR; break; case T_double : this.resolvedType = TypeBinding.DOUBLE; break; case T_float : this.resolvedType = TypeBinding.FLOAT; break; case T_int : this.resolvedType = TypeBinding.INT; break; case T_long : this.resolvedType = TypeBinding.LONG; break; default : //error........ this.constant = Constant.NotAConstant; if (expressionTypeID != T_undefined) scope.problemReporter().invalidOperator(this, expressionType); return null; } // compute the constant when valid if (this.expression.constant != Constant.NotAConstant) { this.constant = Constant.computeConstantOperation( this.expression.constant, expressionTypeID, (this.bits & OperatorMASK) >> OperatorSHIFT); } else { this.constant = Constant.NotAConstant; if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) { Constant cst = this.expression.optimizedBooleanConstant(); if (cst != Constant.NotAConstant) this.optimizedBooleanConstant = BooleanConstant.fromValue(!cst.booleanValue()); } } if (expressionIsCast) { // check need for operand cast CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeID); } return this.resolvedType; } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.expression.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java0000644000175000001440000001136412212041344032273 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Jesper S Moller - Contributions for * bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.*; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class QualifiedThisReference extends ThisReference { public TypeReference qualification; ReferenceBinding currentCompatibleType; public QualifiedThisReference(TypeReference name, int sourceStart, int sourceEnd) { super(sourceStart, sourceEnd); this.qualification = name; name.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage this.sourceStart = name.sourceStart; } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return flowInfo; } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { return flowInfo; } /** * Code generation for QualifiedThisReference * * @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 ((this.bits & DepthMASK) != 0) { Object[] emulationPath = currentScope.getEmulationPath(this.currentCompatibleType, true /*only exact match*/, false/*consider enclosing arg*/); codeStream.generateOuterAccess(emulationPath, this, this.currentCompatibleType, currentScope); } else { // nothing particular after all codeStream.aload_0(); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; // X.this is not a param/raw type as denoting enclosing instance TypeBinding type = this.qualification.resolveType(scope, true /* check bounds*/); if (type == null || !type.isValidBinding()) return null; // X.this is not a param/raw type as denoting enclosing instance type = type.erasure(); // resolvedType needs to be converted to parameterized if (type instanceof ReferenceBinding) { this.resolvedType = scope.environment().convertToParameterizedType((ReferenceBinding) type); } else { // error case this.resolvedType = type; } // the qualification MUST exactly match some enclosing type name // It is 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 != type) { depth++; this.currentCompatibleType = this.currentCompatibleType.isStatic() ? null : this.currentCompatibleType.enclosingType(); } this.bits &= ~DepthMASK; // flush previous depth if any this.bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits if (this.currentCompatibleType == null) { scope.problemReporter().noSuchEnclosingInstance(type, this, false); return this.resolvedType; } else { // Mark all methods between here and the declared type as not static scope.resetDeclaringClassMethodStaticFlag(this.currentCompatibleType); } // 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; } public StringBuffer printExpression(int indent, StringBuffer output) { return this.qualification.print(0, output).append(".this"); //$NON-NLS-1$ } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.qualification.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } public void traverse( ASTVisitor visitor, ClassScope blockScope) { if (visitor.visit(this, blockScope)) { this.qualification.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java0000644000175000001440000000344712212041344031241 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; public class PrefixExpression extends CompoundAssignment { /** * PrefixExpression constructor comment. * @param lhs org.eclipse.jdt.internal.compiler.ast.Expression * @param expression org.eclipse.jdt.internal.compiler.ast.Expression * @param operator int */ public PrefixExpression(Expression lhs, Expression expression, int operator, int pos) { super(lhs, expression, operator, lhs.sourceEnd); this.sourceStart = pos; this.sourceEnd = lhs.sourceEnd; } public boolean checkCastCompatibility() { return false; } public String operatorToString() { switch (this.operator) { case PLUS : return "++"; //$NON-NLS-1$ case MINUS : return "--"; //$NON-NLS-1$ } return "unknown operator"; //$NON-NLS-1$ } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { output.append(operatorToString()).append(' '); return this.lhs.printExpression(0, output); } public boolean restrainUsageToNumericTypes() { return true; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.lhs.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000015112251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.0000644000175000001440000000476212212041344032354 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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; /** * Flatten string literal */ public class StringLiteralConcatenation extends StringLiteral { private static final int INITIAL_SIZE = 5; public Expression[] literals; public int counter; /** * Build a two-strings literal * */ public StringLiteralConcatenation(StringLiteral str1, StringLiteral str2) { super(str1.sourceStart, str1.sourceEnd); this.source = str1.source; this.literals = new StringLiteral[INITIAL_SIZE]; this.counter = 0; this.literals[this.counter++] = str1; extendsWith(str2); } /** * Add the lit source to mine, just as if it was mine */ public StringLiteralConcatenation extendsWith(StringLiteral lit) { this.sourceEnd = lit.sourceEnd; final int literalsLength = this.literals.length; if (this.counter == literalsLength) { // resize System.arraycopy(this.literals, 0, this.literals = new StringLiteral[literalsLength + INITIAL_SIZE], 0, literalsLength); } //uddate the source int length = this.source.length; System.arraycopy( this.source, 0, this.source = new char[length + lit.source.length], 0, length); System.arraycopy(lit.source, 0, this.source, length, lit.source.length); this.literals[this.counter++] = lit; return this; } public StringBuffer printExpression(int indent, StringBuffer output) { output.append("StringLiteralConcatenation{"); //$NON-NLS-1$ for (int i = 0, max = this.counter; i < max; i++) { this.literals[i].printExpression(indent, output); output.append("+\n");//$NON-NLS-1$ } return output.append('}'); } public char[] source() { return this.source; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { for (int i = 0, max = this.counter; i < max; i++) { this.literals[i].traverse(visitor, scope); } } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Javadoc.java0000644000175000001440000011516712212041344027276 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants; /** * Node representing a structured Javadoc comment */ public class Javadoc extends ASTNode { public JavadocSingleNameReference[] paramReferences; // @param public JavadocSingleTypeReference[] paramTypeParameters; // @param public TypeReference[] exceptionReferences; // @throws, @exception public JavadocReturnStatement returnStatement; // @return public Expression[] seeReferences; // @see public long[] inheritedPositions = null; // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600 // Store param references for tag with invalid syntax public JavadocSingleNameReference[] invalidParameters; // @param // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=153399 // Store value tag positions public long valuePositions = -1; public Javadoc(int sourceStart, int sourceEnd) { this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; this.bits |= ASTNode.ResolveJavadoc; } /** * Returns whether a type can be seen at a given visibility level or not. * * @param visibility Level of visiblity allowed to see references * @param modifiers modifiers of java element to be seen * @return true if the type can be seen, false otherwise */ boolean canBeSeen(int visibility, int modifiers) { if (modifiers < 0) return true; switch (modifiers & ExtraCompilerModifiers.AccVisibilityMASK) { case ClassFileConstants.AccPublic : return true; case ClassFileConstants.AccProtected: return (visibility != ClassFileConstants.AccPublic); case ClassFileConstants.AccDefault: return (visibility == ClassFileConstants.AccDefault || visibility == ClassFileConstants.AccPrivate); case ClassFileConstants.AccPrivate: return (visibility == ClassFileConstants.AccPrivate); } return true; } /* * Search node with a given staring position in javadoc objects arrays. */ public ASTNode getNodeStartingAt(int start) { int length = 0; // parameters array if (this.paramReferences != null) { length = this.paramReferences.length; for (int i=0; i\n"); //$NON-NLS-1$ } } if (this.returnStatement != null) { printIndent(indent + 1, output).append(" * @"); //$NON-NLS-1$ this.returnStatement.print(indent, output).append('\n'); } 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.exceptionReferences[i].print(indent, output).append('\n'); } } 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.seeReferences[i].print(indent, output).append('\n'); } } printIndent(indent, output).append(" */\n"); //$NON-NLS-1$ return output; } /* * Resolve type javadoc */ public void resolve(ClassScope scope) { if ((this.bits & ASTNode.ResolveJavadoc) == 0) { return; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=247037, @inheritDoc tag cannot // be used in the documentation comment for a class or interface. if (this.inheritedPositions != null) { int length = this.inheritedPositions.length; for (int i = 0; i < length; ++i) { int start = (int) (this.inheritedPositions[i] >>> 32); int end = (int) this.inheritedPositions[i]; scope.problemReporter().javadocUnexpectedTag(start, end); } } // @param tags int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length; for (int i = 0; i < paramTagsSize; i++) { JavadocSingleNameReference param = this.paramReferences[i]; scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd); } resolveTypeParameterTags(scope, true); // @return tags if (this.returnStatement != null) { scope.problemReporter().javadocUnexpectedTag(this.returnStatement.sourceStart, this.returnStatement.sourceEnd); } // @throws/@exception tags int throwsTagsLength = this.exceptionReferences == null ? 0 : this.exceptionReferences.length; for (int i = 0; i < throwsTagsLength; i++) { TypeReference typeRef = this.exceptionReferences[i]; int start, end; if (typeRef instanceof JavadocSingleTypeReference) { JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef; start = singleRef.tagSourceStart; end = singleRef.tagSourceEnd; } else if (typeRef instanceof JavadocQualifiedTypeReference) { JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef; start = qualifiedRef.tagSourceStart; end = qualifiedRef.tagSourceEnd; } else { start = typeRef.sourceStart; end = typeRef.sourceEnd; } scope.problemReporter().javadocUnexpectedTag(start, end); } // @see tags int seeTagsLength = this.seeReferences == null ? 0 : this.seeReferences.length; for (int i = 0; i < seeTagsLength; i++) { resolveReference(this.seeReferences[i], scope); } // @value tag boolean source15 = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; if (!source15 && this.valuePositions != -1) { scope.problemReporter().javadocUnexpectedTag((int)(this.valuePositions>>>32), (int) this.valuePositions); } } /* * Resolve compilation unit javadoc */ public void resolve(CompilationUnitScope unitScope) { if ((this.bits & ASTNode.ResolveJavadoc) == 0) { return; } // Do nothing - This is to mimic the SDK's javadoc tool behavior, which neither // sanity checks nor generates documentation using comments at the CU scope // (unless the unit happens to be package-info.java - in which case we don't come here.) } /* * Resolve method javadoc */ public void resolve(MethodScope methScope) { if ((this.bits & ASTNode.ResolveJavadoc) == 0) { return; } // get method declaration AbstractMethodDeclaration methDecl = methScope.referenceMethod(); boolean overriding = methDecl == null /* field declaration */ || methDecl.binding == null /* compiler error */ ? false : !methDecl.binding.isStatic() && ((methDecl.binding.modifiers & (ExtraCompilerModifiers.AccImplementing | ExtraCompilerModifiers.AccOverriding)) != 0); // @see tags int seeTagsLength = this.seeReferences == null ? 0 : this.seeReferences.length; boolean superRef = false; for (int i = 0; i < seeTagsLength; i++) { // Resolve reference resolveReference(this.seeReferences[i], methScope); // see whether we can have a super reference if (methDecl != null && !superRef) { if (!methDecl.isConstructor()) { if (overriding && 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() && messageSend.actualReceiverType instanceof ReferenceBinding) { ReferenceBinding methodReceiverType = (ReferenceBinding) messageSend.actualReceiverType; TypeBinding superType = methDecl.binding.declaringClass.findSuperTypeOriginatingFrom(methodReceiverType); if (superType != null && superType.original() != methDecl.binding.declaringClass && CharOperation.equals(messageSend.selector, methDecl.selector)) { if (methScope.environment().methodVerifier().doesMethodOverride(methDecl.binding, messageSend.binding.original())) { superRef = true; } } } } } 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()) { ReferenceBinding allocType = (ReferenceBinding) allocationExpr.resolvedType.original(); ReferenceBinding superType = (ReferenceBinding) methDecl.binding.declaringClass.findSuperTypeOriginatingFrom(allocType); if (superType != null && superType.original() != methDecl.binding.declaringClass) { MethodBinding superConstructor = methScope.getConstructor(superType, methDecl.binding.parameters, allocationExpr); if (superConstructor.isValidBinding() && superConstructor.original() == allocationExpr.binding.original()) { if (superConstructor.areParametersEqual(methDecl.binding)) { superRef = true; } } } } } } } // Look at @Override annotations if (!superRef && methDecl != null && methDecl.annotations != null) { int length = methDecl.annotations.length; for (int i=0; i>> 32); int end = (int) this.inheritedPositions[i]; methScope.problemReporter().javadocUnexpectedTag(start, end); } } // @param tags CompilerOptions compilerOptions = methScope.compilerOptions(); resolveParamTags(methScope, reportMissing, compilerOptions.reportUnusedParameterIncludeDocCommentReference /* considerParamRefAsUsage*/); resolveTypeParameterTags(methScope, reportMissing && compilerOptions.reportMissingJavadocTagsMethodTypeParameters); // @return tags if (this.returnStatement == null) { if (reportMissing && methDecl != null) { if (methDecl.isMethod()) { MethodDeclaration meth = (MethodDeclaration) methDecl; if (meth.binding.returnType != TypeBinding.VOID) { // method with return should have @return tag methScope.problemReporter().javadocMissingReturnTag(meth.returnType.sourceStart, meth.returnType.sourceEnd, methDecl.binding.modifiers); } } } } else { this.returnStatement.resolve(methScope); } // @throws/@exception tags resolveThrowsTags(methScope, reportMissing); // @value tag boolean source15 = compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5; if (!source15 && methDecl != null && this.valuePositions != -1) { methScope.problemReporter().javadocUnexpectedTag((int)(this.valuePositions>>>32), (int) this.valuePositions); } // Resolve param tags with invalid syntax int length = this.invalidParameters == null ? 0 : this.invalidParameters.length; for (int i = 0; i < length; i++) { this.invalidParameters[i].resolve(methScope, false, false); } } private void resolveReference(Expression reference, Scope scope) { // Perform resolve int problemCount = scope.referenceContext().compilationResult().problemCount; switch (scope.kind) { case Scope.METHOD_SCOPE: reference.resolveType((MethodScope)scope); break; case Scope.CLASS_SCOPE: reference.resolveType((ClassScope)scope); break; } boolean hasProblems = scope.referenceContext().compilationResult().problemCount > problemCount; // Verify field references boolean source15 = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; int scopeModifiers = -1; if (reference instanceof JavadocFieldReference) { JavadocFieldReference fieldRef = (JavadocFieldReference) reference; // 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 == JavadocTagConstants.TAG_VALUE_VALUE) { if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, scopeModifiers); } else if (fieldRef.actualReceiverType != null) { if (scope.enclosingSourceType().isCompatibleWith(fieldRef.actualReceiverType)) { fieldRef.bits |= ASTNode.SuperAccess; } ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.actualReceiverType; if (CharOperation.equals(resolvedType.sourceName(), fieldRef.token)) { fieldRef.methodBinding = scope.getConstructor(resolvedType, Binding.NO_TYPES, fieldRef); } else { fieldRef.methodBinding = scope.findMethod(resolvedType, fieldRef.token, Binding.NO_TYPES, fieldRef); } } } // Verify whether field ref should be static or not (for @value tags) else if (source15 && fieldRef.binding != null && fieldRef.binding.isValidBinding()) { if (fieldRef.tagValue == JavadocTagConstants.TAG_VALUE_VALUE && !fieldRef.binding.isStatic()) { if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, scopeModifiers); } } // Verify type references if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.actualReceiverType instanceof ReferenceBinding) { ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.actualReceiverType; verifyTypeReference(fieldRef, fieldRef.receiver, scope, source15, resolvedType, fieldRef.binding.modifiers); } // That's it for field references return; } // Verify type references if (!hasProblems && (reference instanceof JavadocSingleTypeReference || reference instanceof JavadocQualifiedTypeReference) && reference.resolvedType instanceof ReferenceBinding) { ReferenceBinding resolvedType = (ReferenceBinding) reference.resolvedType; verifyTypeReference(reference, reference, scope, source15, resolvedType, resolvedType.modifiers); } // Verify that message reference are not used for @value tags if (reference instanceof JavadocMessageSend) { JavadocMessageSend msgSend = (JavadocMessageSend) reference; // tag value if (source15 && msgSend.tagValue == JavadocTagConstants.TAG_VALUE_VALUE) { // cannot refer to method for @value tag if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidValueReference(msgSend.sourceStart, msgSend.sourceEnd, scopeModifiers); } // Verify type references if (!hasProblems && msgSend.binding != null && msgSend.binding.isValidBinding() && msgSend.actualReceiverType instanceof ReferenceBinding) { ReferenceBinding resolvedType = (ReferenceBinding) msgSend.actualReceiverType; verifyTypeReference(msgSend, msgSend.receiver, scope, source15, resolvedType, msgSend.binding.modifiers); } } // Verify that constructor reference are not used for @value tags else if (reference instanceof JavadocAllocationExpression) { JavadocAllocationExpression alloc = (JavadocAllocationExpression) reference; // tag value if (source15 && alloc.tagValue == JavadocTagConstants.TAG_VALUE_VALUE) { // cannot refer to method for @value tag if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidValueReference(alloc.sourceStart, alloc.sourceEnd, scopeModifiers); } // Verify type references if (!hasProblems && alloc.binding != null && alloc.binding.isValidBinding() && alloc.resolvedType instanceof ReferenceBinding) { ReferenceBinding resolvedType = (ReferenceBinding) alloc.resolvedType; verifyTypeReference(alloc, alloc.type, scope, source15, resolvedType, alloc.binding.modifiers); } } // Verify that there's no type variable reference // (javadoc does not accept them and this is not a referenced bug or requested enhancement) if (reference.resolvedType != null && reference.resolvedType.isTypeVariable()) { scope.problemReporter().javadocInvalidReference(reference.sourceStart, reference.sourceEnd); } } /* * Resolve @param tags while method scope */ private void resolveParamTags(MethodScope scope, boolean reportMissing, boolean considerParamRefAsUsage) { AbstractMethodDeclaration methodDecl = scope.referenceMethod(); 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 (methodDecl == null) { for (int i = 0; i < paramTagsSize; i++) { JavadocSingleNameReference param = this.paramReferences[i]; scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd); } return; } // If no param tags then report a problem for each method argument int argumentsSize = methodDecl.arguments == null ? 0 : methodDecl.arguments.length; if (paramTagsSize == 0) { if (reportMissing) { for (int i = 0; i < argumentsSize; i++) { Argument arg = methodDecl.arguments[i]; scope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, methodDecl.binding.modifiers); } } } else { LocalVariableBinding[] bindings = new LocalVariableBinding[paramTagsSize]; int maxBindings = 0; // Scan all @param tags for (int i = 0; i < paramTagsSize; i++) { JavadocSingleNameReference param = this.paramReferences[i]; param.resolve(scope, true, considerParamRefAsUsage); 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) { scope.problemReporter().javadocDuplicatedParamTag(param.token, param.sourceStart, param.sourceEnd, methodDecl.binding.modifiers); found = true; } } if (!found) { bindings[maxBindings++] = (LocalVariableBinding) param.binding; } } } // Look for undocumented arguments if (reportMissing) { for (int i = 0; i < argumentsSize; i++) { Argument arg = methodDecl.arguments[i]; boolean found = false; for (int j = 0; j < maxBindings && !found; j++) { LocalVariableBinding binding = bindings[j]; if (arg.binding == binding) { found = true; } } if (!found) { scope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, methodDecl.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 TypeParameter[] parameters = null; TypeVariableBinding[] typeVariables = null; int modifiers = -1; switch (scope.kind) { case Scope.METHOD_SCOPE: AbstractMethodDeclaration 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++) { JavadocSingleTypeReference param = this.paramTypeParameters[i]; scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd); } return; } parameters = methodDeclaration.typeParameters(); typeVariables = methodDeclaration.binding.typeVariables; modifiers = methodDeclaration.binding.modifiers; break; case Scope.CLASS_SCOPE: TypeDeclaration typeDeclaration = ((ClassScope) scope).referenceContext; parameters = typeDeclaration.typeParameters; 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 if (parameters != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, avoid secondary errors when <= 1.4 reportMissing = reportMissing && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; int typeParametersLength = parameters.length; if (paramTypeParamLength == 0) { if (reportMissing) { for (int i = 0, l=typeParametersLength; i= 0;) { computedCompoundName[--idx] = topLevelType.fPackage.compoundName[i]; } ClassScope topLevelScope = scope.classScope(); // when scope is not on compilation unit type, then inner class may not be visible... if (topLevelScope.parent.kind != Scope.COMPILATION_UNIT_SCOPE || !CharOperation.equals(topLevelType.sourceName, topLevelScope.referenceContext.name)) { topLevelScope = topLevelScope.outerMostClassScope(); if (typeReference instanceof JavadocSingleTypeReference) { // inner class single reference can only be done in same unit if ((!source15 && depth == 1) || topLevelType != topLevelScope.referenceContext.binding) { // search for corresponding import boolean hasValidImport = false; if (source15) { CompilationUnitScope unitScope = topLevelScope.compilationUnitScope(); ImportBinding[] imports = unitScope.imports; int length = imports == null ? 0 : imports.length; mainLoop: for (int i=0; i= 0;) { if (CharOperation.equals(imports[i].compoundName[j], computedCompoundName[j])) { if (j == 0) { hasValidImport = true; ImportReference importReference = imports[i].reference; if (importReference != null) { importReference.bits |= ASTNode.Used; } break mainLoop; } } else { break; } } } } if (!hasValidImport) { if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidMemberTypeQualification(typeReference.sourceStart, typeReference.sourceEnd, scopeModifiers); } } else { if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidMemberTypeQualification(typeReference.sourceStart, typeReference.sourceEnd, scopeModifiers); return; } } } } if (typeReference instanceof JavadocQualifiedTypeReference && !scope.isDefinedInSameUnit(resolvedType)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=222188 // partially qualified references from a different CU should be warned char[][] typeRefName = ((JavadocQualifiedTypeReference) typeReference).getTypeName(); int skipLength = 0; if (topLevelScope.getCurrentPackage() == resolvedType.getPackage() && typeRefName.length < computedCompoundName.length) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=221539: references can be partially qualified // in same package and hence if the package name is not given, ignore package name check skipLength = resolvedType.fPackage.compoundName.length; } boolean valid = true; if (typeRefName.length == computedCompoundName.length - skipLength) { checkQualification: for (int i = 0; i < typeRefName.length; i++) { if (!CharOperation.equals(typeRefName[i], computedCompoundName[i + skipLength])) { valid = false; break checkQualification; } } } else { valid = false; } // report invalid reference if (!valid) { if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidMemberTypeQualification(typeReference.sourceStart, typeReference.sourceEnd, scopeModifiers); return; } } } /* * https://bugs.eclipse.org/bugs/show_bug.cgi?id=286918 * * We are concerned only about the Single type references (i.e. without any package) If they are not in default package, * then report an error. References with qualified yet incorrect names would have already been taken care of. */ if (scope.referenceCompilationUnit().isPackageInfo() && typeReference instanceof JavadocSingleTypeReference) { if (resolvedType.fPackage.compoundName.length > 0) { scope.problemReporter().javadocInvalidReference(typeReference.sourceStart, typeReference.sourceEnd); return; // Not really needed - just in case more code added in future } } } } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { if (this.paramReferences != null) { for (int i = 0, length = this.paramReferences.length; i < length; i++) { this.paramReferences[i].traverse(visitor, scope); } } if (this.paramTypeParameters != null) { for (int i = 0, length = this.paramTypeParameters.length; i < length; i++) { this.paramTypeParameters[i].traverse(visitor, scope); } } if (this.returnStatement != null) { this.returnStatement.traverse(visitor, scope); } if (this.exceptionReferences != null) { for (int i = 0, length = this.exceptionReferences.length; i < length; i++) { this.exceptionReferences[i].traverse(visitor, scope); } } if (this.seeReferences != null) { for (int i = 0, length = this.seeReferences.length; i < length; i++) { this.seeReferences[i].traverse(visitor, scope); } } } visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { if (visitor.visit(this, scope)) { if (this.paramReferences != null) { for (int i = 0, length = this.paramReferences.length; i < length; i++) { this.paramReferences[i].traverse(visitor, scope); } } if (this.paramTypeParameters != null) { for (int i = 0, length = this.paramTypeParameters.length; i < length; i++) { this.paramTypeParameters[i].traverse(visitor, scope); } } if (this.returnStatement != null) { this.returnStatement.traverse(visitor, scope); } if (this.exceptionReferences != null) { for (int i = 0, length = this.exceptionReferences.length; i < length; i++) { this.exceptionReferences[i].traverse(visitor, scope); } } if (this.seeReferences != null) { for (int i = 0, length = this.seeReferences.length; i < length; i++) { this.seeReferences[i].traverse(visitor, scope); } } } visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.jav0000644000175000001440000004611712212041344032407 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 186342 - [compiler][null] Using annotations for null checking * bug 361407 - Resource leak warning when resource is assigned to a field outside of constructor * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; 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.lookup.VariableBinding; public class ExplicitConstructorCall extends Statement implements InvocationSite { public Expression[] arguments; public Expression qualification; public MethodBinding binding; // exact binding resulting from lookup 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; // TODO Remove once DOMParser is activated public int typeArgumentsSourceStart; public ExplicitConstructorCall(int accessMode) { this.accessMode = accessMode; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // must verify that exceptions potentially thrown by this expression are caught in the method. try { ((MethodScope) currentScope).isConstructorCall = true; // process enclosing instance if (this.qualification != null) { flowInfo = this.qualification .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); } // process arguments if (this.arguments != null) { boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks; for (int i = 0, max = this.arguments.length; i < max; i++) { flowInfo = this.arguments[i] .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); if (analyseResources) { // if argument is an AutoCloseable insert info that it *may* be closed (by the target constructor, i.e.) flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, flowContext, false); } this.arguments[i].checkNPEbyUnboxing(currentScope, flowContext, flowInfo); } analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments); } ReferenceBinding[] thrownExceptions; if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) { if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6 thrownExceptions = currentScope.environment().convertToRawTypes(this.binding.thrownExceptions, true, true); } // check exceptions flowContext.checkExceptionHandlers( thrownExceptions, (this.accessMode == ExplicitConstructorCall.ImplicitSuper) ? (ASTNode) currentScope.methodScope().referenceContext : (ASTNode) this, flowInfo, currentScope); } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); manageSyntheticAccessIfNecessary(currentScope, flowInfo); return flowInfo; } finally { ((MethodScope) currentScope).isConstructorCall = false; } } /** * Constructor call 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 ((this.bits & ASTNode.IsReachable) == 0) { return; } try { ((MethodScope) currentScope).isConstructorCall = true; int pc = codeStream.position; codeStream.aload_0(); MethodBinding codegenBinding = this.binding.original(); ReferenceBinding targetType = codegenBinding.declaringClass; // special name&ordinal argument generation for enum constructors if (targetType.erasure().id == TypeIds.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 // handling innerclass instance allocation - enclosing instance arguments if (targetType.isNestedType()) { codeStream.generateSyntheticEnclosingInstanceValues( currentScope, targetType, (this.bits & ASTNode.DiscardEnclosingInstance) != 0 ? null : this.qualification, this); } // generate arguments generateArguments(this.binding, this.arguments, currentScope, codeStream); // handling innerclass instance allocation - outer local arguments if (targetType.isNestedType()) { codeStream.generateSyntheticOuterArgumentValues( currentScope, targetType, this); } if (this.syntheticAccessor != null) { // synthetic accessor got some extra arguments appended to its signature, which need values for (int i = 0, max = this.syntheticAccessor.parameters.length - codegenBinding.parameters.length; i < max; i++) { codeStream.aconst_null(); } codeStream.invoke(Opcodes.OPC_invokespecial, this.syntheticAccessor, null /* default declaringClass */); } else { codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, null /* default declaringClass */); } 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 (this.accessMode == ExplicitConstructorCall.ImplicitSuper); } public boolean isSuperAccess() { return this.accessMode != ExplicitConstructorCall.This; } public boolean isTypeAccess() { return true; } /* Inner emulation consists in either recording a dependency * link only, or performing one level of propagation. * * Dependency mechanism is used whenever dealing with source target * types, since by the time we reach them, we might not yet know their * exact need. */ void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { ReferenceBinding superTypeErasure = (ReferenceBinding) this.binding.declaringClass.erasure(); if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { // perform some emulation work in case there is some and we are inside a local type only if (superTypeErasure.isNestedType() && currentScope.enclosingSourceType().isLocalType()) { if (superTypeErasure.isLocalType()) { ((LocalTypeBinding) superTypeErasure).addInnerEmulationDependent(currentScope, this.qualification != null); } else { // locally propagate, since we already now the desired shape for sure currentScope.propagateInnerEmulation(superTypeErasure, this.qualification != null); } } } } public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { // if constructor from parameterized type got found, use the original constructor at codegen time MethodBinding codegenBinding = this.binding.original(); // perform some emulation work in case there is some and we are inside a local type only if (this.binding.isPrivate() && this.accessMode != ExplicitConstructorCall.This) { ReferenceBinding declaringClass = codegenBinding.declaringClass; // from 1.4 on, local type constructor can lose their private flag to ease emulation if ((declaringClass.tagBits & TagBits.IsLocalType) != 0 && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { // constructor will not be dumped as private, no emulation required thus codegenBinding.tagBits |= TagBits.ClearPrivateModifier; } else { this.syntheticAccessor = ((SourceTypeBinding) declaringClass).addSyntheticMethod(codegenBinding, isSuperAccess()); currentScope.problemReporter().needToEmulateMethodAccess(codegenBinding, this); } } } } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output); if (this.qualification != null) this.qualification.printExpression(0, output).append('.'); if (this.typeArguments != null) { output.append('<'); int max = this.typeArguments.length - 1; for (int j = 0; j < max; j++) { this.typeArguments[j].print(0, output); output.append(", ");//$NON-NLS-1$ } this.typeArguments[max].print(0, output); output.append('>'); } if (this.accessMode == ExplicitConstructorCall.This) { output.append("this("); //$NON-NLS-1$ } else { output.append("super("); //$NON-NLS-1$ } if (this.arguments != null) { for (int i = 0; i < this.arguments.length; i++) { if (i > 0) output.append(", "); //$NON-NLS-1$ this.arguments[i].printExpression(0, output); } } return output.append(");"); //$NON-NLS-1$ } public void resolve(BlockScope scope) { // the return type should be void for a constructor. // the test is made into getConstructor // mark the fact that we are in a constructor call..... // unmark at all returns MethodScope methodScope = scope.methodScope(); try { AbstractMethodDeclaration methodDeclaration = methodScope.referenceMethod(); if (methodDeclaration == null || !methodDeclaration.isConstructor() || ((ConstructorDeclaration) methodDeclaration).constructorCall != this) { scope.problemReporter().invalidExplicitConstructorCall(this); // fault-tolerance if (this.qualification != null) { this.qualification.resolveType(scope); } if (this.typeArguments != null) { for (int i = 0, max = this.typeArguments.length; i < max; i++) { this.typeArguments[i].resolveType(scope, true /* check bounds*/); } } if (this.arguments != null) { for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return; } methodScope.isConstructorCall = true; ReferenceBinding receiverType = scope.enclosingReceiverType(); boolean rcvHasError = false; if (this.accessMode != ExplicitConstructorCall.This) { receiverType = receiverType.superclass(); TypeReference superclassRef = scope.referenceType().superclass; if (superclassRef != null && superclassRef.resolvedType != null && !superclassRef.resolvedType.isValidBinding()) { rcvHasError = true; } } if (receiverType != null) { // prevent (explicit) super constructor invocation from within enum if (this.accessMode == ExplicitConstructorCall.Super && receiverType.erasure().id == TypeIds.T_JavaLangEnum) { scope.problemReporter().cannotInvokeSuperConstructorInEnum(this, methodScope.referenceMethod().binding); } // qualification should be from the type of the enclosingType if (this.qualification != null) { if (this.accessMode != ExplicitConstructorCall.Super) { scope.problemReporter().unnecessaryEnclosingInstanceSpecification( this.qualification, receiverType); } if (!rcvHasError) { ReferenceBinding enclosingType = receiverType.enclosingType(); if (enclosingType == null) { scope.problemReporter().unnecessaryEnclosingInstanceSpecification(this.qualification, receiverType); this.bits |= ASTNode.DiscardEnclosingInstance; } else { TypeBinding qTb = this.qualification.resolveTypeExpecting(scope, enclosingType); this.qualification.computeConversion(scope, qTb, qTb); } } } } // resolve type arguments (for generic constructor call) if (this.typeArguments != null) { boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5; int length = this.typeArguments.length; this.genericTypeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeReference typeReference = this.typeArguments[i]; if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) { argHasError = true; } if (argHasError && typeReference instanceof Wildcard) { scope.problemReporter().illegalUsageOfWildcard(typeReference); } } if (argHasError) { if (this.arguments != null) { // still attempt to resolve arguments for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return; } } // arguments buffering for the method lookup TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; boolean argsContainCast = false; if (this.arguments != null) { boolean argHasError = false; // typeChecks all arguments int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++) { Expression argument = this.arguments[i]; if (argument instanceof CastExpression) { argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on argsContainCast = true; } if ((argumentTypes[i] = argument.resolveType(scope)) == null) { argHasError = true; } } if (argHasError) { if (receiverType == null) { return; } // record a best guess, for clients who need hint about possible contructor match TypeBinding[] pseudoArgs = new TypeBinding[length]; for (int i = length; --i >= 0;) { pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type } this.binding = scope.findMethod(receiverType, TypeConstants.INIT, pseudoArgs, this); if (this.binding != null && !this.binding.isValidBinding()) { MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; // record the closest match, for clients who may still need hint about possible method match if (closestMatch != null) { if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method // shouldn't return generic method outside its context, rather convert it to raw method (175409) closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null); } this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } return; } } else if (receiverType.erasure().id == TypeIds.T_JavaLangEnum) { // TODO (philippe) get rid of once well-known binding is available argumentTypes = new TypeBinding[] { scope.getJavaLangString(), TypeBinding.INT }; } if (receiverType == null) { return; } if ((this.binding = scope.getConstructor(receiverType, argumentTypes, this)).isValidBinding()) { if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { if (!methodScope.enclosingSourceType().isAnonymousType()) { scope.problemReporter().missingTypeInConstructor(this, this.binding); } } if (isMethodUseDeprecated(this.binding, scope, this.accessMode != ExplicitConstructorCall.ImplicitSuper)) { scope.problemReporter().deprecatedMethod(this.binding, this); } if (checkInvocationArguments(scope, null, receiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } if (this.binding.isOrEnclosedByPrivateType()) { this.binding.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments); } } else { if (this.binding.declaringClass == null) { this.binding.declaringClass = receiverType; } if (rcvHasError) return; scope.problemReporter().invalidConstructor(this, this.binding); } } finally { methodScope.isConstructorCall = false; } } public void setActualReceiverType(ReferenceBinding receiverType) { // ignored } public void setDepth(int depth) { // ignore for here } public void setFieldIndex(int depth) { // ignore for here } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { 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); } } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/IntLiteralMinValue.java0000644000175000001440000000202112212041344031417 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.impl.*; public class IntLiteralMinValue extends IntLiteral { final static char[] CharValue = new char[]{'-','2','1','4','7','4','8','3','6','4','8'}; public IntLiteralMinValue(char[] token, char[] reducedToken, int start, int end) { super(token, reducedToken, start, end, Integer.MIN_VALUE, IntConstant.fromValue(Integer.MIN_VALUE)); } public void computeConstant(){ /*precomputed at creation time*/ } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java0000644000175000001440000002131612212041344031201 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' *******************************************************************************/ 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.*; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class ArrayInitializer extends Expression { public Expression[] expressions; public ArrayBinding binding; //the type of the { , , , } /** * ArrayInitializer constructor comment. */ public ArrayInitializer() { super(); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { if (this.expressions != null) { boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks; for (int i = 0, max = this.expressions.length; i < max; i++) { flowInfo = this.expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); if (analyseResources && FakedTrackingVariable.isAnyCloseable(this.expressions[i].resolvedType)) { flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.expressions[i], flowInfo, flowContext, false); } } } return flowInfo; } /** * Code generation for a array initializer */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { // Flatten the values and compute the dimensions, by iterating in depth into nested array initializers int pc = codeStream.position; int expressionLength = (this.expressions == null) ? 0: this.expressions.length; codeStream.generateInlinedValue(expressionLength); codeStream.newArray(this.binding); if (this.expressions != null) { // binding is an ArrayType, so I can just deal with the dimension int elementsTypeID = this.binding.dimensions > 1 ? -1 : this.binding.leafComponentType.id; for (int i = 0; i < expressionLength; i++) { Expression expr; if ((expr = this.expressions[i]).constant != Constant.NotAConstant) { switch (elementsTypeID) { // filter out initializations to default values case T_int : case T_short : case T_byte : case T_char : case T_long : if (expr.constant.longValue() != 0) { codeStream.dup(); codeStream.generateInlinedValue(i); expr.generateCode(currentScope, codeStream, true); codeStream.arrayAtPut(elementsTypeID, false); } break; case T_float : case T_double : double constantValue = expr.constant.doubleValue(); if (constantValue == -0.0 || constantValue != 0) { codeStream.dup(); codeStream.generateInlinedValue(i); expr.generateCode(currentScope, codeStream, true); codeStream.arrayAtPut(elementsTypeID, false); } break; case T_boolean : if (expr.constant.booleanValue() != false) { codeStream.dup(); codeStream.generateInlinedValue(i); expr.generateCode(currentScope, codeStream, true); codeStream.arrayAtPut(elementsTypeID, false); } break; default : if (!(expr instanceof NullLiteral)) { codeStream.dup(); codeStream.generateInlinedValue(i); expr.generateCode(currentScope, codeStream, true); codeStream.arrayAtPut(elementsTypeID, false); } } } else if (!(expr instanceof NullLiteral)) { codeStream.dup(); codeStream.generateInlinedValue(i); expr.generateCode(currentScope, codeStream, true); codeStream.arrayAtPut(elementsTypeID, false); } } } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { codeStream.pop(); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printExpression(int indent, StringBuffer output) { output.append('{'); if (this.expressions != null) { int j = 20 ; for (int i = 0 ; i < this.expressions.length ; i++) { if (i > 0) output.append(", "); //$NON-NLS-1$ this.expressions[i].printExpression(0, output); j -- ; if (j == 0) { output.append('\n'); printIndent(indent+1, output); j = 20; } } } return output.append('}'); } public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedType) { // Array initializers can only occur on the right hand side of an assignment // expression, therefore the expected type contains the valid information // concerning the type that must be enforced by the elements of the array initializer. // this method is recursive... (the test on isArrayType is the stop case) this.constant = Constant.NotAConstant; if (expectedType instanceof ArrayBinding) { // allow new List[5] if ((this.bits & IsAnnotationDefaultValue) == 0) { // annotation default value need only to be commensurate JLS9.7 // allow new List[5] - only check for generic array when no initializer, since also checked inside initializer resolution TypeBinding leafComponentType = expectedType.leafComponentType(); if (!leafComponentType.isReifiable()) { scope.problemReporter().illegalGenericArray(leafComponentType, this); } } this.resolvedType = this.binding = (ArrayBinding) expectedType; if (this.expressions == null) return this.binding; TypeBinding elementType = this.binding.elementsType(); for (int i = 0, length = this.expressions.length; i < length; i++) { Expression expression = this.expressions[i]; expression.setExpectedType(elementType); TypeBinding expressionType = expression instanceof ArrayInitializer ? expression.resolveTypeExpecting(scope, elementType) : expression.resolveType(scope); if (expressionType == null) continue; // Compile-time conversion required? if (elementType != expressionType) // must call before computeConversion() and typeMismatchError() scope.compilationUnitScope().recordTypeConversion(elementType, expressionType); if (expression.isConstantValueOfTypeAssignableToType(expressionType, elementType) || expressionType.isCompatibleWith(elementType)) { expression.computeConversion(scope, elementType, expressionType); } else if (isBoxingCompatible(expressionType, elementType, expression, scope)) { expression.computeConversion(scope, elementType, expressionType); } else { scope.problemReporter().typeMismatchError(expressionType, elementType, expression, null); } } return this.binding; } // infer initializer type for error reporting based on first element TypeBinding leafElementType = null; int dim = 1; if (this.expressions == null) { leafElementType = scope.getJavaLangObject(); } else { Expression expression = this.expressions[0]; while(expression != null && expression instanceof ArrayInitializer) { dim++; Expression[] subExprs = ((ArrayInitializer) expression).expressions; if (subExprs == null){ leafElementType = scope.getJavaLangObject(); expression = null; break; } expression = ((ArrayInitializer) expression).expressions[0]; } if (expression != null) { leafElementType = expression.resolveType(scope); } // fault-tolerance - resolve other expressions as well for (int i = 1, length = this.expressions.length; i < length; i++) { expression = this.expressions[i]; if (expression != null) { expression.resolveType(scope) ; } } } if (leafElementType != null) { this.resolvedType = scope.createArrayType(leafElementType, dim); if (expectedType != null) scope.problemReporter().typeMismatchError(this.resolvedType, expectedType, this, null); } return null; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { if (this.expressions != null) { int expressionsLength = this.expressions.length; for (int i = 0; i < expressionsLength; i++) this.expressions[i].traverse(visitor, scope); } } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java0000644000175000001440000000505412212041344031704 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; /** * Extra behavior for statements which are generating subroutines */ public abstract class SubRoutineStatement extends Statement { public static void reenterAllExceptionHandlers(SubRoutineStatement[] subroutines, int max, CodeStream codeStream) { if (subroutines == null) return; if (max < 0) max = subroutines.length; for (int i = 0; i < max; i++) { SubRoutineStatement sub = subroutines[i]; sub.enterAnyExceptionHandler(codeStream); sub.enterDeclaredExceptionHandlers(codeStream); } } ExceptionLabel anyExceptionLabel; public ExceptionLabel enterAnyExceptionHandler(CodeStream codeStream) { if (this.anyExceptionLabel == null) { this.anyExceptionLabel = new ExceptionLabel(codeStream, null /*any exception*/); } this.anyExceptionLabel.placeStart(); return this.anyExceptionLabel; } public void enterDeclaredExceptionHandlers(CodeStream codeStream) { // do nothing by default } public void exitAnyExceptionHandler() { if (this.anyExceptionLabel != null) { this.anyExceptionLabel.placeEnd(); } } public void exitDeclaredExceptionHandlers(CodeStream codeStream) { // do nothing by default } /** * Generate an invocation of a subroutine (e.g. jsr finally) in current context. * @param currentScope * @param codeStream * @param targetLocation * @param stateIndex * @param secretLocal * @return boolean, true if the generated code will abrupt completion */ public abstract boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal); public abstract boolean isSubRoutineEscaping(); public void placeAllAnyExceptionHandler() { this.anyExceptionLabel.place(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java0000644000175000001440000006760012212041344032250 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephen Herrmann - Contributions for * bug 133125 - [compiler][null] need to report the null status of expressions and analyze them simultaneously * bug 292478 - Report potentially null across variable assignment * bug 324178 - [null] ConditionalExpression.nullStatus(..) doesn't take into account the analysis of condition itself * bug 354554 - [null] conditional with redundant condition yields weak error message * bug 349326 - [1.7] new warning for missing try-with-resources * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 400761 - [compiler][null] null may be return as boolean without a diagnostic *******************************************************************************/ 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.*; public class ConditionalExpression extends OperatorExpression { public Expression condition, valueIfTrue, valueIfFalse; public Constant optimizedBooleanConstant; public Constant optimizedIfTrueConstant; public Constant optimizedIfFalseConstant; // for local variables table attributes int trueInitStateIndex = -1; int falseInitStateIndex = -1; int mergedInitStateIndex = -1; // we compute and store the null status during analyseCode (https://bugs.eclipse.org/324178): private int nullStatus = FlowInfo.UNKNOWN; public ConditionalExpression( Expression condition, Expression valueIfTrue, Expression valueIfFalse) { this.condition = condition; this.valueIfTrue = valueIfTrue; this.valueIfFalse = valueIfFalse; this.sourceStart = condition.sourceStart; this.sourceEnd = valueIfFalse.sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; Constant cst = this.condition.optimizedBooleanConstant(); boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; int mode = flowInfo.reachMode(); flowInfo = this.condition.analyseCode(currentScope, flowContext, flowInfo, cst == Constant.NotAConstant); flowContext.conditionalLevel++; // process the if-true part FlowInfo trueFlowInfo = flowInfo.initsWhenTrue().copy(); if (isConditionOptimizedFalse) { if ((mode & FlowInfo.UNREACHABLE) == 0) { trueFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { this.valueIfTrue.complainIfUnreachable(trueFlowInfo, currentScope, initialComplaintLevel, false); } } this.trueInitStateIndex = currentScope.methodScope().recordInitializationStates(trueFlowInfo); trueFlowInfo = this.valueIfTrue.analyseCode(currentScope, flowContext, trueFlowInfo); this.valueIfTrue.checkNPEbyUnboxing(currentScope, flowContext, trueFlowInfo); // may need to fetch this null status before expireNullCheckedFieldInfo(): int preComputedTrueNullStatus = -1; if (currentScope.compilerOptions().enableSyntacticNullAnalysisForFields) { preComputedTrueNullStatus = this.valueIfTrue.nullStatus(trueFlowInfo, flowContext); // wipe information that was meant only for valueIfTrue: flowContext.expireNullCheckedFieldInfo(); } // process the if-false part FlowInfo falseFlowInfo = flowInfo.initsWhenFalse().copy(); if (isConditionOptimizedTrue) { if ((mode & FlowInfo.UNREACHABLE) == 0) { falseFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) { this.valueIfFalse.complainIfUnreachable(falseFlowInfo, currentScope, initialComplaintLevel, true); } } this.falseInitStateIndex = currentScope.methodScope().recordInitializationStates(falseFlowInfo); falseFlowInfo = this.valueIfFalse.analyseCode(currentScope, flowContext, falseFlowInfo); this.valueIfFalse.checkNPEbyUnboxing(currentScope, flowContext, falseFlowInfo); flowContext.conditionalLevel--; // merge if-true & if-false initializations FlowInfo mergedInfo; if (isConditionOptimizedTrue){ mergedInfo = trueFlowInfo.addPotentialInitializationsFrom(falseFlowInfo); if (preComputedTrueNullStatus != -1) { this.nullStatus = preComputedTrueNullStatus; } else { this.nullStatus = this.valueIfTrue.nullStatus(trueFlowInfo, flowContext); } } else if (isConditionOptimizedFalse) { mergedInfo = falseFlowInfo.addPotentialInitializationsFrom(trueFlowInfo); this.nullStatus = this.valueIfFalse.nullStatus(falseFlowInfo, flowContext); } else { // this block must meet two conflicting requirements (see https://bugs.eclipse.org/324178): // (1) For null analysis of "Object o2 = (o1 != null) ? o1 : new Object();" we need to distinguish // the paths *originating* from the evaluation of the condition to true/false respectively. // This is used to determine the possible null status of the entire conditional expression. // (2) For definite assignment analysis (JLS 16.1.5) of boolean conditional expressions of the form // "if (c1 ? expr1 : expr2) use(v);" we need to check whether any variable v will be definitely // assigned whenever the entire conditional expression evaluates to true (to reach the then branch). // I.e., we need to collect flowInfo *towards* the overall outcome true/false // (regardless of the evaluation of the condition). // to support (1) use the infos of both branches originating from the condition for computing the nullStatus: computeNullStatus(preComputedTrueNullStatus, trueFlowInfo, falseFlowInfo, flowContext); // to support (2) we split the true/false branches according to their inner structure. Consider this: // if (b ? false : (true && (v = false))) return v; -- ok // - expr1 ("false") has no path towards true (mark as unreachable) // - expr2 ("(true && (v = false))") has a branch towards true on which v is assigned. // -> merging these two branches yields: v is assigned // - the paths towards false are irrelevant since the enclosing if has no else. cst = this.optimizedIfTrueConstant; boolean isValueIfTrueOptimizedTrue = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isValueIfTrueOptimizedFalse = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == false; cst = this.optimizedIfFalseConstant; boolean isValueIfFalseOptimizedTrue = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isValueIfFalseOptimizedFalse = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == false; UnconditionalFlowInfo trueFlowTowardsTrue = trueFlowInfo.initsWhenTrue().unconditionalCopy(); UnconditionalFlowInfo falseFlowTowardsTrue = falseFlowInfo.initsWhenTrue().unconditionalCopy(); UnconditionalFlowInfo trueFlowTowardsFalse = trueFlowInfo.initsWhenFalse().unconditionalInits(); UnconditionalFlowInfo falseFlowTowardsFalse = falseFlowInfo.initsWhenFalse().unconditionalInits(); if (isValueIfTrueOptimizedFalse) { trueFlowTowardsTrue.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (isValueIfFalseOptimizedFalse) { falseFlowTowardsTrue.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (isValueIfTrueOptimizedTrue) { trueFlowTowardsFalse.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (isValueIfFalseOptimizedTrue) { falseFlowTowardsFalse.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } mergedInfo = FlowInfo.conditional( trueFlowTowardsTrue.mergedWith(falseFlowTowardsTrue), trueFlowTowardsFalse.mergedWith(falseFlowTowardsFalse)); } this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); mergedInfo.setReachMode(mode); return mergedInfo; } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { if ((this.nullStatus & FlowInfo.NULL) != 0) scope.problemReporter().expressionNullReference(this); else if ((this.nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) scope.problemReporter().expressionPotentialNullReference(this); return true; // all checking done } private void computeNullStatus(int ifTrueNullStatus, FlowInfo trueBranchInfo, FlowInfo falseBranchInfo, FlowContext flowContext) { // given that the condition cannot be optimized to a constant // we now merge the nullStatus from both branches: if (ifTrueNullStatus == -1) { // has this status been pre-computed? ifTrueNullStatus = this.valueIfTrue.nullStatus(trueBranchInfo, flowContext); } int ifFalseNullStatus = this.valueIfFalse.nullStatus(falseBranchInfo, flowContext); if (ifTrueNullStatus == ifFalseNullStatus) { this.nullStatus = ifTrueNullStatus; return; } if (trueBranchInfo.reachMode() != FlowInfo.REACHABLE) { this.nullStatus = ifFalseNullStatus; return; } if (falseBranchInfo.reachMode() != FlowInfo.REACHABLE) { this.nullStatus = ifTrueNullStatus; return; } // is there a chance of null (or non-null)? -> potentially null etc. // https://bugs.eclipse.org/bugs/show_bug.cgi?id=133125 int status = 0; int combinedStatus = ifTrueNullStatus|ifFalseNullStatus; if ((combinedStatus & (FlowInfo.NULL|FlowInfo.POTENTIALLY_NULL)) != 0) status |= FlowInfo.POTENTIALLY_NULL; if ((combinedStatus & (FlowInfo.NON_NULL|FlowInfo.POTENTIALLY_NON_NULL)) != 0) status |= FlowInfo.POTENTIALLY_NON_NULL; if ((combinedStatus & (FlowInfo.UNKNOWN|FlowInfo.POTENTIALLY_UNKNOWN)) != 0) status |= FlowInfo.POTENTIALLY_UNKNOWN; if (status > 0) this.nullStatus = status; } /** * Code generation for the conditional operator ?: * * @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; BranchLabel endifLabel, falseLabel; if (this.constant != Constant.NotAConstant) { if (valueRequired) codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); return; } Constant cst = this.condition.optimizedBooleanConstant(); boolean needTruePart = !(cst != Constant.NotAConstant && cst.booleanValue() == false); boolean needFalsePart = !(cst != Constant.NotAConstant && cst.booleanValue() == true); endifLabel = new BranchLabel(codeStream); // Generate code for the condition falseLabel = new BranchLabel(codeStream); falseLabel.tagBits |= BranchLabel.USED; this.condition.generateOptimizedBoolean( currentScope, codeStream, null, falseLabel, cst == Constant.NotAConstant); if (this.trueInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables( currentScope, this.trueInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.trueInitStateIndex); } // Then code generation if (needTruePart) { this.valueIfTrue.generateCode(currentScope, codeStream, valueRequired); if (needFalsePart) { // Jump over the else part int position = codeStream.position; codeStream.goto_(endifLabel); codeStream.recordPositionsFrom(position, this.valueIfTrue.sourceEnd); // Tune codestream stack size if (valueRequired) { switch(this.resolvedType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.decrStackSize(2); break; default : codeStream.decrStackSize(1); break; } } } } if (needFalsePart) { if (this.falseInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables( currentScope, this.falseInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.falseInitStateIndex); } if (falseLabel.forwardReferenceCount() > 0) { falseLabel.place(); } this.valueIfFalse.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.recordExpressionType(this.resolvedType); } if (needTruePart) { // End of if statement endifLabel.place(); } } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables( currentScope, this.mergedInitStateIndex); } // implicit conversion if (valueRequired) codeStream.generateImplicitConversion(this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * Optimized boolean code generation for the conditional operator ?: */ public void generateOptimizedBoolean( BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { int pc = codeStream.position; if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == T_boolean) // constant || ((this.valueIfTrue.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_boolean) { // non boolean values super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } Constant cst = this.condition.constant; Constant condCst = this.condition.optimizedBooleanConstant(); boolean needTruePart = !(((cst != Constant.NotAConstant) && (cst.booleanValue() == false)) || ((condCst != Constant.NotAConstant) && (condCst.booleanValue() == false))); boolean needFalsePart = !(((cst != Constant.NotAConstant) && (cst.booleanValue() == true)) || ((condCst != Constant.NotAConstant) && (condCst.booleanValue() == true))); BranchLabel internalFalseLabel, endifLabel = new BranchLabel(codeStream); // Generate code for the condition boolean needConditionValue = (cst == Constant.NotAConstant) && (condCst == Constant.NotAConstant); this.condition.generateOptimizedBoolean( currentScope, codeStream, null, internalFalseLabel = new BranchLabel(codeStream), needConditionValue); if (this.trueInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables( currentScope, this.trueInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.trueInitStateIndex); } // Then code generation if (needTruePart) { this.valueIfTrue.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); if (needFalsePart) { // Jump over the else part JumpEndif: { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case cst = this.optimizedIfTrueConstant; boolean isValueIfTrueOptimizedTrue = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == true; if (isValueIfTrueOptimizedTrue) break JumpEndif; // no need to jump over, since branched to true already } } else { // implicit falling through the TRUE case if (trueLabel == null) { cst = this.optimizedIfTrueConstant; boolean isValueIfTrueOptimizedFalse = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == false; if (isValueIfTrueOptimizedFalse) break JumpEndif; // no need to jump over, since branched to false already } else { // no implicit fall through TRUE/FALSE --> should never occur } } int position = codeStream.position; codeStream.goto_(endifLabel); codeStream.recordPositionsFrom(position, this.valueIfTrue.sourceEnd); } // No need to decrement codestream stack size // since valueIfTrue was already consumed by branch bytecode } } if (needFalsePart) { internalFalseLabel.place(); if (this.falseInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.falseInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.falseInitStateIndex); } this.valueIfFalse.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); // End of if statement endifLabel.place(); } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } // no implicit conversion for boolean values codeStream.recordPositionsFrom(pc, this.sourceEnd); } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { return this.nullStatus; } public Constant optimizedBooleanConstant() { return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant; } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { this.condition.printExpression(indent, output).append(" ? "); //$NON-NLS-1$ this.valueIfTrue.printExpression(0, output).append(" : "); //$NON-NLS-1$ return this.valueIfFalse.printExpression(0, output); } public TypeBinding resolveType(BlockScope scope) { // JLS3 15.25 this.constant = Constant.NotAConstant; LookupEnvironment env = scope.environment(); boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; TypeBinding conditionType = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); this.condition.computeConversion(scope, TypeBinding.BOOLEAN, conditionType); if (this.valueIfTrue instanceof CastExpression) this.valueIfTrue.bits |= DisableUnnecessaryCastCheck; // will check later on TypeBinding originalValueIfTrueType = this.valueIfTrue.resolveType(scope); if (this.valueIfFalse instanceof CastExpression) this.valueIfFalse.bits |= DisableUnnecessaryCastCheck; // will check later on TypeBinding originalValueIfFalseType = this.valueIfFalse.resolveType(scope); if (conditionType == null || originalValueIfTrueType == null || originalValueIfFalseType == null) return null; TypeBinding valueIfTrueType = originalValueIfTrueType; TypeBinding valueIfFalseType = originalValueIfFalseType; if (use15specifics && valueIfTrueType != valueIfFalseType) { if (valueIfTrueType.isBaseType()) { if (valueIfFalseType.isBaseType()) { // bool ? baseType : baseType if (valueIfTrueType == TypeBinding.NULL) { // bool ? null : 12 --> Integer valueIfFalseType = env.computeBoxingType(valueIfFalseType); // boxing } else if (valueIfFalseType == TypeBinding.NULL) { // bool ? 12 : null --> Integer valueIfTrueType = env.computeBoxingType(valueIfTrueType); // boxing } } else { // bool ? baseType : nonBaseType TypeBinding unboxedIfFalseType = valueIfFalseType.isBaseType() ? valueIfFalseType : env.computeBoxingType(valueIfFalseType); if (valueIfTrueType.isNumericType() && unboxedIfFalseType.isNumericType()) { valueIfFalseType = unboxedIfFalseType; // unboxing } else if (valueIfTrueType != TypeBinding.NULL) { // bool ? 12 : new Integer(12) --> int valueIfFalseType = env.computeBoxingType(valueIfFalseType); // unboxing } } } else if (valueIfFalseType.isBaseType()) { // bool ? nonBaseType : baseType TypeBinding unboxedIfTrueType = valueIfTrueType.isBaseType() ? valueIfTrueType : env.computeBoxingType(valueIfTrueType); if (unboxedIfTrueType.isNumericType() && valueIfFalseType.isNumericType()) { valueIfTrueType = unboxedIfTrueType; // unboxing } else if (valueIfFalseType != TypeBinding.NULL) { // bool ? new Integer(12) : 12 --> int valueIfTrueType = env.computeBoxingType(valueIfTrueType); // unboxing } } else { // bool ? nonBaseType : nonBaseType TypeBinding unboxedIfTrueType = env.computeBoxingType(valueIfTrueType); TypeBinding unboxedIfFalseType = env.computeBoxingType(valueIfFalseType); if (unboxedIfTrueType.isNumericType() && unboxedIfFalseType.isNumericType()) { valueIfTrueType = unboxedIfTrueType; valueIfFalseType = unboxedIfFalseType; } } } // Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible Constant condConstant, trueConstant, falseConstant; if ((condConstant = this.condition.constant) != Constant.NotAConstant && (trueConstant = this.valueIfTrue.constant) != Constant.NotAConstant && (falseConstant = this.valueIfFalse.constant) != Constant.NotAConstant) { // all terms are constant expression so we can propagate the constant // from valueIFTrue or valueIfFalse to the receiver constant this.constant = condConstant.booleanValue() ? trueConstant : falseConstant; } if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion this.valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType); if (valueIfTrueType == TypeBinding.BOOLEAN) { this.optimizedIfTrueConstant = this.valueIfTrue.optimizedBooleanConstant(); this.optimizedIfFalseConstant = this.valueIfFalse.optimizedBooleanConstant(); if (this.optimizedIfTrueConstant != Constant.NotAConstant && this.optimizedIfFalseConstant != Constant.NotAConstant && this.optimizedIfTrueConstant.booleanValue() == this.optimizedIfFalseConstant.booleanValue()) { // a ? true : true / a ? false : false this.optimizedBooleanConstant = this.optimizedIfTrueConstant; } else if ((condConstant = this.condition.optimizedBooleanConstant()) != Constant.NotAConstant) { // Propagate the optimized boolean constant if possible this.optimizedBooleanConstant = condConstant.booleanValue() ? this.optimizedIfTrueConstant : this.optimizedIfFalseConstant; } } return this.resolvedType = valueIfTrueType; } // Determine the return type depending on argument types // Numeric types if (valueIfTrueType.isNumericType() && valueIfFalseType.isNumericType()) { // (Short x Byte) or (Byte x Short)" if ((valueIfTrueType == TypeBinding.BYTE && valueIfFalseType == TypeBinding.SHORT) || (valueIfTrueType == TypeBinding.SHORT && valueIfFalseType == TypeBinding.BYTE)) { this.valueIfTrue.computeConversion(scope, TypeBinding.SHORT, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, TypeBinding.SHORT, originalValueIfFalseType); return this.resolvedType = TypeBinding.SHORT; } // x constant(Int) ---> and reciprocally if ((valueIfTrueType == TypeBinding.BYTE || valueIfTrueType == TypeBinding.SHORT || valueIfTrueType == TypeBinding.CHAR) && (valueIfFalseType == TypeBinding.INT && this.valueIfFalse.isConstantValueOfTypeAssignableToType(valueIfFalseType, valueIfTrueType))) { this.valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, valueIfTrueType, originalValueIfFalseType); return this.resolvedType = valueIfTrueType; } if ((valueIfFalseType == TypeBinding.BYTE || valueIfFalseType == TypeBinding.SHORT || valueIfFalseType == TypeBinding.CHAR) && (valueIfTrueType == TypeBinding.INT && this.valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) { this.valueIfTrue.computeConversion(scope, valueIfFalseType, originalValueIfTrueType); this.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)) { this.valueIfTrue.computeConversion(scope, TypeBinding.INT, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, TypeBinding.INT, originalValueIfFalseType); return this.resolvedType = TypeBinding.INT; } // long if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_long) && BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_long)) { this.valueIfTrue.computeConversion(scope, TypeBinding.LONG, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, TypeBinding.LONG, originalValueIfFalseType); return this.resolvedType = TypeBinding.LONG; } // float if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_float) && BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_float)) { this.valueIfTrue.computeConversion(scope, TypeBinding.FLOAT, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, TypeBinding.FLOAT, originalValueIfFalseType); return this.resolvedType = TypeBinding.FLOAT; } // double this.valueIfTrue.computeConversion(scope, TypeBinding.DOUBLE, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, TypeBinding.DOUBLE, originalValueIfFalseType); return this.resolvedType = TypeBinding.DOUBLE; } // Type references (null null is already tested) if (valueIfTrueType.isBaseType() && valueIfTrueType != TypeBinding.NULL) { if (use15specifics) { valueIfTrueType = env.computeBoxingType(valueIfTrueType); } else { scope.problemReporter().conditionalArgumentsIncompatibleTypes(this, valueIfTrueType, valueIfFalseType); return null; } } if (valueIfFalseType.isBaseType() && valueIfFalseType != TypeBinding.NULL) { if (use15specifics) { valueIfFalseType = env.computeBoxingType(valueIfFalseType); } else { scope.problemReporter().conditionalArgumentsIncompatibleTypes(this, valueIfTrueType, valueIfFalseType); return null; } } if (use15specifics) { // >= 1.5 : LUB(operand types) must exist TypeBinding commonType = null; if (valueIfTrueType == TypeBinding.NULL) { commonType = valueIfFalseType; } else if (valueIfFalseType == TypeBinding.NULL) { commonType = valueIfTrueType; } else { commonType = scope.lowerUpperBound(new TypeBinding[] { valueIfTrueType, valueIfFalseType }); } if (commonType != null) { this.valueIfTrue.computeConversion(scope, commonType, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, commonType, originalValueIfFalseType); return this.resolvedType = commonType.capture(scope, this.sourceEnd); } } else { // < 1.5 : one operand must be convertible to the other if (valueIfFalseType.isCompatibleWith(valueIfTrueType)) { this.valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, valueIfTrueType, originalValueIfFalseType); return this.resolvedType = valueIfTrueType; } else if (valueIfTrueType.isCompatibleWith(valueIfFalseType)) { this.valueIfTrue.computeConversion(scope, valueIfFalseType, originalValueIfTrueType); this.valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType); return this.resolvedType = valueIfFalseType; } } scope.problemReporter().conditionalArgumentsIncompatibleTypes( this, valueIfTrueType, valueIfFalseType); return null; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.condition.traverse(visitor, scope); this.valueIfTrue.traverse(visitor, scope); this.valueIfFalse.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Initializer.java0000644000175000001440000000763612212041344030213 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.parser.*; public class Initializer extends FieldDeclaration { public Block block; public int lastVisibleFieldID; public int bodyStart; public int bodyEnd; public Initializer(Block block, int modifiers) { this.block = block; this.modifiers = modifiers; if (block != null) { this.declarationSourceStart = this.sourceStart = block.sourceStart; } } public FlowInfo analyseCode( MethodScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { if (this.block != null) { return this.block.analyseCode(currentScope, flowContext, flowInfo); } return flowInfo; } /** * Code generation for a non-static initializer: * standard block code gen * * @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 ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; if (this.block != null) this.block.generateCode(currentScope, codeStream); codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind() */ public int getKind() { return INITIALIZER; } public boolean isStatic() { return (this.modifiers & ClassFileConstants.AccStatic) != 0; } public void parseStatements( Parser parser, TypeDeclaration typeDeclaration, CompilationUnitDeclaration unit) { //fill up the method body with statement parser.parse(this, typeDeclaration, unit); } public StringBuffer printStatement(int indent, StringBuffer output) { if (this.modifiers != 0) { printIndent(indent, output); printModifiers(this.modifiers, output); if (this.annotations != null) printAnnotations(this.annotations, output); output.append("{\n"); //$NON-NLS-1$ if (this.block != null) { this.block.printBody(indent, output); } printIndent(indent, output).append('}'); return output; } else if (this.block != null) { this.block.printStatement(indent, output); } else { printIndent(indent, output).append("{}"); //$NON-NLS-1$ } return output; } public void resolve(MethodScope scope) { FieldBinding previousField = scope.initializedField; int previousFieldID = scope.lastVisibleFieldID; try { scope.initializedField = null; scope.lastVisibleFieldID = this.lastVisibleFieldID; if (isStatic()) { ReferenceBinding declaringType = scope.enclosingSourceType(); if (declaringType.isNestedType() && !declaringType.isStatic()) scope.problemReporter().innerTypesCannotDeclareStaticInitializers( declaringType, this); } if (this.block != null) this.block.resolve(scope); } finally { scope.initializedField = previousField; scope.lastVisibleFieldID = previousFieldID; } } public void traverse(ASTVisitor visitor, MethodScope scope) { if (visitor.visit(this, scope)) { if (this.block != null) this.block.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ASTNode.java0000644000175000001440000011302712212041344027155 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Matt McCutchen - partial fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=122995 * Karen Moore - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=207411 * Stephan Herrmann - Contributions for * bug 185682 - Increment/decrement operators mark local variables as read * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 374605 - Unreasonable warning for enum-based switch statements * bug 384870 - [compiler] @Deprecated annotation not detected if preceded by other annotation * bug 393719 - [compiler] inconsistent warnings on iteration variables *******************************************************************************/ 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.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.ASTVisitor; public abstract class ASTNode implements TypeConstants, TypeIds { public int sourceStart, sourceEnd; // storage for internal flags (32 bits) BIT USAGE public final static int Bit1 = 0x1; // return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement) 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 (name ref,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) | supertype ref (type ref) | resolved (field decl) public final static int Bit6 = 0x20; // depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer) | is recovered (annotation reference) public final static int Bit7 = 0x40; // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration) public final static int Bit8 = 0x80; // depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement) public final static int Bit9 = 0x100; // depth (name ref, msg) | operator (operator) | is local type (type decl) | isThenStatementUnreachable (if statement) | can be static 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) | has abstract methods (type decl) public final static int Bit13 = 0x1000; // depth (name ref, msg) | is secondary type (type decl) public final static int Bit14 = 0x2000; // strictly assigned (reference lhs) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl) public final static int Bit15 = 0x4000; // is unnecessary cast (expression) | is varargs (type ref) | isSubRoutineEscaping (try statement) | superAccess (javadoc allocation expression/javadoc message send/javadoc return statement) public final static int Bit16 = 0x8000; // in javadoc comment (name ref, type ref, msg) public final static int Bit17 = 0x10000; // compound assigned (reference lhs) | unchecked (msg, alloc, explicit constr call) public final static int Bit18 = 0x20000; // non null (expression) | onDemand (import reference) public final static int Bit19 = 0x40000; // didResolve (parameterized qualified type ref/parameterized single type ref) | empty (javadoc return statement) | needReceiverGenericCast (msg/fieldref) public final static int Bit20 = 0x80000; // contains syntax errors (method declaration, type declaration, field declarations, initializer) public final static int Bit21 = 0x100000; public final static int Bit22 = 0x200000; // parenthesis count (expression) | used (import reference) public final static int Bit23 = 0x400000; // parenthesis count (expression) public final static int Bit24 = 0x800000; // parenthesis count (expression) public final static int Bit25 = 0x1000000; // parenthesis count (expression) public final static int Bit26 = 0x2000000; // parenthesis count (expression) public final static int Bit27 = 0x4000000; // parenthesis count (expression) public final static int Bit28 = 0x8000000; // parenthesis count (expression) public final static int Bit29 = 0x10000000; // parenthesis count (expression) public final static int Bit30 = 0x20000000; // elseif (if statement) | try block exit (try statement) | fall-through (case statement) | ignore no effect assign (expression ref) | needScope (for statement) | isAnySubRoutineEscaping (return statement) | blockExit (synchronized statement) public final static int Bit31 = 0x40000000; // local declaration reachable (local decl) | ignore raw type check (type ref) | discard entire assignment (assignment) | isSynchronized (return statement) | thenExit (if statement) public final static int Bit32 = 0x80000000; // reachable (statement) public final static long Bit32L = 0x80000000L; public final static long Bit33L = 0x100000000L; public final static long Bit34L = 0x200000000L; public final static long Bit35L = 0x400000000L; public final static long Bit36L = 0x800000000L; public final static long Bit37L = 0x1000000000L; 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 final static long Bit57L = 0x100000000000000L; public final static long Bit58L = 0x200000000000000L; public final static long Bit59L = 0x400000000000000L; public final static long Bit60L = 0x800000000000000L; public final static long Bit61L = 0x1000000000000000L; public final static long Bit62L = 0x2000000000000000L; public final static long Bit63L = 0x4000000000000000L; public final static long Bit64L = 0x8000000000000000L; public int bits = IsReachable; // reachable by default // for operators public static final int ReturnTypeIDMASK = Bit1|Bit2|Bit3|Bit4; public static final int OperatorSHIFT = 6; // Bit7 -> Bit12 public static final int OperatorMASK = Bit7|Bit8|Bit9|Bit10|Bit11|Bit12; // 6 bits for operator ID // for binary expressions public static final int IsReturnedValue = Bit5; // for cast expressions public static final int UnnecessaryCast = Bit15; public static final int DisableUnnecessaryCastCheck = Bit6; public static final int GenerateCheckcast = Bit7; public static final int UnsafeCast = Bit8; // for name references public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3; // for local decls public static final int IsArgument = Bit3; public static final int IsForeachElementVariable = Bit5; // for name refs or local decls public static final int FirstAssignmentToLocal = Bit4; // for msg or field references public static final int NeedReceiverGenericCast = Bit19; // for this reference public static final int IsImplicitThis = Bit3; // for single name references public static final int DepthSHIFT = 5; // Bit6 -> Bit13 public static final int DepthMASK = Bit6|Bit7|Bit8|Bit9|Bit10|Bit11|Bit12|Bit13; // 8 bits for actual depth value (max. 255) // for statements public static final int IsReachable = Bit32; public static final int LabelUsed = Bit7; public static final int DocumentedFallthrough = Bit30; // switch statement public static final int DocumentedCasesOmitted = Bit31; // switch statement // local decls public static final int IsLocalDeclarationReachable = Bit31; // try statements public static final int IsSubRoutineEscaping = Bit15; public static final int IsTryBlockExiting = Bit30; // for type declaration public static final int ContainsAssertion = Bit1; public static final int IsLocalType = Bit9; public static final int IsAnonymousType = Bit10; // used to test for anonymous public static final int IsMemberType = 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 public static final int IsSecondaryType = Bit13; // used to test for secondary public static final int HasBeenGenerated = Bit14; // for type, method and field declarations public static final int HasLocalType = Bit2; // cannot conflict with AddAssertionMASK public static final int HasBeenResolved = Bit5; // field decl only (to handle forward references) // for expression public static final int ParenthesizedSHIFT = 21; // Bit22 -> Bit29 public static final int ParenthesizedMASK = Bit22|Bit23|Bit24|Bit25|Bit26|Bit27|Bit28|Bit29; // 8 bits for parenthesis count value (max. 255) public static final int IgnoreNoEffectAssignCheck = Bit30; // for references on lhs of assignment public static final int IsStrictlyAssigned = Bit14; // set only for true assignments, as opposed to compound ones public static final int IsCompoundAssigned = Bit17; // set only for compound assignments, as opposed to other ones // for explicit constructor call public static final int DiscardEnclosingInstance = Bit14; // used for codegen // for all method/constructor invocations (msg, alloc, expl. constr call) public static final int Unchecked = Bit17; // for javadoc - used to indicate whether the javadoc has to be resolved public static final int ResolveJavadoc = Bit17; // for empty statement public static final int IsUsefulEmptyStatement = Bit1; // for block and method declaration public static final int UndocumentedEmptyBlock = Bit4; public static final int OverridingMethodWithSupercall = Bit5; public static final int CanBeStatic = Bit9; // used to flag a method that can be declared static // for initializer and method declaration public static final int ErrorInSignature = Bit6; // for abstract method declaration public static final int NeedFreeReturn = Bit7; // abstract method declaration // for constructor declaration public static final int IsDefaultConstructor = Bit8; // for compilation unit public static final int HasAllMethodBodies = Bit5; public static final int IsImplicitUnit = Bit1; // for references in Javadoc comments public static final int InsideJavadoc = Bit16; // for javadoc allocation expression/javadoc message send/javadoc return statement public static final int SuperAccess = Bit15; // for javadoc return statement public static final int Empty = Bit19; // for if statement public static final int IsElseIfStatement = Bit30; public static final int ThenExit = Bit31; public static final int IsElseStatementUnreachable = Bit8; public static final int IsThenStatementUnreachable = Bit9; // for type reference public static final int IsSuperType = Bit5; public static final int IsVarArgs = Bit15; public static final int IgnoreRawTypeCheck = Bit31; // for array initializer public static final int IsAnnotationDefaultValue = Bit1; // for null reference analysis public static final int IsNonNull = Bit18; // for for statement public static final int NeededScope = Bit30; // for import reference public static final int OnDemand = Bit18; public static final int Used = Bit2; // for parameterized qualified/single type ref public static final int DidResolve = Bit19; // for return statement public static final int IsAnySubRoutineEscaping = Bit30; public static final int IsSynchronized = Bit31; // for synchronized statement public static final int BlockExit = Bit30; // for annotation reference public static final int IsRecovered = Bit6; // for type declaration, initializer and method declaration public static final int HasSyntaxErrors = Bit20; // constants used when checking invocation arguments public static final int INVOCATION_ARGUMENT_OK = 0; public static final int INVOCATION_ARGUMENT_UNCHECKED = 1; public static final int INVOCATION_ARGUMENT_WILDCARD = 2; // for type reference (diamond case) - Java 7 public static final int IsUnionType = Bit30; // Used to tag ParameterizedSingleTypeReference or ParameterizedQualifiedTypeReference when they are // used without any type args. It is also used to tag CompletionOnQualifiedExpression when the // generics inference has failed and the resolved type still has <>. public static final int IsDiamond = Bit20; // this is only used for method invocation as the expression inside an expression statement public static final int InsideExpressionStatement = Bit5; // for annotation reference, signal if annotation was created from a default: public static final int IsSynthetic = ASTNode.Bit7; public ASTNode() { super(); } private static int checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType, TypeBinding originalParameterType) { argument.computeConversion(scope, parameterType, argumentType); if (argumentType != TypeBinding.NULL && parameterType.kind() == Binding.WILDCARD_TYPE) { // intersection types are tolerated WildcardBinding wildcard = (WildcardBinding) parameterType; if (wildcard.boundKind != Wildcard.SUPER) { return INVOCATION_ARGUMENT_WILDCARD; } } TypeBinding checkedParameterType = parameterType; // originalParameterType == null ? parameterType : originalParameterType; if (argumentType != checkedParameterType && argumentType.needsUncheckedConversion(checkedParameterType)) { scope.problemReporter().unsafeTypeConversion(argument, argumentType, checkedParameterType); return INVOCATION_ARGUMENT_UNCHECKED; } return INVOCATION_ARGUMENT_OK; } public static boolean checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) { boolean is1_7 = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7; if (is1_7 && method.isPolymorphic()) { return false; } TypeBinding[] params = method.parameters; int paramLength = params.length; boolean isRawMemberInvocation = !method.isStatic() && !receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters(); boolean uncheckedBoundCheck = (method.tagBits & TagBits.HasUncheckedTypeArgumentForBoundCheck) != 0; MethodBinding rawOriginalGenericMethod = null; if (!isRawMemberInvocation) { if (method instanceof ParameterizedGenericMethodBinding) { ParameterizedGenericMethodBinding paramMethod = (ParameterizedGenericMethodBinding) method; if (paramMethod.isRaw && method.hasSubstitutedParameters()) { rawOriginalGenericMethod = method.original(); } } } int invocationStatus = INVOCATION_ARGUMENT_OK; if (arguments == null) { if (method.isVarargs()) { TypeBinding parameterType = ((ArrayBinding) params[paramLength-1]).elementsType(); // no element was supplied for vararg parameter if (!parameterType.isReifiable() && (!is1_7 || ((method.tagBits & TagBits.AnnotationSafeVarargs) == 0))) { scope.problemReporter().unsafeGenericArrayForVarargs(parameterType, (ASTNode)invocationSite); } } } else { 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 = paramLength - 1; for (int i = 0; i < lastIndex; i++) { TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i]; invocationStatus |= checkInvocationArgument(scope, arguments[i], params[i] , argumentTypes[i], originalRawParam); } int argLength = arguments.length; if (lastIndex <= argLength) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=337093 TypeBinding parameterType = params[lastIndex]; TypeBinding originalRawParam = null; if (paramLength != argLength || parameterType.dimensions() != argumentTypes[lastIndex].dimensions()) { parameterType = ((ArrayBinding) parameterType).elementsType(); // single element was provided for vararg parameter if (!parameterType.isReifiable() && (!is1_7 || ((method.tagBits & TagBits.AnnotationSafeVarargs) == 0))) { scope.problemReporter().unsafeGenericArrayForVarargs(parameterType, (ASTNode)invocationSite); } originalRawParam = rawOriginalGenericMethod == null ? null : ((ArrayBinding)rawOriginalGenericMethod.parameters[lastIndex]).elementsType(); } for (int i = lastIndex; i < argLength; i++) { invocationStatus |= checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i], originalRawParam); } } if (paramLength == argLength) { // 70056 int varargsIndex = paramLength - 1; ArrayBinding varargsType = (ArrayBinding) params[varargsIndex]; TypeBinding lastArgType = argumentTypes[varargsIndex]; int dimensions; if (lastArgType == TypeBinding.NULL) { if (!(varargsType.leafComponentType().isBaseType() && varargsType.dimensions() == 1)) scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite); } else if (varargsType.dimensions <= (dimensions = lastArgType.dimensions())) { if (lastArgType.leafComponentType().isBaseType()) { dimensions--; } if (varargsType.dimensions < dimensions) { scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite); } else if (varargsType.dimensions == dimensions && lastArgType != varargsType && lastArgType.leafComponentType().erasure() != varargsType.leafComponentType.erasure() && lastArgType.isCompatibleWith(varargsType.elementsType()) && lastArgType.isCompatibleWith(varargsType)) { scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite); } } } } else { for (int i = 0; i < paramLength; i++) { TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i]; invocationStatus |= checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i], originalRawParam); } } if (argsContainCast) { CastExpression.checkNeedForArgumentCasts(scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite); } } if ((invocationStatus & INVOCATION_ARGUMENT_WILDCARD) != 0) { scope.problemReporter().wildcardInvocation((ASTNode)invocationSite, receiverType, method, argumentTypes); } else if (!method.isStatic() && !receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) { if (scope.compilerOptions().reportUnavoidableGenericTypeProblems || receiver == null || !receiver.forcedToBeRaw(scope.referenceContext())) { scope.problemReporter().unsafeRawInvocation((ASTNode)invocationSite, method); } } else if (rawOriginalGenericMethod != null || uncheckedBoundCheck || ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0 && method instanceof ParameterizedGenericMethodBinding /*&& method.returnType != scope.environment().convertToRawType(method.returnType.erasure(), true)*/)) { scope.problemReporter().unsafeRawGenericMethodInvocation((ASTNode)invocationSite, method, argumentTypes); return true; } return false; } public ASTNode concreteStatement() { return this; } public final boolean isFieldUseDeprecated(FieldBinding field, Scope scope, int filteredBits) { if ((this.bits & ASTNode.InsideJavadoc) == 0 // ignore references inside Javadoc comments && (filteredBits & IsStrictlyAssigned) == 0 // ignore write access && field.isOrEnclosedByPrivateType() && !scope.isDefinedInField(field)) // ignore cases where field is used from inside itself { if (((filteredBits & IsCompoundAssigned) != 0)) // used, but usage may not be relevant field.original().compoundUseFlag++; else field.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } if ((field.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0) { AccessRestriction restriction = scope.environment().getAccessRestriction(field.declaringClass.erasure()); if (restriction != null) { scope.problemReporter().forbiddenReference(field, this, restriction.classpathEntryType, restriction.classpathEntryName, restriction.getProblemId()); } } if (!field.isViewedAsDeprecated()) return false; // inside same unit - no report if (scope.isDefinedInSameUnit(field.declaringClass)) return false; // if context is deprecated, may avoid reporting if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false; return true; } public boolean isImplicitThis() { return false; } /* Answer true if the method use is considered deprecated. * An access in the same compilation unit is allowed. */ public final boolean isMethodUseDeprecated(MethodBinding method, Scope scope, boolean isExplicitUse) { // ignore references insing Javadoc comments if ((this.bits & ASTNode.InsideJavadoc) == 0 && method.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(method)) { // ignore cases where method is used from inside itself (e.g. direct recursions) method.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } // TODO (maxime) consider separating concerns between deprecation and access restriction. // Caveat: this was not the case when access restriction funtion was added. if (isExplicitUse && (method.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0) { // note: explicit constructors calls warnings are kept despite the 'new C1()' case (two // warnings, one on type, the other on constructor), because of the 'super()' case. AccessRestriction restriction = scope.environment().getAccessRestriction(method.declaringClass.erasure()); if (restriction != null) { scope.problemReporter().forbiddenReference(method, this, restriction.classpathEntryType, restriction.classpathEntryName, restriction.getProblemId()); } } if (!method.isViewedAsDeprecated()) return false; // inside same unit - no report if (scope.isDefinedInSameUnit(method.declaringClass)) return false; // non explicit use and non explicitly deprecated - no report if (!isExplicitUse && (method.modifiers & ClassFileConstants.AccDeprecated) == 0) { return false; } // if context is deprecated, may avoid reporting if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false; return true; } public boolean isSuper() { return false; } public boolean isThis() { return false; } /* Answer true if the type use is considered deprecated. * An access in the same compilation unit is allowed. */ public final boolean isTypeUseDeprecated(TypeBinding type, Scope scope) { if (type.isArrayType()) { type = ((ArrayBinding) type).leafComponentType; } if (type.isBaseType()) return false; ReferenceBinding refType = (ReferenceBinding) type; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=397888 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=385780 if ((this.bits & ASTNode.InsideJavadoc) == 0 && refType instanceof TypeVariableBinding) { refType.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } // ignore references insing Javadoc comments if ((this.bits & ASTNode.InsideJavadoc) == 0 && refType.isOrEnclosedByPrivateType() && !scope.isDefinedInType(refType)) { // ignore cases where type is used from inside itself ((ReferenceBinding)refType.erasure()).modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } if (refType.hasRestrictedAccess()) { AccessRestriction restriction = scope.environment().getAccessRestriction(type.erasure()); if (restriction != null) { scope.problemReporter().forbiddenReference(type, this, restriction.classpathEntryType, restriction.classpathEntryName, restriction.getProblemId()); } } // force annotations resolution before deciding whether the type may be deprecated refType.initializeDeprecatedAnnotationTagBits(); if (!refType.isViewedAsDeprecated()) return false; // inside same unit - no report if (scope.isDefinedInSameUnit(refType)) return false; // if context is deprecated, may avoid reporting if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false; return true; } 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$ return output; } public static StringBuffer printModifiers(int modifiers, StringBuffer output) { if ((modifiers & ClassFileConstants.AccPublic) != 0) output.append("public "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccPrivate) != 0) output.append("private "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccProtected) != 0) output.append("protected "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccStatic) != 0) output.append("static "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccFinal) != 0) output.append("final "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccSynchronized) != 0) output.append("synchronized "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccVolatile) != 0) output.append("volatile "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccTransient) != 0) output.append("transient "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccNative) != 0) output.append("native "); //$NON-NLS-1$ if ((modifiers & ClassFileConstants.AccAbstract) != 0) output.append("abstract "); //$NON-NLS-1$ return output; } /** * Resolve annotations, and check duplicates, answers combined tagBits * for recognized standard annotations */ public static void resolveAnnotations(BlockScope scope, Annotation[] sourceAnnotations, Binding recipient) { AnnotationBinding[] annotations = null; int length = sourceAnnotations == null ? 0 : sourceAnnotations.length; if (recipient != null) { switch (recipient.kind()) { case Binding.PACKAGE : PackageBinding packageBinding = (PackageBinding) recipient; if ((packageBinding.tagBits & TagBits.AnnotationResolved) != 0) return; packageBinding.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); break; case Binding.TYPE : case Binding.GENERIC_TYPE : ReferenceBinding type = (ReferenceBinding) recipient; if ((type.tagBits & TagBits.AnnotationResolved) != 0) return; type.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; type.setAnnotations(annotations); } break; case Binding.METHOD : MethodBinding method = (MethodBinding) recipient; if ((method.tagBits & TagBits.AnnotationResolved) != 0) return; method.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; method.setAnnotations(annotations); } break; case Binding.FIELD : FieldBinding field = (FieldBinding) recipient; if ((field.tagBits & TagBits.AnnotationResolved) != 0) return; field.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; field.setAnnotations(annotations); } break; case Binding.LOCAL : LocalVariableBinding local = (LocalVariableBinding) recipient; if ((local.tagBits & TagBits.AnnotationResolved) != 0) return; local.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; local.setAnnotations(annotations, scope); } break; default : return; } } if (sourceAnnotations == null) return; for (int i = 0; i < length; i++) { Annotation annotation = sourceAnnotations[i]; final Binding annotationRecipient = annotation.recipient; if (annotationRecipient != null && recipient != null) { // only local and field can share annnotations switch (recipient.kind()) { case Binding.FIELD : FieldBinding field = (FieldBinding) recipient; field.tagBits = ((FieldBinding) annotationRecipient).tagBits; if (annotations != null) { // need to fill the instances array for (int j = 0; j < length; j++) { Annotation annot = sourceAnnotations[j]; annotations[j] = annot.getCompilerAnnotation(); } } break; case Binding.LOCAL : LocalVariableBinding local = (LocalVariableBinding) recipient; long otherLocalTagBits = ((LocalVariableBinding) annotationRecipient).tagBits; local.tagBits = otherLocalTagBits; if ((otherLocalTagBits & TagBits.AnnotationSuppressWarnings) == 0) { // None of the annotations is a SuppressWarnings annotation // need to fill the instances array if (annotations != null) { for (int j = 0; j < length; j++) { Annotation annot = sourceAnnotations[j]; annotations[j] = annot.getCompilerAnnotation(); } } } else if (annotations != null) { // One of the annotations at least is a SuppressWarnings annotation LocalDeclaration localDeclaration = local.declaration; int declarationSourceEnd = localDeclaration.declarationSourceEnd; int declarationSourceStart = localDeclaration.declarationSourceStart; for (int j = 0; j < length; j++) { Annotation annot = sourceAnnotations[j]; /* * Annotations are shared between two locals, but we still need to record * the suppress annotation range for the second local */ AnnotationBinding annotationBinding = annot.getCompilerAnnotation(); annotations[j] = annotationBinding; if (annotationBinding != null) { final ReferenceBinding annotationType = annotationBinding.getAnnotationType(); if (annotationType != null && annotationType.id == TypeIds.T_JavaLangSuppressWarnings) { annot.recordSuppressWarnings(scope, declarationSourceStart, declarationSourceEnd, scope.compilerOptions().suppressWarnings); } } } } break; } return; } else { annotation.recipient = recipient; annotation.resolveType(scope); // null if receiver is a package binding if (annotations != null) { annotations[i] = annotation.getCompilerAnnotation(); } } } // check duplicate annotations if (annotations != null) { AnnotationBinding[] distinctAnnotations = annotations; // only copy after 1st duplicate is detected for (int i = 0; i < length; i++) { AnnotationBinding annotation = distinctAnnotations[i]; if (annotation == null) continue; TypeBinding annotationType = annotation.getAnnotationType(); boolean foundDuplicate = false; for (int j = i+1; j < length; j++) { AnnotationBinding otherAnnotation = distinctAnnotations[j]; if (otherAnnotation == null) continue; if (otherAnnotation.getAnnotationType() == annotationType) { foundDuplicate = true; if (distinctAnnotations == annotations) { System.arraycopy(distinctAnnotations, 0, distinctAnnotations = new AnnotationBinding[length], 0, length); } distinctAnnotations[j] = null; // report it only once scope.problemReporter().duplicateAnnotation(sourceAnnotations[j]); } } if (foundDuplicate) { scope.problemReporter().duplicateAnnotation(sourceAnnotations[i]); } } } } /** * Figures if @Deprecated annotation is specified, do not resolve entire annotations. */ public static void resolveDeprecatedAnnotations(BlockScope scope, Annotation[] annotations, Binding recipient) { if (recipient != null) { int kind = recipient.kind(); if (annotations != null) { int length; if ((length = annotations.length) >= 0) { switch (kind) { case Binding.PACKAGE : PackageBinding packageBinding = (PackageBinding) recipient; if ((packageBinding.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return; break; case Binding.TYPE : case Binding.GENERIC_TYPE : ReferenceBinding type = (ReferenceBinding) recipient; if ((type.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return; break; case Binding.METHOD : MethodBinding method = (MethodBinding) recipient; if ((method.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return; break; case Binding.FIELD : FieldBinding field = (FieldBinding) recipient; if ((field.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return; break; case Binding.LOCAL : LocalVariableBinding local = (LocalVariableBinding) recipient; if ((local.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return; break; default : return; } for (int i = 0; i < length; i++) { TypeReference annotationTypeRef = annotations[i].type; // only resolve type name if 'Deprecated' last token if (!CharOperation.equals(TypeConstants.JAVA_LANG_DEPRECATED[2], annotationTypeRef.getLastToken())) continue; TypeBinding annotationType = annotations[i].type.resolveType(scope); if(annotationType != null && annotationType.isValidBinding() && annotationType.id == TypeIds.T_JavaLangDeprecated) { switch (kind) { case Binding.PACKAGE : PackageBinding packageBinding = (PackageBinding) recipient; packageBinding.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); return; case Binding.TYPE : case Binding.GENERIC_TYPE : case Binding.TYPE_PARAMETER : ReferenceBinding type = (ReferenceBinding) recipient; type.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); return; case Binding.METHOD : MethodBinding method = (MethodBinding) recipient; method.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); return; case Binding.FIELD : FieldBinding field = (FieldBinding) recipient; field.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); return; case Binding.LOCAL : LocalVariableBinding local = (LocalVariableBinding) recipient; local.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); return; default: return; } } } } } switch (kind) { case Binding.PACKAGE : PackageBinding packageBinding = (PackageBinding) recipient; packageBinding.tagBits |= TagBits.DeprecatedAnnotationResolved; return; case Binding.TYPE : case Binding.GENERIC_TYPE : case Binding.TYPE_PARAMETER : ReferenceBinding type = (ReferenceBinding) recipient; type.tagBits |= TagBits.DeprecatedAnnotationResolved; return; case Binding.METHOD : MethodBinding method = (MethodBinding) recipient; method.tagBits |= TagBits.DeprecatedAnnotationResolved; return; case Binding.FIELD : FieldBinding field = (FieldBinding) recipient; field.tagBits |= TagBits.DeprecatedAnnotationResolved; return; case Binding.LOCAL : LocalVariableBinding local = (LocalVariableBinding) recipient; local.tagBits |= TagBits.DeprecatedAnnotationResolved; return; default: return; } } } public int sourceStart() { return this.sourceStart; } public int sourceEnd() { return this.sourceEnd; } public String toString() { return print(0, new StringBuffer(30)).toString(); } public void traverse(ASTVisitor visitor, BlockScope scope) { // do nothing by default } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java0000644000175000001440000001311512212041344030131 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.impl.LongConstant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; public class LongLiteral extends NumberLiteral { private static final char[] HEXA_MIN_VALUE = "0x8000000000000000L".toCharArray(); //$NON-NLS-1$ private static final char[] HEXA_MINUS_ONE_VALUE = "0xffffffffffffffffL".toCharArray(); //$NON-NLS-1$ private static final char[] OCTAL_MIN_VALUE = "01000000000000000000000L".toCharArray(); //$NON-NLS-1$ private static final char[] OCTAL_MINUS_ONE_VALUE = "01777777777777777777777L".toCharArray(); //$NON-NLS-1$ private static final char[] DECIMAL_MIN_VALUE = "9223372036854775808L".toCharArray(); //$NON-NLS-1$ private static final char[] DECIMAL_MAX_VALUE = "9223372036854775807L".toCharArray(); //$NON-NLS-1$ private char[] reducedForm; // no underscores public static LongLiteral buildLongLiteral(char[] token, int s, int e) { // remove '_' and prefix '0' first char[] longReducedToken = removePrefixZerosAndUnderscores(token, true); switch(longReducedToken.length) { case 19 : // 0x8000000000000000L if (CharOperation.equals(longReducedToken, HEXA_MIN_VALUE)) { return new LongLiteralMinValue(token, longReducedToken != token ? longReducedToken : null, s, e); } break; case 24 : // 01000000000000000000000L if (CharOperation.equals(longReducedToken, OCTAL_MIN_VALUE)) { return new LongLiteralMinValue(token, longReducedToken != token ? longReducedToken : null, s, e); } break; } return new LongLiteral(token, longReducedToken != token ? longReducedToken : null, s, e); } LongLiteral(char[] token, char[] reducedForm, int start, int end) { super(token, start, end); this.reducedForm = reducedForm; } public LongLiteral convertToMinValue() { if (((this.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) { return this; } char[] token = this.reducedForm != null ? this.reducedForm : this.source; switch(token.length) { case 20 : // 9223372036854775808L if (CharOperation.equals(token, DECIMAL_MIN_VALUE, false)) { return new LongLiteralMinValue(this.source, this.reducedForm, this.sourceStart, this.sourceEnd); } break; } return this; } public void computeConstant() { char[] token = this.reducedForm != null ? this.reducedForm : this.source; int tokenLength = token.length; int length = tokenLength - 1; int radix = 10; int j = 0; if (token[0] == '0') { if (length == 1) { this.constant = LongConstant.fromValue(0L); return; } if ((token[1] == 'x') || (token[1] == 'X')) { radix = 16; j = 2; } else if ((token[1] == 'b') || (token[1] == 'B')) { radix = 2; j = 2; } else { radix = 8; j = 1; } } switch(radix) { case 2 : if ((length - 2) > 64) { // remove 0b or 0B return; /*constant stays null*/ } computeValue(token, length, radix, j); break; case 16 : if (tokenLength <= 19) { if (CharOperation.equals(token, HEXA_MINUS_ONE_VALUE)) { this.constant = LongConstant.fromValue(-1L); return; } computeValue(token, length, radix, j); } break; case 10 : if (tokenLength > DECIMAL_MAX_VALUE.length || (tokenLength == DECIMAL_MAX_VALUE.length && CharOperation.compareTo(token, DECIMAL_MAX_VALUE, 0, length) > 0)) { return; /*constant stays null*/ } computeValue(token, length, radix, j); break; case 8 : if (tokenLength <= 24) { if (tokenLength == 24 && token[j] > '1') { return; /*constant stays null*/ } if (CharOperation.equals(token, OCTAL_MINUS_ONE_VALUE)) { this.constant = LongConstant.fromValue(-1L); return; } computeValue(token, length, radix, j); } break; } } private void computeValue(char[] token, int tokenLength, int radix, int j) { int digitValue; long computedValue = 0; while (j < tokenLength) { if ((digitValue = ScannerHelper.digit(token[j++],radix)) < 0) { return; /*constant stays null*/ } computedValue = (computedValue * radix) + digitValue ; } this.constant = LongConstant.fromValue(computedValue); } /** * Code generation for long 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(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.LONG; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java0000644000175000001440000005726012212041344032073 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 358903 - Filter practically unimportant resource leak warnings * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking * Jesper S Moller - Contributions for * bug 378674 - "The method can be declared as static" is wrong * Till Brychcy - Contributions for * bug 413460 - NonNullByDefault is not inherited to Constructors when accessed via Class File *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.core.compiler.IProblem; 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.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class AllocationExpression extends Expression implements InvocationSite { public TypeReference type; public Expression[] arguments; public MethodBinding binding; // exact binding resulting from lookup MethodBinding syntheticAccessor; // synthetic accessor for inner-emulation public TypeReference[] typeArguments; public TypeBinding[] genericTypeArguments; public FieldDeclaration enumConstant; // for enum constant initializations protected TypeBinding typeExpected; // for <> inference public boolean inferredReturnType; public FakedTrackingVariable closeTracker; // when allocation a Closeable store a pre-liminary tracking variable here public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // check captured variables are initialized in current context (26134) checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo); // process arguments if (this.arguments != null) { boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks; boolean hasResourceWrapperType = analyseResources && this.resolvedType instanceof ReferenceBinding && ((ReferenceBinding)this.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable); for (int i = 0, count = this.arguments.length; i < count; i++) { flowInfo = this.arguments[i] .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) if (analyseResources && !hasResourceWrapperType) { // allocation of wrapped closeables is analyzed specially flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, flowContext, false); } this.arguments[i].checkNPEbyUnboxing(currentScope, flowContext, flowInfo); } analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments); } // record some dependency information for exception types ReferenceBinding[] thrownExceptions; if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) { if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6 thrownExceptions = currentScope.environment().convertToRawTypes(this.binding.thrownExceptions, true, true); } // check exception handling flowContext.checkExceptionHandlers( thrownExceptions, this, flowInfo.unconditionalCopy(), currentScope); } // after having analysed exceptions above start tracking newly allocated resource: if (currentScope.compilerOptions().analyseResourceLeaks && FakedTrackingVariable.isAnyCloseable(this.resolvedType)) FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this); if (this.binding.declaringClass.isMemberType() && !this.binding.declaringClass.isStatic()) { // allocating a non-static member type without an enclosing instance of parent type // https://bugs.eclipse.org/bugs/show_bug.cgi?id=335845 currentScope.resetDeclaringClassMethodStaticFlag(this.binding.declaringClass.enclosingType()); // Reviewed for https://bugs.eclipse.org/bugs/show_bug.cgi?id=378674 : // The corresponding problem (when called from static) is not produced until during code generation } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); manageSyntheticAccessIfNecessary(currentScope, flowInfo); // account for possible exceptions thrown by the constructor flowContext.recordAbruptExit(); // TODO whitelist of ctors that cannot throw any exc.?? return flowInfo; } public void checkCapturedLocalInitializationIfNecessary(ReferenceBinding checkedType, BlockScope currentScope, FlowInfo flowInfo) { if (((checkedType.tagBits & ( TagBits.AnonymousTypeMask|TagBits.LocalTypeMask)) == TagBits.LocalTypeMask) && !currentScope.isDefinedInType(checkedType)) { // only check external allocations NestedTypeBinding nestedType = (NestedTypeBinding) checkedType; SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables(); if (syntheticArguments != null) for (int i = 0, count = syntheticArguments.length; i < count; i++){ SyntheticArgumentBinding syntheticArgument = syntheticArguments[i]; LocalVariableBinding targetLocal; if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null) continue; if (targetLocal.declaration != null && !flowInfo.isDefinitelyAssigned(targetLocal)){ currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this); } } } } public Expression enclosingInstance() { return null; } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { if (!valueRequired) currentScope.problemReporter().unusedObjectAllocation(this); int pc = codeStream.position; MethodBinding codegenBinding = this.binding.original(); ReferenceBinding allocatedType = codegenBinding.declaringClass; codeStream.new_(allocatedType); boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; if (valueRequired || isUnboxing) { codeStream.dup(); } // better highlight for allocation: display the type individually 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(this.enumConstant.name)); codeStream.generateInlinedValue(this.enumConstant.binding.id); } // handling innerclass instance allocation - enclosing instance arguments if (allocatedType.isNestedType()) { codeStream.generateSyntheticEnclosingInstanceValues( currentScope, allocatedType, enclosingInstance(), this); } // generate the arguments for constructor generateArguments(this.binding, this.arguments, currentScope, codeStream); // handling innerclass instance allocation - outer local arguments if (allocatedType.isNestedType()) { codeStream.generateSyntheticOuterArgumentValues( currentScope, allocatedType, this); } // invoke constructor if (this.syntheticAccessor == null) { codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, null /* default declaringClass */); } else { // synthetic accessor got some extra arguments appended to its signature, which need values for (int i = 0, max = this.syntheticAccessor.parameters.length - codegenBinding.parameters.length; i < max; i++) { codeStream.aconst_null(); } codeStream.invoke(Opcodes.OPC_invokespecial, this.syntheticAccessor, null /* default declaringClass */); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else if (isUnboxing) { // conversion only generated if unboxing codeStream.generateImplicitConversion(this.implicitConversion); switch (postConversionType(currentScope).id) { case T_long : case T_double : codeStream.pop2(); break; default : codeStream.pop(); } } 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; } public boolean isTypeAccess() { return true; } /* Inner emulation consists in either recording a dependency * link only, or performing one level of propagation. * * Dependency mechanism is used whenever dealing with source target * types, since by the time we reach them, we might not yet know their * exact need. */ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return; ReferenceBinding allocatedTypeErasure = (ReferenceBinding) this.binding.declaringClass.erasure(); // perform some emulation work in case there is some and we are inside a local type only if (allocatedTypeErasure.isNestedType() && currentScope.enclosingSourceType().isLocalType()) { 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(allocatedTypeErasure, false); // request cascade of accesses } } } public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return; // if constructor from parameterized type got found, use the original constructor at codegen time MethodBinding codegenBinding = this.binding.original(); ReferenceBinding declaringClass; if (codegenBinding.isPrivate() && currentScope.enclosingSourceType() != (declaringClass = codegenBinding.declaringClass)) { // from 1.4 on, local type constructor can lose their private flag to ease emulation if ((declaringClass.tagBits & TagBits.IsLocalType) != 0 && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { // constructor will not be dumped as private, no emulation required thus codegenBinding.tagBits |= TagBits.ClearPrivateModifier; } else { this.syntheticAccessor = ((SourceTypeBinding) declaringClass).addSyntheticMethod(codegenBinding, isSuperAccess()); currentScope.problemReporter().needToEmulateMethodAccess(codegenBinding, this); } } } public StringBuffer printExpression(int indent, StringBuffer output) { if (this.type != null) { // type null for enum constant initializations output.append("new "); //$NON-NLS-1$ } if (this.typeArguments != null) { output.append('<'); int max = this.typeArguments.length - 1; for (int j = 0; j < max; j++) { this.typeArguments[j].print(0, output); output.append(", ");//$NON-NLS-1$ } this.typeArguments[max].print(0, output); output.append('>'); } if (this.type != null) { // type null for enum constant initializations this.type.printExpression(0, output); } output.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].printExpression(0, output); } } return output.append(')'); } public TypeBinding resolveType(BlockScope scope) { // Propagate the type checking to the arguments, and check if the constructor is defined. this.constant = Constant.NotAConstant; if (this.type == null) { // initialization of an enum constant this.resolvedType = scope.enclosingReceiverType(); } else { this.resolvedType = this.type.resolveType(scope, true /* check bounds*/); checkParameterizedAllocation: { if (this.type instanceof ParameterizedQualifiedTypeReference) { // disallow new X.Y() ReferenceBinding currentType = (ReferenceBinding)this.resolvedType; if (currentType == null) return currentType; do { // isStatic() is answering true for toplevel types if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0) break checkParameterizedAllocation; if (currentType.isRawType()) break checkParameterizedAllocation; } while ((currentType = currentType.enclosingType())!= null); ParameterizedQualifiedTypeReference qRef = (ParameterizedQualifiedTypeReference) this.type; for (int i = qRef.typeArguments.length - 2; i >= 0; i--) { if (qRef.typeArguments[i] != null) { scope.problemReporter().illegalQualifiedParameterizedTypeAllocation(this.type, this.resolvedType); break; } } } } } // will check for null after args are resolved final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0; // resolve type arguments (for generic constructor call) if (this.typeArguments != null) { int length = this.typeArguments.length; boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5; this.genericTypeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeReference typeReference = this.typeArguments[i]; if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) { argHasError = true; } if (argHasError && typeReference instanceof Wildcard) { scope.problemReporter().illegalUsageOfWildcard(typeReference); } } if (isDiamond) { scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments); return null; } if (argHasError) { if (this.arguments != null) { // still attempt to resolve arguments for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return null; } } // buffering the arguments' types boolean argsContainCast = false; TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; if (this.arguments != null) { boolean argHasError = false; int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++) { Expression argument = this.arguments[i]; if (argument instanceof CastExpression) { argument.bits |= DisableUnnecessaryCastCheck; // will check later on argsContainCast = true; } if ((argumentTypes[i] = argument.resolveType(scope)) == null) { argHasError = true; } } if (argHasError) { /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case. No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do not return the partially resolved type. */ if (isDiamond) { return null; // not the partially cooked this.resolvedType } if (this.resolvedType instanceof ReferenceBinding) { // record a best guess, for clients who need hint about possible constructor match TypeBinding[] pseudoArgs = new TypeBinding[length]; for (int i = length; --i >= 0;) { pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type } this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this); if (this.binding != null && !this.binding.isValidBinding()) { MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; // record the closest match, for clients who may still need hint about possible method match if (closestMatch != null) { if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method // shouldn't return generic method outside its context, rather convert it to raw method (175409) closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null); } this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } } return this.resolvedType; } } if (this.resolvedType == null || !this.resolvedType.isValidBinding()) { return null; } // null type denotes fake allocation for enum constant inits if (this.type != null && !this.resolvedType.canBeInstantiated()) { scope.problemReporter().cannotInstantiate(this.type, this.resolvedType); return this.resolvedType; } if (isDiamond) { TypeBinding [] inferredTypes = inferElidedTypes(((ParameterizedTypeBinding) this.resolvedType).genericType(), null, argumentTypes, scope); if (inferredTypes == null) { scope.problemReporter().cannotInferElidedTypes(this); return this.resolvedType = null; } this.resolvedType = this.type.resolvedType = scope.environment().createParameterizedType(((ParameterizedTypeBinding) this.resolvedType).genericType(), inferredTypes, ((ParameterizedTypeBinding) this.resolvedType).enclosingType()); } ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType; if (!(this.binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) { if (this.binding.declaringClass == null) { this.binding.declaringClass = allocationType; } if (this.type != null && !this.type.resolvedType.isValidBinding()) { return null; } scope.problemReporter().invalidConstructor(this, this.binding); return this.resolvedType; } if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInConstructor(this, this.binding); } if (isMethodUseDeprecated(this.binding, scope, true)) scope.problemReporter().deprecatedMethod(this.binding, this); if (checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments); } if (!isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) { checkTypeArgumentRedundancy((ParameterizedTypeBinding) this.resolvedType, null, argumentTypes, scope); } final CompilerOptions compilerOptions = scope.compilerOptions(); if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) { new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations) .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope); } return allocationType; } public TypeBinding[] inferElidedTypes(ReferenceBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) { /* Given the allocation type and the arguments to the constructor, see if we can synthesize a generic static factory method that would, given the argument types and the invocation site, manufacture a parameterized object of type allocationType. If we are successful then by design and construction, the parameterization of the return type of the factory method is identical to the types elided in the <>. */ MethodBinding factory = scope.getStaticFactory(allocationType, enclosingType, argumentTypes, this); if (factory instanceof ParameterizedGenericMethodBinding && factory.isValidBinding()) { ParameterizedGenericMethodBinding genericFactory = (ParameterizedGenericMethodBinding) factory; this.inferredReturnType = genericFactory.inferredReturnType; return ((ParameterizedTypeBinding)factory.returnType).arguments; } return null; } public void checkTypeArgumentRedundancy(ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) { ProblemReporter reporter = scope.problemReporter(); if ((reporter.computeSeverity(IProblem.RedundantSpecificationOfTypeArguments) == ProblemSeverities.Ignore) || scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return; if (allocationType.arguments == null) return; // raw binding if (this.genericTypeArguments != null) return; // diamond can't occur with explicit type args for constructor if (argumentTypes == Binding.NO_PARAMETERS && this.typeExpected instanceof ParameterizedTypeBinding) { ParameterizedTypeBinding expected = (ParameterizedTypeBinding) this.typeExpected; if (expected.arguments != null && allocationType.arguments.length == expected.arguments.length) { // check the case when no ctor takes no params and inference uses the expected type directly // eg. X x = new X() int i; for (i = 0; i < allocationType.arguments.length; i++) { if (allocationType.arguments[i] != expected.arguments[i]) break; } if (i == allocationType.arguments.length) { reporter.redundantSpecificationOfTypeArguments(this.type, allocationType.arguments); return; } } } TypeBinding [] inferredTypes = inferElidedTypes(allocationType.genericType(), enclosingType, argumentTypes, scope); if (inferredTypes == null) { return; } for (int i = 0; i < inferredTypes.length; i++) { if (inferredTypes[i] != allocationType.arguments[i]) return; } reporter.redundantSpecificationOfTypeArguments(this.type, allocationType.arguments); } public void setActualReceiverType(ReferenceBinding receiverType) { // ignored } public void setDepth(int i) { // ignored } public void setFieldIndex(int i) { // ignored } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, 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); } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#setExpectedType(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) */ public void setExpectedType(TypeBinding expectedType) { this.typeExpected = expectedType; } /** * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#expectedType() */ public TypeBinding expectedType() { return this.typeExpected; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Expression.java0000644000175000001440000012474712212041344030072 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 292478 - Report potentially null across variable assignment * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 400761 - [compiler][null] null may be return as boolean without a diagnostic * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement; import org.eclipse.jdt.internal.compiler.util.Messages; public abstract class Expression extends Statement { public Constant constant; public int statementEnd = -1; //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 static final boolean isConstantValueRepresentable(Constant constant, int constantTypeID, int targetTypeID) { //true if there is no loss of precision while casting. // constantTypeID == constant.typeID if (targetTypeID == constantTypeID) return true; switch (targetTypeID) { case T_char : switch (constantTypeID) { case T_char : return true; case T_double : return constant.doubleValue() == constant.charValue(); case T_float : return constant.floatValue() == constant.charValue(); case T_int : return constant.intValue() == constant.charValue(); case T_short : return constant.shortValue() == constant.charValue(); case T_byte : return constant.byteValue() == constant.charValue(); case T_long : return constant.longValue() == constant.charValue(); default : return false;//boolean } case T_float : switch (constantTypeID) { case T_char : return constant.charValue() == constant.floatValue(); case T_double : return constant.doubleValue() == constant.floatValue(); case T_float : return true; case T_int : return constant.intValue() == constant.floatValue(); case T_short : return constant.shortValue() == constant.floatValue(); case T_byte : return constant.byteValue() == constant.floatValue(); case T_long : return constant.longValue() == constant.floatValue(); default : return false;//boolean } case T_double : switch (constantTypeID) { case T_char : return constant.charValue() == constant.doubleValue(); case T_double : return true; case T_float : return constant.floatValue() == constant.doubleValue(); case T_int : return constant.intValue() == constant.doubleValue(); case T_short : return constant.shortValue() == constant.doubleValue(); case T_byte : return constant.byteValue() == constant.doubleValue(); case T_long : return constant.longValue() == constant.doubleValue(); default : return false; //boolean } case T_byte : switch (constantTypeID) { case T_char : return constant.charValue() == constant.byteValue(); case T_double : return constant.doubleValue() == constant.byteValue(); case T_float : return constant.floatValue() == constant.byteValue(); case T_int : return constant.intValue() == constant.byteValue(); case T_short : return constant.shortValue() == constant.byteValue(); case T_byte : return true; case T_long : return constant.longValue() == constant.byteValue(); default : return false; //boolean } case T_short : switch (constantTypeID) { case T_char : return constant.charValue() == constant.shortValue(); case T_double : return constant.doubleValue() == constant.shortValue(); case T_float : return constant.floatValue() == constant.shortValue(); case T_int : return constant.intValue() == constant.shortValue(); case T_short : return true; case T_byte : return constant.byteValue() == constant.shortValue(); case T_long : return constant.longValue() == constant.shortValue(); default : return false; //boolean } case T_int : switch (constantTypeID) { case T_char : return constant.charValue() == constant.intValue(); case T_double : return constant.doubleValue() == constant.intValue(); case T_float : return constant.floatValue() == constant.intValue(); case T_int : return true; case T_short : return constant.shortValue() == constant.intValue(); case T_byte : return constant.byteValue() == constant.intValue(); case T_long : return constant.longValue() == constant.intValue(); default : return false; //boolean } case T_long : switch (constantTypeID) { case T_char : return constant.charValue() == constant.longValue(); case T_double : return constant.doubleValue() == constant.longValue(); case T_float : return constant.floatValue() == constant.longValue(); case T_int : return constant.intValue() == constant.longValue(); case T_short : return constant.shortValue() == constant.longValue(); case T_byte : return constant.byteValue() == constant.longValue(); case T_long : return true; default : return false; //boolean } default : return false; //boolean } } public Expression() { super(); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return flowInfo; } /** * More sophisticated for of the flow analysis used for analyzing expressions, and be able to optimize out * portions of expressions where no actual value is required. * * @param currentScope * @param flowContext * @param flowInfo * @param valueRequired * @return The state of initialization after the analysis of the current expression */ 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 boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; boolean use17specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7; 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) { this.constant = expression.constant.castTo(expression.implicitConversion); } } if (!necessary) tagAsUnnecessaryCast(scope, castType); return true; } } else if (use17specifics && expressionType.id == TypeIds.T_JavaLangObject){ // cast from Object to base type allowed from 1.7, see JLS $5.5 return true; } else if (use15specifics && scope.environment().computeBoxingType(expressionType).isCompatibleWith(castType)) { // unboxing - only widening match is allowed tagAsUnnecessaryCast(scope, castType); return true; } return false; } else if (use15specifics && expressionType.isBaseType() && scope.environment().computeBoxingType(expressionType).isCompatibleWith(castType)) { // boxing - only widening match is allowed tagAsUnnecessaryCast(scope, castType); return true; } switch(expressionType.kind()) { case Binding.BASE_TYPE : //-----------cast to something which is NOT a base type-------------------------- if (expressionType == TypeBinding.NULL) { tagAsUnnecessaryCast(scope, castType); return true; //null is compatible with every thing } return false; case Binding.ARRAY_TYPE : if (castType == expressionType) { tagAsUnnecessaryCast(scope, castType); return true; // identity conversion } switch (castType.kind()) { case Binding.ARRAY_TYPE : // ( ARRAY ) ARRAY TypeBinding castElementType = ((ArrayBinding) castType).elementsType(); TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(); if (exprElementType.isBaseType() || castElementType.isBaseType()) { if (castElementType == exprElementType) { tagAsNeedCheckCast(); return true; } return false; } // recurse on array type elements return checkCastTypesCompatibility(scope, castElementType, exprElementType, expression); case Binding.TYPE_PARAMETER : // ( TYPE_PARAMETER ) ARRAY TypeBinding match = expressionType.findSuperTypeOriginatingFrom(castType); if (match == null) { checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true); } // recurse on the type variable upper bound return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression); default: // ( CLASS/INTERFACE ) ARRAY switch (castType.id) { case T_JavaLangCloneable : case T_JavaIoSerializable : tagAsNeedCheckCast(); return true; case T_JavaLangObject : tagAsUnnecessaryCast(scope, castType); return true; default : return false; } } case Binding.TYPE_PARAMETER : TypeBinding match = expressionType.findSuperTypeOriginatingFrom(castType); if (match != null) { return checkUnsafeCast(scope, castType, expressionType, match, false); } // recursively on the type variable upper bound return checkCastTypesCompatibility(scope, castType, ((TypeVariableBinding)expressionType).upperBound(), expression); case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : match = expressionType.findSuperTypeOriginatingFrom(castType); if (match != null) { return checkUnsafeCast(scope, castType, expressionType, match, false); } // recursively on the type variable upper bound return checkCastTypesCompatibility(scope, castType, ((WildcardBinding)expressionType).bound, expression); default: if (expressionType.isInterface()) { switch (castType.kind()) { case Binding.ARRAY_TYPE : // ( ARRAY ) INTERFACE switch (expressionType.id) { case T_JavaLangCloneable : case T_JavaIoSerializable : tagAsNeedCheckCast(); return true; default : return false; } case Binding.TYPE_PARAMETER : // ( INTERFACE ) TYPE_PARAMETER match = expressionType.findSuperTypeOriginatingFrom(castType); if (match == null) { checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true); } // recurse on the type variable upper bound return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression); default : if (castType.isInterface()) { // ( INTERFACE ) INTERFACE ReferenceBinding interfaceType = (ReferenceBinding) expressionType; match = interfaceType.findSuperTypeOriginatingFrom(castType); if (match != null) { return checkUnsafeCast(scope, castType, interfaceType, match, false); } tagAsNeedCheckCast(); match = castType.findSuperTypeOriginatingFrom(interfaceType); if (match != null) { return checkUnsafeCast(scope, castType, interfaceType, match, true); } if (use15specifics) { checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true); // ensure there is no collision between both interfaces: i.e. I1 extends List, I2 extends List if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) { if (interfaceType.hasIncompatibleSuperType((ReferenceBinding) castType)) { return false; } } else if (!castType.isRawType() && interfaceType.hasIncompatibleSuperType((ReferenceBinding) castType)) { return false; } } else { // pre1.5 semantics - no covariance allowed (even if 1.5 compliant, but 1.4 source) // look at original methods rather than the parameterized variants at 1.4 to detect // covariance. Otherwise when confronted with one raw type and one parameterized type, // we could mistakenly detect covariance and scream foul. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=332744 MethodBinding[] castTypeMethods = getAllOriginalInheritedMethods((ReferenceBinding) castType); MethodBinding[] expressionTypeMethods = getAllOriginalInheritedMethods((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])) { return false; } } } } return true; } else { // ( CLASS ) INTERFACE if (castType.id == TypeIds.T_JavaLangObject) { // no runtime error tagAsUnnecessaryCast(scope, castType); return true; } // can only be a downcast tagAsNeedCheckCast(); match = castType.findSuperTypeOriginatingFrom(expressionType); if (match != null) { return checkUnsafeCast(scope, castType, expressionType, match, true); } if (((ReferenceBinding) castType).isFinal()) { // no subclass for castType, thus compile-time check is invalid return false; } if (use15specifics) { checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true); // ensure there is no collision between both interfaces: i.e. I1 extends List, I2 extends List if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) { if (((ReferenceBinding)castType).hasIncompatibleSuperType((ReferenceBinding) expressionType)) { return false; } } else if (!castType.isRawType() && ((ReferenceBinding)castType).hasIncompatibleSuperType((ReferenceBinding) expressionType)) { return false; } } return true; } } } else { switch (castType.kind()) { case Binding.ARRAY_TYPE : // ( ARRAY ) CLASS if (expressionType.id == TypeIds.T_JavaLangObject) { // potential runtime error if (use15specifics) checkUnsafeCast(scope, castType, expressionType, expressionType, true); tagAsNeedCheckCast(); return true; } return false; case Binding.TYPE_PARAMETER : // ( TYPE_PARAMETER ) CLASS match = expressionType.findSuperTypeOriginatingFrom(castType); if (match == null) { checkUnsafeCast(scope, castType, expressionType, null, true); } // recurse on the type variable upper bound return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression); default : if (castType.isInterface()) { // ( INTERFACE ) CLASS ReferenceBinding refExprType = (ReferenceBinding) expressionType; match = refExprType.findSuperTypeOriginatingFrom(castType); if (match != null) { return checkUnsafeCast(scope, castType, expressionType, match, false); } // unless final a subclass may implement the interface ==> no check at compile time if (refExprType.isFinal()) { return false; } tagAsNeedCheckCast(); match = castType.findSuperTypeOriginatingFrom(expressionType); if (match != null) { return checkUnsafeCast(scope, castType, expressionType, match, true); } if (use15specifics) { checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true); // ensure there is no collision between both interfaces: i.e. I1 extends List, I2 extends List if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) { if (refExprType.hasIncompatibleSuperType((ReferenceBinding) castType)) { return false; } } else if (!castType.isRawType() && refExprType.hasIncompatibleSuperType((ReferenceBinding) castType)) { return false; } } return true; } else { // ( CLASS ) CLASS match = expressionType.findSuperTypeOriginatingFrom(castType); if (match != null) { if (expression != null && castType.id == TypeIds.T_JavaLangString) this.constant = expression.constant; // (String) cst is still a constant return checkUnsafeCast(scope, castType, expressionType, match, false); } match = castType.findSuperTypeOriginatingFrom(expressionType); if (match != null) { tagAsNeedCheckCast(); return checkUnsafeCast(scope, castType, expressionType, match, true); } return false; } } } } } /** * Check this expression against potential NPEs, which may occur: *
    *
  • if the expression is the receiver in a field access, qualified allocation, array reference or message send * incl. implicit message sends like it happens for the collection in a foreach statement.
  • *
  • if the expression is subject to unboxing
  • *
  • if the expression is the exception in a throw statement
  • *
* If a risk of NPE is detected report it to the context. * If the expression denotes a local variable, mark it as checked, which affects the flow info. * @param scope the scope of the analysis * @param flowContext the current flow context * @param flowInfo the upstream flow info; caveat: may get modified * @return could this expression be checked by the current implementation? */ public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { LocalVariableBinding local = localVariableBinding(); if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { if ((this.bits & ASTNode.IsNonNull) == 0) { flowContext.recordUsingNullReference(scope, local, this, FlowContext.MAY_NULL, flowInfo); // account for possible NPE: if (!flowInfo.isDefinitelyNonNull(local)) { flowContext.recordAbruptExit(); } } flowInfo.markAsComparedEqualToNonNull(local); // from thereon it is set flowContext.markFinallyNullStatus(local, FlowInfo.NON_NULL); return true; } return false; // not checked } /** If this expression requires unboxing check if that operation can throw NPE. */ protected void checkNPEbyUnboxing(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { int status; if ((this.implicitConversion & UNBOXING) != 0 && (this.bits & ASTNode.IsNonNull) == 0 && (status = nullStatus(flowInfo, flowContext)) != FlowInfo.NON_NULL) { flowContext.recordUnboxing(scope, this, status, flowInfo); } } public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) { if (match == castType) { if (!isNarrowing) tagAsUnnecessaryCast(scope, castType); return true; } if (match != null && (!castType.isReifiable() || !expressionType.isReifiable())) { if(isNarrowing ? match.isProvablyDistinct(expressionType) : castType.isProvablyDistinct(match)) { 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 runtimeType, TypeBinding compileTimeType) { if (runtimeType == null || compileTimeType == null) return; if (this.implicitConversion != 0) return; // already set independently // 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 (runtimeType != TypeBinding.NULL && runtimeType.isBaseType()) { if (!compileTimeType.isBaseType()) { TypeBinding unboxedType = scope.environment().computeBoxingType(compileTimeType); this.implicitConversion = TypeIds.UNBOXING; scope.problemReporter().autoboxing(this, compileTimeType, runtimeType); compileTimeType = unboxedType; } } else if (compileTimeType != TypeBinding.NULL && compileTimeType.isBaseType()) { TypeBinding boxedType = scope.environment().computeBoxingType(runtimeType); if (boxedType == runtimeType) // Object o = 12; boxedType = compileTimeType; this.implicitConversion = TypeIds.BOXING | (boxedType.id << 4) + compileTimeType.id; scope.problemReporter().autoboxing(this, compileTimeType, scope.environment().computeBoxingType(boxedType)); return; } else if (this.constant != Constant.NotAConstant && this.constant.typeID() != TypeIds.T_JavaLangString) { this.implicitConversion = TypeIds.BOXING; return; } int compileTimeTypeID, runtimeTypeID; if ((compileTimeTypeID = compileTimeType.id) == TypeIds.NoId) { // e.g. ? extends String ==> String (103227) compileTimeTypeID = compileTimeType.erasure().id == TypeIds.T_JavaLangString ? TypeIds.T_JavaLangString : TypeIds.T_JavaLangObject; } switch (runtimeTypeID = runtimeType.id) { case T_byte : case T_short : case T_char : if (compileTimeTypeID == TypeIds.T_JavaLangObject) { this.implicitConversion |= (runtimeTypeID << 4) + compileTimeTypeID; } else { this.implicitConversion |= (TypeIds.T_int << 4) + compileTimeTypeID; } 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 |= (runtimeTypeID << 4) + compileTimeTypeID; 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. * * @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 ((this.bits & ASTNode.IsReachable) == 0) { return; } generateCode(currentScope, codeStream, false); } /** * Every expression is responsible for generating its implicit conversion when necessary. * * @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 (this.constant != Constant.NotAConstant) { // generate a constant expression int pc = codeStream.position; codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); } else { // actual non-constant code generation throw new ShouldNotImplement(Messages.ast_missingCode); } } /** * Default generation of a boolean value * @param currentScope * @param codeStream * @param trueLabel * @param falseLabel * @param valueRequired */ public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { // a label valued to nil means: by default we fall through the case... // both nil means we leave the value on the stack Constant cst = optimizedBooleanConstant(); generateCode(currentScope, codeStream, valueRequired && cst == Constant.NotAConstant); if ((cst != Constant.NotAConstant) && (cst.typeID() == TypeIds.T_boolean)) { int pc = codeStream.position; if (cst.booleanValue() == true) { // constant == true if (valueRequired) { if (falseLabel == null) { // implicit falling through the FALSE case if (trueLabel != null) { codeStream.goto_(trueLabel); } } } } else { if (valueRequired) { if (falseLabel != null) { // implicit falling through the TRUE case if (trueLabel == null) { codeStream.goto_(falseLabel); } } } } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } // branching int position = codeStream.position; if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // Implicit falling through the FALSE case codeStream.ifne(trueLabel); } } else { if (trueLabel == null) { // Implicit falling through the TRUE case codeStream.ifeq(falseLabel); } else { // No implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(position, this.sourceEnd); } /* 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. * By default: no optimization. */ public void generateOptimizedStringConcatenation(BlockScope blockScope, CodeStream codeStream, int typeID) { if (typeID == TypeIds.T_JavaLangString && this.constant != Constant.NotAConstant && this.constant.stringValue().length() == 0) { return; // optimize str + "" } generateCode(blockScope, codeStream, true); 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 generateOptimizedStringConcatenationCreation(BlockScope blockScope, CodeStream codeStream, int typeID) { codeStream.newStringContatenation(); codeStream.dup(); 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.invokeStringConcatenationAppendForType(TypeIds.T_JavaLangObject); return; case T_JavaLangString : case T_null : if (this.constant != Constant.NotAConstant) { String stringValue = this.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(TypeIds.T_JavaLangObject); } break; default : generateCode(blockScope, codeStream, true); codeStream.invokeStringValueOf(typeID); } codeStream.invokeStringConcatenationStringConstructor(); } private MethodBinding[] getAllOriginalInheritedMethods(ReferenceBinding binding) { ArrayList collector = new ArrayList(); getAllInheritedMethods0(binding, collector); for (int i = 0, len = collector.size(); i < len; i++) { collector.set(i, ((MethodBinding)collector.get(i)).original()); } 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 static Binding getDirectBinding(Expression someExpression) { if ((someExpression.bits & ASTNode.IgnoreNoEffectAssignCheck) != 0) { return null; } if (someExpression instanceof SingleNameReference) { return ((SingleNameReference)someExpression).binding; } else if (someExpression instanceof FieldReference) { FieldReference fieldRef = (FieldReference)someExpression; if (fieldRef.receiver.isThis() && !(fieldRef.receiver instanceof QualifiedThisReference)) { return fieldRef.binding; } } else if (someExpression instanceof Assignment) { Expression lhs = ((Assignment)someExpression).lhs; if ((lhs.bits & ASTNode.IsStrictlyAssigned) != 0) { // i = i = ...; // eq to int i = ...; return getDirectBinding (((Assignment)someExpression).lhs); } else if (someExpression instanceof PrefixExpression) { // i = i++; // eq to ++i; return getDirectBinding (((Assignment)someExpression).lhs); } } else if (someExpression instanceof QualifiedNameReference) { QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) someExpression; if (qualifiedNameReference.indexOfFirstFieldBinding != 1 && qualifiedNameReference.otherBindings == null) { // case where a static field is retrieved using ClassName.fieldname return qualifiedNameReference.binding; } } else if (someExpression.isThis()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=276741 return someExpression.resolvedType; } // } else if (someExpression instanceof PostfixExpression) { // recurse for postfix: i++ --> i // // note: "b = b++" is equivalent to doing nothing, not to "b++" // return getDirectBinding(((PostfixExpression) someExpression).lhs); return null; } public boolean isCompactableOperation() { return false; } //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 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) { if (this.constant == Constant.NotAConstant) return false; if (constantType == targetType) return true; //No free assignment conversion from anything but to integral ones. if (BaseTypeBinding.isWidening(TypeIds.T_int, constantType.id) && (BaseTypeBinding.isNarrowing(targetType.id, TypeIds.T_int))) { //use current explicit conversion in order to get some new value to compare with current one return isConstantValueRepresentable(this.constant, constantType.id, targetType.id); } return false; } public boolean isTypeReference() { return false; } /** * 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; } /** * Mark this expression as being non null, per a specific tag in the * source code. */ // this is no more called for now, waiting for inter procedural null reference analysis public void markAsNonNull() { this.bits |= ASTNode.IsNonNull; } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { if (/* (this.bits & IsNonNull) != 0 || */ this.constant != null && this.constant != Constant.NotAConstant) return FlowInfo.NON_NULL; // constant expression cannot be null LocalVariableBinding local = localVariableBinding(); if (local != null) return flowInfo.nullStatus(local); 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; } /** * Returns the type of the expression after required implicit conversions. When expression type gets promoted * or inserted a generic cast, the converted type will differ from the resolved type (surface side-effects from * #computeConversion(...)). * @return the type after implicit conversion */ public TypeBinding postConversionType(Scope scope) { TypeBinding convertedType = this.resolvedType; int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; switch (runtimeType) { case T_boolean : convertedType = TypeBinding.BOOLEAN; break; case T_byte : convertedType = TypeBinding.BYTE; break; case T_short : convertedType = TypeBinding.SHORT; break; case T_char : convertedType = TypeBinding.CHAR; break; case T_int : convertedType = TypeBinding.INT; break; case T_float : convertedType = TypeBinding.FLOAT; break; case T_long : convertedType = TypeBinding.LONG; break; case T_double : convertedType = TypeBinding.DOUBLE; break; default : } if ((this.implicitConversion & TypeIds.BOXING) != 0) { convertedType = scope.environment().computeBoxingType(convertedType); } return convertedType; } 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 resolve(BlockScope scope) { // drops the returning expression's type whatever the type is. this.resolveType(scope); return; } /** * Resolve the type of this expression in the context of a blockScope * * @param scope * @return * Return the actual type of this expression after resolution */ public TypeBinding resolveType(BlockScope scope) { // by default... subclasses should implement a better TB if required. return null; } /** * Resolve the type of this expression in the context of a classScope * * @param scope * @return * Return the actual type of this expression after resolution */ public TypeBinding resolveType(ClassScope scope) { // by default... subclasses should implement a better TB if required. return null; } public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedType) { 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)) { if (scope.isBoxingCompatibleWith(expressionType, expectedType)) { computeConversion(scope, expectedType, expressionType); } else { scope.problemReporter().typeMismatchError(expressionType, expectedType, this, null); return null; } } return expressionType; } /** * Returns true if the receiver is forced to be of raw type either to satisfy the contract imposed * by a super type or because it *is* raw and the current type has no control over it (i.e the rawness * originates from some other file.) */ public boolean forcedToBeRaw(ReferenceContext referenceContext) { if (this instanceof NameReference) { final Binding receiverBinding = ((NameReference) this).binding; if (receiverBinding.isParameter() && (((LocalVariableBinding) receiverBinding).tagBits & TagBits.ForcedToBeRawType) != 0) { return true; // parameter is forced to be raw since super method uses raw types. } else if (receiverBinding instanceof FieldBinding) { FieldBinding field = (FieldBinding) receiverBinding; if (field.type.isRawType()) { if (referenceContext instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration) referenceContext; if (field.declaringClass != methodDecl.binding.declaringClass) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962 return true; } } else if (referenceContext instanceof TypeDeclaration) { TypeDeclaration type = (TypeDeclaration) referenceContext; if (field.declaringClass != type.binding) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962 return true; } } } } } else if (this instanceof MessageSend) { if (!CharOperation.equals(((MessageSend) this).binding.declaringClass.getFileName(), referenceContext.compilationResult().getFileName())) { // problem is rooted elsewhere return true; } } else if (this instanceof FieldReference) { FieldBinding field = ((FieldReference) this).binding; if (!CharOperation.equals(field.declaringClass.getFileName(), referenceContext.compilationResult().getFileName())) { // problem is rooted elsewhere return true; } if (field.type.isRawType()) { if (referenceContext instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration) referenceContext; if (field.declaringClass != methodDecl.binding.declaringClass) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962 return true; } } else if (referenceContext instanceof TypeDeclaration) { TypeDeclaration type = (TypeDeclaration) referenceContext; if (field.declaringClass != type.binding) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962 return true; } } } } else if (this instanceof ConditionalExpression) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=337751 ConditionalExpression ternary = (ConditionalExpression) this; if (ternary.valueIfTrue.forcedToBeRaw(referenceContext) || ternary.valueIfFalse.forcedToBeRaw(referenceContext)) { return true; } } return false; } /** * Returns an object which can be used to identify identical JSR sequence targets * (see TryStatement subroutine codegen) * or null if not reusable */ public Object reusableJSRTarget() { if (this.constant != Constant.NotAConstant && (this.implicitConversion & TypeIds.BOXING) == 0) { return this.constant; } return null; } /** * 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. * * @param expectedType * The type denoting an expectation in the context of an assignment conversion */ public void setExpectedType(TypeBinding expectedType) { // do nothing by default } public void tagAsNeedCheckCast() { // do nothing by default } /** * Record the fact a cast expression got detected as being unnecessary. * * @param scope * @param castType */ public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) { // do nothing by default } public Expression toTypeReference() { //by default undefined //this method is meanly used by the parser in order to transform //an expression that is used as a type reference in a cast .... //--appreciate the fact that castExpression and ExpressionWithParenthesis //--starts with the same pattern..... return this; } /** * Traverse an expression in the context of a blockScope * @param visitor * @param scope */ public void traverse(ASTVisitor visitor, BlockScope scope) { // nothing to do } /** * Traverse an expression in the context of a classScope * @param visitor * @param scope */ public void traverse(ASTVisitor visitor, ClassScope scope) { // nothing to do } /** * Used on the lhs of an assignment for detecting null spec violation. * If this expression represents a null-annotated variable return the variable binding, * otherwise null. */ public VariableBinding nullAnnotatedVariableBinding() { return null; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java0000644000175000001440000010715612212041344031055 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields *******************************************************************************/ 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.*; public class EqualExpression extends BinaryExpression { public EqualExpression(Expression left, Expression right,int operator) { super(left,right,operator); } private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) { // collect null status of child nodes: int rightStatus = this.right.nullStatus(flowInfo, flowContext); int leftStatus = this.left.nullStatus(flowInfo, flowContext); boolean leftNonNullChecked = false; boolean rightNonNullChecked = false; // check if either is a non-local expression known to be nonnull and compared to null, candidates are // - method/field annotated @NonNull // - allocation expression, some literals, this reference (see inside expressionNonNullComparison(..)) // these checks do not leverage the flowInfo. boolean checkEquality = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL; if (leftStatus == FlowInfo.NON_NULL && rightStatus == FlowInfo.NULL) { leftNonNullChecked = scope.problemReporter().expressionNonNullComparison(this.left, checkEquality); } else if (leftStatus == FlowInfo.NULL && rightStatus == FlowInfo.NON_NULL) { rightNonNullChecked = scope.problemReporter().expressionNonNullComparison(this.right, checkEquality); } boolean contextualCheckEquality = checkEquality ^ ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) != 0); // perform flowInfo-based checks for variables and record info for syntactic null analysis for fields: if (!leftNonNullChecked) { LocalVariableBinding local = this.left.localVariableBinding(); if (local != null) { if ((local.type.tagBits & TagBits.IsBaseType) == 0) { checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, rightStatus, this.left); } } else if (this.left instanceof Reference && ((!contextualCheckEquality && rightStatus == FlowInfo.NULL) || (contextualCheckEquality && rightStatus == FlowInfo.NON_NULL)) && scope.compilerOptions().enableSyntacticNullAnalysisForFields) { FieldBinding field = ((Reference)this.left).lastFieldBinding(); if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) { flowContext.recordNullCheckedFieldReference((Reference) this.left, 1); } } } if (!rightNonNullChecked) { LocalVariableBinding local = this.right.localVariableBinding(); if (local != null) { if ((local.type.tagBits & TagBits.IsBaseType) == 0) { checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, leftStatus, this.right); } } else if (this.right instanceof Reference && ((!contextualCheckEquality && leftStatus == FlowInfo.NULL) || (contextualCheckEquality && leftStatus == FlowInfo.NON_NULL)) && scope.compilerOptions().enableSyntacticNullAnalysisForFields) { FieldBinding field = ((Reference)this.right).lastFieldBinding(); if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) { flowContext.recordNullCheckedFieldReference((Reference) this.right, 1); } } } // handle reachability: if (leftNonNullChecked || rightNonNullChecked) { // above checks have not propagated unreachable into the corresponding branch, do it now: if (checkEquality) { initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } else { initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS); } } } private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) { switch (nullStatus) { case FlowInfo.NULL : if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { flowContext.recordUsingNullReference(scope, local, reference, FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo); initsWhenTrue.markAsComparedEqualToNull(local); // from thereon it is set initsWhenFalse.markAsComparedEqualToNonNull(local); // from thereon it is set } else { flowContext.recordUsingNullReference(scope, local, reference, FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo); initsWhenTrue.markAsComparedEqualToNonNull(local); // from thereon it is set initsWhenFalse.markAsComparedEqualToNull(local); // from thereon it is set } break; case FlowInfo.NON_NULL : if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { flowContext.recordUsingNullReference(scope, local, reference, FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo); initsWhenTrue.markAsComparedEqualToNonNull(local); // from thereon it is set } else { flowContext.recordUsingNullReference(scope, local, reference, FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo); } break; } // we do not impact enclosing try context because this kind of protection // does not preclude the variable from being null in an enclosing scope } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { FlowInfo result; if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == T_boolean)) { if (this.left.constant.booleanValue()) { // true == anything // this is equivalent to the right argument inits result = this.right.analyseCode(currentScope, flowContext, flowInfo); } else { // false == anything // this is equivalent to the right argument inits negated result = this.right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); } } else if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == T_boolean)) { if (this.right.constant.booleanValue()) { // anything == true // this is equivalent to the left argument inits result = this.left.analyseCode(currentScope, flowContext, flowInfo); } else { // anything == false // this is equivalent to the right argument inits negated result = this.left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); } } else { result = this.right.analyseCode( currentScope, flowContext, this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits(); } } else { //NOT_EQUAL : if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == T_boolean)) { if (!this.left.constant.booleanValue()) { // false != anything // this is equivalent to the right argument inits result = this.right.analyseCode(currentScope, flowContext, flowInfo); } else { // true != anything // this is equivalent to the right argument inits negated result = this.right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); } } else if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == T_boolean)) { if (!this.right.constant.booleanValue()) { // anything != false // this is equivalent to the right argument inits result = this.left.analyseCode(currentScope, flowContext, flowInfo); } else { // anything != true // this is equivalent to the right argument inits negated result = this.left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); } } else { result = this.right.analyseCode( currentScope, flowContext, this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()). /* unneeded since we flatten it: asNegatedCondition(). */ unconditionalInits(); } } if (result instanceof UnconditionalFlowInfo && (result.tagBits & FlowInfo.UNREACHABLE) == 0) { // the flow info is flat result = FlowInfo.conditional(result.copy(), result.copy()); // TODO (maxime) check, reintroduced copy } checkNullComparison(currentScope, flowContext, result, result.initsWhenTrue(), result.initsWhenFalse()); return result; } public final void computeConstant(TypeBinding leftType, TypeBinding rightType) { if ((this.left.constant != Constant.NotAConstant) && (this.right.constant != Constant.NotAConstant)) { this.constant = Constant.computeConstantOperationEQUAL_EQUAL( this.left.constant, leftType.id, this.right.constant, rightType.id); if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL) this.constant = BooleanConstant.fromValue(!this.constant.booleanValue()); } else { this.constant = 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) { int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { if (valueRequired) codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); return; } if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) { generateBooleanEqual(currentScope, codeStream, valueRequired); } else { generateNonBooleanEqual(currentScope, codeStream, valueRequired); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * Boolean operator code generation * Optimized operations are: == and != */ public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { if (this.constant != Constant.NotAConstant) { super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) { generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired); } else { generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired); } } else { if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) { generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired); } else { generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired); } } } /** * Boolean generation for == with boolean operands * * Note this code does not optimize conditional constants !!!! */ public void generateBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { // optimized cases: == x, == x, // optimized cases: != x, != x, boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL; Constant cst = this.left.optimizedBooleanConstant(); if (cst != Constant.NotAConstant) { Constant rightCst = this.right.optimizedBooleanConstant(); if (rightCst != Constant.NotAConstant) { // == , != // == , != this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, false); if (valueRequired) { boolean leftBool = cst.booleanValue(); boolean rightBool = rightCst.booleanValue(); if (isEqualOperator) { if (leftBool == rightBool) { codeStream.iconst_1(); } else { codeStream.iconst_0(); } } else { if (leftBool != rightBool) { codeStream.iconst_1(); } else { codeStream.iconst_0(); } } } } else if (cst.booleanValue() == isEqualOperator) { // == x, != x this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, valueRequired); } else { // == x, != x if (valueRequired) { BranchLabel falseLabel = new BranchLabel(codeStream); this.left.generateCode(currentScope, codeStream, false); this.right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired); // comparison is TRUE codeStream.iconst_0(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_1(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_1(); endLabel.place(); } } else { this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, false); } // left.generateCode(currentScope, codeStream, false); // right.generateCode(currentScope, codeStream, valueRequired); // if (valueRequired) { // codeStream.iconst_1(); // codeStream.ixor(); // negate // } } return; } cst = this.right.optimizedBooleanConstant(); if (cst != Constant.NotAConstant) { if (cst.booleanValue() == isEqualOperator) { // x == , x != this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, false); } else { // x == , x != if (valueRequired) { BranchLabel falseLabel = new BranchLabel(codeStream); this.left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired); this.right.generateCode(currentScope, codeStream, false); // comparison is TRUE codeStream.iconst_0(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_1(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_1(); endLabel.place(); } } else { this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, false); } // left.generateCode(currentScope, codeStream, valueRequired); // right.generateCode(currentScope, codeStream, false); // if (valueRequired) { // codeStream.iconst_1(); // codeStream.ixor(); // negate // } } return; } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (isEqualOperator) { BranchLabel falseLabel; codeStream.if_icmpne(falseLabel = new BranchLabel(codeStream)); // comparison is TRUE codeStream.iconst_1(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } else { codeStream.ixor(); } } } /** * Boolean generation for == with boolean operands * * Note this code does not optimize conditional constants !!!! */ public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { // optimized cases: true == x, false == x if (this.left.constant != Constant.NotAConstant) { boolean inline = this.left.constant.booleanValue(); this.right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired); return; } // optimized cases: x == true, x == false if (this.right.constant != Constant.NotAConstant) { boolean inline = this.right.constant.booleanValue(); this.left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired); return; } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); int pc = codeStream.position; 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 { // no implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(pc, this.sourceEnd); } /** * Boolean generation for == with non-boolean operands * */ public void generateNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL; if (((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) { Constant cst; if ((cst = this.left.constant) != Constant.NotAConstant && cst.intValue() == 0) { // optimized case: 0 == x, 0 != x this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { BranchLabel falseLabel = new BranchLabel(codeStream); if (isEqualOperator) { codeStream.ifne(falseLabel); } else { codeStream.ifeq(falseLabel); } // comparison is TRUE codeStream.iconst_1(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } return; } if ((cst = this.right.constant) != Constant.NotAConstant && cst.intValue() == 0) { // optimized case: x == 0, x != 0 this.left.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { BranchLabel falseLabel = new BranchLabel(codeStream); if (isEqualOperator) { codeStream.ifne(falseLabel); } else { codeStream.ifeq(falseLabel); } // comparison is TRUE codeStream.iconst_1(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } return; } } // null cases if (this.right instanceof NullLiteral) { if (this.left instanceof NullLiteral) { // null == null, null != null if (valueRequired) { if (isEqualOperator) { codeStream.iconst_1(); } else { codeStream.iconst_0(); } } } else { // x == null, x != null this.left.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { BranchLabel falseLabel = new BranchLabel(codeStream); if (isEqualOperator) { codeStream.ifnonnull(falseLabel); } else { codeStream.ifnull(falseLabel); } // comparison is TRUE codeStream.iconst_1(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } } return; } else if (this.left instanceof NullLiteral) { // null = x, null != x this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { BranchLabel falseLabel = new BranchLabel(codeStream); if (isEqualOperator) { codeStream.ifnonnull(falseLabel); } else { codeStream.ifnull(falseLabel); } // comparison is TRUE codeStream.iconst_1(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } return; } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { BranchLabel falseLabel = new BranchLabel(codeStream); if (isEqualOperator) { switch ((this.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 { switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type case T_int : codeStream.if_icmpeq(falseLabel); break; case T_float : codeStream.fcmpl(); codeStream.ifeq(falseLabel); break; case T_long : codeStream.lcmp(); codeStream.ifeq(falseLabel); break; case T_double : codeStream.dcmpl(); codeStream.ifeq(falseLabel); break; default : codeStream.if_acmpeq(falseLabel); } } // comparison is TRUE codeStream.iconst_1(); if ((this.bits & IsReturnedValue) != 0){ codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); } else { BranchLabel endLabel = new BranchLabel(codeStream); codeStream.goto_(endLabel); codeStream.decrStackSize(1); // comparison is FALSE falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } } /** * Boolean generation for == with non-boolean operands * */ public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { int pc = codeStream.position; Constant inline; if ((inline = this.right.constant) != Constant.NotAConstant) { // optimized case: x == 0 if ((((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) && (inline.intValue() == 0)) { this.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 } } } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } } if ((inline = this.left.constant) != Constant.NotAConstant) { // optimized case: 0 == x if ((((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) && (inline.intValue() == 0)) { this.right.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 } } } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } } // null cases // optimized case: x == null if (this.right instanceof NullLiteral) { if (this.left instanceof NullLiteral) { // null == null if (valueRequired) { if (falseLabel == null) { // implicit falling through the FALSE case if (trueLabel != null) { codeStream.goto_(trueLabel); } } } } else { this.left.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case codeStream.ifnull(trueLabel); } } else { // implicit falling through the TRUE case if (trueLabel == null) { codeStream.ifnonnull(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } else if (this.left instanceof NullLiteral) { // optimized case: null == x this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case codeStream.ifnull(trueLabel); } } else { // implicit falling through the TRUE case if (trueLabel == null) { codeStream.ifnonnull(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case switch ((this.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) { switch ((this.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); } public boolean isCompactableOperation() { return false; } public TypeBinding resolveType(BlockScope scope) { boolean leftIsCast, rightIsCast; if ((leftIsCast = this.left instanceof CastExpression) == true) this.left.bits |= DisableUnnecessaryCastCheck; // will check later on TypeBinding originalLeftType = this.left.resolveType(scope); if ((rightIsCast = this.right instanceof CastExpression) == true) this.right.bits |= DisableUnnecessaryCastCheck; // will check later on TypeBinding originalRightType = this.right.resolveType(scope); // always return BooleanBinding if (originalLeftType == null || originalRightType == null){ this.constant = Constant.NotAConstant; return null; } // autoboxing support boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; TypeBinding leftType = originalLeftType, rightType = originalRightType; if (use15specifics) { if (leftType != TypeBinding.NULL && leftType.isBaseType()) { if (!rightType.isBaseType()) { rightType = scope.environment().computeBoxingType(rightType); } } else { if (rightType != TypeBinding.NULL && rightType.isBaseType()) { leftType = scope.environment().computeBoxingType(leftType); } } } // 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]; this.left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), originalLeftType); this.right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), originalRightType); this.bits |= operatorSignature & 0xF; if ((operatorSignature & 0x0000F) == T_undefined) { this.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, this.left, leftType.id, leftIsCast, this.right, rightType.id, rightIsCast); } computeConstant(leftType, rightType); // check whether comparing identical expressions Binding leftDirect = Expression.getDirectBinding(this.left); if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) { if (leftTypeID != TypeIds.T_double && leftTypeID != TypeIds.T_float &&(!(this.right instanceof Assignment))) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=281776 scope.problemReporter().comparingIdenticalExpressions(this); } else if (this.constant != Constant.NotAConstant) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=276740 int operator = (this.bits & OperatorMASK) >> OperatorSHIFT; if ((operator == EQUAL_EQUAL && this.constant == BooleanConstant.fromValue(true)) || (operator == NOT_EQUAL && this.constant == BooleanConstant.fromValue(false))) scope.problemReporter().comparingIdenticalExpressions(this); } return this.resolvedType = TypeBinding.BOOLEAN; } // Object references // spec 15.20.3 if ((!leftType.isBaseType() || leftType == TypeBinding.NULL) // cannot compare: Object == (int)0 && (!rightType.isBaseType() || rightType == TypeBinding.NULL) && (checkCastTypesCompatibility(scope, leftType, rightType, null) || checkCastTypesCompatibility(scope, rightType, leftType, null))) { // (special case for String) if ((rightType.id == T_JavaLangString) && (leftType.id == T_JavaLangString)) { computeConstant(leftType, rightType); } else { this.constant = Constant.NotAConstant; } TypeBinding objectType = scope.getJavaLangObject(); this.left.computeConversion(scope, objectType, leftType); this.right.computeConversion(scope, objectType, rightType); // check need for operand cast boolean unnecessaryLeftCast = (this.left.bits & UnnecessaryCast) != 0; boolean unnecessaryRightCast = (this.right.bits & UnnecessaryCast) != 0; if (unnecessaryLeftCast || unnecessaryRightCast) { TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)this.left).expression.resolvedType : leftType; TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)this.right).expression.resolvedType : rightType; if (checkCastTypesCompatibility(scope, alternateLeftType, alternateRightType, null) || checkCastTypesCompatibility(scope, alternateRightType, alternateLeftType, null)) { if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)this.left); if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)this.right); } } // check whether comparing identical expressions Binding leftDirect = Expression.getDirectBinding(this.left); if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) { if (!(this.right instanceof Assignment)) { scope.problemReporter().comparingIdenticalExpressions(this); } } return this.resolvedType = TypeBinding.BOOLEAN; } this.constant = Constant.NotAConstant; scope.problemReporter().notCompatibleTypesError(this, leftType, rightType); return null; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.left.traverse(visitor, scope); this.right.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java0000644000175000001440000000406712212041344032327 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; /** * SingleMemberAnnotation node */ public class SingleMemberAnnotation extends Annotation { public Expression memberValue; private MemberValuePair[] singlePairs; // fake pair set, only value has accurate positions public SingleMemberAnnotation(TypeReference type, int sourceStart) { this.type = type; this.sourceStart = sourceStart; this.sourceEnd = type.sourceEnd; } public ElementValuePair[] computeElementValuePairs() { return new ElementValuePair[] {memberValuePairs()[0].compilerElementPair}; } /** * @see org.eclipse.jdt.internal.compiler.ast.Annotation#memberValuePairs() */ public MemberValuePair[] memberValuePairs() { if (this.singlePairs == null) { this.singlePairs = new MemberValuePair[]{ new MemberValuePair(VALUE, this.memberValue.sourceStart, this.memberValue.sourceEnd, this.memberValue) }; } return this.singlePairs; } 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.type != null) { this.type.traverse(visitor, scope); } if (this.memberValue != null) { this.memberValue.traverse(visitor, scope); } } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java0000644000175000001440000001120212212041344031125 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class LabeledStatement extends Statement { public Statement statement; public char[] label; public BranchLabel targetLabel; public int labelEnd; // for local variables table attributes int mergedInitStateIndex = -1; /** * LabeledStatement constructor comment. */ public LabeledStatement(char[] label, Statement statement, long labelPosition, int sourceEnd) { this.statement = statement; // remember useful empty statement if (statement instanceof EmptyStatement) statement.bits |= IsUsefulEmptyStatement; this.label = label; this.sourceStart = (int)(labelPosition >>> 32); this.labelEnd = (int) labelPosition; this.sourceEnd = sourceEnd; } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // need to stack a context to store explicit label, answer inits in case of normal completion merged // with those relative to the exit path from break statement occurring inside the labeled statement. if (this.statement == null) { return flowInfo; } else { LabelFlowContext labelContext; FlowInfo statementInfo, mergedInfo; statementInfo = this.statement.analyseCode( currentScope, (labelContext = new LabelFlowContext( flowContext, this, this.label, (this.targetLabel = new BranchLabel()), currentScope)), flowInfo); boolean reinjectNullInfo = (statementInfo.tagBits & FlowInfo.UNREACHABLE) != 0 && (labelContext.initsOnBreak.tagBits & FlowInfo.UNREACHABLE) == 0; mergedInfo = statementInfo.mergedWith(labelContext.initsOnBreak); if (reinjectNullInfo) { // an embedded loop has had no chance to reinject forgotten null info ((UnconditionalFlowInfo)mergedInfo).addInitializationsFrom(flowInfo.unconditionalFieldLessCopy()). addInitializationsFrom(labelContext.initsOnBreak.unconditionalFieldLessCopy()); } this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); if ((this.bits & ASTNode.LabelUsed) == 0) { currentScope.problemReporter().unusedLabel(this); } return mergedInfo; } } public ASTNode concreteStatement() { // return statement.concreteStatement(); // for supporting nested labels: a:b:c: someStatement (see 21912) return this.statement; } /** * Code generation for labeled statement * * may not need actual source positions recording * * @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 ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; if (this.targetLabel != null) { this.targetLabel.initialize(codeStream); if (this.statement != null) { this.statement.generateCode(currentScope, codeStream); } this.targetLabel.place(); } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output).append(this.label).append(": "); //$NON-NLS-1$ if (this.statement == null) output.append(';'); else this.statement.printStatement(0, output); return output; } public void resolve(BlockScope scope) { if (this.statement != null) { this.statement.resolve(scope); } } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { if (this.statement != null) this.statement.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ././@LongLink0000644000000000000000000000015712251602427011646 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeRefe0000644000175000001440000003111512212041344032377 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for Bug 342671 - ClassCastException: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ArrayBinding *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; 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; 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.genericType(); TypeVariableBinding[] typeVariables = currentType.typeVariables(); TypeBinding[] argTypes = parameterizedType.arguments; if (argTypes != null && typeVariables != null) { // may be null in error cases parameterizedType.boundCheck(scope, this.typeArguments); } } } /** * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int) */ public TypeReference copyDims(int dim) { return new ParameterizedSingleTypeReference(this.token, this.typeArguments, dim, (((long)this.sourceStart)<<32)+this.sourceEnd); } /** * @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 = Constant.NotAConstant; if ((this.bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved if (this.resolvedType != null) { // is a shared type reference which was already resolved if (this.resolvedType.isValidBinding()) { return this.resolvedType; } else { switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : case ProblemReasons.InheritedNameHidesEnclosingName : TypeBinding type = this.resolvedType.closestMatch(); return type; default : return null; } } } } this.bits |= ASTNode.DidResolve; TypeBinding type = internalResolveLeafType(scope, enclosingType, checkBounds); // handle three different outcomes: if (type == null) { this.resolvedType = createArrayType(scope, this.resolvedType); return null; // no useful type, but still captured dimensions into this.resolvedType } else { type = createArrayType(scope, type); if (!this.resolvedType.isValidBinding()) return type; // found some error, but could recover useful type (like closestMatch) else return this.resolvedType = type; // no complaint, keep fully resolved type (incl. dimensions) } } private TypeBinding internalResolveLeafType(Scope scope, ReferenceBinding enclosingType, boolean checkBounds) { ReferenceBinding currentType; if (enclosingType == null) { this.resolvedType = scope.getType(this.token); if (this.resolvedType.isValidBinding()) { currentType = (ReferenceBinding) this.resolvedType; } else { reportInvalidType(scope); switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : case ProblemReasons.InheritedNameHidesEnclosingName : TypeBinding type = this.resolvedType.closestMatch(); if (type instanceof ReferenceBinding) { currentType = (ReferenceBinding) type; break; } //$FALL-THROUGH$ - unable to complete type binding, but still resolve type arguments default : boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; int argLength = this.typeArguments.length; for (int i = 0; i < argLength; i++) { TypeReference typeArgument = this.typeArguments[i]; if (isClassScope) { typeArgument.resolveType((ClassScope) scope); } else { typeArgument.resolveType((BlockScope) scope, checkBounds); } } return null; } // be resilient, still attempt resolving arguments } enclosingType = currentType.enclosingType(); // if member type if (enclosingType != null) { enclosingType = currentType.isStatic() ? (ReferenceBinding) scope.environment().convertToRawType(enclosingType, false /*do not force conversion of enclosing types*/) : scope.environment().convertToParameterizedType(enclosingType); currentType = scope.environment().createParameterizedType((ReferenceBinding) currentType.erasure(), null /* no arg */, enclosingType); } } else { // resolving member type (relatively to enclosingType) this.resolvedType = currentType = scope.getMemberType(this.token, enclosingType); if (!this.resolvedType.isValidBinding()) { scope.problemReporter().invalidEnclosingType(this, currentType, enclosingType); return null; } if (isTypeUseDeprecated(currentType, scope)) scope.problemReporter().deprecatedType(currentType, this); ReferenceBinding currentEnclosing = currentType.enclosingType(); if (currentEnclosing != null && currentEnclosing.erasure() != enclosingType.erasure()) { enclosingType = currentEnclosing; // inherited member type, leave it associated with its enclosing rather than subtype } } // check generic and arity boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; TypeReference keep = null; if (isClassScope) { keep = ((ClassScope) scope).superTypeReference; ((ClassScope) scope).superTypeReference = null; } int argLength = this.typeArguments.length; TypeBinding[] argTypes = new TypeBinding[argLength]; boolean argHasError = false; ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original(); for (int i = 0; i < argLength; i++) { TypeReference typeArgument = this.typeArguments[i]; TypeBinding argType = isClassScope ? typeArgument.resolveTypeArgument((ClassScope) scope, currentOriginal, i) : typeArgument.resolveTypeArgument((BlockScope) scope, currentOriginal, i); if (argType == null) { argHasError = true; } else { argTypes[i] = argType; } } if (argHasError) { return null; } if (isClassScope) { ((ClassScope) scope).superTypeReference = keep; if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null; } final boolean isDiamond = (this.bits & ASTNode.IsDiamond) != 0; TypeVariableBinding[] typeVariables = currentOriginal.typeVariables(); if (typeVariables == Binding.NO_TYPE_VARIABLES) { // non generic invoked with arguments boolean isCompliant15 = scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5; if ((currentOriginal.tagBits & TagBits.HasMissingType) == 0) { if (isCompliant15) { // below 1.5, already reported as syntax error this.resolvedType = currentType; scope.problemReporter().nonGenericTypeCannotBeParameterized(0, this, currentType, argTypes); return null; } } // resilience do not rebuild a parameterized type unless compliance is allowing it if (!isCompliant15) { if (!this.resolvedType.isValidBinding()) return currentType; return this.resolvedType = currentType; } // if missing generic type, and compliance >= 1.5, then will rebuild a parameterized binding } else if (argLength != typeVariables.length) { if (!isDiamond) { // check arity, IsDiamond never set for 1.6- scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes); return null; } } else if (!currentType.isStatic()) { ReferenceBinding actualEnclosing = currentType.enclosingType(); if (actualEnclosing != null && actualEnclosing.isRawType()){ scope.problemReporter().rawMemberTypeCannotBeParameterized( this, scope.environment().createRawType(currentOriginal, actualEnclosing), argTypes); return null; } } ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType(currentOriginal, argTypes, enclosingType); // check argument type compatibility for non <> cases - <> case needs no bounds check, we will scream foul if needed during inference. if (!isDiamond) { if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution parameterizedType.boundCheck(scope, this.typeArguments); else scope.deferBoundCheck(this); } if (isTypeUseDeprecated(parameterizedType, scope)) reportDeprecatedType(parameterizedType, scope); if (!this.resolvedType.isValidBinding()) { return parameterizedType; } return this.resolvedType = parameterizedType; } private TypeBinding createArrayType(Scope scope, TypeBinding type) { if (this.dimensions > 0) { if (this.dimensions > 255) scope.problemReporter().tooManyDimensions(this); return scope.createArrayType(type, this.dimensions); } return type; } public StringBuffer printExpression(int indent, StringBuffer output){ output.append(this.token); output.append("<"); //$NON-NLS-1$ int length = this.typeArguments.length; if (length > 0) { int max = length - 1; for (int i= 0; i < max; i++) { this.typeArguments[i].print(0, output); output.append(", ");//$NON-NLS-1$ } this.typeArguments[max].print(0, output); } output.append(">"); //$NON-NLS-1$ if ((this.bits & IsVarArgs) != 0) { for (int i= 0 ; i < this.dimensions - 1; i++) { output.append("[]"); //$NON-NLS-1$ } output.append("..."); //$NON-NLS-1$ } else { for (int i= 0 ; i < this.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); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java0000644000175000001440000002156712212041344030624 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public class ArrayReference extends Reference { public Expression receiver; public Expression position; public ArrayReference(Expression rec, Expression pos) { this.receiver = rec; this.position = pos; this.sourceStart = rec.sourceStart; } public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean compoundAssignment) { // TODO (maxime) optimization: unconditionalInits is applied to all existing calls // account for potential ArrayIndexOutOfBoundsException: flowContext.recordAbruptExit(); if (assignment.expression == null) { return analyseCode(currentScope, flowContext, flowInfo); } return assignment .expression .analyseCode( currentScope, flowContext, analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.receiver.checkNPE(currentScope, flowContext, flowInfo); flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo); flowInfo = this.position.analyseCode(currentScope, flowContext, flowInfo); this.position.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); // account for potential ArrayIndexOutOfBoundsException: flowContext.recordAbruptExit(); return flowInfo; } public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { int pc = codeStream.position; this.receiver.generateCode(currentScope, codeStream, true); if (this.receiver instanceof CastExpression // ((type[])null)[0] && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ codeStream.checkcast(this.receiver.resolvedType); } codeStream.recordPositionsFrom(pc, this.sourceStart); this.position.generateCode(currentScope, codeStream, true); assignment.expression.generateCode(currentScope, codeStream, true); codeStream.arrayAtPut(this.resolvedType.id, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } } /** * Code generation for a array reference */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; this.receiver.generateCode(currentScope, codeStream, true); if (this.receiver instanceof CastExpression // ((type[])null)[0] && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ codeStream.checkcast(this.receiver.resolvedType); } this.position.generateCode(currentScope, codeStream, true); codeStream.arrayAt(this.resolvedType.id); // Generating code for the potential runtime type checking if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; // conversion only generated if unboxing if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); switch (isUnboxing ? postConversionType(currentScope).id : this.resolvedType.id) { case T_long : case T_double : codeStream.pop2(); break; default : codeStream.pop(); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { this.receiver.generateCode(currentScope, codeStream, true); if (this.receiver instanceof CastExpression // ((type[])null)[0] && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ codeStream.checkcast(this.receiver.resolvedType); } this.position.generateCode(currentScope, codeStream, true); codeStream.dup2(); codeStream.arrayAt(this.resolvedType.id); int operationTypeID; switch(operationTypeID = (this.implicitConversion & TypeIds.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(this.implicitConversion); // generate the increment value (will by itself be promoted to the operation value) if (expression == IntLiteral.One) { // prefix operation codeStream.generateConstant(expression.constant, this.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); } public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { this.receiver.generateCode(currentScope, codeStream, true); if (this.receiver instanceof CastExpression // ((type[])null)[0] && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ codeStream.checkcast(this.receiver.resolvedType); } this.position.generateCode(currentScope, codeStream, true); codeStream.dup2(); codeStream.arrayAt(this.resolvedType.id); if (valueRequired) { switch(this.resolvedType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2_x2(); break; default : codeStream.dup_x2(); break; } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateConstant( postIncrement.expression.constant, this.implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion( postIncrement.preAssignImplicitConversion); codeStream.arrayAtPut(this.resolvedType.id, false); } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { return FlowInfo.UNKNOWN; } public StringBuffer printExpression(int indent, StringBuffer output) { this.receiver.printExpression(0, output).append('['); return this.position.printExpression(0, output).append(']'); } public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; if (this.receiver instanceof CastExpression // no cast check for ((type[])null)[0] && ((CastExpression)this.receiver).innermostCastedExpression() instanceof NullLiteral) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on } TypeBinding arrayType = this.receiver.resolveType(scope); if (arrayType != null) { this.receiver.computeConversion(scope, arrayType, arrayType); if (arrayType.isArrayType()) { TypeBinding elementType = ((ArrayBinding) arrayType).elementsType(); this.resolvedType = ((this.bits & ASTNode.IsStrictlyAssigned) == 0) ? elementType.capture(scope, this.sourceEnd) : elementType; } else { scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this); } } TypeBinding positionType = this.position.resolveTypeExpecting(scope, TypeBinding.INT); if (positionType != null) { this.position.computeConversion(scope, TypeBinding.INT, positionType); } return this.resolvedType; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.receiver.traverse(visitor, scope); this.position.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Literal.java0000644000175000001440000000330112212041344027305 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.*; import org.eclipse.jdt.internal.compiler.lookup.*; public abstract class Literal extends Expression { public Literal(int s, int e) { this.sourceStart = s; this.sourceEnd = e; } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return flowInfo; } public abstract void computeConstant(); public abstract TypeBinding literalType(BlockScope scope); public StringBuffer printExpression(int indent, StringBuffer output){ return output.append(source()); } public TypeBinding resolveType(BlockScope scope) { // compute the real value, which must range its type's range this.resolvedType = literalType(scope); // in case of error, constant did remain null computeConstant(); if (this.constant == null) { scope.problemReporter().constantOutOfRange(this, this.resolvedType); this.constant = Constant.NotAConstant; } return this.resolvedType; } public abstract char[] source(); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Reference.java0000644000175000001440000002153712212041344027622 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 185682 - Increment/decrement operators mark local variables as read * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public abstract class Reference extends Expression { /** * BaseLevelReference constructor comment. */ public Reference() { super(); } public abstract FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound); public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return flowInfo; } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { if (flowContext.isNullcheckedFieldAccess(this)) { return true; // enough seen } return super.checkNPE(scope, flowContext, flowInfo); } protected boolean checkNullableFieldDereference(Scope scope, FieldBinding field, long sourcePosition) { if ((field.tagBits & TagBits.AnnotationNullable) != 0) { scope.problemReporter().nullableFieldDereference(field, sourcePosition); return true; } return false; } public FieldBinding fieldBinding() { //this method should be sent one FIELD-tagged references // (ref.bits & BindingIds.FIELD != 0)() return null ; } public void fieldStore(Scope currentScope, CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, TypeBinding receiverType, boolean isImplicitThisReceiver, boolean valueRequired) { int pc = codeStream.position; if (fieldBinding.isStatic()) { if (valueRequired) { switch (fieldBinding.type.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2(); break; default : codeStream.dup(); break; } } if (syntheticWriteAccessor == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, fieldBinding, receiverType, isImplicitThisReceiver); codeStream.fieldAccess(Opcodes.OPC_putstatic, fieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */); } } else { // Stack: [owner][new field value] ---> [new field value][owner][new field value] if (valueRequired) { switch (fieldBinding.type.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2_x1(); break; default : codeStream.dup_x1(); break; } } if (syntheticWriteAccessor == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, fieldBinding, receiverType, isImplicitThisReceiver); codeStream.fieldAccess(Opcodes.OPC_putfield, fieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } public abstract void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired); public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired); public abstract void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired); /** * Is the given reference equivalent to the receiver, * meaning that both denote the same path of field reads? * Used from {@link FlowContext#isNullcheckedFieldAccess(Reference)}. */ public boolean isEquivalent(Reference reference) { return false; } public FieldBinding lastFieldBinding() { // override to answer the field designated by the entire reference // (as opposed to fieldBinding() which answers the first field in a QNR) return null; } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { FieldBinding fieldBinding = lastFieldBinding(); if (fieldBinding != null) { if (fieldBinding.isNonNull() || flowContext.isNullcheckedFieldAccess(this)) { return FlowInfo.NON_NULL; } else if (fieldBinding.isNullable()) { return FlowInfo.POTENTIALLY_NULL; } return FlowInfo.UNKNOWN; } return super.nullStatus(flowInfo, flowContext); } /* report if a private field is only read from a 'special operator', * i.e., in a postIncrement expression or a compound assignment, * where the information is never flowing out off the field. */ void reportOnlyUselesslyReadPrivateField(BlockScope currentScope, FieldBinding fieldBinding, boolean valueRequired) { if (valueRequired) { // access is relevant, turn compound use into real use: fieldBinding.compoundUseFlag = 0; fieldBinding.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } else { if (fieldBinding.isUsedOnlyInCompound()) { fieldBinding.compoundUseFlag--; // consume one if (fieldBinding.compoundUseFlag == 0 // report only the last usage && fieldBinding.isOrEnclosedByPrivateType() && (this.implicitConversion & TypeIds.UNBOXING) == 0) // don't report if unboxing is involved (might cause NPE) { // compoundAssignment/postIncrement is the only usage of this field currentScope.problemReporter().unusedPrivateField(fieldBinding.sourceField()); fieldBinding.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; // don't report again } } } } /* report a local/arg that is only read from a 'special operator', * i.e., in a postIncrement expression or a compound assignment, * where the information is never flowing out off the local/arg. */ static void reportOnlyUselesslyReadLocal(BlockScope currentScope, LocalVariableBinding localBinding, boolean valueRequired) { if (localBinding.declaration == null) return; // secret local if ((localBinding.declaration.bits & ASTNode.IsLocalDeclarationReachable) == 0) return; // declaration is unreachable if (localBinding.useFlag >= LocalVariableBinding.USED) return; // we're only interested in cases with only compound access (negative count) if (valueRequired) { // access is relevant localBinding.useFlag = LocalVariableBinding.USED; return; } else { localBinding.useFlag++; if (localBinding.useFlag != LocalVariableBinding.UNUSED) // have all negative counts been consumed? return; // still waiting to see more usages of this kind } // at this point we know we have something to report if (localBinding.declaration instanceof Argument) { // check compiler options to report against unused arguments MethodScope methodScope = currentScope.methodScope(); if (methodScope != null) { MethodBinding method = ((AbstractMethodDeclaration)methodScope.referenceContext()).binding; boolean shouldReport = !method.isMain(); if (method.isImplementing()) { shouldReport &= currentScope.compilerOptions().reportUnusedParameterWhenImplementingAbstract; } else if (method.isOverriding()) { shouldReport &= currentScope.compilerOptions().reportUnusedParameterWhenOverridingConcrete; } if (shouldReport) { // report the case of an argument that is unread except through a special operator currentScope.problemReporter().unusedArgument(localBinding.declaration); } } } else { // report the case of a local variable that is unread except for a special operator currentScope.problemReporter().unusedLocalVariable(localBinding.declaration); } localBinding.useFlag = LocalVariableBinding.USED; // don't report again } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java0000644000175000001440000001357612212041344027777 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.IntConstant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; public class IntLiteral extends NumberLiteral { private static final char[] HEXA_MIN_VALUE = "0x80000000".toCharArray(); //$NON-NLS-1$ private static final char[] HEXA_MINUS_ONE_VALUE = "0xffffffff".toCharArray(); //$NON-NLS-1$ private static final char[] OCTAL_MIN_VALUE = "020000000000".toCharArray(); //$NON-NLS-1$ private static final char[] OCTAL_MINUS_ONE_VALUE = "037777777777".toCharArray(); //$NON-NLS-1$ private static final char[] DECIMAL_MIN_VALUE = "2147483648".toCharArray(); //$NON-NLS-1$ private static final char[] DECIMAL_MAX_VALUE = "2147483647".toCharArray(); //$NON-NLS-1$ private char[] reducedForm; // no underscores public int value; //used for ++ and -- public static final IntLiteral One = new IntLiteral(new char[]{'1'}, null, 0, 0, 1, IntConstant.fromValue(1)); public static IntLiteral buildIntLiteral(char[] token, int s, int e) { // remove '_' and prefix '0' first char[] intReducedToken = removePrefixZerosAndUnderscores(token, false); switch(intReducedToken.length) { case 10 : // 0x80000000 if (CharOperation.equals(intReducedToken, HEXA_MIN_VALUE)) { return new IntLiteralMinValue(token, intReducedToken != token ? intReducedToken : null, s, e); } break; case 12 : // 020000000000 if (CharOperation.equals(intReducedToken, OCTAL_MIN_VALUE)) { return new IntLiteralMinValue(token, intReducedToken != token ? intReducedToken : null, s, e); } break; } return new IntLiteral(token, intReducedToken != token ? intReducedToken : null, s, e); } IntLiteral(char[] token, char[] reducedForm, int start, int end) { super(token, start, end); this.reducedForm = reducedForm; } IntLiteral(char[] token, char[] reducedForm, int start, int end, int value, Constant constant) { super(token, start, end); this.reducedForm = reducedForm; this.value = value; this.constant = constant; } public void computeConstant() { char[] token = this.reducedForm != null ? this.reducedForm : this.source; int tokenLength = token.length; int radix = 10; int j = 0; if (token[0] == '0') { if (tokenLength == 1) { this.constant = IntConstant.fromValue(0); return; } if ((token[1] == 'x') || (token[1] == 'X')) { radix = 16; j = 2; } else if ((token[1] == 'b') || (token[1] == 'B')) { radix = 2; j = 2; } else { radix = 8; j = 1; } } switch(radix) { case 2 : if ((tokenLength - 2) > 32) { // remove 0b or 0B return; /*constant stays null*/ } computeValue(token, tokenLength, radix, j); return; case 16 : if (tokenLength <= 10) { if (CharOperation.equals(token, HEXA_MINUS_ONE_VALUE)) { this.constant = IntConstant.fromValue(-1); return; } computeValue(token, tokenLength, radix, j); return; } break; case 10 : if (tokenLength > DECIMAL_MAX_VALUE.length || (tokenLength == DECIMAL_MAX_VALUE.length && CharOperation.compareTo(token, DECIMAL_MAX_VALUE) > 0)) { return; /*constant stays null*/ } computeValue(token, tokenLength, radix, j); break; case 8 : if (tokenLength <= 12) { if (tokenLength == 12 && token[j] > '4') { return; /*constant stays null*/ } if (CharOperation.equals(token, OCTAL_MINUS_ONE_VALUE)) { this.constant = IntConstant.fromValue(-1); return; } computeValue(token, tokenLength, radix, j); return; } break; } } private void computeValue(char[] token, int tokenLength, int radix, int j) { int digitValue; int computedValue = 0; while (j < tokenLength) { if ((digitValue = ScannerHelper.digit(token[j++],radix)) < 0) { return; /*constant stays null*/ } computedValue = (computedValue * radix) + digitValue ; } this.constant = IntConstant.fromValue(computedValue); } public IntLiteral convertToMinValue() { if (((this.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) { return this; } char[] token = this.reducedForm != null ? this.reducedForm : this.source; switch(token.length) { case 10 : // 2147483648 if (CharOperation.equals(token, DECIMAL_MIN_VALUE)) { return new IntLiteralMinValue(this.source, this.reducedForm, this.sourceStart, this.sourceEnd); } break; } return this; } /** * Code generation for long 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(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.INT; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java0000644000175000001440000002444412212041344030744 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; 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; /** * The representation of this pair in the type system. */ public ElementValuePair compilerElementPair = null; public MemberValuePair(char[] token, int sourceStart, int sourceEnd, Expression value) { this.name = token; this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; this.value = value; if (value instanceof ArrayInitializer) { value.bits |= IsAnnotationDefaultValue; } } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer) */ public StringBuffer print(int indent, StringBuffer output) { output .append(this.name) .append(" = "); //$NON-NLS-1$ this.value.print(0, output); return output; } public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) { if (this.value == null) { this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding); return; } if (requiredType == null) { // fault tolerance: keep resolving if (this.value instanceof ArrayInitializer) { this.value.resolveTypeExpecting(scope, null); } else { this.value.resolveType(scope); } this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding); return; } this.value.setExpectedType(requiredType); // needed in case of generic method invocation TypeBinding valueType; if (this.value instanceof ArrayInitializer) { ArrayInitializer initializer = (ArrayInitializer) this.value; valueType = initializer.resolveTypeExpecting(scope, this.binding.returnType); } else if (this.value instanceof ArrayAllocationExpression) { scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value); this.value.resolveType(scope); valueType = null; // no need to pursue } else { valueType = this.value.resolveType(scope); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=248897 ASTVisitor visitor = new ASTVisitor() { public boolean visit(SingleNameReference reference, BlockScope scop) { if (reference.binding instanceof LocalVariableBinding) { ((LocalVariableBinding) reference.binding).useFlag = LocalVariableBinding.USED; } return true; } }; this.value.traverse(visitor, scope); } this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding); if (valueType == null) return; TypeBinding leafType = requiredType.leafComponentType(); if (!(this.value.isConstantValueOfTypeAssignableToType(valueType, requiredType) || valueType.isCompatibleWith(requiredType))) { if (!(requiredType.isArrayType() && requiredType.dimensions() == 1 && (this.value.isConstantValueOfTypeAssignableToType(valueType, leafType) || valueType.isCompatibleWith(leafType)))) { if (leafType.isAnnotationType() && !valueType.isAnnotationType()) { scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType); } else { scope.problemReporter().typeMismatchError(valueType, requiredType, this.value, null); } 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++) { Expression expression = expressions[i]; if (expression.resolvedType == null) continue; // fault-tolerance if (expression.constant == Constant.NotAConstant) { scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, expressions[i], false); } } } } else if (this.value.constant == Constant.NotAConstant) { if (valueType.isArrayType()) { scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value); } else { scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, false); } } 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++) { Expression currentExpression = expressions[i]; if (!(currentExpression instanceof ClassLiteralAccess)) { scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, currentExpression); } } } } else if (!(this.value instanceof ClassLiteralAccess)) { scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, this.value); } break checkAnnotationMethodType; } if (leafType.isEnum()) { if (this.value instanceof NullLiteral) { scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, true); } else 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++) { Expression currentExpression = expressions[i]; if (currentExpression instanceof NullLiteral) { scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, currentExpression, true); } else if (currentExpression instanceof NameReference) { NameReference nameReference = (NameReference) currentExpression; final Binding nameReferenceBinding = nameReference.binding; if (nameReferenceBinding.kind() == Binding.FIELD) { FieldBinding fieldBinding = (FieldBinding) nameReferenceBinding; if (!fieldBinding.declaringClass.isEnum()) { scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, currentExpression, true); } } } } } } else if (this.value instanceof NameReference) { NameReference nameReference = (NameReference) this.value; final Binding nameReferenceBinding = nameReference.binding; if (nameReferenceBinding.kind() == Binding.FIELD) { FieldBinding fieldBinding = (FieldBinding) nameReferenceBinding; if (!fieldBinding.declaringClass.isEnum()) { if (!fieldBinding.type.isArrayType()) { scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, true); } else { scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value); } } } } else { scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, true); } break checkAnnotationMethodType; } if (leafType.isAnnotationType()) { if (!valueType.leafComponentType().isAnnotationType()) { // check annotation type and also reject null literal scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType); } else 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++) { Expression currentExpression = expressions[i]; if (currentExpression instanceof NullLiteral || !(currentExpression instanceof Annotation)) { scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, currentExpression, leafType); } } } } else if (!(this.value instanceof Annotation)) { scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType); } 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); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Annotation.java0000644000175000001440000004532612212041344030040 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 365662 - [compiler][null] warn on contradictory and redundant null annotations * bug 331649 - [compiler][null] consider null annotations for fields *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.IrritantSet; import org.eclipse.jdt.internal.compiler.lookup.*; /** * Annotation */ public abstract class Annotation extends Expression { final static MemberValuePair[] NoValuePairs = new MemberValuePair[0]; private static final long TAGBITS_NULLABLE_OR_NONNULL = TagBits.AnnotationNullable|TagBits.AnnotationNonNull; public int declarationSourceEnd; public Binding recipient; public TypeReference type; /** * The representation of this annotation in the type system. */ private AnnotationBinding compilerAnnotation = null; 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 } public ElementValuePair[] computeElementValuePairs() { return Binding.NO_ELEMENT_VALUE_PAIRS; } /** * 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; case TypeIds.T_JavaLangSafeVarargs : tagBits |= TagBits.AnnotationSafeVarargs; break; case TypeIds.T_JavaLangInvokeMethodHandlePolymorphicSignature : tagBits |= TagBits.AnnotationPolymorphicSignature; break; case TypeIds.T_ConfiguredAnnotationNullable : tagBits |= TagBits.AnnotationNullable; break; case TypeIds.T_ConfiguredAnnotationNonNull : tagBits |= TagBits.AnnotationNonNull; break; case TypeIds.T_ConfiguredAnnotationNonNullByDefault : if (valueAttribute != null && valueAttribute.value instanceof FalseLiteral) { // parameter 'false' means: this annotation cancels any defaults tagBits |= TagBits.AnnotationNullUnspecifiedByDefault; break; } tagBits |= TagBits.AnnotationNonNullByDefault; break; } return tagBits; } public AnnotationBinding getCompilerAnnotation() { return this.compilerAnnotation; } public boolean isRuntimeInvisible() { final TypeBinding annotationBinding = this.resolvedType; if (annotationBinding == null) { return false; } long metaTagBits = annotationBinding.getAnnotationTagBits(); // could be forward reference if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0) return true; // by default the retention is CLASS return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention; } public boolean isRuntimeVisible() { final TypeBinding annotationBinding = this.resolvedType; if (annotationBinding == null) { return false; } long metaTagBits = annotationBinding.getAnnotationTagBits(); if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0) return false; // by default the retention is CLASS return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention; } public abstract MemberValuePair[] memberValuePairs(); public StringBuffer printExpression(int indent, StringBuffer output) { output.append('@'); this.type.printExpression(0, output); return output; } public void recordSuppressWarnings(Scope scope, int startSuppresss, int endSuppress, boolean isSuppressingWarnings) { IrritantSet suppressWarningIrritants = null; MemberValuePair[] pairs = memberValuePairs(); pairLoop: for (int i = 0, length = pairs.length; i < length; i++) { MemberValuePair pair = pairs[i]; if (CharOperation.equals(pair.name, TypeConstants.VALUE)) { Expression value = pair.value; if (value instanceof ArrayInitializer) { ArrayInitializer initializer = (ArrayInitializer) value; Expression[] inits = initializer.expressions; if (inits != null) { for (int j = 0, initsLength = inits.length; j < initsLength; j++) { Constant cst = inits[j].constant; if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) { IrritantSet irritants = CompilerOptions.warningTokenToIrritants(cst.stringValue()); if (irritants != null) { if (suppressWarningIrritants == null) { suppressWarningIrritants = new IrritantSet(irritants); } else if (suppressWarningIrritants.set(irritants) == null) { scope.problemReporter().unusedWarningToken(inits[j]); } } else { scope.problemReporter().unhandledWarningToken(inits[j]); } } } } } else { Constant cst = value.constant; if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) { IrritantSet irritants = CompilerOptions.warningTokenToIrritants(cst.stringValue()); if (irritants != null) { suppressWarningIrritants = new IrritantSet(irritants); // TODO: should check for unused warning token against enclosing annotation as well ? } else { scope.problemReporter().unhandledWarningToken(value); } } } break pairLoop; } } if (isSuppressingWarnings && suppressWarningIrritants != null) { scope.referenceCompilationUnit().recordSuppressWarnings(suppressWarningIrritants, this, startSuppresss, endSuppress); } } public TypeBinding resolveType(BlockScope scope) { if (this.compilerAnnotation != null) return this.resolvedType; this.constant = 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() && typeBinding.isValidBinding()) { scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type, null); return null; } ReferenceBinding annotationType = (ReferenceBinding) this.resolvedType; MethodBinding[] methods = annotationType.methods(); // clone valuePairs to keep track of unused ones MemberValuePair[] originalValuePairs = memberValuePairs(); MemberValuePair valueAttribute = null; // remember the first 'value' pair MemberValuePair[] pairs; int pairsLength = originalValuePairs.length; if (pairsLength > 0) { System.arraycopy(originalValuePairs, 0, pairs = new MemberValuePair[pairsLength], 0, pairsLength); } else { pairs = originalValuePairs; } 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 pair = pairs[j]; if (pair == null) continue nextPair; char[] name = pair.name; if (CharOperation.equals(name, selector)) { if (valueAttribute == null && CharOperation.equals(name, TypeConstants.VALUE)) { valueAttribute = pair; } pair.binding = method; pair.resolveTypeExpecting(scope, method.returnType); pairs[j] = null; // consumed foundValue = true; // check duplicates boolean foundDuplicate = false; for (int k = j+1; k < pairsLength; k++) { MemberValuePair otherPair = pairs[k]; if (otherPair == null) continue; if (CharOperation.equals(otherPair.name, selector)) { foundDuplicate = true; scope.problemReporter().duplicateAnnotationValue(annotationType, otherPair); otherPair.binding = method; otherPair.resolveTypeExpecting(scope, method.returnType); pairs[k] = null; } } if (foundDuplicate) { scope.problemReporter().duplicateAnnotationValue(annotationType, pair); continue nextMember; } } } if (!foundValue && (method.modifiers & ClassFileConstants.AccAnnotationDefault) == 0 && (this.bits & IsRecovered) == 0) { scope.problemReporter().missingValueForAnnotationMember(this, selector); } } // check unused pairs for (int i = 0; i < pairsLength; i++) { if (pairs[i] != null) { scope.problemReporter().undefinedAnnotationValue(annotationType, pairs[i]); pairs[i].resolveTypeExpecting(scope, null); // resilient } } // if (scope.compilerOptions().storeAnnotations) this.compilerAnnotation = scope.environment().createAnnotation((ReferenceBinding) this.resolvedType, computeElementValuePairs()); // recognize standard annotations ? long tagBits = detectStandardAnnotation(scope, annotationType, valueAttribute); // record annotation positions in the compilation result scope.referenceCompilationUnit().recordSuppressWarnings(IrritantSet.NLS, null, this.sourceStart, this.declarationSourceEnd); if (this.recipient != null) { if (tagBits != 0) { // tag bits onto recipient switch (this.recipient.kind()) { case Binding.PACKAGE : ((PackageBinding)this.recipient).tagBits |= tagBits; break; case Binding.TYPE : case Binding.GENERIC_TYPE : SourceTypeBinding sourceType = (SourceTypeBinding) this.recipient; sourceType.tagBits |= tagBits; if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { TypeDeclaration typeDeclaration = sourceType.scope.referenceContext; int start; if (scope.referenceCompilationUnit().types[0] == typeDeclaration) { start = 0; } else { start = typeDeclaration.declarationSourceStart; } recordSuppressWarnings(scope, start, typeDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); } break; case Binding.METHOD : MethodBinding sourceMethod = (MethodBinding) this.recipient; sourceMethod.tagBits |= tagBits; if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { sourceType = (SourceTypeBinding) sourceMethod.declaringClass; AbstractMethodDeclaration methodDeclaration = sourceType.scope.referenceContext.declarationOf(sourceMethod); recordSuppressWarnings(scope, methodDeclaration.declarationSourceStart, methodDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); } if ((sourceMethod.tagBits & TAGBITS_NULLABLE_OR_NONNULL) == TAGBITS_NULLABLE_OR_NONNULL) { scope.problemReporter().contradictoryNullAnnotations(this); sourceMethod.tagBits &= ~TAGBITS_NULLABLE_OR_NONNULL; // avoid secondary problems } break; case Binding.FIELD : FieldBinding sourceField = (FieldBinding) this.recipient; sourceField.tagBits |= tagBits; if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { sourceType = (SourceTypeBinding) sourceField.declaringClass; FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField); recordSuppressWarnings(scope, fieldDeclaration.declarationSourceStart, fieldDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); } if ((sourceField.tagBits & TAGBITS_NULLABLE_OR_NONNULL) == TAGBITS_NULLABLE_OR_NONNULL) { scope.problemReporter().contradictoryNullAnnotations(this); sourceField.tagBits &= ~TAGBITS_NULLABLE_OR_NONNULL; // avoid secondary problems } break; case Binding.LOCAL : LocalVariableBinding variable = (LocalVariableBinding) this.recipient; variable.tagBits |= tagBits; if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { LocalDeclaration localDeclaration = variable.declaration; recordSuppressWarnings(scope, localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); } if ((variable.tagBits & TAGBITS_NULLABLE_OR_NONNULL) == TAGBITS_NULLABLE_OR_NONNULL) { scope.problemReporter().contradictoryNullAnnotations(this); variable.tagBits &= ~TAGBITS_NULLABLE_OR_NONNULL; // avoid secondary problems } break; } } // check (meta)target compatibility checkTargetCompatibility: { long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) // does not specify any target restriction break checkTargetCompatibility; switch (this.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; } else if ((metaTagBits & TagBits.AnnotationForPackage) != 0) { if (CharOperation.equals(((ReferenceBinding)this.recipient).sourceName, TypeConstants.PACKAGE_INFO_NAME)) 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).tagBits & TagBits.IsArgument) != 0) { 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); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java0000644000175000001440000022200412212041344031567 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Perry James - nullStatus method improvement (165346) * Stephan Herrmann - Contribution for * bug 383368 - [compiler][null] syntactic null analysis for field references *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.util.Util; public abstract class OperatorExpression extends Expression implements OperatorIds { public static int[][] OperatorSignatures = new int[NumberOfTables][]; static {classInitialize();} /** * OperatorExpression constructor comment. */ public OperatorExpression() { super(); } public static final void classInitialize() { OperatorSignatures[AND] = get_AND(); OperatorSignatures[AND_AND] = get_AND_AND(); OperatorSignatures[DIVIDE] = get_DIVIDE(); OperatorSignatures[EQUAL_EQUAL] = get_EQUAL_EQUAL(); OperatorSignatures[GREATER] = get_GREATER(); OperatorSignatures[GREATER_EQUAL] = get_GREATER_EQUAL(); OperatorSignatures[LEFT_SHIFT] = get_LEFT_SHIFT(); OperatorSignatures[LESS] = get_LESS(); OperatorSignatures[LESS_EQUAL] = get_LESS_EQUAL(); OperatorSignatures[MINUS] = get_MINUS(); OperatorSignatures[MULTIPLY] = get_MULTIPLY(); OperatorSignatures[OR] = get_OR(); OperatorSignatures[OR_OR] = get_OR_OR(); OperatorSignatures[PLUS] = get_PLUS(); OperatorSignatures[REMAINDER] = get_REMAINDER(); OperatorSignatures[RIGHT_SHIFT] = get_RIGHT_SHIFT(); OperatorSignatures[UNSIGNED_RIGHT_SHIFT] = get_UNSIGNED_RIGHT_SHIFT(); OperatorSignatures[XOR] = get_XOR(); } public static final String generateTableTestCase(){ //return a String which is a java method allowing to test //the non zero entries of all tables /* org.eclipse.jdt.internal.compiler.ast. OperatorExpression.generateTableTestCase(); */ int[] operators = new int[]{AND,AND_AND,DIVIDE,GREATER,GREATER_EQUAL, LEFT_SHIFT,LESS,LESS_EQUAL,MINUS,MULTIPLY,OR,OR_OR,PLUS,REMAINDER, RIGHT_SHIFT,UNSIGNED_RIGHT_SHIFT,XOR}; class Decode { public final String constant(int code){ switch(code){ case T_boolean : return "true"; //$NON-NLS-1$ case T_byte : return "((byte) 3)"; //$NON-NLS-1$ case T_char : return "'A'"; //$NON-NLS-1$ case T_double : return "300.0d"; //$NON-NLS-1$ 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_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_JavaLangObject : return "null";} //$NON-NLS-1$ return Util.EMPTY_STRING;} public final String type(int code){ switch(code){ case T_boolean : return "z"; //$NON-NLS-1$ case T_byte : return "b"; //$NON-NLS-1$ case T_char : return "c"; //$NON-NLS-1$ case T_double : return "d"; //$NON-NLS-1$ 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_JavaLangString : return "str"; //$NON-NLS-1$ case T_null : return "null"; //$NON-NLS-1$ case T_short : return "s"; //$NON-NLS-1$ case T_JavaLangObject : return "obj";} //$NON-NLS-1$ return "xxx";} //$NON-NLS-1$ public final String operator(int operator){ switch (operator) { case EQUAL_EQUAL : return "=="; //$NON-NLS-1$ case LESS_EQUAL : return "<="; //$NON-NLS-1$ case GREATER_EQUAL :return ">="; //$NON-NLS-1$ case LEFT_SHIFT : return "<<"; //$NON-NLS-1$ case RIGHT_SHIFT : return ">>"; //$NON-NLS-1$ case UNSIGNED_RIGHT_SHIFT : return ">>>"; //$NON-NLS-1$ case OR_OR :return "||"; //$NON-NLS-1$ case AND_AND : return "&&"; //$NON-NLS-1$ case PLUS : return "+"; //$NON-NLS-1$ case MINUS : return "-"; //$NON-NLS-1$ case NOT : return "!"; //$NON-NLS-1$ case REMAINDER : return "%"; //$NON-NLS-1$ case XOR : return "^"; //$NON-NLS-1$ case AND : return "&"; //$NON-NLS-1$ case MULTIPLY : return "*"; //$NON-NLS-1$ case OR : return "|"; //$NON-NLS-1$ case TWIDDLE : return "~"; //$NON-NLS-1$ case DIVIDE : return "/"; //$NON-NLS-1$ case GREATER : return ">"; //$NON-NLS-1$ case LESS : return "<"; } //$NON-NLS-1$ return "????";} //$NON-NLS-1$ } Decode decode = new Decode(); String s; s = "\tpublic static void binaryOperationTablesTestCase(){\n" + //$NON-NLS-1$ "\t\t//TC test : all binary operation (described in tables)\n"+ //$NON-NLS-1$ "\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_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$ "\t\tfloat f0; \t float f\t= "+decode.constant(T_float)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$ "\t\tdouble d0;\t double d\t= "+decode.constant(T_double)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$ "\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_JavaLangObject)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$ "\n"; //$NON-NLS-1$ int error = 0; for (int i=0; i < operators.length; i++) { int operator = operators[i]; for (int left=0; left<16;left++) for (int right=0; right<16;right++) { int result = (OperatorSignatures[operator][(left<<4)+right]) & 0x0000F; if (result != T_undefined) //1/ First regular computation then 2/ comparaison //with a compile time constant (generated by the compiler) // z0 = s >= s; // if ( z0 != (((short) 5) >= ((short) 5))) // System.out.println(155); { 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_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$ +decode.constant(right)+"))\n"; //$NON-NLS-1$ s += "\t\t\tSystem.out.println("+ (++error) +");\n"; //$NON-NLS-1$ //$NON-NLS-2$ } } } return s += "\n\t\tSystem.out.println(\"binary tables test : done\");}"; //$NON-NLS-1$ } public static final int[] get_AND(){ //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 int[] table = new int[16*16]; // table[(T_undefined<<4)+T_undefined] = T_undefined; // table[(T_undefined<<4)+T_byte] = T_undefined; // table[(T_undefined<<4)+T_long] = T_undefined; // table[(T_undefined<<4)+T_short] = T_undefined; // table[(T_undefined<<4)+T_void] = T_undefined; // table[(T_undefined<<4)+T_String] = T_undefined; // table[(T_undefined<<4)+T_Object] = T_undefined; // table[(T_undefined<<4)+T_double] = T_undefined; // table[(T_undefined<<4)+T_float] = T_undefined; // table[(T_undefined<<4)+T_boolean] = T_undefined; // table[(T_undefined<<4)+T_char] = T_undefined; // table[(T_undefined<<4)+T_int] = T_undefined; // table[(T_undefined<<4)+T_null] = T_undefined; // table[(T_byte<<4)+T_undefined] = T_undefined; table[(T_byte<<4)+T_byte] = (Byte2Int<<12) +(Byte2Int<<4) +T_int; 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] = T_undefined; // table[(T_byte<<4)+T_Object] = T_undefined; // table[(T_byte<<4)+T_double] = T_undefined; // table[(T_byte<<4)+T_float] = T_undefined; // table[(T_byte<<4)+T_boolean] = T_undefined; table[(T_byte<<4)+T_char] = (Byte2Int<<12) +(Char2Int<<4) +T_int; table[(T_byte<<4)+T_int] = (Byte2Int<<12) +(Int2Int<<4) +T_int; // table[(T_byte<<4)+T_null] = T_undefined; // table[(T_long<<4)+T_undefined] = T_undefined; table[(T_long<<4)+T_byte] = (Long2Long<<12)+(Byte2Long<<4)+T_long; 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] = T_undefined; // table[(T_long<<4)+T_Object] = T_undefined; // table[(T_long<<4)+T_double] = T_undefined; // table[(T_long<<4)+T_float] = T_undefined; // table[(T_long<<4)+T_boolean] = T_undefined; table[(T_long<<4)+T_char] = (Long2Long<<12)+(Char2Long<<4)+T_long; table[(T_long<<4)+T_int] = (Long2Long<<12)+(Int2Long<<4)+T_long; // table[(T_long<<4)+T_null] = T_undefined; // table[(T_short<<4)+T_undefined] = T_undefined; table[(T_short<<4)+T_byte] = (Short2Int<<12)+(Byte2Int<<4)+T_int; 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] = T_undefined; // table[(T_short<<4)+T_Object] = T_undefined; // table[(T_short<<4)+T_double] = T_undefined; // table[(T_short<<4)+T_float] = T_undefined; // table[(T_short<<4)+T_boolean] = T_undefined; table[(T_short<<4)+T_char] = (Short2Int<<12)+(Char2Int<<4)+T_int; table[(T_short<<4)+T_int] = (Short2Int<<12)+(Int2Int<<4)+T_int; // table[(T_short<<4)+T_null] = T_undefined; // table[(T_void<<4)+T_undefined] = T_undefined; // table[(T_void<<4)+T_byte] = T_undefined; // table[(T_void<<4)+T_long] = T_undefined; // table[(T_void<<4)+T_short] = T_undefined; // table[(T_void<<4)+T_void] = T_undefined; // table[(T_void<<4)+T_String] = T_undefined; // table[(T_void<<4)+T_Object] = T_undefined; // table[(T_void<<4)+T_double] = T_undefined; // table[(T_void<<4)+T_float] = T_undefined; // table[(T_void<<4)+T_boolean] = T_undefined; // table[(T_void<<4)+T_char] = T_undefined; // table[(T_void<<4)+T_int] = T_undefined; // table[(T_void<<4)+T_null] = T_undefined; // table[(T_String<<4)+T_undefined] = T_undefined; // 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_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] = T_undefined; // table[(T_Object<<4)+T_Object] = T_undefined; // 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] = T_undefined; // table[(T_double<<4)+T_undefined] = T_undefined; // table[(T_double<<4)+T_byte] = T_undefined; // table[(T_double<<4)+T_long] = T_undefined; // table[(T_double<<4)+T_short] = T_undefined; // table[(T_double<<4)+T_void] = T_undefined; // table[(T_double<<4)+T_String] = T_undefined; // table[(T_double<<4)+T_Object] = T_undefined; // table[(T_double<<4)+T_double] = T_undefined; // table[(T_double<<4)+T_float] = T_undefined; // table[(T_double<<4)+T_boolean] = T_undefined; // table[(T_double<<4)+T_char] = T_undefined; // table[(T_double<<4)+T_int] = T_undefined; // table[(T_double<<4)+T_null] = T_undefined; // table[(T_float<<4)+T_undefined] = T_undefined; // table[(T_float<<4)+T_byte] = T_undefined; // table[(T_float<<4)+T_long] = T_undefined; // table[(T_float<<4)+T_short] = T_undefined; // table[(T_float<<4)+T_void] = T_undefined; // table[(T_float<<4)+T_String] = T_undefined; // table[(T_float<<4)+T_Object] = T_undefined; // table[(T_float<<4)+T_double] = T_undefined; // table[(T_float<<4)+T_float] = T_undefined; // table[(T_float<<4)+T_boolean] = T_undefined; // table[(T_float<<4)+T_char] = T_undefined; // table[(T_float<<4)+T_int] = T_undefined; // table[(T_float<<4)+T_null] = T_undefined; // table[(T_boolean<<4)+T_undefined] = T_undefined; // table[(T_boolean<<4)+T_byte] = T_undefined; // 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] = T_undefined; // table[(T_boolean<<4)+T_Object] = T_undefined; // table[(T_boolean<<4)+T_double] = T_undefined; // table[(T_boolean<<4)+T_float] = T_undefined; table[(T_boolean<<4)+T_boolean] = (Boolean2Boolean << 12)+(Boolean2Boolean << 4)+T_boolean; // table[(T_boolean<<4)+T_char] = T_undefined; // table[(T_boolean<<4)+T_int] = T_undefined; // table[(T_boolean<<4)+T_null] = T_undefined; // table[(T_char<<4)+T_undefined] = T_undefined; table[(T_char<<4)+T_byte] = (Char2Int<<12)+(Byte2Int<<4)+T_int; 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] = T_undefined; // table[(T_char<<4)+T_Object] = T_undefined; // table[(T_char<<4)+T_double] = T_undefined; // table[(T_char<<4)+T_float] = T_undefined; // table[(T_char<<4)+T_boolean] = T_undefined; table[(T_char<<4)+T_char] = (Char2Int<<12)+(Char2Int<<4)+T_int; table[(T_char<<4)+T_int] = (Char2Int<<12)+(Int2Int<<4)+T_int; // table[(T_char<<4)+T_null] = T_undefined; // table[(T_int<<4)+T_undefined] = T_undefined; table[(T_int<<4)+T_byte] = (Int2Int<<12)+(Byte2Int<<4)+T_int; 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] = T_undefined; // table[(T_int<<4)+T_Object] = T_undefined; // table[(T_int<<4)+T_double] = T_undefined; // table[(T_int<<4)+T_float] = T_undefined; // table[(T_int<<4)+T_boolean] = T_undefined; table[(T_int<<4)+T_char] = (Int2Int<<12)+(Char2Int<<4)+T_int; table[(T_int<<4)+T_int] = (Int2Int<<12)+(Int2Int<<4)+T_int; // table[(T_int<<4)+T_null] = T_undefined; // table[(T_null<<4)+T_undefined] = T_undefined; // table[(T_null<<4)+T_byte] = T_undefined; // 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_undefined; // table[(T_null<<4)+T_Object] = T_undefined; // 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] = T_undefined; return table; } public static final int[] get_AND_AND(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 int[] table = new int[16*16]; // table[(T_undefined<<4)+T_undefined] = T_undefined; // table[(T_undefined<<4)+T_byte] = T_undefined; // table[(T_undefined<<4)+T_long] = T_undefined; // table[(T_undefined<<4)+T_short] = T_undefined; // table[(T_undefined<<4)+T_void] = T_undefined; // table[(T_undefined<<4)+T_String] = T_undefined; // table[(T_undefined<<4)+T_Object] = T_undefined; // table[(T_undefined<<4)+T_double] = T_undefined; // table[(T_undefined<<4)+T_float] = T_undefined; // table[(T_undefined<<4)+T_boolean] = T_undefined; // table[(T_undefined<<4)+T_char] = T_undefined; // table[(T_undefined<<4)+T_int] = T_undefined; // table[(T_undefined<<4)+T_null] = T_undefined; // table[(T_byte<<4)+T_undefined] = T_undefined; // table[(T_byte<<4)+T_byte] = T_undefined; // table[(T_byte<<4)+T_long] = T_undefined; // table[(T_byte<<4)+T_short] = T_undefined; // table[(T_byte<<4)+T_void] = T_undefined; // table[(T_byte<<4)+T_String] = T_undefined; // table[(T_byte<<4)+T_Object] = T_undefined; // table[(T_byte<<4)+T_double] = T_undefined; // table[(T_byte<<4)+T_float] = T_undefined; // table[(T_byte<<4)+T_boolean] = T_undefined; // table[(T_byte<<4)+T_char] = T_undefined; // table[(T_byte<<4)+T_int] = T_undefined; // table[(T_byte<<4)+T_null] = T_undefined; // table[(T_long<<4)+T_undefined] = T_undefined; // table[(T_long<<4)+T_byte] = T_undefined; // table[(T_long<<4)+T_long] = T_undefined; // table[(T_long<<4)+T_short] = T_undefined; // table[(T_long<<4)+T_void] = T_undefined; // table[(T_long<<4)+T_String] = T_undefined; // table[(T_long<<4)+T_Object] = T_undefined; // table[(T_long<<4)+T_double] = T_undefined; // table[(T_long<<4)+T_float] = T_undefined; // table[(T_long<<4)+T_boolean] = T_undefined; // table[(T_long<<4)+T_char] = T_undefined; // table[(T_long<<4)+T_int] = T_undefined; // table[(T_long<<4)+T_null] = T_undefined; // table[(T_short<<4)+T_undefined] = T_undefined; // table[(T_short<<4)+T_byte] = T_undefined; // table[(T_short<<4)+T_long] = T_undefined; // table[(T_short<<4)+T_short] = T_undefined; // table[(T_short<<4)+T_void] = T_undefined; // table[(T_short<<4)+T_String] = T_undefined; // table[(T_short<<4)+T_Object] = T_undefined; // table[(T_short<<4)+T_double] = T_undefined; // table[(T_short<<4)+T_float] = T_undefined; // table[(T_short<<4)+T_boolean] = T_undefined; // table[(T_short<<4)+T_char] = T_undefined; // table[(T_short<<4)+T_int] = T_undefined; // table[(T_short<<4)+T_null] = T_undefined; // table[(T_void<<4)+T_undefined] = T_undefined; // table[(T_void<<4)+T_byte] = T_undefined; // table[(T_void<<4)+T_long] = T_undefined; // table[(T_void<<4)+T_short] = T_undefined; // table[(T_void<<4)+T_void] = T_undefined; // table[(T_void<<4)+T_String] = T_undefined; // table[(T_void<<4)+T_Object] = T_undefined; // table[(T_void<<4)+T_double] = T_undefined; // table[(T_void<<4)+T_float] = T_undefined; // table[(T_void<<4)+T_boolean] = T_undefined; // table[(T_void<<4)+T_char] = T_undefined; // table[(T_void<<4)+T_int] = T_undefined; // table[(T_void<<4)+T_null] = T_undefined; // table[(T_String<<4)+T_undefined] = T_undefined; // 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_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] = T_undefined; // table[(T_Object<<4)+T_Object] = T_undefined; // 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] = T_undefined; // table[(T_double<<4)+T_undefined] = T_undefined; // table[(T_double<<4)+T_byte] = T_undefined; // table[(T_double<<4)+T_long] = T_undefined; // table[(T_double<<4)+T_short] = T_undefined; // table[(T_double<<4)+T_void] = T_undefined; // table[(T_double<<4)+T_String] = T_undefined; // table[(T_double<<4)+T_Object] = T_undefined; // table[(T_double<<4)+T_double] = T_undefined; // table[(T_double<<4)+T_float] = T_undefined; // table[(T_double<<4)+T_boolean] = T_undefined; // table[(T_double<<4)+T_char] = T_undefined; // table[(T_double<<4)+T_int] = T_undefined; // table[(T_double<<4)+T_null] = T_undefined; // table[(T_float<<4)+T_undefined] = T_undefined; // table[(T_float<<4)+T_byte] = T_undefined; // table[(T_float<<4)+T_long] = T_undefined; // table[(T_float<<4)+T_short] = T_undefined; // table[(T_float<<4)+T_void] = T_undefined; // table[(T_float<<4)+T_String] = T_undefined; // table[(T_float<<4)+T_Object] = T_undefined; // table[(T_float<<4)+T_double] = T_undefined; // table[(T_float<<4)+T_float] = T_undefined; // table[(T_float<<4)+T_boolean] = T_undefined; // table[(T_float<<4)+T_char] = T_undefined; // table[(T_float<<4)+T_int] = T_undefined; // table[(T_float<<4)+T_null] = T_undefined; // table[(T_boolean<<4)+T_undefined] = T_undefined; // table[(T_boolean<<4)+T_byte] = T_undefined; // 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] = T_undefined; // table[(T_boolean<<4)+T_Object] = T_undefined; // table[(T_boolean<<4)+T_double] = T_undefined; // table[(T_boolean<<4)+T_float] = T_undefined; table[(T_boolean<<4)+T_boolean] = (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean; // table[(T_boolean<<4)+T_char] = T_undefined; // table[(T_boolean<<4)+T_int] = T_undefined; // table[(T_boolean<<4)+T_null] = T_undefined; // table[(T_char<<4)+T_undefined] = T_undefined; // table[(T_char<<4)+T_byte] = T_undefined; // table[(T_char<<4)+T_long] = T_undefined; // table[(T_char<<4)+T_short] = T_undefined; // table[(T_char<<4)+T_void] = T_undefined; // table[(T_char<<4)+T_String] = T_undefined; // table[(T_char<<4)+T_Object] = T_undefined; // table[(T_char<<4)+T_double] = T_undefined; // table[(T_char<<4)+T_float] = T_undefined; // table[(T_char<<4)+T_boolean] = T_undefined; // table[(T_char<<4)+T_char] = T_undefined; // table[(T_char<<4)+T_int] = T_undefined; // table[(T_char<<4)+T_null] = T_undefined; // table[(T_int<<4)+T_undefined] = T_undefined; // table[(T_int<<4)+T_byte] = T_undefined; // table[(T_int<<4)+T_long] = T_undefined; // table[(T_int<<4)+T_short] = T_undefined; // table[(T_int<<4)+T_void] = T_undefined; // table[(T_int<<4)+T_String] = T_undefined; // table[(T_int<<4)+T_Object] = T_undefined; // table[(T_int<<4)+T_double] = T_undefined; // table[(T_int<<4)+T_float] = T_undefined; // table[(T_int<<4)+T_boolean] = T_undefined; // table[(T_int<<4)+T_char] = T_undefined; // table[(T_int<<4)+T_int] = T_undefined; // table[(T_int<<4)+T_null] = T_undefined; // table[(T_null<<4)+T_undefined] = T_undefined; // table[(T_null<<4)+T_byte] = T_undefined; // 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_undefined; // table[(T_null<<4)+T_Object] = T_undefined; // 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] = T_undefined; return table; } public static final int[] get_DIVIDE(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_MINUS(); } public static final int[] get_EQUAL_EQUAL(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 int[] table = new int[16*16]; // table[(T_undefined<<4)+T_undefined] = T_undefined; // table[(T_undefined<<4)+T_byte] = T_undefined; // table[(T_undefined<<4)+T_long] = T_undefined; // table[(T_undefined<<4)+T_short] = T_undefined; // table[(T_undefined<<4)+T_void] = T_undefined; // table[(T_undefined<<4)+T_String] = T_undefined; // table[(T_undefined<<4)+T_Object] = T_undefined; // table[(T_undefined<<4)+T_double] = T_undefined; // table[(T_undefined<<4)+T_float] = T_undefined; // table[(T_undefined<<4)+T_boolean] = T_undefined; // table[(T_undefined<<4)+T_char] = T_undefined; // table[(T_undefined<<4)+T_int] = T_undefined; // table[(T_undefined<<4)+T_null] = T_undefined; // table[(T_byte<<4)+T_undefined] = T_undefined; table[(T_byte<<4)+T_byte] = (Byte2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_byte<<4)+T_long] = (Byte2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_byte<<4)+T_short] = (Byte2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_byte<<4)+T_void] = T_undefined; // table[(T_byte<<4)+T_String] = T_undefined; // table[(T_byte<<4)+T_Object] = T_undefined; table[(T_byte<<4)+T_double] = (Byte2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_byte<<4)+T_float] = (Byte2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_byte<<4)+T_boolean] = T_undefined; table[(T_byte<<4)+T_char] = (Byte2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_byte<<4)+T_int] = (Byte2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_byte<<4)+T_null] = T_undefined; // table[(T_long<<4)+T_undefined] = T_undefined; table[(T_long<<4)+T_byte] = (Long2Long<<12)+(Byte2Long<<4)+T_boolean; table[(T_long<<4)+T_long] = (Long2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_long<<4)+T_short] = (Long2Long<<12)+(Short2Long<<4)+T_boolean; // table[(T_long<<4)+T_void] = T_undefined; // table[(T_long<<4)+T_String] = T_undefined; // table[(T_long<<4)+T_Object] = T_undefined; table[(T_long<<4)+T_double] = (Long2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_long<<4)+T_float] = (Long2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_long<<4)+T_boolean] = T_undefined; table[(T_long<<4)+T_char] = (Long2Long<<12)+(Char2Long<<4)+T_boolean; table[(T_long<<4)+T_int] = (Long2Long<<12)+(Int2Long<<4)+T_boolean; // table[(T_long<<4)+T_null] = T_undefined; // table[(T_short<<4)+T_undefined] = T_undefined; table[(T_short<<4)+T_byte] = (Short2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_short<<4)+T_long] = (Short2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_short<<4)+T_short] = (Short2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_short<<4)+T_void] = T_undefined; // table[(T_short<<4)+T_String] = T_undefined; // table[(T_short<<4)+T_Object] = T_undefined; table[(T_short<<4)+T_double] = (Short2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_short<<4)+T_float] = (Short2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_short<<4)+T_boolean] = T_undefined; table[(T_short<<4)+T_char] = (Short2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_short<<4)+T_int] = (Short2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_short<<4)+T_null] = T_undefined; // table[(T_void<<4)+T_undefined] = T_undefined; // table[(T_void<<4)+T_byte] = T_undefined; // table[(T_void<<4)+T_long] = T_undefined; // table[(T_void<<4)+T_short] = T_undefined; // table[(T_void<<4)+T_void] = T_undefined; // table[(T_void<<4)+T_String] = T_undefined; // table[(T_void<<4)+T_Object] = T_undefined; // table[(T_void<<4)+T_double] = T_undefined; // table[(T_void<<4)+T_float] = T_undefined; // table[(T_void<<4)+T_boolean] = T_undefined; // table[(T_void<<4)+T_char] = T_undefined; // table[(T_void<<4)+T_int] = T_undefined; // table[(T_void<<4)+T_null] = T_undefined; // table[(T_String<<4)+T_undefined] = T_undefined; // 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_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_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_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_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; table[(T_double<<4)+T_long] = (Double2Double<<12)+(Long2Double<<4)+T_boolean; table[(T_double<<4)+T_short] = (Double2Double<<12)+(Short2Double<<4)+T_boolean; // table[(T_double<<4)+T_void] = T_undefined; // table[(T_double<<4)+T_String] = T_undefined; // table[(T_double<<4)+T_Object] = T_undefined; table[(T_double<<4)+T_double] = (Double2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_double<<4)+T_float] = (Double2Double<<12)+(Float2Double<<4)+T_boolean; // table[(T_double<<4)+T_boolean] = T_undefined; table[(T_double<<4)+T_char] = (Double2Double<<12)+(Char2Double<<4)+T_boolean; table[(T_double<<4)+T_int] = (Double2Double<<12)+(Int2Double<<4)+T_boolean; // table[(T_double<<4)+T_null] = T_undefined; // table[(T_float<<4)+T_undefined] = T_undefined; table[(T_float<<4)+T_byte] = (Float2Float<<12)+(Byte2Float<<4)+T_boolean; table[(T_float<<4)+T_long] = (Float2Float<<12)+(Long2Float<<4)+T_boolean; table[(T_float<<4)+T_short] = (Float2Float<<12)+(Short2Float<<4)+T_boolean; // table[(T_float<<4)+T_void] = T_undefined; // table[(T_float<<4)+T_String] = T_undefined; // table[(T_float<<4)+T_Object] = T_undefined; table[(T_float<<4)+T_double] = (Float2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_float<<4)+T_float] = (Float2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_float<<4)+T_boolean] = T_undefined; table[(T_float<<4)+T_char] = (Float2Float<<12)+(Char2Float<<4)+T_boolean; table[(T_float<<4)+T_int] = (Float2Float<<12)+(Int2Float<<4)+T_boolean; // table[(T_float<<4)+T_null] = T_undefined; // table[(T_boolean<<4)+T_undefined] = T_undefined; // table[(T_boolean<<4)+T_byte] = T_undefined; // 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] = T_undefined; // table[(T_boolean<<4)+T_Object] = T_undefined; // table[(T_boolean<<4)+T_double] = T_undefined; // table[(T_boolean<<4)+T_float] = T_undefined; table[(T_boolean<<4)+T_boolean] = (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean; // table[(T_boolean<<4)+T_char] = T_undefined; // table[(T_boolean<<4)+T_int] = T_undefined; // table[(T_boolean<<4)+T_null] = T_undefined; // table[(T_char<<4)+T_undefined] = T_undefined; table[(T_char<<4)+T_byte] = (Char2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_char<<4)+T_long] = (Char2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_char<<4)+T_short] = (Char2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_char<<4)+T_void] = T_undefined; // table[(T_char<<4)+T_String] = T_undefined; // table[(T_char<<4)+T_Object] = T_undefined; table[(T_char<<4)+T_double] = (Char2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_char<<4)+T_float] = (Char2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_char<<4)+T_boolean] = T_undefined; table[(T_char<<4)+T_char] = (Char2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_char<<4)+T_int] = (Char2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_char<<4)+T_null] = T_undefined; // table[(T_int<<4)+T_undefined] = T_undefined; table[(T_int<<4)+T_byte] = (Int2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_int<<4)+T_long] = (Int2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_int<<4)+T_short] = (Int2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_int<<4)+T_void] = T_undefined; // table[(T_int<<4)+T_String] = T_undefined; // table[(T_int<<4)+T_Object] = T_undefined; table[(T_int<<4)+T_double] = (Int2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_int<<4)+T_float] = (Int2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_int<<4)+T_boolean] = T_undefined; table[(T_int<<4)+T_char] = (Int2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_int<<4)+T_int] = (Int2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_int<<4)+T_null] = T_undefined; // table[(T_null<<4)+T_undefined] = T_undefined; // table[(T_null<<4)+T_byte] = T_undefined; // 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_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_JavaLangObject<<16)+(T_null<<12)+(T_JavaLangObject<<8)+(T_null<<4)+T_boolean; return table; } public static final int[] get_GREATER(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_LESS(); } public static final int[] get_GREATER_EQUAL(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_LESS(); } public static final int[] get_LEFT_SHIFT(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 int[] table = new int[16*16]; // table[(T_undefined<<4)+T_undefined] = T_undefined; // table[(T_undefined<<4)+T_byte] = T_undefined; // table[(T_undefined<<4)+T_long] = T_undefined; // table[(T_undefined<<4)+T_short] = T_undefined; // table[(T_undefined<<4)+T_void] = T_undefined; // table[(T_undefined<<4)+T_String] = T_undefined; // table[(T_undefined<<4)+T_Object] = T_undefined; // table[(T_undefined<<4)+T_double] = T_undefined; // table[(T_undefined<<4)+T_float] = T_undefined; // table[(T_undefined<<4)+T_boolean] = T_undefined; // table[(T_undefined<<4)+T_char] = T_undefined; // table[(T_undefined<<4)+T_int] = T_undefined; // table[(T_undefined<<4)+T_null] = T_undefined; // table[(T_byte<<4)+T_undefined] = T_undefined; table[(T_byte<<4)+T_byte] = (Byte2Int<<12)+(Byte2Int<<4)+T_int; table[(T_byte<<4)+T_long] = (Byte2Int<<12)+(Long2Int<<4)+T_int; 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] = T_undefined; // table[(T_byte<<4)+T_Object] = T_undefined; // table[(T_byte<<4)+T_double] = T_undefined; // table[(T_byte<<4)+T_float] = T_undefined; // table[(T_byte<<4)+T_boolean] = T_undefined; table[(T_byte<<4)+T_char] = (Byte2Int<<12)+(Char2Int<<4)+T_int; table[(T_byte<<4)+T_int] = (Byte2Int<<12)+(Int2Int<<4)+T_int; // table[(T_byte<<4)+T_null] = T_undefined; // table[(T_long<<4)+T_undefined] = T_undefined; table[(T_long<<4)+T_byte] = (Long2Long<<12)+(Byte2Int<<4)+T_long; table[(T_long<<4)+T_long] = (Long2Long<<12)+(Long2Int<<4)+T_long; table[(T_long<<4)+T_short] = (Long2Long<<12)+(Short2Int<<4)+T_long; // table[(T_long<<4)+T_void] = T_undefined; // table[(T_long<<4)+T_String] = T_undefined; // table[(T_long<<4)+T_Object] = T_undefined; // table[(T_long<<4)+T_double] = T_undefined; // table[(T_long<<4)+T_float] = T_undefined; // table[(T_long<<4)+T_boolean] = T_undefined; table[(T_long<<4)+T_char] = (Long2Long<<12)+(Char2Int<<4)+T_long; table[(T_long<<4)+T_int] = (Long2Long<<12)+(Int2Int<<4)+T_long; // table[(T_long<<4)+T_null] = T_undefined; // table[(T_short<<4)+T_undefined] = T_undefined; table[(T_short<<4)+T_byte] = (Short2Int<<12)+(Byte2Int<<4)+T_int; table[(T_short<<4)+T_long] = (Short2Int<<12)+(Long2Int<<4)+T_int; 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] = T_undefined; // table[(T_short<<4)+T_Object] = T_undefined; // table[(T_short<<4)+T_double] = T_undefined; // table[(T_short<<4)+T_float] = T_undefined; // table[(T_short<<4)+T_boolean] = T_undefined; table[(T_short<<4)+T_char] = (Short2Int<<12)+(Char2Int<<4)+T_int; table[(T_short<<4)+T_int] = (Short2Int<<12)+(Int2Int<<4)+T_int; // table[(T_short<<4)+T_null] = T_undefined; // table[(T_void<<4)+T_undefined] = T_undefined; // table[(T_void<<4)+T_byte] = T_undefined; // table[(T_void<<4)+T_long] = T_undefined; // table[(T_void<<4)+T_short] = T_undefined; // table[(T_void<<4)+T_void] = T_undefined; // table[(T_void<<4)+T_String] = T_undefined; // table[(T_void<<4)+T_Object] = T_undefined; // table[(T_void<<4)+T_double] = T_undefined; // table[(T_void<<4)+T_float] = T_undefined; // table[(T_void<<4)+T_boolean] = T_undefined; // table[(T_void<<4)+T_char] = T_undefined; // table[(T_void<<4)+T_int] = T_undefined; // table[(T_void<<4)+T_null] = T_undefined; // table[(T_String<<4)+T_undefined] = T_undefined; // 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_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] = T_undefined; // table[(T_Object<<4)+T_Object] = T_undefined; // 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] = T_undefined; // table[(T_double<<4)+T_undefined] = T_undefined; // table[(T_double<<4)+T_byte] = T_undefined; // table[(T_double<<4)+T_long] = T_undefined; // table[(T_double<<4)+T_short] = T_undefined; // table[(T_double<<4)+T_void] = T_undefined; // table[(T_double<<4)+T_String] = T_undefined; // table[(T_double<<4)+T_Object] = T_undefined; // table[(T_double<<4)+T_double] = T_undefined; // table[(T_double<<4)+T_float] = T_undefined; // table[(T_double<<4)+T_boolean] = T_undefined; // table[(T_double<<4)+T_char] = T_undefined; // table[(T_double<<4)+T_int] = T_undefined; // table[(T_double<<4)+T_null] = T_undefined; // table[(T_float<<4)+T_undefined] = T_undefined; // table[(T_float<<4)+T_byte] = T_undefined; // table[(T_float<<4)+T_long] = T_undefined; // table[(T_float<<4)+T_short] = T_undefined; // table[(T_float<<4)+T_void] = T_undefined; // table[(T_float<<4)+T_String] = T_undefined; // table[(T_float<<4)+T_Object] = T_undefined; // table[(T_float<<4)+T_double] = T_undefined; // table[(T_float<<4)+T_float] = T_undefined; // table[(T_float<<4)+T_boolean] = T_undefined; // table[(T_float<<4)+T_char] = T_undefined; // table[(T_float<<4)+T_int] = T_undefined; // table[(T_float<<4)+T_null] = T_undefined; // table[(T_boolean<<4)+T_undefined] = T_undefined; // table[(T_boolean<<4)+T_byte] = T_undefined; // 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] = T_undefined; // table[(T_boolean<<4)+T_Object] = T_undefined; // table[(T_boolean<<4)+T_double] = T_undefined; // table[(T_boolean<<4)+T_float] = T_undefined; // table[(T_boolean<<4)+T_boolean] = T_undefined; // table[(T_boolean<<4)+T_char] = T_undefined; // table[(T_boolean<<4)+T_int] = T_undefined; // table[(T_boolean<<4)+T_null] = T_undefined; // table[(T_char<<4)+T_undefined] = T_undefined; table[(T_char<<4)+T_byte] = (Char2Int<<12)+(Byte2Int<<4)+T_int; table[(T_char<<4)+T_long] = (Char2Int<<12)+(Long2Int<<4)+T_int; 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] = T_undefined; // table[(T_char<<4)+T_Object] = T_undefined; // table[(T_char<<4)+T_double] = T_undefined; // table[(T_char<<4)+T_float] = T_undefined; // table[(T_char<<4)+T_boolean] = T_undefined; table[(T_char<<4)+T_char] = (Char2Int<<12)+(Char2Int<<4)+T_int; table[(T_char<<4)+T_int] = (Char2Int<<12)+(Int2Int<<4)+T_int; // table[(T_char<<4)+T_null] = T_undefined; // table[(T_int<<4)+T_undefined] = T_undefined; table[(T_int<<4)+T_byte] = (Int2Int<<12)+(Byte2Int<<4)+T_int; table[(T_int<<4)+T_long] = (Int2Int<<12)+(Long2Int<<4)+T_int; 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] = T_undefined; // table[(T_int<<4)+T_Object] = T_undefined; // table[(T_int<<4)+T_double] = T_undefined; // table[(T_int<<4)+T_float] = T_undefined; // table[(T_int<<4)+T_boolean] = T_undefined; table[(T_int<<4)+T_char] = (Int2Int<<12)+(Char2Int<<4)+T_int; table[(T_int<<4)+T_int] = (Int2Int<<12)+(Int2Int<<4)+T_int; // table[(T_int<<4)+T_null] = T_undefined; // table[(T_null<<4)+T_undefined] = T_undefined; // table[(T_null<<4)+T_byte] = T_undefined; // 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_undefined; // table[(T_null<<4)+T_Object] = T_undefined; // 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] = T_undefined; return table; } public static final int[] get_LESS(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 int[] table = new int[16*16]; // table[(T_undefined<<4)+T_undefined] = T_undefined; // table[(T_undefined<<4)+T_byte] = T_undefined; // table[(T_undefined<<4)+T_long] = T_undefined; // table[(T_undefined<<4)+T_short] = T_undefined; // table[(T_undefined<<4)+T_void] = T_undefined; // table[(T_undefined<<4)+T_String] = T_undefined; // table[(T_undefined<<4)+T_Object] = T_undefined; // table[(T_undefined<<4)+T_double] = T_undefined; // table[(T_undefined<<4)+T_float] = T_undefined; // table[(T_undefined<<4)+T_boolean] = T_undefined; // table[(T_undefined<<4)+T_char] = T_undefined; // table[(T_undefined<<4)+T_int] = T_undefined; // table[(T_undefined<<4)+T_null] = T_undefined; // table[(T_byte<<4)+T_undefined] = T_undefined; table[(T_byte<<4)+T_byte] = (Byte2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_byte<<4)+T_long] = (Byte2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_byte<<4)+T_short] = (Byte2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_byte<<4)+T_void] = T_undefined; // table[(T_byte<<4)+T_String] = T_undefined; // table[(T_byte<<4)+T_Object] = T_undefined; table[(T_byte<<4)+T_double] = (Byte2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_byte<<4)+T_float] = (Byte2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_byte<<4)+T_boolean] = T_undefined; table[(T_byte<<4)+T_char] = (Byte2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_byte<<4)+T_int] = (Byte2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_byte<<4)+T_null] = T_undefined; // table[(T_long<<4)+T_undefined] = T_undefined; table[(T_long<<4)+T_byte] = (Long2Long<<12)+(Byte2Long<<4)+T_boolean; table[(T_long<<4)+T_long] = (Long2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_long<<4)+T_short] = (Long2Long<<12)+(Short2Long<<4)+T_boolean; // table[(T_long<<4)+T_void] = T_undefined; // table[(T_long<<4)+T_String] = T_undefined; // table[(T_long<<4)+T_Object] = T_undefined; table[(T_long<<4)+T_double] = (Long2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_long<<4)+T_float] = (Long2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_long<<4)+T_boolean] = T_undefined; table[(T_long<<4)+T_char] = (Long2Long<<12)+(Char2Long<<4)+T_boolean; table[(T_long<<4)+T_int] = (Long2Long<<12)+(Int2Long<<4)+T_boolean; // table[(T_long<<4)+T_null] = T_undefined; // table[(T_short<<4)+T_undefined] = T_undefined; table[(T_short<<4)+T_byte] = (Short2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_short<<4)+T_long] = (Short2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_short<<4)+T_short] = (Short2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_short<<4)+T_void] = T_undefined; // table[(T_short<<4)+T_String] = T_undefined; // table[(T_short<<4)+T_Object] = T_undefined; table[(T_short<<4)+T_double] = (Short2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_short<<4)+T_float] = (Short2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_short<<4)+T_boolean] = T_undefined; table[(T_short<<4)+T_char] = (Short2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_short<<4)+T_int] = (Short2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_short<<4)+T_null] = T_undefined; // table[(T_void<<4)+T_undefined] = T_undefined; // table[(T_void<<4)+T_byte] = T_undefined; // table[(T_void<<4)+T_long] = T_undefined; // table[(T_void<<4)+T_short] = T_undefined; // table[(T_void<<4)+T_void] = T_undefined; // table[(T_void<<4)+T_String] = T_undefined; // table[(T_void<<4)+T_Object] = T_undefined; // table[(T_void<<4)+T_double] = T_undefined; // table[(T_void<<4)+T_float] = T_undefined; // table[(T_void<<4)+T_boolean] = T_undefined; // table[(T_void<<4)+T_char] = T_undefined; // table[(T_void<<4)+T_int] = T_undefined; // table[(T_void<<4)+T_null] = T_undefined; // table[(T_String<<4)+T_undefined] = T_undefined; // 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_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] = T_undefined; // table[(T_Object<<4)+T_Object] = T_undefined; // 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] = T_undefined; // table[(T_double<<4)+T_undefined] = T_undefined; table[(T_double<<4)+T_byte] = (Double2Double<<12)+(Byte2Double<<4)+T_boolean; table[(T_double<<4)+T_long] = (Double2Double<<12)+(Long2Double<<4)+T_boolean; table[(T_double<<4)+T_short] = (Double2Double<<12)+(Short2Double<<4)+T_boolean; // table[(T_double<<4)+T_void] = T_undefined; // table[(T_double<<4)+T_String] = T_undefined; // table[(T_double<<4)+T_Object] = T_undefined; table[(T_double<<4)+T_double] = (Double2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_double<<4)+T_float] = (Double2Double<<12)+(Float2Double<<4)+T_boolean; // table[(T_double<<4)+T_boolean] = T_undefined; table[(T_double<<4)+T_char] = (Double2Double<<12)+(Char2Double<<4)+T_boolean; table[(T_double<<4)+T_int] = (Double2Double<<12)+(Int2Double<<4)+T_boolean; // table[(T_double<<4)+T_null] = T_undefined; // table[(T_float<<4)+T_undefined] = T_undefined; table[(T_float<<4)+T_byte] = (Float2Float<<12)+(Byte2Float<<4)+T_boolean; table[(T_float<<4)+T_long] = (Float2Float<<12)+(Long2Float<<4)+T_boolean; table[(T_float<<4)+T_short] = (Float2Float<<12)+(Short2Float<<4)+T_boolean; // table[(T_float<<4)+T_void] = T_undefined; // table[(T_float<<4)+T_String] = T_undefined; // table[(T_float<<4)+T_Object] = T_undefined; table[(T_float<<4)+T_double] = (Float2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_float<<4)+T_float] = (Float2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_float<<4)+T_boolean] = T_undefined; table[(T_float<<4)+T_char] = (Float2Float<<12)+(Char2Float<<4)+T_boolean; table[(T_float<<4)+T_int] = (Float2Float<<12)+(Int2Float<<4)+T_boolean; // table[(T_float<<4)+T_null] = T_undefined; // table[(T_boolean<<4)+T_undefined] = T_undefined; // table[(T_boolean<<4)+T_byte] = T_undefined; // 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] = T_undefined; // table[(T_boolean<<4)+T_Object] = T_undefined; // table[(T_boolean<<4)+T_double] = T_undefined; // table[(T_boolean<<4)+T_float] = T_undefined; // table[(T_boolean<<4)+T_boolean] = T_undefined; // table[(T_boolean<<4)+T_char] = T_undefined; // table[(T_boolean<<4)+T_int] = T_undefined; // table[(T_boolean<<4)+T_null] = T_undefined; // table[(T_char<<4)+T_undefined] = T_undefined; table[(T_char<<4)+T_byte] = (Char2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_char<<4)+T_long] = (Char2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_char<<4)+T_short] = (Char2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_char<<4)+T_void] = T_undefined; // table[(T_char<<4)+T_String] = T_undefined; // table[(T_char<<4)+T_Object] = T_undefined; table[(T_char<<4)+T_double] = (Char2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_char<<4)+T_float] = (Char2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_char<<4)+T_boolean] = T_undefined; table[(T_char<<4)+T_char] = (Char2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_char<<4)+T_int] = (Char2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_char<<4)+T_null] = T_undefined; // table[(T_int<<4)+T_undefined] = T_undefined; table[(T_int<<4)+T_byte] = (Int2Int<<12)+(Byte2Int<<4)+T_boolean; table[(T_int<<4)+T_long] = (Int2Long<<12)+(Long2Long<<4)+T_boolean; table[(T_int<<4)+T_short] = (Int2Int<<12)+(Short2Int<<4)+T_boolean; // table[(T_int<<4)+T_void] = T_undefined; // table[(T_int<<4)+T_String] = T_undefined; // table[(T_int<<4)+T_Object] = T_undefined; table[(T_int<<4)+T_double] = (Int2Double<<12)+(Double2Double<<4)+T_boolean; table[(T_int<<4)+T_float] = (Int2Float<<12)+(Float2Float<<4)+T_boolean; // table[(T_int<<4)+T_boolean] = T_undefined; table[(T_int<<4)+T_char] = (Int2Int<<12)+(Char2Int<<4)+T_boolean; table[(T_int<<4)+T_int] = (Int2Int<<12)+(Int2Int<<4)+T_boolean; // table[(T_int<<4)+T_null] = T_undefined; // table[(T_null<<4)+T_undefined] = T_undefined; // table[(T_null<<4)+T_byte] = T_undefined; // 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_undefined; // table[(T_null<<4)+T_Object] = T_undefined; // 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] = T_undefined; return table; } public static final int[] get_LESS_EQUAL(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_LESS(); } public static final int[] get_MINUS(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 int[] table = (int[]) get_PLUS().clone(); // customization 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; return table; } public static final int[] get_MULTIPLY(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_MINUS(); } public static final int[] get_OR(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_AND(); } public static final int[] get_OR_OR(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_AND_AND(); } public static final int[] get_PLUS(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 int[] table = new int[16*16]; // table[(T_undefined<<4)+T_undefined] = T_undefined; // table[(T_undefined<<4)+T_byte] = T_undefined; // table[(T_undefined<<4)+T_long] = T_undefined; // table[(T_undefined<<4)+T_short] = T_undefined; // table[(T_undefined<<4)+T_void] = T_undefined; // table[(T_undefined<<4)+T_String] = T_undefined; // table[(T_undefined<<4)+T_Object] = T_undefined; // table[(T_undefined<<4)+T_double] = T_undefined; // table[(T_undefined<<4)+T_float] = T_undefined; // table[(T_undefined<<4)+T_boolean] = T_undefined; // table[(T_undefined<<4)+T_char] = T_undefined; // table[(T_undefined<<4)+T_int] = T_undefined; // table[(T_undefined<<4)+T_null] = T_undefined; // table[(T_byte<<4)+T_undefined] = T_undefined; table[(T_byte<<4)+T_byte] = (Byte2Int<<12)+(Byte2Int<<4)+T_int; 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_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; // table[(T_byte<<4)+T_boolean] = T_undefined; table[(T_byte<<4)+T_char] = (Byte2Int<<12)+(Char2Int<<4)+T_int; table[(T_byte<<4)+T_int] = (Byte2Int<<12)+(Int2Int<<4)+T_int; // table[(T_byte<<4)+T_null] = T_undefined; // table[(T_long<<4)+T_undefined] = T_undefined; table[(T_long<<4)+T_byte] = (Long2Long<<12)+(Byte2Long<<4)+T_long; 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_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; // table[(T_long<<4)+T_boolean] = T_undefined; table[(T_long<<4)+T_char] = (Long2Long<<12)+(Char2Long<<4)+T_long; table[(T_long<<4)+T_int] = (Long2Long<<12)+(Int2Long<<4)+T_long; // table[(T_long<<4)+T_null] = T_undefined; // table[(T_short<<4)+T_undefined] = T_undefined; table[(T_short<<4)+T_byte] = (Short2Int<<12)+(Byte2Int<<4)+T_int; 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_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; // table[(T_short<<4)+T_boolean] = T_undefined; table[(T_short<<4)+T_char] = (Short2Int<<12)+(Char2Int<<4)+T_int; table[(T_short<<4)+T_int] = (Short2Int<<12)+(Int2Int<<4)+T_int; // table[(T_short<<4)+T_null] = T_undefined; // table[(T_void<<4)+T_undefined] = T_undefined; // table[(T_void<<4)+T_byte] = T_undefined; // table[(T_void<<4)+T_long] = T_undefined; // table[(T_void<<4)+T_short] = T_undefined; // table[(T_void<<4)+T_void] = T_undefined; // table[(T_void<<4)+T_String] = T_undefined; // table[(T_void<<4)+T_Object] = T_undefined; // table[(T_void<<4)+T_double] = T_undefined; // table[(T_void<<4)+T_float] = T_undefined; // table[(T_void<<4)+T_boolean] = T_undefined; // table[(T_void<<4)+T_char] = T_undefined; // table[(T_void<<4)+T_int] = T_undefined; // table[(T_void<<4)+T_null] = T_undefined; // table[(T_String<<4)+T_undefined] = T_undefined; 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_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_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; // 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] = T_undefined; // table[(T_double<<4)+T_undefined] = T_undefined; table[(T_double<<4)+T_byte] = (Double2Double<<12)+(Byte2Double<<4)+T_double; 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_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; // table[(T_double<<4)+T_boolean] = T_undefined; table[(T_double<<4)+T_char] = (Double2Double<<12)+(Char2Double<<4)+T_double; table[(T_double<<4)+T_int] = (Double2Double<<12)+(Int2Double<<4)+T_double; // table[(T_double<<4)+T_null] = T_undefined; // table[(T_float<<4)+T_undefined] = T_undefined; table[(T_float<<4)+T_byte] = (Float2Float<<12)+(Byte2Float<<4)+T_float; 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_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; // table[(T_float<<4)+T_boolean] = T_undefined; table[(T_float<<4)+T_char] = (Float2Float<<12)+(Char2Float<<4)+T_float; table[(T_float<<4)+T_int] = (Float2Float<<12)+(Int2Float<<4)+T_float; // table[(T_float<<4)+T_null] = T_undefined; // table[(T_boolean<<4)+T_undefined] = T_undefined; // table[(T_boolean<<4)+T_byte] = T_undefined; // 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_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; // table[(T_boolean<<4)+T_boolean] = T_undefined; // table[(T_boolean<<4)+T_char] = T_undefined; // table[(T_boolean<<4)+T_int] = T_undefined; // table[(T_boolean<<4)+T_null] = T_undefined; // table[(T_char<<4)+T_undefined] = T_undefined; table[(T_char<<4)+T_byte] = (Char2Int<<12)+(Byte2Int<<4)+T_int; 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_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; // table[(T_char<<4)+T_boolean] = T_undefined; table[(T_char<<4)+T_char] = (Char2Int<<12)+(Char2Int<<4)+T_int; table[(T_char<<4)+T_int] = (Char2Int<<12)+(Int2Int<<4)+T_int; // table[(T_char<<4)+T_null] = T_undefined; // table[(T_int<<4)+T_undefined] = T_undefined; table[(T_int<<4)+T_byte] = (Int2Int<<12)+(Byte2Int<<4)+T_int; 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_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; // table[(T_int<<4)+T_boolean] = T_undefined; table[(T_int<<4)+T_char] = (Int2Int<<12)+(Char2Int<<4)+T_int; table[(T_int<<4)+T_int] = (Int2Int<<12)+(Int2Int<<4)+T_int; // table[(T_int<<4)+T_null] = T_undefined; // table[(T_null<<4)+T_undefined] = T_undefined; // table[(T_null<<4)+T_byte] = T_undefined; // 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_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; // 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] = (Null2String<<12)+(Null2String<<4)+T_String;; return table; } public static final int[] get_REMAINDER(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_MINUS(); } public static final int[] get_RIGHT_SHIFT(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_LEFT_SHIFT(); } public static final int[] get_UNSIGNED_RIGHT_SHIFT(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_LEFT_SHIFT(); } public static final int[] get_XOR(){ //the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 // int[] table = new int[16*16]; return get_AND(); } public String operatorToString() { switch ((this.bits & OperatorMASK) >> OperatorSHIFT) { case EQUAL_EQUAL : return "=="; //$NON-NLS-1$ case LESS_EQUAL : return "<="; //$NON-NLS-1$ case GREATER_EQUAL : return ">="; //$NON-NLS-1$ case NOT_EQUAL : return "!="; //$NON-NLS-1$ case LEFT_SHIFT : return "<<"; //$NON-NLS-1$ case RIGHT_SHIFT : return ">>"; //$NON-NLS-1$ case UNSIGNED_RIGHT_SHIFT : return ">>>"; //$NON-NLS-1$ case OR_OR : return "||"; //$NON-NLS-1$ case AND_AND : return "&&"; //$NON-NLS-1$ case PLUS : return "+"; //$NON-NLS-1$ case MINUS : return "-"; //$NON-NLS-1$ case NOT : return "!"; //$NON-NLS-1$ case REMAINDER : return "%"; //$NON-NLS-1$ case XOR : return "^"; //$NON-NLS-1$ case AND : return "&"; //$NON-NLS-1$ case MULTIPLY : return "*"; //$NON-NLS-1$ case OR : return "|"; //$NON-NLS-1$ case TWIDDLE : return "~"; //$NON-NLS-1$ case DIVIDE : return "/"; //$NON-NLS-1$ case GREATER : return ">"; //$NON-NLS-1$ case LESS : return "<"; //$NON-NLS-1$ case QUESTIONCOLON : return "?:"; //$NON-NLS-1$ case EQUAL : return "="; //$NON-NLS-1$ } return "unknown operator"; //$NON-NLS-1$ } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { return FlowInfo.NON_NULL; } public StringBuffer printExpression(int indent, StringBuffer output){ output.append('('); return printExpressionNoParenthesis(0, output).append(')'); } public abstract StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output); } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration0000644000175000001440000001021112212041344032346 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.flow.FlowContext; 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; /** * For local declarations (outside of for statement initialization) and field declarations, * the declarationSourceEnd covers multiple locals if any. * For local declarations inside for statement initialization, this is not the case. */ public int declarationSourceEnd; public int declarationSourceStart; public int hiddenVariableDepth; // used to diagnose hiding scenarii public Expression initialization; public int modifiers; public int modifiersSourceStart; public Annotation[] annotations; public char[] name; public TypeReference type; 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() */ public boolean isSuperAccess() { return false; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isTypeAccess() */ public boolean isTypeAccess() { return false; } public StringBuffer printStatement(int indent, StringBuffer output) { printAsExpression(indent, output); switch(getKind()) { case ENUM_CONSTANT: return output.append(','); default: return output.append(';'); } } public StringBuffer printAsExpression(int indent, StringBuffer output) { printIndent(indent, output); printModifiers(this.modifiers, output); if (this.annotations != null) printAnnotations(this.annotations, output); if (this.type != null) { this.type.print(0, output).append(' '); } output.append(this.name); switch(getKind()) { case ENUM_CONSTANT: if (this.initialization != null) { this.initialization.printExpression(indent, output); } break; default: if (this.initialization != null) { output.append(" = "); //$NON-NLS-1$ this.initialization.printExpression(indent, output); } } return output; } public void resolve(BlockScope scope) { // do nothing by default (redefined for local variables) } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setActualReceiverType(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding) */ public void setActualReceiverType(ReferenceBinding receiverType) { // do nothing by default } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setDepth(int) */ public void setDepth(int depth) { this.hiddenVariableDepth = depth; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setFieldIndex(int) */ public void setFieldIndex(int depth) { // do nothing by default } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Block.java0000644000175000001440000001272112212041344026751 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check *******************************************************************************/ 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.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class Block extends Statement { public Statement[] statements; public int explicitDeclarations; // the number of explicit declaration , used to create scope public BlockScope scope; public Block(int explicitDeclarations) { this.explicitDeclarations = explicitDeclarations; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // empty block if (this.statements == null) return flowInfo; int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; boolean enableSyntacticNullAnalysisForFields = currentScope.compilerOptions().enableSyntacticNullAnalysisForFields; for (int i = 0, max = this.statements.length; i < max; i++) { Statement stat = this.statements[i]; if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo); } // record the effect of stat on the finally block of an enclosing try-finally, if any: flowContext.mergeFinallyNullInfo(flowInfo); if (enableSyntacticNullAnalysisForFields) { flowContext.expireNullCheckedFieldInfo(); } } if (this.explicitDeclarations > 0) { // if block has its own scope analyze tracking vars now: this.scope.checkUnclosedCloseables(flowInfo, flowContext, null, null); // cleanup assignment info for locals that are scoped to this block: LocalVariableBinding[] locals = this.scope.locals; if (locals != null) { int numLocals = this.scope.localIndex; for (int i = 0; i < numLocals; i++) { flowInfo.resetAssignmentInfo(locals[i]); } } } return flowInfo; } /** * Code generation for a block */ public void generateCode(BlockScope currentScope, CodeStream codeStream) { if ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; if (this.statements != null) { for (int i = 0, max = this.statements.length; i < max; i++) { this.statements[i].generateCode(this.scope, codeStream); } } // for local variable debug attributes if (this.scope != currentScope) { // was really associated with its own scope codeStream.exitUserScope(this.scope); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public boolean isEmptyBlock() { return this.statements == null; } public StringBuffer printBody(int indent, StringBuffer output) { if (this.statements == null) return output; for (int i = 0; i < this.statements.length; i++) { this.statements[i].printStatement(indent + 1, output); output.append('\n'); } return output; } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output); output.append("{\n"); //$NON-NLS-1$ printBody(indent, output); return printIndent(indent, output).append('}'); } public void resolve(BlockScope upperScope) { if ((this.bits & UndocumentedEmptyBlock) != 0) { upperScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd); } if (this.statements != null) { this.scope = this.explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope, this.explicitDeclarations); for (int i = 0, length = this.statements.length; i < length; i++) { this.statements[i].resolve(this.scope); } } } public void resolveUsing(BlockScope givenScope) { if ((this.bits & UndocumentedEmptyBlock) != 0) { givenScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd); } // this optimized resolve(...) is sent only on none empty blocks this.scope = givenScope; if (this.statements != null) { for (int i = 0, length = this.statements.length; i < length; i++) { this.statements[i].resolve(this.scope); } } } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { if (this.statements != null) { for (int i = 0, length = this.statements.length; i < length; i++) this.statements[i].traverse(visitor, this.scope); } } visitor.endVisit(this, blockScope); } /** * Dispatch the call on its last statement. */ public void branchChainTo(BranchLabel label) { if (this.statements != null) { this.statements[this.statements.length - 1].branchChainTo(label); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java0000644000175000001440000000643212212041344030504 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.StringConstant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class StringLiteral extends Literal { char[] source; int lineNumber; public StringLiteral(char[] token, int start, int end, int lineNumber) { this(start,end); this.source = token; this.lineNumber = lineNumber - 1; // line number is 1 based } public StringLiteral(int s, int e) { super(s,e); } public void computeConstant() { this.constant = StringConstant.fromValue(String.valueOf(this.source)); } public ExtendedStringLiteral extendWith(CharLiteral lit){ //add the lit source to mine, just as if it was mine return new ExtendedStringLiteral(this,lit); } public ExtendedStringLiteral extendWith(StringLiteral lit){ //add the lit source to mine, just as if it was mine return new ExtendedStringLiteral(this,lit); } /** * Add the lit source to mine, just as if it was mine */ public StringLiteralConcatenation extendsWith(StringLiteral lit) { return new StringLiteralConcatenation(this, lit); } /** * Code generation for string literal */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (valueRequired) codeStream.ldc(this.constant.stringValue()); codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return scope.getJavaLangString(); } public StringBuffer printExpression(int indent, StringBuffer output) { // handle some special char..... output.append('\"'); for (int i = 0; i < this.source.length; i++) { switch (this.source[i]) { case '\b' : output.append("\\b"); //$NON-NLS-1$ break; case '\t' : output.append("\\t"); //$NON-NLS-1$ break; case '\n' : output.append("\\n"); //$NON-NLS-1$ break; case '\f' : output.append("\\f"); //$NON-NLS-1$ break; case '\r' : output.append("\\r"); //$NON-NLS-1$ break; case '\"' : output.append("\\\""); //$NON-NLS-1$ break; case '\'' : output.append("\\'"); //$NON-NLS-1$ break; case '\\' : //take care not to display the escape as a potential real char output.append("\\\\"); //$NON-NLS-1$ break; default : output.append(this.source[i]); } } output.append('\"'); return output; } public char[] source() { return this.source; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ForStatement.java0000644000175000001440000004026112212041344030332 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class ForStatement extends Statement { public Statement[] initializations; public Expression condition; public Statement[] increments; public Statement action; //when there is no local declaration, there is no need of a new scope //scope is positioned either to a new scope, or to the "upper"scope (see resolveType) public BlockScope scope; private BranchLabel breakLabel, continueLabel; // for local variables table attributes int preCondInitStateIndex = -1; int preIncrementsInitStateIndex = -1; int condIfTrueInitStateIndex = -1; int mergedInitStateIndex = -1; public ForStatement( Statement[] initializations, Expression condition, Statement[] increments, Statement action, boolean neededScope, int s, int e) { this.sourceStart = s; this.sourceEnd = e; this.initializations = initializations; this.condition = condition; this.increments = increments; this.action = action; // remember useful empty statement if (action instanceof EmptyStatement) action.bits |= ASTNode.IsUsefulEmptyStatement; if (neededScope) { this.bits |= ASTNode.NeededScope; } } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.breakLabel = new BranchLabel(); this.continueLabel = new BranchLabel(); int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; // process the initializations if (this.initializations != null) { for (int i = 0, count = this.initializations.length; i < count; i++) { flowInfo = this.initializations[i].analyseCode(this.scope, flowContext, flowInfo); } } this.preCondInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); Constant cst = this.condition == null ? null : this.condition.constant; boolean isConditionTrue = cst == null || (cst != Constant.NotAConstant && cst.booleanValue() == true); boolean isConditionFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false); cst = this.condition == null ? null : this.condition.optimizedBooleanConstant(); boolean isConditionOptimizedTrue = cst == null || (cst != Constant.NotAConstant && cst.booleanValue() == true); boolean isConditionOptimizedFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false); // process the condition LoopingFlowContext condLoopContext = null; FlowInfo condInfo = flowInfo.nullInfoLessUnconditionalCopy(); if (this.condition != null) { if (!isConditionTrue) { condInfo = this.condition.analyseCode( this.scope, (condLoopContext = new LoopingFlowContext(flowContext, flowInfo, this, null, null, this.scope, true)), condInfo); this.condition.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); } } // process the action LoopingFlowContext loopingContext; UnconditionalFlowInfo actionInfo; if (this.action == null || (this.action.isEmptyBlock() && currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3)) { if (condLoopContext != null) condLoopContext.complainOnDeferredFinalChecks(this.scope, condInfo); if (isConditionTrue) { if (condLoopContext != null) { condLoopContext.complainOnDeferredNullChecks(currentScope, condInfo); } return FlowInfo.DEAD_END; } else { if (isConditionFalse){ this.continueLabel = null; // for(;false;p()); } actionInfo = condInfo.initsWhenTrue().unconditionalCopy(); loopingContext = new LoopingFlowContext(flowContext, flowInfo, this, this.breakLabel, this.continueLabel, this.scope, false); // there is no action guarded by a preTest, so we use preTest=false // to avoid pointless burdens of updating FlowContext.conditionalLevel } } else { loopingContext = new LoopingFlowContext(flowContext, flowInfo, this, this.breakLabel, this.continueLabel, this.scope, true); FlowInfo initsWhenTrue = condInfo.initsWhenTrue(); this.condIfTrueInitStateIndex = currentScope.methodScope().recordInitializationStates(initsWhenTrue); if (isConditionFalse) { actionInfo = FlowInfo.DEAD_END; } else { actionInfo = initsWhenTrue.unconditionalCopy(); if (isConditionOptimizedFalse){ actionInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } } if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalInits(); } // code generation can be optimized when no need to continue in the loop if ((actionInfo.tagBits & loopingContext.initsOnContinue.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) { this.continueLabel = null; } else { if (condLoopContext != null) { condLoopContext.complainOnDeferredFinalChecks(this.scope, condInfo); } actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue); loopingContext.complainOnDeferredFinalChecks(this.scope, actionInfo); } } // for increments FlowInfo exitBranch = flowInfo.copy(); // recover null inits from before condition analysis LoopingFlowContext incrementContext = null; if (this.continueLabel != null) { if (this.increments != null) { incrementContext = new LoopingFlowContext(flowContext, flowInfo, this, null, null, this.scope, true); FlowInfo incrementInfo = actionInfo; this.preIncrementsInitStateIndex = currentScope.methodScope().recordInitializationStates(incrementInfo); for (int i = 0, count = this.increments.length; i < count; i++) { incrementInfo = this.increments[i]. analyseCode(this.scope, incrementContext, incrementInfo); } incrementContext.complainOnDeferredFinalChecks(this.scope, actionInfo = incrementInfo.unconditionalInits()); } exitBranch.addPotentialInitializationsFrom(actionInfo). addInitializationsFrom(condInfo.initsWhenFalse()); } else { exitBranch.addInitializationsFrom(condInfo.initsWhenFalse()); if (this.increments != null) { if (initialComplaintLevel == Statement.NOT_COMPLAINED) { currentScope.problemReporter().fakeReachable(this.increments[0]); } } } // nulls checks if (condLoopContext != null) { condLoopContext.complainOnDeferredNullChecks(currentScope, actionInfo); } loopingContext.complainOnDeferredNullChecks(currentScope, actionInfo); if (incrementContext != null) { incrementContext.complainOnDeferredNullChecks(currentScope, actionInfo); } if (loopingContext.hasEscapingExceptions()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321926 FlowInfo loopbackFlowInfo = flowInfo.copy(); if (this.continueLabel != null) { // we do get to the bottom loopbackFlowInfo.mergedWith(actionInfo.unconditionalCopy()); } loopingContext.simulateThrowAfterLoopBack(loopbackFlowInfo); } //end of loop FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( (loopingContext.initsOnBreak.tagBits & FlowInfo.UNREACHABLE) != 0 ? loopingContext.initsOnBreak : flowInfo.addInitializationsFrom(loopingContext.initsOnBreak), // recover upstream null info isConditionOptimizedTrue, exitBranch, isConditionOptimizedFalse, !isConditionTrue /*for(;;){}while(true); unreachable(); */); // Variables initialized only for the purpose of the for loop can be removed for further flow info // https://bugs.eclipse.org/bugs/show_bug.cgi?id=359495 if (this.initializations != null) { for (int i = 0; i < this.initializations.length; i++) { Statement init = this.initializations[i]; if (init instanceof LocalDeclaration) { LocalVariableBinding binding = ((LocalDeclaration) init).binding; mergedInfo.resetAssignmentInfo(binding); } } } this.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 ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; // generate the initializations if (this.initializations != null) { for (int i = 0, max = this.initializations.length; i < max; i++) { this.initializations[i].generateCode(this.scope, codeStream); } } Constant cst = this.condition == null ? null : this.condition.optimizedBooleanConstant(); boolean isConditionOptimizedFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false); if (isConditionOptimizedFalse) { this.condition.generateCode(this.scope, codeStream, false); // May loose some local variable initializations : affecting the local variable attributes if ((this.bits & ASTNode.NeededScope) != 0) { codeStream.exitUserScope(this.scope); } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } // label management BranchLabel actionLabel = new BranchLabel(codeStream); actionLabel.tagBits |= BranchLabel.USED; BranchLabel conditionLabel = new BranchLabel(codeStream); this.breakLabel.initialize(codeStream); if (this.continueLabel == null) { conditionLabel.place(); if ((this.condition != null) && (this.condition.constant == Constant.NotAConstant)) { this.condition.generateOptimizedBoolean(this.scope, codeStream, null, this.breakLabel, true); } } else { this.continueLabel.initialize(codeStream); // jump over the actionBlock if ((this.condition != null) && (this.condition.constant == Constant.NotAConstant) && !((this.action == null || this.action.isEmptyBlock()) && (this.increments == null))) { conditionLabel.tagBits |= BranchLabel.USED; int jumpPC = codeStream.position; codeStream.goto_(conditionLabel); codeStream.recordPositionsFrom(jumpPC, this.condition.sourceStart); } } // generate the loop action if (this.action != null) { // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect if (this.condIfTrueInitStateIndex != -1) { // insert all locals initialized inside the condition into the action generated prior to the condition codeStream.addDefinitelyAssignedVariables( currentScope, this.condIfTrueInitStateIndex); } actionLabel.place(); this.action.generateCode(this.scope, codeStream); } else { actionLabel.place(); } if (this.preIncrementsInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preIncrementsInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.preIncrementsInitStateIndex); } // continuation point if (this.continueLabel != null) { this.continueLabel.place(); // generate the increments for next iteration if (this.increments != null) { for (int i = 0, max = this.increments.length; i < max; i++) { this.increments[i].generateCode(this.scope, codeStream); } } // May loose some local variable initializations : affecting the local variable attributes if (this.preCondInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preCondInitStateIndex); } // generate the condition conditionLabel.place(); if ((this.condition != null) && (this.condition.constant == Constant.NotAConstant)) { this.condition.generateOptimizedBoolean(this.scope, codeStream, actionLabel, null, true); } else { codeStream.goto_(actionLabel); } } else { // May loose some local variable initializations : affecting the local variable attributes if (this.preCondInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preCondInitStateIndex); } } // May loose some local variable initializations : affecting the local variable attributes if ((this.bits & ASTNode.NeededScope) != 0) { codeStream.exitUserScope(this.scope); } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } this.breakLabel.place(); codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output).append("for ("); //$NON-NLS-1$ //inits if (this.initializations != null) { for (int i = 0; i < this.initializations.length; i++) { //nice only with expressions if (i > 0) output.append(", "); //$NON-NLS-1$ this.initializations[i].print(0, output); } } output.append("; "); //$NON-NLS-1$ //cond if (this.condition != null) this.condition.printExpression(0, output); output.append("; "); //$NON-NLS-1$ //updates if (this.increments != null) { for (int i = 0; i < this.increments.length; i++) { if (i > 0) output.append(", "); //$NON-NLS-1$ this.increments[i].print(0, output); } } output.append(") "); //$NON-NLS-1$ //block if (this.action == null) output.append(';'); else { output.append('\n'); this.action.printStatement(tab + 1, output); } return output; } public void resolve(BlockScope upperScope) { // use the scope that will hold the init declarations this.scope = (this.bits & ASTNode.NeededScope) != 0 ? new BlockScope(upperScope) : upperScope; if (this.initializations != null) for (int i = 0, length = this.initializations.length; i < length; i++) this.initializations[i].resolve(this.scope); if (this.condition != null) { TypeBinding type = this.condition.resolveTypeExpecting(this.scope, TypeBinding.BOOLEAN); this.condition.computeConversion(this.scope, type, type); } if (this.increments != null) for (int i = 0, length = this.increments.length; i < length; i++) this.increments[i].resolve(this.scope); if (this.action != null) this.action.resolve(this.scope); } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { if (this.initializations != null) { int initializationsLength = this.initializations.length; for (int i = 0; i < initializationsLength; i++) this.initializations[i].traverse(visitor, this.scope); } if (this.condition != null) this.condition.traverse(visitor, this.scope); if (this.increments != null) { int incrementsLength = this.increments.length; for (int i = 0; i < incrementsLength; i++) this.increments[i].traverse(visitor, this.scope); } if (this.action != null) this.action.traverse(visitor, this.scope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/UnionTypeReference.java0000644000175000001440000001350612212041344031472 0ustar dokousers/******************************************************************************* * Copyright (c) 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.Binding; 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; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public class UnionTypeReference extends TypeReference { public TypeReference[] typeReferences; public UnionTypeReference(TypeReference[] typeReferences) { this.bits |= ASTNode.IsUnionType; this.typeReferences = typeReferences; this.sourceStart = typeReferences[0].sourceStart; int length = typeReferences.length; this.sourceEnd = typeReferences[length - 1].sourceEnd; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int) */ public TypeReference copyDims(int dim) { return this; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getLastToken() */ public char[] getLastToken() { return null; } /** * @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(...) } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope) */ public TypeBinding resolveType(BlockScope scope, boolean checkBounds) { // return the lub (least upper bound of all type binding) int length = this.typeReferences.length; TypeBinding[] allExceptionTypes = new TypeBinding[length]; boolean hasError = false; for (int i = 0; i < length; i++) { TypeBinding exceptionType = this.typeReferences[i].resolveType(scope, checkBounds); if (exceptionType == null) { return null; } switch(exceptionType.kind()) { case Binding.PARAMETERIZED_TYPE : if (exceptionType.isBoundParameterizedType()) { hasError = true; scope.problemReporter().invalidParameterizedExceptionType(exceptionType, this.typeReferences[i]); // fall thru to create the variable - avoids additional errors because the variable is missing } break; case Binding.TYPE_PARAMETER : scope.problemReporter().invalidTypeVariableAsException(exceptionType, this.typeReferences[i]); hasError = true; // fall thru to create the variable - avoids additional errors because the variable is missing break; } if (exceptionType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null && exceptionType.isValidBinding()) { scope.problemReporter().cannotThrowType(this.typeReferences[i], exceptionType); hasError = true; } allExceptionTypes[i] = exceptionType; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=340486, ensure types are of union type. for (int j = 0; j < i; j++) { if (allExceptionTypes[j].isCompatibleWith(exceptionType)) { scope.problemReporter().wrongSequenceOfExceptionTypes( this.typeReferences[j], allExceptionTypes[j], exceptionType); hasError = true; } else if (exceptionType.isCompatibleWith(allExceptionTypes[j])) { scope.problemReporter().wrongSequenceOfExceptionTypes( this.typeReferences[i], exceptionType, allExceptionTypes[j]); hasError = true; } } } if (hasError) { return null; } // compute lub return (this.resolvedType = scope.lowerUpperBound(allExceptionTypes)); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeName() */ public char[][] getTypeName() { // we need to keep a return value that is a char[][] return this.typeReferences[0].getTypeName(); } /* (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 scope) { if (visitor.visit(this, scope)) { int length = this.typeReferences == null ? 0 : this.typeReferences.length; for (int i = 0; i < length; i++) { this.typeReferences[i].traverse(visitor, scope); } } visitor.endVisit(this, scope); } /* (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 scope) { if (visitor.visit(this, scope)) { int length = this.typeReferences == null ? 0 : this.typeReferences.length; for (int i = 0; i < length; i++) { this.typeReferences[i].traverse(visitor, scope); } } visitor.endVisit(this, scope); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.Expression#printExpression(int, java.lang.StringBuffer) */ public StringBuffer printExpression(int indent, StringBuffer output) { int length = this.typeReferences == null ? 0 : this.typeReferences.length; printIndent(indent, output); for (int i = 0; i < length; i++) { this.typeReferences[i].printExpression(0, output); if (i != length - 1) { output.append(" | "); //$NON-NLS-1$ } } return output; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java0000644000175000001440000000447212212041344032167 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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; public class ExtendedStringLiteral extends StringLiteral { /** * Build a string+char literal */ public ExtendedStringLiteral(StringLiteral str, CharLiteral character) { super(str.source, str.sourceStart, str.sourceEnd, str.lineNumber); extendWith(character); } /** * Build a two-strings literal * */ public ExtendedStringLiteral(StringLiteral str1, StringLiteral str2) { super(str1.source, str1.sourceStart, str1.sourceEnd, str1.lineNumber); extendWith(str2); } /** * Add the lit source to mine, just as if it was mine */ public ExtendedStringLiteral extendWith(CharLiteral lit) { //update the source int length = this.source.length; System.arraycopy(this.source, 0, (this.source = new char[length + 1]), 0, length); this.source[length] = lit.value; //position at the end of all literals this.sourceEnd = lit.sourceEnd; return this; } /** * Add the lit source to mine, just as if it was mine */ public ExtendedStringLiteral extendWith(StringLiteral lit) { //uddate the source int length = this.source.length; System.arraycopy( this.source, 0, this.source = new char[length + lit.source.length], 0, length); System.arraycopy(lit.source, 0, this.source, length, lit.source.length); //position at the end of all literals this.sourceEnd = lit.sourceEnd; return this; } public StringBuffer printExpression(int indent, StringBuffer output) { return output.append("ExtendedStringLiteral{").append(this.source).append('}'); //$NON-NLS-1$ } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java0000644000175000001440000000462712212041344031441 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class PostfixExpression extends CompoundAssignment { public PostfixExpression(Expression lhs, Expression expression, int operator, int pos) { super(lhs, expression, operator, pos); this.sourceStart = lhs.sourceStart; this.sourceEnd = pos; } public boolean checkCastCompatibility() { return false; } /** * Code generation for PostfixExpression * * @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) { // various scenarii are possible, setting an array reference, // a field reference, a blank final field reference, a field of an enclosing instance or // just a local variable. int pc = codeStream.position; ((Reference) this.lhs).generatePostIncrement(currentScope, codeStream, this, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public String operatorToString() { switch (this.operator) { case PLUS : return "++"; //$NON-NLS-1$ case MINUS : return "--"; //$NON-NLS-1$ } return "unknown operator"; //$NON-NLS-1$ } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { return this.lhs.printExpression(indent, output).append(' ').append(operatorToString()); } public boolean restrainUsageToNumericTypes() { return true; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.lhs.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java0000644000175000001440000000263512212041344031176 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ /* * 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) { if (visitor.visit(this, scope)) { if (this.type != null) { this.type.traverse(visitor, scope); } } visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000016212251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeR0000644000175000001440000003511312212041344032403 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for Bug 342671 - ClassCastException: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ArrayBinding *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; 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; /** * @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) { // recurse on enclosing type if any, and assuming explictly part of the reference (index>0) if (index > 0 && type.enclosingType() != null) { checkBounds(type.enclosingType(), scope, index - 1); } if (type.isParameterizedTypeWithActualArguments()) { ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type; ReferenceBinding currentType = parameterizedType.genericType(); TypeVariableBinding[] typeVariables = currentType.typeVariables(); if (typeVariables != null) { // argTypes may be null in error cases parameterizedType.boundCheck(scope, this.typeArguments[index]); } } } public TypeReference copyDims(int dim){ return new ParameterizedQualifiedTypeReference(this.tokens, this.typeArguments, dim, this.sourcePositions); } /** * @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 = Constant.NotAConstant; if ((this.bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved if (this.resolvedType != null) { // is a shared type reference which was already resolved if (this.resolvedType.isValidBinding()) { return this.resolvedType; } else { switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : case ProblemReasons.InheritedNameHidesEnclosingName : TypeBinding type = this.resolvedType.closestMatch(); return type; default : return null; } } } } this.bits |= ASTNode.DidResolve; TypeBinding type = internalResolveLeafType(scope, checkBounds); createArrayType(scope); return type == null ? type : this.resolvedType; } private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) { boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; Binding binding = scope.getPackage(this.tokens); if (binding != null && !binding.isValidBinding()) { this.resolvedType = (ReferenceBinding) binding; reportInvalidType(scope); // be resilient, still attempt resolving arguments for (int i = 0, max = this.tokens.length; i < max; i++) { TypeReference[] args = this.typeArguments[i]; if (args != null) { int argLength = args.length; for (int j = 0; j < argLength; j++) { TypeReference typeArgument = args[j]; if (isClassScope) { typeArgument.resolveType((ClassScope) scope); } else { typeArgument.resolveType((BlockScope) scope, checkBounds); } } } } return null; } PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding; boolean typeIsConsistent = true; ReferenceBinding qualifyingType = 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); // be resilient, still attempt resolving arguments for (int j = i; j < max; j++) { TypeReference[] args = this.typeArguments[j]; if (args != null) { int argLength = args.length; for (int k = 0; k < argLength; k++) { TypeReference typeArgument = args[k]; if (isClassScope) { typeArgument.resolveType((ClassScope) scope); } else { typeArgument.resolveType((BlockScope) scope); } } } } return null; } ReferenceBinding currentType = (ReferenceBinding) this.resolvedType; if (qualifyingType == null) { qualifyingType = currentType.enclosingType(); // if member type if (qualifyingType != null) { qualifyingType = currentType.isStatic() ? (ReferenceBinding) scope.environment().convertToRawType(qualifyingType, false /*do not force conversion of enclosing types*/) : scope.environment().convertToParameterizedType(qualifyingType); } } else { if (typeIsConsistent && currentType.isStatic() && (qualifyingType.isParameterizedTypeWithActualArguments() || qualifyingType.isGenericType())) { scope.problemReporter().staticMemberOfParameterizedType(this, scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifyingType), i); typeIsConsistent = false; } ReferenceBinding enclosingType = currentType.enclosingType(); if (enclosingType != null && enclosingType.erasure() != qualifyingType.erasure()) { // qualifier != declaring/enclosing qualifyingType = enclosingType; // inherited member type, leave it associated with its enclosing rather than subtype } } // check generic and arity TypeReference[] args = this.typeArguments[i]; if (args != null) { TypeReference keep = null; if (isClassScope) { keep = ((ClassScope) scope).superTypeReference; ((ClassScope) scope).superTypeReference = null; } int argLength = args.length; boolean isDiamond = argLength == 0 && (i == (max -1)) && ((this.bits & ASTNode.IsDiamond) != 0); TypeBinding[] argTypes = new TypeBinding[argLength]; boolean argHasError = false; ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original(); for (int j = 0; j < argLength; j++) { TypeReference arg = args[j]; TypeBinding argType = isClassScope ? arg.resolveTypeArgument((ClassScope) scope, currentOriginal, j) : arg.resolveTypeArgument((BlockScope) scope, currentOriginal, j); if (argType == null) { argHasError = true; } else { argTypes[j] = argType; } } if (argHasError) { return null; } if (isClassScope) { ((ClassScope) scope).superTypeReference = keep; if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null; } TypeVariableBinding[] typeVariables = currentOriginal.typeVariables(); if (typeVariables == Binding.NO_TYPE_VARIABLES) { // check generic if (scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5) { // below 1.5, already reported as syntax error scope.problemReporter().nonGenericTypeCannotBeParameterized(i, this, currentType, argTypes); return null; } this.resolvedType = (qualifyingType != null && qualifyingType.isParameterizedType()) ? scope.environment().createParameterizedType(currentOriginal, null, qualifyingType) : currentType; return this.resolvedType; } else if (argLength != typeVariables.length) { if (!isDiamond) { // check arity scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes, i); return null; } } // check parameterizing non-static member type of raw type if (typeIsConsistent && !currentType.isStatic()) { ReferenceBinding actualEnclosing = currentType.enclosingType(); if (actualEnclosing != null && actualEnclosing.isRawType()) { scope.problemReporter().rawMemberTypeCannotBeParameterized( this, scope.environment().createRawType(currentOriginal, actualEnclosing), argTypes); typeIsConsistent = false; } } ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType(currentOriginal, argTypes, qualifyingType); // check argument type compatibility for non <> cases - <> case needs no bounds check, we will scream foul if needed during inference. if (!isDiamond) { if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution parameterizedType.boundCheck(scope, args); else scope.deferBoundCheck(this); } qualifyingType = parameterizedType; } else { ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original(); if (isClassScope) if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null; if (currentOriginal.isGenericType()) { if (typeIsConsistent && qualifyingType != null && qualifyingType.isParameterizedType()) { scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.environment().createParameterizedType(currentOriginal, null, qualifyingType), i); typeIsConsistent = false; } qualifyingType = scope.environment().createRawType(currentOriginal, qualifyingType); // raw type } else { qualifyingType = (qualifyingType != null && qualifyingType.isParameterizedType()) ? scope.environment().createParameterizedType(currentOriginal, null, qualifyingType) : currentType; } } if (isTypeUseDeprecated(qualifyingType, scope)) reportDeprecatedType(qualifyingType, scope, i); this.resolvedType = qualifyingType; recordResolution(scope.environment(), this.resolvedType); } return this.resolvedType; } private void createArrayType(Scope scope) { if (this.dimensions > 0) { if (this.dimensions > 255) scope.problemReporter().tooManyDimensions(this); this.resolvedType = scope.createArrayType(this.resolvedType, this.dimensions); } } public StringBuffer printExpression(int indent, StringBuffer output) { int length = this.tokens.length; for (int i = 0; i < length - 1; i++) { output.append(this.tokens[i]); TypeReference[] typeArgument = this.typeArguments[i]; if (typeArgument != null) { output.append('<'); int typeArgumentLength = typeArgument.length; if (typeArgumentLength > 0) { int max = typeArgumentLength - 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(this.tokens[length - 1]); TypeReference[] typeArgument = this.typeArguments[length - 1]; if (typeArgument != null) { output.append('<'); int typeArgumentLength = typeArgument.length; if (typeArgumentLength > 0) { int max = typeArgumentLength - 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 < this.dimensions - 1; i++) { output.append("[]"); //$NON-NLS-1$ } output.append("..."); //$NON-NLS-1$ } else { for (int i= 0 ; i < this.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); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java0000644000175000001440000000501412212041344030776 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.codegen.*; import org.eclipse.jdt.internal.compiler.lookup.*; public abstract class BranchStatement extends Statement { public char[] label; public BranchLabel targetLabel; public SubRoutineStatement[] subroutines; public int initStateIndex = -1; /** * BranchStatement constructor comment. */ public BranchStatement(char[] label, int sourceStart,int sourceEnd) { this.label = label ; this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; } /** * Branch code generation * * generate the finallyInvocationSequence. */ public void generateCode(BlockScope currentScope, CodeStream codeStream) { if ((this.bits & ASTNode.IsReachable) == 0) { return; } int pc = codeStream.position; // generation of code responsible for invoking the finally // blocks in sequence if (this.subroutines != null){ for (int i = 0, max = this.subroutines.length; i < max; i++){ SubRoutineStatement sub = this.subroutines[i]; boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, this.targetLabel, this.initStateIndex, null); if (didEscape) { codeStream.recordPositionsFrom(pc, this.sourceStart); SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream); if (this.initStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex); } return; } } } codeStream.goto_(this.targetLabel); codeStream.recordPositionsFrom(pc, this.sourceStart); SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream); if (this.initStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex); } } public void resolve(BlockScope scope) { // nothing to do during name resolution } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java0000644000175000001440000000464712212041344030276 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.BranchLabel; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.impl.BooleanConstant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class FalseLiteral extends MagicLiteral { static final char[] source = {'f', 'a', 'l', 's', 'e'}; public FalseLiteral(int s , int e) { super(s,e); } public void computeConstant() { this.constant = BooleanConstant.fromValue(false); } /** * Code generation for false 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(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { // falseLabel being not nil means that we will not fall through into the FALSE case int pc = codeStream.position; if (valueRequired) { if (falseLabel != null) { // implicit falling through the TRUE case if (trueLabel == null) { codeStream.goto_(falseLabel); } } } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.BOOLEAN; } /** * */ public char[] source() { return source; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/OperatorIds.java0000644000175000001440000000324012212041344030146 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; public interface OperatorIds { public static final int AND_AND = 0; public static final int OR_OR = 1; public static final int AND = 2; public static final int OR = 3; public static final int LESS = 4; public static final int LESS_EQUAL = 5; public static final int GREATER = 6; public static final int GREATER_EQUAL = 7; public static final int XOR = 8; public static final int DIVIDE = 9; public static final int LEFT_SHIFT = 10; public static final int NOT = 11; public static final int TWIDDLE = 12; public static final int MINUS = 13; public static final int PLUS = 14; public static final int MULTIPLY = 15; public static final int REMAINDER = 16; public static final int RIGHT_SHIFT = 17; public static final int EQUAL_EQUAL = 18; public static final int UNSIGNED_RIGHT_SHIFT= 19; public static final int NumberOfTables = 20; public static final int QUESTIONCOLON = 23; public static final int NOT_EQUAL = 29; public static final int EQUAL = 30; public static final int INSTANCEOF = 31; public static final int PLUS_PLUS = 32; public static final int MINUS_MINUS = 33; } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java0000644000175000001440000000431112212041344030460 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; public abstract class NumberLiteral extends Literal { char[] source; public NumberLiteral(char[] token, int s, int e) { this(s,e) ; this.source = token ; } public NumberLiteral(int s, int e) { super (s,e) ; } public boolean isValidJavaStatement(){ return false ; } public char[] source(){ return this.source; } protected static char[] removePrefixZerosAndUnderscores(char[] token, boolean isLong) { int max = token.length; int start = 0; int end = max - 1; if (isLong) { end--; // remove the 'L' or 'l' } if (max > 1 && token[0] == '0') { if (max > 2 && (token[1] == 'x' || token[1] == 'X')) { start = 2; } else if (max > 2 && (token[1] == 'b' || token[1] == 'B')) { start = 2; } else { start = 1; } } boolean modified = false; boolean ignore = true; loop: for (int i = start; i < max; i++) { char currentChar = token[i]; switch(currentChar) { case '0' : // this is a prefix '0' if (ignore && !modified && (i < end)) { modified = true; } break; case '_' : modified = true; break loop; default : ignore = false; } } if (!modified) { return token; } ignore = true; StringBuffer buffer = new StringBuffer(); buffer.append(token, 0, start); loop: for (int i = start; i < max; i++) { char currentChar = token[i]; switch(currentChar) { case '0' : if (ignore && (i < end)) { // this is a prefix '0' continue loop; } break; case '_' : continue loop; default: ignore = false; } buffer.append(currentChar); } return buffer.toString().toCharArray(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java0000644000175000001440000002205012212041344031530 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check *******************************************************************************/ 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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class CompoundAssignment extends Assignment implements OperatorIds { public int operator; public int preAssignImplicitConversion; // var op exp is equivalent to var = (varType) var op exp // assignmentImplicitConversion stores the cast needed for the assignment public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) { //lhs is always a reference by construction , //but is build as an expression ==> the checkcast cannot fail super(lhs, expression, sourceEnd); lhs.bits &= ~IsStrictlyAssigned; // tag lhs as NON assigned - it is also a read access lhs.bits |= IsCompoundAssigned; // tag lhs as assigned by compound this.operator = operator ; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // record setting a variable: various scenarii are possible, setting an array reference, // a field reference, a blank final field reference, a field of an enclosing instance or // just a local variable. if (this.resolvedType.id != T_JavaLangString) { this.lhs.checkNPE(currentScope, flowContext, flowInfo); // account for exceptions thrown by any arithmetics: flowContext.recordAbruptExit(); } flowInfo = ((Reference) this.lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits(); if (this.resolvedType.id == T_JavaLangString) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=339250 LocalVariableBinding local = this.lhs.localVariableBinding(); if (local != null) { // compound assignment results in a definitely non null value for String flowInfo.markAsDefinitelyNonNull(local); flowContext.markFinallyNullStatus(local, FlowInfo.NON_NULL); } } return flowInfo; } public boolean checkCastCompatibility() { return true; } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { // various scenarii are possible, setting an array reference, // a field reference, a blank final field reference, a field of an enclosing instance or // just a local variable. int pc = codeStream.position; ((Reference) this.lhs).generateCompoundAssignment(currentScope, codeStream, this.expression, this.operator, this.preAssignImplicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { return FlowInfo.NON_NULL; // we may have complained on checkNPE, but we avoid duplicate error } public String operatorToString() { switch (this.operator) { case PLUS : return "+="; //$NON-NLS-1$ case MINUS : return "-="; //$NON-NLS-1$ case MULTIPLY : return "*="; //$NON-NLS-1$ case DIVIDE : return "/="; //$NON-NLS-1$ case AND : return "&="; //$NON-NLS-1$ case OR : return "|="; //$NON-NLS-1$ case XOR : return "^="; //$NON-NLS-1$ case REMAINDER : return "%="; //$NON-NLS-1$ case LEFT_SHIFT : return "<<="; //$NON-NLS-1$ case RIGHT_SHIFT : return ">>="; //$NON-NLS-1$ case UNSIGNED_RIGHT_SHIFT : return ">>>="; //$NON-NLS-1$ } return "unknown operator"; //$NON-NLS-1$ } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { this.lhs.printExpression(indent, output).append(' ').append(operatorToString()).append(' '); return this.expression.printExpression(0, output) ; } public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; if (!(this.lhs instanceof Reference) || this.lhs.isThis()) { scope.problemReporter().expressionShouldBeAVariable(this.lhs); return null; } boolean expressionIsCast = this.expression instanceof CastExpression; if (expressionIsCast) this.expression.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on TypeBinding originalLhsType = this.lhs.resolveType(scope); TypeBinding originalExpressionType = this.expression.resolveType(scope); if (originalLhsType == null || originalExpressionType == null) return null; LocalVariableBinding localVariableBinding = this.lhs.localVariableBinding(); if (localVariableBinding != null) { localVariableBinding.tagBits &= ~TagBits.IsEffectivelyFinal; } // autoboxing support LookupEnvironment env = scope.environment(); TypeBinding lhsType = originalLhsType, expressionType = originalExpressionType; boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.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; } 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_JavaLangObject; // use the Object has tag table } // the code is an int // (cast) left Op (cast) rigth --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 <<0 // the conversion is stored INTO the reference (info needed for the code gen) int result = OperatorExpression.OperatorSignatures[this.operator][ (lhsID << 4) + expressionID]; if (result == T_undefined) { scope.problemReporter().invalidOperator(this, lhsType, expressionType); return null; } if (this.operator == PLUS){ if(lhsID == T_JavaLangObject && (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7)) { // += is illegal (39248) for compliance < 1.7 scope.problemReporter().invalidOperator(this, lhsType, expressionType); return null; } else { // += is illegal if ((lhsType.isNumericType() || lhsID == T_boolean) && !expressionType.isNumericType()){ scope.problemReporter().invalidOperator(this, lhsType, expressionType); return null; } } } TypeBinding resultType = TypeBinding.wellKnownType(scope, result & 0x0000F); if (checkCastCompatibility()) { if (originalLhsType.id != T_JavaLangString && resultType.id != T_JavaLangString) { if (!checkCastTypesCompatibility(scope, originalLhsType, resultType, null)) { scope.problemReporter().invalidOperator(this, originalLhsType, expressionType); return null; } } } this.lhs.computeConversion(scope, TypeBinding.wellKnownType(scope, (result >>> 16) & 0x0000F), originalLhsType); this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (result >>> 8) & 0x0000F), originalExpressionType); this.preAssignImplicitConversion = (unboxedLhs ? BOXING : 0) | (lhsID << 4) | (result & 0x0000F); if (unboxedLhs) scope.problemReporter().autoboxing(this, lhsType, originalLhsType); if (expressionIsCast) CastExpression.checkNeedForArgumentCasts(scope, this.operator, result, this.lhs, originalLhsType.id, false, this.expression, originalExpressionType.id, true); return this.resolvedType = originalLhsType; } public boolean restrainUsageToNumericTypes(){ return false ; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.lhs.traverse(visitor, scope); this.expression.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java0000644000175000001440000000742312212041344030304 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.impl.FloatConstant; 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; public FloatLiteral(char[] token, int s, int e) { super(token, s, e); } public void computeConstant() { Float computedValue; boolean containsUnderscores = CharOperation.indexOf('_', this.source) > 0; if (containsUnderscores) { // remove all underscores from source this.source = CharOperation.remove(this.source, '_'); } try { computedValue = Float.valueOf(String.valueOf(this.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(this.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; } this.value = v; this.constant = FloatConstant.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 < this.source.length; i++) { //it is welled formated so just test against '0' and potential . D d switch (this.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; } } } this.value = floatValue; this.constant = FloatConstant.fromValue(this.value); } /** * 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(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.FLOAT; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/LongLiteralMinValue.java0000644000175000001440000000206612212041344031575 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.impl.*; public class LongLiteralMinValue extends LongLiteral { final static char[] CharValue = new char[]{'-', '9','2','2','3','3','7','2','0','3','6','8','5','4','7','7','5','8','0','8','L'}; public LongLiteralMinValue(char[] token, char[] reducedForm, int start, int end) { super(token, reducedForm, start, end); this.constant = LongConstant.fromValue(Long.MIN_VALUE); } public void computeConstant() { /*precomputed at creation time*/} } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.j0000644000175000001440000001527112212041344032376 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class ArrayAllocationExpression extends Expression { public TypeReference type; //dimensions.length gives the number of dimensions, but the // last ones may be nulled as in new int[4][5][][] public Expression[] dimensions; public ArrayInitializer initializer; public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { for (int i = 0, max = this.dimensions.length; i < max; i++) { Expression dim; if ((dim = this.dimensions[i]) != null) { flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo); dim.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); } } // account for potential OutOfMemoryError: flowContext.recordAbruptExit(); if (this.initializer != null) { return this.initializer.analyseCode(currentScope, flowContext, flowInfo); } return flowInfo; } /** * Code generation for a array allocation expression */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (this.initializer != null) { this.initializer.generateCode(currentScope, codeStream, valueRequired); return; } int explicitDimCount = 0; for (int i = 0, max = this.dimensions.length; i < max; i++) { Expression dimExpression; if ((dimExpression = this.dimensions[i]) == null) break; // implicit dim, no further explict after this point dimExpression.generateCode(currentScope, codeStream, true); explicitDimCount++; } // array allocation if (explicitDimCount == 1) { // Mono-dimensional array codeStream.newArray((ArrayBinding)this.resolvedType); } else { // Multi-dimensional array codeStream.multianewarray(this.resolvedType, explicitDimCount); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { codeStream.pop(); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printExpression(int indent, StringBuffer output) { output.append("new "); //$NON-NLS-1$ this.type.print(0, output); for (int i = 0; i < this.dimensions.length; i++) { if (this.dimensions[i] == null) output.append("[]"); //$NON-NLS-1$ else { output.append('['); this.dimensions[i].printExpression(0, output); output.append(']'); } } if (this.initializer != null) this.initializer.printExpression(0, output); return output; } public TypeBinding resolveType(BlockScope scope) { // Build an array type reference using the current dimensions // The parser does not check for the fact that dimension may be null // 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 = this.type.resolveType(scope, true /* check bounds*/); // will check for null after dimensions are checked this.constant = Constant.NotAConstant; if (referenceType == TypeBinding.VOID) { scope.problemReporter().cannotAllocateVoidArray(this); referenceType = null; } // check the validity of the dimension syntax (and test for all null dimensions) int explicitDimIndex = -1; loop: for (int i = this.dimensions.length; --i >= 0;) { if (this.dimensions[i] != null) { if (explicitDimIndex < 0) explicitDimIndex = i; } else if (explicitDimIndex > 0) { // should not have an empty dimension before an non-empty one scope.problemReporter().incorrectLocationForNonEmptyDimension(this, explicitDimIndex); break loop; } } // explicitDimIndex < 0 says if all dimensions are nulled // when an initializer is given, no dimension must be specified if (this.initializer == null) { 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); } // dimensions resolution for (int i = 0; i <= explicitDimIndex; i++) { Expression dimExpression; if ((dimExpression = this.dimensions[i]) != null) { TypeBinding dimensionType = dimExpression.resolveTypeExpecting(scope, TypeBinding.INT); if (dimensionType != null) { this.dimensions[i].computeConversion(scope, TypeBinding.INT, dimensionType); } } } // building the array binding if (referenceType != null) { if (this.dimensions.length > 255) { scope.problemReporter().tooManyDimensions(this); } this.resolvedType = scope.createArrayType(referenceType, this.dimensions.length); // check the initializer if (this.initializer != null) { if ((this.initializer.resolveTypeExpecting(scope, this.resolvedType)) != null) this.initializer.binding = (ArrayBinding)this.resolvedType; } if ((referenceType.tagBits & TagBits.HasMissingType) != 0) { return null; } } return this.resolvedType; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { int dimensionsLength = this.dimensions.length; this.type.traverse(visitor, scope); for (int i = 0; i < dimensionsLength; i++) { if (this.dimensions[i] != null) this.dimensions[i].traverse(visitor, scope); } if (this.initializer != null) this.initializer.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java0000644000175000001440000003335012212041344031064 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop) * bug 186342 - [compiler][null] Using annotations for null checking * bug 365835 - [compiler][null] inconsistent error reporting. * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 358903 - Filter practically unimportant resource leak warnings * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 400761 - [compiler][null] null may be return as boolean without a diagnostic *******************************************************************************/ 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.*; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class ReturnStatement extends Statement { public Expression expression; public SubRoutineStatement[] subroutines; public LocalVariableBinding saveValueVariable; public int initStateIndex = -1; public ReturnStatement(Expression expression, int sourceStart, int sourceEnd) { this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; this.expression = expression ; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // here requires to generate a sequence of finally blocks invocations depending corresponding // to each of the traversed try statements, so that execution will terminate properly. // lookup the label, this should answer the returnContext MethodScope methodScope = currentScope.methodScope(); if (this.expression != null) { flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo); this.expression.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); if (flowInfo.reachMode() == FlowInfo.REACHABLE) checkAgainstNullAnnotation(currentScope, flowContext, this.expression.nullStatus(flowInfo, flowContext)); if (currentScope.compilerOptions().analyseResourceLeaks) { FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression, flowInfo, flowContext); if (trackingVariable != null) { if (methodScope != trackingVariable.methodScope) trackingVariable.markClosedInNestedMethod(); // by returning the method passes the responsibility to the caller: flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.expression, flowInfo, flowContext, true); } } } this.initStateIndex = methodScope.recordInitializationStates(flowInfo); // compute the return sequence (running the finally blocks) FlowContext traversedContext = flowContext; int subCount = 0; boolean saveValueNeeded = false; boolean hasValueToSave = needValueStore(); boolean noAutoCloseables = true; do { SubRoutineStatement sub; if ((sub = traversedContext.subroutine()) != null) { if (this.subroutines == null){ this.subroutines = new SubRoutineStatement[5]; } if (subCount == this.subroutines.length) { System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow } this.subroutines[subCount++] = sub; if (sub.isSubRoutineEscaping()) { saveValueNeeded = false; this.bits |= ASTNode.IsAnySubRoutineEscaping; break; } if (sub instanceof TryStatement) { if (((TryStatement) sub).resources.length > 0) { noAutoCloseables = false; } } } traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); if (traversedContext instanceof InsideSubRoutineFlowContext) { ASTNode node = traversedContext.associatedNode; if (node instanceof SynchronizedStatement) { this.bits |= ASTNode.IsSynchronized; } else if (node instanceof TryStatement) { TryStatement tryStatement = (TryStatement) node; flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits if (hasValueToSave) { if (this.saveValueVariable == null){ // closest subroutine secret variable is used prepareSaveValueLocation(tryStatement); } saveValueNeeded = true; this.initStateIndex = methodScope.recordInitializationStates(flowInfo); } } } else if (traversedContext instanceof InitializationFlowContext) { currentScope.problemReporter().cannotReturnInInitializer(this); return FlowInfo.DEAD_END; } } while ((traversedContext = traversedContext.getLocalParent()) != null); // resize subroutines if ((this.subroutines != null) && (subCount != this.subroutines.length)) { System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount); } // secret local variable for return value (note that this can only occur in a real method) if (saveValueNeeded) { if (this.saveValueVariable != null) { this.saveValueVariable.useFlag = LocalVariableBinding.USED; } } else { this.saveValueVariable = null; if (((this.bits & ASTNode.IsSynchronized) == 0) && this.expression != null && this.expression.resolvedType == TypeBinding.BOOLEAN) { if (noAutoCloseables) { // can't abruptly return in the presence of autocloseables. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=367566 this.expression.bits |= ASTNode.IsReturnedValue; } } } currentScope.checkUnclosedCloseables(flowInfo, flowContext, this, currentScope); // inside conditional structure respect that a finally-block may conditionally be entered directly from here flowContext.recordAbruptExit(); return FlowInfo.DEAD_END; } void checkAgainstNullAnnotation(BlockScope scope, FlowContext flowContext, int nullStatus) { if (nullStatus != FlowInfo.NON_NULL) { // if we can't prove non-null check against declared null-ness of the enclosing method: long tagBits; MethodBinding methodBinding; try { methodBinding = scope.methodScope().referenceMethod().binding; tagBits = methodBinding.tagBits; } catch (NullPointerException npe) { // chain of references in try-block has several potential nulls; // any null means we cannot perform the following check return; } if ((tagBits & TagBits.AnnotationNonNull) != 0) { flowContext.recordNullityMismatch(scope, this.expression, this.expression.resolvedType, methodBinding.returnType, nullStatus); } } } /** * Retrun statement code generation * * generate the finallyInvocationSequence. * * @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 ((this.bits & ASTNode.IsReachable) == 0) { return; } int pc = codeStream.position; boolean alreadyGeneratedExpression = false; // generate the expression if (needValueStore()) { alreadyGeneratedExpression = true; this.expression.generateCode(currentScope, codeStream, needValue()); // no value needed if non-returning subroutine generateStoreSaveValueIfNecessary(codeStream); } // generation of code responsible for invoking the finally blocks in sequence if (this.subroutines != null) { Object reusableJSRTarget = this.expression == null ? (Object)TypeBinding.VOID : this.expression.reusableJSRTarget(); for (int i = 0, max = this.subroutines.length; i < max; i++) { SubRoutineStatement sub = this.subroutines[i]; boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, reusableJSRTarget, this.initStateIndex, this.saveValueVariable); if (didEscape) { codeStream.recordPositionsFrom(pc, this.sourceStart); SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream); return; } } } if (this.saveValueVariable != null) { codeStream.load(this.saveValueVariable); } if (this.expression != null && !alreadyGeneratedExpression) { this.expression.generateCode(currentScope, codeStream, true); // hook necessary for Code Snippet generateStoreSaveValueIfNecessary(codeStream); } // output the suitable return bytecode or wrap the value inside a descriptor for doits generateReturnBytecode(codeStream); if (this.saveValueVariable != null) { codeStream.removeVariable(this.saveValueVariable); } if (this.initStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream); } /** * Dump the suitable return bytecode for a return statement * */ public void generateReturnBytecode(CodeStream codeStream) { codeStream.generateReturnBytecode(this.expression); } public void generateStoreSaveValueIfNecessary(CodeStream codeStream){ if (this.saveValueVariable != null) { codeStream.store(this.saveValueVariable, false); // the variable is visible as soon as the local is stored codeStream.addVariable(this.saveValueVariable); } } private boolean needValueStore() { return this.expression != null && (this.expression.constant == Constant.NotAConstant || (this.expression.implicitConversion & TypeIds.BOXING)!= 0) && !(this.expression instanceof NullLiteral); } public boolean needValue() { return this.saveValueVariable != null || (this.bits & ASTNode.IsSynchronized) != 0 || ((this.bits & ASTNode.IsAnySubRoutineEscaping) == 0); } public void prepareSaveValueLocation(TryStatement targetTryStatement){ this.saveValueVariable = targetTryStatement.secretReturnValue; } public StringBuffer printStatement(int tab, StringBuffer output){ printIndent(tab, output).append("return "); //$NON-NLS-1$ if (this.expression != null ) this.expression.printExpression(0, output) ; return output.append(';'); } public void resolve(BlockScope scope) { MethodScope methodScope = scope.methodScope(); MethodBinding methodBinding; TypeBinding methodType = (methodScope.referenceContext instanceof AbstractMethodDeclaration) ? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null ? null : methodBinding.returnType) : TypeBinding.VOID; TypeBinding expressionType; if (methodType == TypeBinding.VOID) { // the expression should be null if (this.expression == null) return; if ((expressionType = this.expression.resolveType(scope)) != null) scope.problemReporter().attemptToReturnNonVoidExpression(this, expressionType); return; } if (this.expression == null) { if (methodType != null) scope.problemReporter().shouldReturn(methodType, this); return; } this.expression.setExpectedType(methodType); // needed in case of generic method invocation if ((expressionType = this.expression.resolveType(scope)) == null) return; if (expressionType == TypeBinding.VOID) { scope.problemReporter().attemptToReturnVoidValue(this); return; } if (methodType == null) return; if (methodType != expressionType) // must call before computeConversion() and typeMismatchError() scope.compilationUnitScope().recordTypeConversion(methodType, expressionType); if (this.expression.isConstantValueOfTypeAssignableToType(expressionType, methodType) || expressionType.isCompatibleWith(methodType)) { this.expression.computeConversion(scope, methodType, expressionType); if (expressionType.needsUncheckedConversion(methodType)) { scope.problemReporter().unsafeTypeConversion(this.expression, expressionType, methodType); } if (this.expression instanceof CastExpression && (this.expression.bits & (ASTNode.UnnecessaryCast|ASTNode.DisableUnnecessaryCastCheck)) == 0) { CastExpression.checkNeedForAssignedCast(scope, methodType, (CastExpression) this.expression); } return; } else if (isBoxingCompatible(expressionType, methodType, this.expression, scope)) { this.expression.computeConversion(scope, methodType, expressionType); if (this.expression instanceof CastExpression && (this.expression.bits & (ASTNode.UnnecessaryCast|ASTNode.DisableUnnecessaryCastCheck)) == 0) { CastExpression.checkNeedForAssignedCast(scope, methodType, (CastExpression) this.expression); } return; } if ((methodType.tagBits & TagBits.HasMissingType) == 0) { // no need to complain if return type was missing (avoid secondary error : 220967) scope.problemReporter().typeMismatchError(expressionType, methodType, this.expression, null); } } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { if (this.expression != null) this.expression.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/IfStatement.java0000644000175000001440000002747612212041344030157 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class IfStatement extends Statement { //this class represents the case of only one statement in //either else and/or then branches. public Expression condition; public Statement thenStatement; public Statement elseStatement; // for local variables table attributes int thenInitStateIndex = -1; int elseInitStateIndex = -1; int mergedInitStateIndex = -1; public IfStatement(Expression condition, Statement thenStatement, int sourceStart, int sourceEnd) { this.condition = condition; this.thenStatement = thenStatement; // remember useful empty statement if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatement; this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; } public IfStatement(Expression condition, Statement thenStatement, Statement elseStatement, int sourceStart, int sourceEnd) { this.condition = condition; this.thenStatement = thenStatement; // remember useful empty statement if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatement; this.elseStatement = elseStatement; if (elseStatement instanceof IfStatement) elseStatement.bits |= IsElseIfStatement; if (elseStatement instanceof EmptyStatement) elseStatement.bits |= IsUsefulEmptyStatement; this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // process the condition FlowInfo conditionFlowInfo = this.condition.analyseCode(currentScope, flowContext, flowInfo); int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; Constant cst = this.condition.optimizedBooleanConstant(); this.condition.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; flowContext.conditionalLevel++; // process the THEN part FlowInfo thenFlowInfo = conditionFlowInfo.safeInitsWhenTrue(); if (isConditionOptimizedFalse) { thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } FlowInfo elseFlowInfo = conditionFlowInfo.initsWhenFalse().copy(); if (isConditionOptimizedTrue) { elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) && ((thenFlowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)) { // Mark then block as unreachable // No need if the whole if-else construct itself lies in unreachable code this.bits |= ASTNode.IsThenStatementUnreachable; } else if (((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) && ((elseFlowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)) { // Mark else block as unreachable // No need if the whole if-else construct itself lies in unreachable code this.bits |= ASTNode.IsElseStatementUnreachable; } boolean reportDeadCodeForKnownPattern = !isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement; if (this.thenStatement != null) { // Save info for code gen this.thenInitStateIndex = currentScope.methodScope().recordInitializationStates(thenFlowInfo); if (isConditionOptimizedFalse || ((this.bits & ASTNode.IsThenStatementUnreachable) != 0)) { if (reportDeadCodeForKnownPattern) { this.thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, initialComplaintLevel, false); } else { // its a known coding pattern which should be tolerated by dead code analysis // according to isKnowDeadCodePattern() this.bits &= ~ASTNode.IsThenStatementUnreachable; } } thenFlowInfo = this.thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo); } // any null check from the condition is now expired flowContext.expireNullCheckedFieldInfo(); // code gen: optimizing the jump around the ELSE part if ((thenFlowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) { this.bits |= ASTNode.ThenExit; } // process the ELSE part if (this.elseStatement != null) { // signal else clause unnecessarily nested, tolerate else-if code pattern if (thenFlowInfo == FlowInfo.DEAD_END && (this.bits & IsElseIfStatement) == 0 // else of an else-if && !(this.elseStatement instanceof IfStatement)) { currentScope.problemReporter().unnecessaryElse(this.elseStatement); } // Save info for code gen this.elseInitStateIndex = currentScope.methodScope().recordInitializationStates(elseFlowInfo); if (isConditionOptimizedTrue || ((this.bits & ASTNode.IsElseStatementUnreachable) != 0)) { if (reportDeadCodeForKnownPattern) { this.elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, initialComplaintLevel, false); } else { // its a known coding pattern which should be tolerated by dead code analysis // according to isKnowDeadCodePattern() this.bits &= ~ASTNode.IsElseStatementUnreachable; } } elseFlowInfo = this.elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo); } // process AutoCloseable resources closed in only one branch: currentScope.correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo); // merge THEN & ELSE initializations FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranchesIfElse( thenFlowInfo, isConditionOptimizedTrue, elseFlowInfo, isConditionOptimizedFalse, true /*if(true){ return; } fake-reachable(); */, flowInfo, this, reportDeadCodeForKnownPattern); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); flowContext.conditionalLevel--; return mergedInfo; } /** * If 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 ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; BranchLabel endifLabel = new BranchLabel(codeStream); // optimizing the then/else part code gen Constant cst; boolean hasThenPart = !(((cst = this.condition.optimizedBooleanConstant()) != Constant.NotAConstant && cst.booleanValue() == false) || this.thenStatement == null || this.thenStatement.isEmptyBlock()); boolean hasElsePart = !((cst != Constant.NotAConstant && cst.booleanValue() == true) || this.elseStatement == null || this.elseStatement.isEmptyBlock()); if (hasThenPart) { BranchLabel falseLabel = null; // generate boolean condition only if needed if (cst != Constant.NotAConstant && cst.booleanValue() == true) { this.condition.generateCode(currentScope, codeStream, false); } else { this.condition.generateOptimizedBoolean( currentScope, codeStream, null, hasElsePart ? (falseLabel = new BranchLabel(codeStream)) : endifLabel, true/*cst == Constant.NotAConstant*/); } // May loose some local variable initializations : affecting the local variable attributes if (this.thenInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.thenInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.thenInitStateIndex); } // generate then statement this.thenStatement.generateCode(currentScope, codeStream); // jump around the else statement if (hasElsePart) { if ((this.bits & ASTNode.ThenExit) == 0) { this.thenStatement.branchChainTo(endifLabel); int position = codeStream.position; codeStream.goto_(endifLabel); //goto is pointing to the last line of the thenStatement codeStream.recordPositionsFrom(position, this.thenStatement.sourceEnd); // generate else statement } // May loose some local variable initializations : affecting the local variable attributes if (this.elseInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables( currentScope, this.elseInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.elseInitStateIndex); } if (falseLabel != null) falseLabel.place(); this.elseStatement.generateCode(currentScope, codeStream); } } else if (hasElsePart) { // generate boolean condition only if needed if (cst != Constant.NotAConstant && cst.booleanValue() == false) { this.condition.generateCode(currentScope, codeStream, false); } else { this.condition.generateOptimizedBoolean( currentScope, codeStream, endifLabel, null, true/*cst == Constant.NotAConstant*/); } // generate else statement // May loose some local variable initializations : affecting the local variable attributes if (this.elseInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables( currentScope, this.elseInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.elseInitStateIndex); } this.elseStatement.generateCode(currentScope, codeStream); } else { // generate condition side-effects this.condition.generateCode(currentScope, codeStream, false); codeStream.recordPositionsFrom(pc, this.sourceStart); } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables( currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } endifLabel.place(); codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output).append("if ("); //$NON-NLS-1$ this.condition.printExpression(0, output).append(")\n"); //$NON-NLS-1$ this.thenStatement.printStatement(indent + 2, output); if (this.elseStatement != null) { output.append('\n'); printIndent(indent, output); output.append("else\n"); //$NON-NLS-1$ this.elseStatement.printStatement(indent + 2, output); } return output; } public void resolve(BlockScope scope) { TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); this.condition.computeConversion(scope, type, type); if (this.thenStatement != null) this.thenStatement.resolve(scope); if (this.elseStatement != null) this.elseStatement.resolve(scope); } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.condition.traverse(visitor, blockScope); if (this.thenStatement != null) this.thenStatement.traverse(visitor, blockScope); if (this.elseStatement != null) this.elseStatement.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ThisReference.java0000644000175000001440000001030112212041344030435 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * Jesper S Moller - Contributions for * Bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class ThisReference extends Reference { public static ThisReference implicitThis(){ ThisReference implicitThis = new ThisReference(0, 0); implicitThis.bits |= IsImplicitThis; return implicitThis; } public ThisReference(int sourceStart, int sourceEnd) { this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; } /* * @see Reference#analyseAssignment(...) */ public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { return flowInfo; // this cannot be assigned } public boolean checkAccess(MethodScope methodScope) { // this/super cannot be used in constructor call if (methodScope.isConstructorCall) { methodScope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this); return false; } // static may not refer to this/super if (methodScope.isStatic) { methodScope.problemReporter().errorThisSuperInStatic(this); return false; } methodScope.resetEnclosingMethodStaticFlag(); return true; } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { return true; // never problematic } /* * @see Reference#generateAssignment(...) */ public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { // this cannot be assigned } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (valueRequired) codeStream.aload_0(); if ((this.bits & IsImplicitThis) == 0) codeStream.recordPositionsFrom(pc, this.sourceStart); } /* * @see Reference#generateCompoundAssignment(...) */ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { // this cannot be assigned } /* * @see org.eclipse.jdt.internal.compiler.ast.Reference#generatePostIncrement() */ public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { // this cannot be assigned } public boolean isImplicitThis() { return (this.bits & IsImplicitThis) != 0; } public boolean isThis() { return true ; } public StringBuffer printExpression(int indent, StringBuffer output){ if (isImplicitThis()) return output; return output.append("this"); //$NON-NLS-1$ } public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; if (!isImplicitThis() &&!checkAccess(scope.methodScope())) { return null; } return this.resolvedType = scope.enclosingReceiverType(); } public void traverse(ASTVisitor visitor, BlockScope blockScope) { visitor.visit(this, blockScope); visitor.endVisit(this, blockScope); } public void traverse(ASTVisitor visitor, ClassScope blockScope) { visitor.visit(this, blockScope); visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/TypeReference.java0000644000175000001440000002125312212041344030457 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public abstract class TypeReference extends Expression { public static final TypeReference[] NO_TYPE_ARGUMENTS = new TypeReference[0]; /* * Answer a base type reference (can be an array of base type). */ public static final TypeReference baseTypeReference(int baseType, int dim) { if (dim == 0) { switch (baseType) { case (TypeIds.T_void) : return new SingleTypeReference(TypeBinding.VOID.simpleName, 0); case (TypeIds.T_boolean) : return new SingleTypeReference(TypeBinding.BOOLEAN.simpleName, 0); case (TypeIds.T_char) : return new SingleTypeReference(TypeBinding.CHAR.simpleName, 0); case (TypeIds.T_float) : return new SingleTypeReference(TypeBinding.FLOAT.simpleName, 0); case (TypeIds.T_double) : return new SingleTypeReference(TypeBinding.DOUBLE.simpleName, 0); case (TypeIds.T_byte) : return new SingleTypeReference(TypeBinding.BYTE.simpleName, 0); case (TypeIds.T_short) : return new SingleTypeReference(TypeBinding.SHORT.simpleName, 0); case (TypeIds.T_int) : return new SingleTypeReference(TypeBinding.INT.simpleName, 0); default : //T_long return new SingleTypeReference(TypeBinding.LONG.simpleName, 0); } } switch (baseType) { case (TypeIds.T_void) : return new ArrayTypeReference(TypeBinding.VOID.simpleName, dim, 0); case (TypeIds.T_boolean) : return new ArrayTypeReference(TypeBinding.BOOLEAN.simpleName, dim, 0); case (TypeIds.T_char) : return new ArrayTypeReference(TypeBinding.CHAR.simpleName, dim, 0); case (TypeIds.T_float) : return new ArrayTypeReference(TypeBinding.FLOAT.simpleName, dim, 0); case (TypeIds.T_double) : return new ArrayTypeReference(TypeBinding.DOUBLE.simpleName, dim, 0); case (TypeIds.T_byte) : return new ArrayTypeReference(TypeBinding.BYTE.simpleName, dim, 0); case (TypeIds.T_short) : return new ArrayTypeReference(TypeBinding.SHORT.simpleName, dim, 0); case (TypeIds.T_int) : return new ArrayTypeReference(TypeBinding.INT.simpleName, dim, 0); default : //T_long return new ArrayTypeReference(TypeBinding.LONG.simpleName, dim, 0); } } // allows us to trap completion & selection nodes public void aboutToResolve(Scope scope) { // default implementation: do nothing } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return flowInfo; } public void checkBounds(Scope scope) { // only parameterized type references have bounds } public abstract TypeReference copyDims(int dim); public int dimensions() { return 0; } public abstract char[] getLastToken(); /** * @return char[][] * TODO (jerome) should merge back into #getTypeName() */ public char [][] getParameterizedTypeName(){ return getTypeName(); } protected abstract TypeBinding getTypeBinding(Scope scope); /** * @return char[][] */ public abstract char [][] getTypeName() ; protected TypeBinding internalResolveType(Scope scope) { // handle the error here this.constant = Constant.NotAConstant; if (this.resolvedType != null) { // is a shared type reference which was already resolved if (this.resolvedType.isValidBinding()) { return this.resolvedType; } else { switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : case ProblemReasons.InheritedNameHidesEnclosingName : TypeBinding type = this.resolvedType.closestMatch(); if (type == null) return null; return scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/); default : return null; } } } boolean hasError; TypeBinding type = this.resolvedType = getTypeBinding(scope); if (type == null) { return null; // detected cycle while resolving hierarchy } else if ((hasError = !type.isValidBinding()) == true) { reportInvalidType(scope); switch (type.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : case ProblemReasons.InheritedNameHidesEnclosingName : type = type.closestMatch(); if (type == null) return null; break; default : return null; } } if (type.isArrayType() && ((ArrayBinding) type).leafComponentType == TypeBinding.VOID) { scope.problemReporter().cannotAllocateVoidArray(this); return null; } if (!(this instanceof QualifiedTypeReference) // QualifiedTypeReference#getTypeBinding called above will have already checked deprecation && isTypeUseDeprecated(type, scope)) { reportDeprecatedType(type, scope); } type = scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/); if (type.leafComponentType().isRawType() && (this.bits & ASTNode.IgnoreRawTypeCheck) == 0 && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) { scope.problemReporter().rawTypeReference(this, type); } if (hasError) { // do not store the computed type, keep the problem type instead return type; } return this.resolvedType = type; } public boolean isTypeReference() { return true; } protected void reportDeprecatedType(TypeBinding type, Scope scope, int index) { scope.problemReporter().deprecatedType(type, this, index); } protected void reportDeprecatedType(TypeBinding type, Scope scope) { scope.problemReporter().deprecatedType(type, this, Integer.MAX_VALUE); } protected void reportInvalidType(Scope scope) { scope.problemReporter().invalidType(this, this.resolvedType); } public TypeBinding resolveSuperType(ClassScope scope) { // assumes the implementation of resolveType(ClassScope) will call back to detect cycles TypeBinding superType = resolveType(scope); if (superType == null) return null; if (superType.isTypeVariable()) { if (this.resolvedType.isValidBinding()) { this.resolvedType = new ProblemReferenceBinding(getTypeName(), (ReferenceBinding)this.resolvedType, ProblemReasons.IllegalSuperTypeVariable); reportInvalidType(scope); } return null; } return superType; } public final TypeBinding resolveType(BlockScope blockScope) { return resolveType(blockScope, true /* checkbounds if any */); } public TypeBinding resolveType(BlockScope scope, boolean checkBounds) { return internalResolveType(scope); } public TypeBinding resolveType(ClassScope scope) { return internalResolveType(scope); } public TypeBinding resolveTypeArgument(BlockScope blockScope, ReferenceBinding genericType, int rank) { return resolveType(blockScope, true /* check bounds*/); } public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding genericType, int rank) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=294057, circularity is allowed when we are // resolving type arguments i.e interface A {} interface B extends A {} // interface D extends C {} interface C extends B {} ReferenceBinding ref = classScope.referenceContext.binding; boolean pauseHierarchyCheck = false; try { if (ref.isHierarchyBeingConnected()) { ref.tagBits |= TagBits.PauseHierarchyCheck; pauseHierarchyCheck = true; } return resolveType(classScope); } finally { if (pauseHierarchyCheck) { ref.tagBits &= ~TagBits.PauseHierarchyCheck; } } } public abstract void traverse(ASTVisitor visitor, BlockScope scope); public abstract void traverse(ASTVisitor visitor, ClassScope scope); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java0000644000175000001440000003520712212041344031311 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 383368 - [compiler][null] syntactic null analysis for field references * Jesper S Moller - Contributions for * bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.CompilationResult; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class MethodDeclaration extends AbstractMethodDeclaration { public TypeReference returnType; public TypeParameter[] typeParameters; /** * MethodDeclaration constructor comment. */ public MethodDeclaration(CompilationResult compilationResult) { super(compilationResult); this.bits |= ASTNode.CanBeStatic; // Start with this assumption, will course correct during resolve and analyseCode. } public void analyseCode(ClassScope classScope, FlowContext flowContext, FlowInfo flowInfo) { // starting of the code analysis for methods if (this.ignoreFurtherInvestigation) return; try { if (this.binding == null) return; if (!this.binding.isUsed() && !this.binding.isAbstract()) { if (this.binding.isPrivate() || (((this.binding.modifiers & (ExtraCompilerModifiers.AccOverriding|ExtraCompilerModifiers.AccImplementing)) == 0) && this.binding.isOrEnclosedByPrivateType())) { if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError) { this.scope.problemReporter().unusedPrivateMethod(this); } } } // skip enum implicit methods if (this.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 (this.binding.isAbstract() || this.binding.isNative()) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=385780 if (this.typeParameters != null && !this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) { for (int i = 0, length = this.typeParameters.length; i < length; ++i) { TypeParameter typeParameter = this.typeParameters[i]; if ((typeParameter.binding.modifiers & ExtraCompilerModifiers.AccLocallyUsed) == 0) { this.scope.problemReporter().unusedTypeParameter(typeParameter); } } } ExceptionHandlingFlowContext methodContext = new ExceptionHandlingFlowContext( flowContext, this, this.binding.thrownExceptions, null, this.scope, FlowInfo.DEAD_END); // nullity and mark as assigned analyseArguments(flowInfo); if (this.binding.declaringClass instanceof MemberTypeBinding && !this.binding.declaringClass.isStatic()) { // method of a non-static member type can't be static. this.bits &= ~ASTNode.CanBeStatic; } // propagate to statements if (this.statements != null) { boolean enableSyntacticNullAnalysisForFields = this.scope.compilerOptions().enableSyntacticNullAnalysisForFields; int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE; for (int i = 0, count = this.statements.length; i < count; i++) { Statement stat = this.statements[i]; if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { flowInfo = stat.analyseCode(this.scope, methodContext, flowInfo); } if (enableSyntacticNullAnalysisForFields) { methodContext.expireNullCheckedFieldInfo(); } } } else { // method with empty body should not be flagged as static. this.bits &= ~ASTNode.CanBeStatic; } // check for missing returning path TypeBinding returnTypeBinding = this.binding.returnType; if ((returnTypeBinding == TypeBinding.VOID) || isAbstract()) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.bits |= ASTNode.NeedFreeReturn; } } else { if (flowInfo != FlowInfo.DEAD_END) { this.scope.problemReporter().shouldReturn(returnTypeBinding, this); } } // check unreachable catch blocks methodContext.complainIfUnusedExceptionHandlers(this); // check unused parameters this.scope.checkUnusedParameters(this.binding); // check if the method could have been static if (!this.binding.isStatic() && (this.bits & ASTNode.CanBeStatic) != 0) { if(!this.binding.isOverriding() && !this.binding.isImplementing()) { if (this.binding.isPrivate() || this.binding.isFinal() || this.binding.declaringClass.isFinal()) { this.scope.problemReporter().methodCanBeDeclaredStatic(this); } else { this.scope.problemReporter().methodCanBePotentiallyDeclaredStatic(this); } } } this.scope.checkUnclosedCloseables(flowInfo, null, null/*don't report against a specific location*/, null); } catch (AbortMethod e) { this.ignoreFurtherInvestigation = true; } } public boolean isMethod() { return true; } public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { //fill up the method body with statement parser.parse(this, unit); } public StringBuffer printReturnType(int indent, StringBuffer output) { if (this.returnType == null) return output; return this.returnType.printExpression(0, output).append(' '); } public void resolveStatements() { // ========= abort on fatal error ============= if (this.returnType != null && this.binding != null) { this.returnType.resolvedType = this.binding.returnType; // record the return type binding } // check if method with constructor name if (CharOperation.equals(this.scope.enclosingSourceType().sourceName, this.selector)) { this.scope.problemReporter().methodWithConstructorName(this); } // to check whether the method returns a type parameter not declared by it. boolean returnsUndeclTypeVar = false; if (this.returnType != null && this.returnType.resolvedType instanceof TypeVariableBinding) { returnsUndeclTypeVar = true; } if (this.typeParameters != null) { for (int i = 0, length = this.typeParameters.length; i < length; i++) { this.typeParameters[i].resolve(this.scope); if (returnsUndeclTypeVar && this.typeParameters[i].binding == this.returnType.resolvedType) { returnsUndeclTypeVar = false; } } } // check @Override annotation final CompilerOptions compilerOptions = this.scope.compilerOptions(); checkOverride: { if (this.binding == null) break checkOverride; long complianceLevel = compilerOptions.complianceLevel; if (complianceLevel < ClassFileConstants.JDK1_5) break checkOverride; int bindingModifiers = this.binding.modifiers; boolean hasOverrideAnnotation = (this.binding.tagBits & TagBits.AnnotationOverride) != 0; boolean hasUnresolvedArguments = (this.binding.tagBits & TagBits.HasUnresolvedArguments) != 0; if (hasOverrideAnnotation && !hasUnresolvedArguments) { // no static method is considered overriding if ((bindingModifiers & (ClassFileConstants.AccStatic|ExtraCompilerModifiers.AccOverriding)) == ExtraCompilerModifiers.AccOverriding) break checkOverride; // in 1.5, strictly for overriding superclass method // in 1.6 and above, also tolerate implementing interface method if (complianceLevel >= ClassFileConstants.JDK1_6 && ((bindingModifiers & (ClassFileConstants.AccStatic|ExtraCompilerModifiers.AccImplementing)) == ExtraCompilerModifiers.AccImplementing)) break checkOverride; // claims to override, and doesn't actually do so this.scope.problemReporter().methodMustOverride(this, complianceLevel); } else { //In case of a concrete class method, we have to check if it overrides(in 1.5 and above) OR implements a method(1.6 and above). //Also check if the method has a signature that is override-equivalent to that of any public method declared in Object. if (!this.binding.declaringClass.isInterface()){ if((bindingModifiers & (ClassFileConstants.AccStatic|ExtraCompilerModifiers.AccOverriding)) == ExtraCompilerModifiers.AccOverriding) { this.scope.problemReporter().missingOverrideAnnotation(this); } else { if(complianceLevel >= ClassFileConstants.JDK1_6 && compilerOptions.reportMissingOverrideAnnotationForInterfaceMethodImplementation && this.binding.isImplementing()) { // actually overrides, but did not claim to do so this.scope.problemReporter().missingOverrideAnnotationForInterfaceMethodImplementation(this); } } } else { //For 1.6 and above only //In case of a interface class method, we have to check if it overrides a method (isImplementing returns true in case it overrides) //Also check if the method has a signature that is override-equivalent to that of any public method declared in Object. if(complianceLevel >= ClassFileConstants.JDK1_6 && compilerOptions.reportMissingOverrideAnnotationForInterfaceMethodImplementation && (((bindingModifiers & (ClassFileConstants.AccStatic|ExtraCompilerModifiers.AccOverriding)) == ExtraCompilerModifiers.AccOverriding) || this.binding.isImplementing())){ // actually overrides, but did not claim to do so this.scope.problemReporter().missingOverrideAnnotationForInterfaceMethodImplementation(this); } } } } // by grammatical construction, interface methods are always abstract switch (TypeDeclaration.kind(this.scope.referenceType().modifiers)) { case TypeDeclaration.ENUM_DECL : if (this.selector == TypeConstants.VALUES) break; if (this.selector == TypeConstants.VALUEOF) break; //$FALL-THROUGH$ case TypeDeclaration.CLASS_DECL : // if a method has an semicolon body and is not declared as abstract==>error // native methods may have a semicolon body if ((this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) { if ((this.modifiers & ClassFileConstants.AccNative) == 0) if ((this.modifiers & ClassFileConstants.AccAbstract) == 0) this.scope.problemReporter().methodNeedBody(this); } else { // the method HAS a body --> abstract native modifiers are forbidden if (((this.modifiers & ClassFileConstants.AccNative) != 0) || ((this.modifiers & ClassFileConstants.AccAbstract) != 0)) this.scope.problemReporter().methodNeedingNoBody(this); else if (this.binding == null || this.binding.isStatic() || (this.binding.declaringClass instanceof LocalTypeBinding) || returnsUndeclTypeVar) { // Cannot be static for one of the reasons stated above this.bits &= ~ASTNode.CanBeStatic; } } } super.resolveStatements(); // TagBits.OverridingMethodWithSupercall is set during the resolveStatements() call if (compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) { if (this.binding != null) { int bindingModifiers = this.binding.modifiers; if ((bindingModifiers & (ExtraCompilerModifiers.AccOverriding|ExtraCompilerModifiers.AccImplementing)) == ExtraCompilerModifiers.AccOverriding && (this.bits & ASTNode.OverridingMethodWithSupercall) == 0) { this.scope.problemReporter().overridesMethodWithoutSuperInvocation(this.binding); } } } } public void traverse( ASTVisitor visitor, ClassScope classScope) { if (visitor.visit(this, classScope)) { if (this.javadoc != null) { this.javadoc.traverse(visitor, this.scope); } if (this.annotations != null) { int annotationsLength = this.annotations.length; for (int i = 0; i < annotationsLength; i++) this.annotations[i].traverse(visitor, this.scope); } if (this.typeParameters != null) { int typeParametersLength = this.typeParameters.length; for (int i = 0; i < typeParametersLength; i++) { this.typeParameters[i].traverse(visitor, this.scope); } } if (this.returnType != null) this.returnType.traverse(visitor, this.scope); if (this.arguments != null) { int argumentLength = this.arguments.length; for (int i = 0; i < argumentLength; i++) this.arguments[i].traverse(visitor, this.scope); } if (this.thrownExceptions != null) { int thrownExceptionsLength = this.thrownExceptions.length; for (int i = 0; i < thrownExceptionsLength; i++) this.thrownExceptions[i].traverse(visitor, this.scope); } if (this.statements != null) { int statementsLength = this.statements.length; for (int i = 0; i < statementsLength; i++) this.statements[i].traverse(visitor, this.scope); } } visitor.endVisit(this, classScope); } public TypeParameter[] typeParameters() { return this.typeParameters; } void validateNullAnnotations() { super.validateNullAnnotations(); // null-annotations on the return type? if (this.binding != null) this.scope.validateNullAnnotation(this.binding.tagBits, this.returnType, this.annotations); } } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.j0000644000175000001440000004431012212041344032300 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 367203 - [compiler][null] detect assigning null to nonnull argument * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults * bug 388281 - [compiler][null] inheritance of null annotations as an option *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.*; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; 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.lookup.*; import org.eclipse.jdt.internal.compiler.problem.*; import org.eclipse.jdt.internal.compiler.parser.*; import org.eclipse.jdt.internal.compiler.util.Util; public abstract class AbstractMethodDeclaration extends ASTNode implements ProblemSeverities, ReferenceContext { public MethodScope scope; //it is not relevent for constructor but it helps to have the name of the constructor here //which is always the name of the class.....parsing do extra work to fill it up while it do not have to.... public char[] selector; public int declarationSourceStart; public int declarationSourceEnd; public int modifiers; public int modifiersSourceStart; public Annotation[] annotations; public Argument[] arguments; public TypeReference[] thrownExceptions; public Statement[] statements; public int explicitDeclarations; public MethodBinding binding; public boolean ignoreFurtherInvestigation = false; public Javadoc javadoc; public int bodyStart; public int bodyEnd = -1; public CompilationResult compilationResult; AbstractMethodDeclaration(CompilationResult compilationResult){ this.compilationResult = compilationResult; } /* * We cause the compilation task to abort to a given extent. */ public void abort(int abortLevel, CategorizedProblem problem) { switch (abortLevel) { case AbortCompilation : throw new AbortCompilation(this.compilationResult, problem); case AbortCompilationUnit : throw new AbortCompilationUnit(this.compilationResult, problem); case AbortType : throw new AbortType(this.compilationResult, problem); default : throw new AbortMethod(this.compilationResult, problem); } } /** * When a method is accessed via SourceTypeBinding.resolveTypesFor(MethodBinding) * we create the argument binding and resolve annotations in order to compute null annotation tagbits. */ public void createArgumentBindings() { if (this.arguments != null && this.binding != null) { for (int i = 0, length = this.arguments.length; i < length; i++) { Argument argument = this.arguments[i]; argument.createBinding(this.scope, this.binding.parameters[i]); // createBinding() has resolved annotations, now transfer nullness info from the argument to the method: if ((argument.binding.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0) { if (this.binding.parameterNonNullness == null) { this.binding.parameterNonNullness = new Boolean[this.arguments.length]; this.binding.tagBits |= TagBits.IsNullnessKnown; } this.binding.parameterNonNullness[i] = Boolean.valueOf((argument.binding.tagBits & TagBits.AnnotationNonNull) != 0); } } } } /** * Bind and add argument's binding into the scope of the method */ public void bindArguments() { if (this.arguments != null) { // by default arguments in abstract/native methods are considered to be used (no complaint is expected) if (this.binding == null) { for (int i = 0, length = this.arguments.length; i < length; i++) { this.arguments[i].bind(this.scope, null, true); } return; } boolean used = this.binding.isAbstract() || this.binding.isNative(); AnnotationBinding[][] paramAnnotations = null; for (int i = 0, length = this.arguments.length; i < length; i++) { Argument argument = this.arguments[i]; argument.bind(this.scope, this.binding.parameters[i], used); if (argument.annotations != null) { if (paramAnnotations == null) { paramAnnotations = new AnnotationBinding[length][]; for (int j=0; j 0xFF) { this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration); } } } public CompilationUnitDeclaration getCompilationUnitDeclaration() { if (this.scope != null) { return this.scope.compilationUnitScope().referenceContext; } return null; } public boolean hasErrors() { return this.ignoreFurtherInvestigation; } public boolean isAbstract() { if (this.binding != null) return this.binding.isAbstract(); return (this.modifiers & ClassFileConstants.AccAbstract) != 0; } public boolean isAnnotationMethod() { return false; } public boolean isClinit() { return false; } public boolean isConstructor() { return false; } public boolean isDefaultConstructor() { return false; } public boolean isInitializationMethod() { return false; } public boolean isMethod() { return false; } public boolean isNative() { if (this.binding != null) return this.binding.isNative(); return (this.modifiers & ClassFileConstants.AccNative) != 0; } public boolean isStatic() { if (this.binding != null) return this.binding.isStatic(); return (this.modifiers & ClassFileConstants.AccStatic) != 0; } /** * Fill up the method body with statement * @param parser * @param unit */ public abstract void parseStatements(Parser parser, CompilationUnitDeclaration unit); public StringBuffer print(int tab, StringBuffer output) { if (this.javadoc != null) { this.javadoc.print(tab, output); } printIndent(tab, output); printModifiers(this.modifiers, output); if (this.annotations != null) printAnnotations(this.annotations, output); TypeParameter[] typeParams = typeParameters(); if (typeParams != null) { output.append('<'); 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); } } printBody(tab + 1, output); return output; } public StringBuffer printBody(int indent, StringBuffer output) { if (isAbstract() || (this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) return output.append(';'); output.append(" {"); //$NON-NLS-1$ if (this.statements != null) { for (int i = 0; i < this.statements.length; i++) { output.append('\n'); this.statements[i].printStatement(indent, output); } } output.append('\n'); printIndent(indent == 0 ? 0 : indent - 1, output).append('}'); return output; } public StringBuffer printReturnType(int indent, StringBuffer output) { return output; } public void resolve(ClassScope upperScope) { if (this.binding == null) { this.ignoreFurtherInvestigation = true; } try { bindArguments(); bindThrownExceptions(); resolveJavadoc(); resolveAnnotations(this.scope, this.annotations, this.binding); validateNullAnnotations(); resolveStatements(); // check @Deprecated annotation presence if (this.binding != null && (this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0 && (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0 && this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { this.scope.problemReporter().missingDeprecatedAnnotationForMethod(this); } } catch (AbortMethod e) { // ========= abort on fatal error ============= this.ignoreFurtherInvestigation = true; } } public void resolveJavadoc() { if (this.binding == null) return; if (this.javadoc != null) { this.javadoc.resolve(this.scope); return; } if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) { // Set javadoc visibility int javadocVisibility = this.binding.modifiers & ExtraCompilerModifiers.AccVisibilityMASK; ClassScope classScope = this.scope.classScope(); ProblemReporter reporter = this.scope.problemReporter(); int severity = reporter.computeSeverity(IProblem.JavadocMissing); if (severity != ProblemSeverities.Ignore) { if (classScope != null) { javadocVisibility = Util.computeOuterMostVisibility(classScope.referenceType(), javadocVisibility); } int javadocModifiers = (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK) | javadocVisibility; reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers); } } } public void resolveStatements() { if (this.statements != null) { for (int i = 0, length = this.statements.length; i < length; i++) { this.statements[i].resolve(this.scope); } } else if ((this.bits & UndocumentedEmptyBlock) != 0) { if (!this.isConstructor() || this.arguments != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=319626 this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd+1); } } } public void tagAsHavingErrors() { this.ignoreFurtherInvestigation = true; } public void traverse( ASTVisitor visitor, ClassScope classScope) { // default implementation: subclass will define it } public TypeParameter[] typeParameters() { return null; } void validateNullAnnotations() { // null annotations on parameters? if (this.binding != null && this.binding.parameterNonNullness != null) { int length = this.binding.parameters.length; for (int i=0; i 255) { scope.problemReporter().tooManyDimensions(this); } LookupEnvironment env = scope.environment(); try { env.missingClassFileLocation = this; TypeBinding leafComponentType = super.getTypeBinding(scope); if (leafComponentType != null) { return this.resolvedType = scope.createArrayType(leafComponentType, this.dimensions); } return null; } catch (AbortCompilation e) { e.updateContext(this, scope.referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } } public StringBuffer printExpression(int indent, StringBuffer output){ super.printExpression(indent, output); if ((this.bits & IsVarArgs) != 0) { for (int i= 0 ; i < this.dimensions - 1; i++) { output.append("[]"); //$NON-NLS-1$ } output.append("..."); //$NON-NLS-1$ } else { for (int i= 0 ; i < this.dimensions; i++) { output.append("[]"); //$NON-NLS-1$ } } return output; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java0000644000175000001440000017256312212041344031236 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 383368 - [compiler][null] syntactic null analysis for field references *******************************************************************************/ 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.*; public class BinaryExpression extends OperatorExpression { /* Tracking helpers * The following are used to elaborate realistic statistics about binary * expressions. This must be neutralized in the released code. * Search the keyword BE_INSTRUMENTATION to reenable. * An external device must install a suitable probe so as to monitor the * emission of events and publish the results. public interface Probe { public void ping(int depth); } public int depthTracker; public static Probe probe; */ public Expression left, right; public Constant optimizedBooleanConstant; public BinaryExpression(Expression left, Expression right, int operator) { this.left = left; this.right = right; this.bits |= operator << ASTNode.OperatorSHIFT; // encode operator this.sourceStart = left.sourceStart; this.sourceEnd = right.sourceEnd; // BE_INSTRUMENTATION: neutralized in the released code // if (left instanceof BinaryExpression && // ((left.bits & OperatorMASK) ^ (this.bits & OperatorMASK)) == 0) { // this.depthTracker = ((BinaryExpression)left).depthTracker + 1; // } else { // this.depthTracker = 1; // } } public BinaryExpression(BinaryExpression expression) { this.left = expression.left; this.right = expression.right; this.bits = expression.bits; this.sourceStart = expression.sourceStart; this.sourceEnd = expression.sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // keep implementation in sync with CombinedBinaryExpression#analyseCode try { if (this.resolvedType.id == TypeIds.T_JavaLangString) { return this.right.analyseCode( currentScope, flowContext, this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()) .unconditionalInits(); } else { this.left.checkNPE(currentScope, flowContext, flowInfo); flowInfo = this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); if (((this.bits & OperatorMASK) >> OperatorSHIFT) != AND) { flowContext.expireNullCheckedFieldInfo(); } this.right.checkNPE(currentScope, flowContext, flowInfo); flowInfo = this.right.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); if (((this.bits & OperatorMASK) >> OperatorSHIFT) != AND) { flowContext.expireNullCheckedFieldInfo(); } return flowInfo; } } finally { // account for exception possibly thrown by arithmetics flowContext.recordAbruptExit(); } } public void computeConstant(BlockScope scope, int leftId, int rightId) { //compute the constant when valid if ((this.left.constant != Constant.NotAConstant) && (this.right.constant != Constant.NotAConstant)) { try { this.constant = Constant.computeConstantOperation( this.left.constant, leftId, (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT, this.right.constant, rightId); } catch (ArithmeticException e) { this.constant = Constant.NotAConstant; // 1.2 no longer throws an exception at compile-time //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this); } } else { this.constant = Constant.NotAConstant; //add some work for the boolean operators & | this.optimizedBooleanConstant( leftId, (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT, rightId); } } public Constant optimizedBooleanConstant() { return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant; } /** * Code generation for a binary operation */ // given the current focus of CombinedBinaryExpression on strings concatenation, // we do not provide a general, non-recursive implementation of generateCode, // but rely upon generateOptimizedStringConcatenationCreation instead public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { if (valueRequired) codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); return; } switch ((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) { case PLUS : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_JavaLangString : // BE_INSTRUMENTATION: neutralized in the released code // if (probe != null) { // probe.ping(this.depthTracker); // } codeStream.generateStringConcatenationAppend(currentScope, this.left, this.right); if (!valueRequired) codeStream.pop(); break; case T_int : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.iadd(); break; case T_long : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.ladd(); break; case T_double : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.dadd(); break; case T_float : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.fadd(); break; } break; case MINUS : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.isub(); break; case T_long : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.lsub(); break; case T_double : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.dsub(); break; case T_float : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.fsub(); break; } break; case MULTIPLY : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.imul(); break; case T_long : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.lmul(); break; case T_double : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.dmul(); break; case T_float : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.fmul(); break; } break; case DIVIDE : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : this.left.generateCode(currentScope, codeStream, true); this.right.generateCode(currentScope, codeStream, true); codeStream.idiv(); if (!valueRequired) codeStream.pop(); break; case T_long : this.left.generateCode(currentScope, codeStream, true); this.right.generateCode(currentScope, codeStream, true); codeStream.ldiv(); if (!valueRequired) codeStream.pop2(); break; case T_double : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.ddiv(); break; case T_float : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.fdiv(); break; } break; case REMAINDER : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : this.left.generateCode(currentScope, codeStream, true); this.right.generateCode(currentScope, codeStream, true); codeStream.irem(); if (!valueRequired) codeStream.pop(); break; case T_long : this.left.generateCode(currentScope, codeStream, true); this.right.generateCode(currentScope, codeStream, true); codeStream.lrem(); if (!valueRequired) codeStream.pop2(); break; case T_double : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.drem(); break; case T_float : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.frem(); break; } break; case AND : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : // 0 & x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == TypeIds.T_int) && (this.left.constant.intValue() == 0)) { this.right.generateCode(currentScope, codeStream, false); if (valueRequired) codeStream.iconst_0(); } else { // x & 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == TypeIds.T_int) && (this.right.constant.intValue() == 0)) { this.left.generateCode(currentScope, codeStream, false); if (valueRequired) codeStream.iconst_0(); } else { this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.iand(); } } break; case T_long : // 0 & x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == TypeIds.T_long) && (this.left.constant.longValue() == 0L)) { this.right.generateCode(currentScope, codeStream, false); if (valueRequired) codeStream.lconst_0(); } else { // x & 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == TypeIds.T_long) && (this.right.constant.longValue() == 0L)) { this.left.generateCode(currentScope, codeStream, false); if (valueRequired) codeStream.lconst_0(); } else { this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.land(); } } break; case T_boolean : // logical and generateLogicalAnd(currentScope, codeStream, valueRequired); break; } break; case OR : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : // 0 | x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == TypeIds.T_int) && (this.left.constant.intValue() == 0)) { this.right.generateCode(currentScope, codeStream, valueRequired); } else { // x | 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == TypeIds.T_int) && (this.right.constant.intValue() == 0)) { this.left.generateCode(currentScope, codeStream, valueRequired); } else { this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.ior(); } } break; case T_long : // 0 | x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == TypeIds.T_long) && (this.left.constant.longValue() == 0L)) { this.right.generateCode(currentScope, codeStream, valueRequired); } else { // x | 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == TypeIds.T_long) && (this.right.constant.longValue() == 0L)) { this.left.generateCode(currentScope, codeStream, valueRequired); } else { this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.lor(); } } break; case T_boolean : // logical or generateLogicalOr(currentScope, codeStream, valueRequired); break; } break; case XOR : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : // 0 ^ x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == TypeIds.T_int) && (this.left.constant.intValue() == 0)) { this.right.generateCode(currentScope, codeStream, valueRequired); } else { // x ^ 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == TypeIds.T_int) && (this.right.constant.intValue() == 0)) { this.left.generateCode(currentScope, codeStream, valueRequired); } else { this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.ixor(); } } break; case T_long : // 0 ^ x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == TypeIds.T_long) && (this.left.constant.longValue() == 0L)) { this.right.generateCode(currentScope, codeStream, valueRequired); } else { // x ^ 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == TypeIds.T_long) && (this.right.constant.longValue() == 0L)) { this.left.generateCode(currentScope, codeStream, valueRequired); } else { this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.lxor(); } } break; case T_boolean : generateLogicalXor(currentScope, codeStream, valueRequired); break; } break; case LEFT_SHIFT : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.ishl(); break; case T_long : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.lshl(); } break; case RIGHT_SHIFT : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.ishr(); break; case T_long : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.lshr(); } break; case UNSIGNED_RIGHT_SHIFT : switch (this.bits & ASTNode.ReturnTypeIDMASK) { case T_int : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.iushr(); break; case T_long : this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) codeStream.lushr(); } break; case GREATER : BranchLabel falseLabel, endLabel; generateOptimizedGreaterThan( currentScope, codeStream, null, (falseLabel = new BranchLabel(codeStream)), valueRequired); if (valueRequired) { codeStream.iconst_1(); if ((this.bits & ASTNode.IsReturnedValue) != 0) { codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); falseLabel.place(); codeStream.iconst_0(); } else { codeStream.goto_(endLabel = new BranchLabel(codeStream)); codeStream.decrStackSize(1); falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } break; case GREATER_EQUAL : generateOptimizedGreaterThanOrEqual( currentScope, codeStream, null, (falseLabel = new BranchLabel(codeStream)), valueRequired); if (valueRequired) { codeStream.iconst_1(); if ((this.bits & ASTNode.IsReturnedValue) != 0) { codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); falseLabel.place(); codeStream.iconst_0(); } else { codeStream.goto_(endLabel = new BranchLabel(codeStream)); codeStream.decrStackSize(1); falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } break; case LESS : generateOptimizedLessThan( currentScope, codeStream, null, (falseLabel = new BranchLabel(codeStream)), valueRequired); if (valueRequired) { codeStream.iconst_1(); if ((this.bits & ASTNode.IsReturnedValue) != 0) { codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); falseLabel.place(); codeStream.iconst_0(); } else { codeStream.goto_(endLabel = new BranchLabel(codeStream)); codeStream.decrStackSize(1); falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } break; case LESS_EQUAL : generateOptimizedLessThanOrEqual( currentScope, codeStream, null, (falseLabel = new BranchLabel(codeStream)), valueRequired); if (valueRequired) { codeStream.iconst_1(); if ((this.bits & ASTNode.IsReturnedValue) != 0) { codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); falseLabel.place(); codeStream.iconst_0(); } else { codeStream.goto_(endLabel = new BranchLabel(codeStream)); codeStream.decrStackSize(1); falseLabel.place(); codeStream.iconst_0(); endLabel.place(); } } } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * Boolean operator code generation * Optimized operations are: <, <=, >, >=, &, |, ^ */ public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == TypeIds.T_boolean)) { super.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } switch ((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) { case LESS : generateOptimizedLessThan( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; case LESS_EQUAL : generateOptimizedLessThanOrEqual( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; case GREATER : generateOptimizedGreaterThan( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; case GREATER_EQUAL : generateOptimizedGreaterThanOrEqual( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; case AND : generateOptimizedLogicalAnd( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; case OR : generateOptimizedLogicalOr( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; case XOR : generateOptimizedLogicalXor( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } super.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); } /** * Boolean generation for > */ public void generateOptimizedGreaterThan(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; // both sides got promoted in the same way if (promotedTypeID == TypeIds.T_int) { // 0 > x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.iflt(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.ifge(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } // x > 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { this.left.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.ifgt(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.ifle(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } // default comparison this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case switch (promotedTypeID) { case T_int : codeStream.if_icmpgt(trueLabel); break; case T_float : codeStream.fcmpl(); codeStream.ifgt(trueLabel); break; case T_long : codeStream.lcmp(); codeStream.ifgt(trueLabel); break; case T_double : codeStream.dcmpl(); codeStream.ifgt(trueLabel); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } else { if (trueLabel == null) { // implicit falling through the TRUE case switch (promotedTypeID) { case T_int : codeStream.if_icmple(falseLabel); break; case T_float : codeStream.fcmpl(); codeStream.ifle(falseLabel); break; case T_long : codeStream.lcmp(); codeStream.ifle(falseLabel); break; case T_double : codeStream.dcmpl(); codeStream.ifle(falseLabel); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } else { // no implicit fall through TRUE/FALSE --> should never occur } } } } /** * Boolean generation for >= */ public void generateOptimizedGreaterThanOrEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; // both sides got promoted in the same way if (promotedTypeID == TypeIds.T_int) { // 0 >= x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.ifle(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.ifgt(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } // x >= 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { this.left.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.ifge(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.iflt(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } // default comparison this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case switch (promotedTypeID) { case T_int : codeStream.if_icmpge(trueLabel); break; case T_float : codeStream.fcmpl(); codeStream.ifge(trueLabel); break; case T_long : codeStream.lcmp(); codeStream.ifge(trueLabel); break; case T_double : codeStream.dcmpl(); codeStream.ifge(trueLabel); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } else { if (trueLabel == null) { // implicit falling through the TRUE case switch (promotedTypeID) { case T_int : codeStream.if_icmplt(falseLabel); break; case T_float : codeStream.fcmpl(); codeStream.iflt(falseLabel); break; case T_long : codeStream.lcmp(); codeStream.iflt(falseLabel); break; case T_double : codeStream.dcmpl(); codeStream.iflt(falseLabel); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } else { // no implicit fall through TRUE/FALSE --> should never occur } } } } /** * Boolean generation for < */ public void generateOptimizedLessThan(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; // both sides got promoted in the same way if (promotedTypeID == TypeIds.T_int) { // 0 < x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.ifgt(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.ifle(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } // x < 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { this.left.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.iflt(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.ifge(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } // default comparison this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case switch (promotedTypeID) { case T_int : codeStream.if_icmplt(trueLabel); break; case T_float : codeStream.fcmpg(); codeStream.iflt(trueLabel); break; case T_long : codeStream.lcmp(); codeStream.iflt(trueLabel); break; case T_double : codeStream.dcmpg(); codeStream.iflt(trueLabel); } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } else { if (trueLabel == null) { // implicit falling through the TRUE case switch (promotedTypeID) { case T_int : codeStream.if_icmpge(falseLabel); break; case T_float : codeStream.fcmpg(); codeStream.ifge(falseLabel); break; case T_long : codeStream.lcmp(); codeStream.ifge(falseLabel); break; case T_double : codeStream.dcmpg(); codeStream.ifge(falseLabel); } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } else { // no implicit fall through TRUE/FALSE --> should never occur } } } } /** * Boolean generation for <= */ public void generateOptimizedLessThanOrEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { int promotedTypeID = (this.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; // both sides got promoted in the same way if (promotedTypeID == TypeIds.T_int) { // 0 <= x if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.intValue() == 0)) { this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.ifge(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.iflt(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } // x <= 0 if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.intValue() == 0)) { this.left.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicitly falling through the FALSE case codeStream.ifle(trueLabel); } } else { if (trueLabel == null) { // implicitly falling through the TRUE case codeStream.ifgt(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } // default comparison this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case switch (promotedTypeID) { case T_int : codeStream.if_icmple(trueLabel); break; case T_float : codeStream.fcmpg(); codeStream.ifle(trueLabel); break; case T_long : codeStream.lcmp(); codeStream.ifle(trueLabel); break; case T_double : codeStream.dcmpg(); codeStream.ifle(trueLabel); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } } else { if (trueLabel == null) { // implicit falling through the TRUE case switch (promotedTypeID) { case T_int : codeStream.if_icmpgt(falseLabel); break; case T_float : codeStream.fcmpg(); codeStream.ifgt(falseLabel); break; case T_long : codeStream.lcmp(); codeStream.ifgt(falseLabel); break; case T_double : codeStream.dcmpg(); codeStream.ifgt(falseLabel); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); return; } else { // no implicit fall through TRUE/FALSE --> should never occur } } } } /** * Boolean generation for & */ public void generateLogicalAnd(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { Constant condConst; if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // & x this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, valueRequired); } else { // & x this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, false); if (valueRequired) { codeStream.iconst_0(); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } return; } if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // x & this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, false); } else { // x & this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, false); if (valueRequired) { codeStream.iconst_0(); } // reposition the endPC codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } return; } } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.iand(); } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } /** * Boolean generation for | */ public void generateLogicalOr(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { Constant condConst; if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // | x this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, false); if (valueRequired) { codeStream.iconst_1(); } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } else { // | x this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, valueRequired); } return; } if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // x | this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, false); if (valueRequired) { codeStream.iconst_1(); } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } else { // x | this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, false); } return; } } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.ior(); } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } /** * Boolean generation for ^ */ public void generateLogicalXor(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { Constant condConst; if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // ^ x this.left.generateCode(currentScope, codeStream, false); if (valueRequired) { codeStream.iconst_1(); } this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.ixor(); // negate codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } } else { // ^ x this.left.generateCode(currentScope, codeStream, false); this.right.generateCode(currentScope, codeStream, valueRequired); } return; } if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // x ^ this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, false); if (valueRequired) { codeStream.iconst_1(); codeStream.ixor(); // negate codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } } else { // x ^ this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, false); } return; } } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.ixor(); } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } /** * Boolean generation for & */ public void generateOptimizedLogicalAnd(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { Constant condConst; if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // & x this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); } else { // & x this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); if (valueRequired) { if (falseLabel != null) { // implicit falling through the TRUE case codeStream.goto_(falseLabel); } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } return; } if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // x & this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); } else { // x & BranchLabel internalTrueLabel = new BranchLabel(codeStream); this.left.generateOptimizedBoolean( currentScope, codeStream, internalTrueLabel, falseLabel, false); internalTrueLabel.place(); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); if (valueRequired) { if (falseLabel != null) { // implicit falling through the TRUE case codeStream.goto_(falseLabel); } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } return; } } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.iand(); if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case codeStream.ifne(trueLabel); } } else { // implicit falling through the TRUE case if (trueLabel == null) { codeStream.ifeq(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } /** * Boolean generation for | */ public void generateOptimizedLogicalOr(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { Constant condConst; if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // | x this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); BranchLabel internalFalseLabel = new BranchLabel(codeStream); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, internalFalseLabel, false); internalFalseLabel.place(); if (valueRequired) { if (trueLabel != null) { codeStream.goto_(trueLabel); } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } else { // | x this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); } return; } if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // x | BranchLabel internalFalseLabel = new BranchLabel(codeStream); this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, internalFalseLabel, false); internalFalseLabel.place(); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); if (valueRequired) { if (trueLabel != null) { codeStream.goto_(trueLabel); } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } else { // x | this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); } return; } } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.ior(); if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case codeStream.ifne(trueLabel); } } else { // implicit falling through the TRUE case if (trueLabel == null) { codeStream.ifeq(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } /** * Boolean generation for ^ */ public void generateOptimizedLogicalXor(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { Constant condConst; if ((this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK) == TypeIds.T_boolean) { if ((condConst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // ^ x this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); this.right.generateOptimizedBoolean( currentScope, codeStream, falseLabel, // negating trueLabel, valueRequired); } else { // ^ x this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); } return; } if ((condConst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (condConst.booleanValue() == true) { // x ^ this.left.generateOptimizedBoolean( currentScope, codeStream, falseLabel, // negating trueLabel, valueRequired); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); } else { // x ^ this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, false); } return; } } // default case this.left.generateCode(currentScope, codeStream, valueRequired); this.right.generateCode(currentScope, codeStream, valueRequired); if (valueRequired) { codeStream.ixor(); if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case codeStream.ifne(trueLabel); } } else { // implicit falling through the TRUE case if (trueLabel == null) { codeStream.ifeq(falseLabel); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } public void generateOptimizedStringConcatenation(BlockScope blockScope, CodeStream codeStream, int typeID) { // keep implementation in sync with CombinedBinaryExpression // #generateOptimizedStringConcatenation /* In the case trying to make a string concatenation, there is no need to create a new * string buffer, thus use a lower-level API for code generation involving only the * appending of arguments to the existing StringBuffer */ if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { if (this.constant != Constant.NotAConstant) { codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.invokeStringConcatenationAppendForType(this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); } else { int pc = codeStream.position; this.left.generateOptimizedStringConcatenation( blockScope, codeStream, this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.left.sourceStart); pc = codeStream.position; this.right.generateOptimizedStringConcatenation( blockScope, codeStream, this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.right.sourceStart); } } else { super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID); } } public void generateOptimizedStringConcatenationCreation(BlockScope blockScope, CodeStream codeStream, int typeID) { // keep implementation in sync with CombinedBinaryExpression // #generateOptimizedStringConcatenationCreation /* In the case trying to make a string concatenation, there is no need to create a new * string buffer, thus use a lower-level API for code generation involving only the * appending of arguments to the existing StringBuffer */ if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { if (this.constant != Constant.NotAConstant) { codeStream.newStringContatenation(); // new: java.lang.StringBuffer codeStream.dup(); codeStream.ldc(this.constant.stringValue()); codeStream.invokeStringConcatenationStringConstructor(); // invokespecial: java.lang.StringBuffer.(Ljava.lang.String;)V } else { int pc = codeStream.position; this.left.generateOptimizedStringConcatenationCreation( blockScope, codeStream, this.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.left.sourceStart); pc = codeStream.position; this.right.generateOptimizedStringConcatenation( blockScope, codeStream, this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.right.sourceStart); } } else { super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID); } } public boolean isCompactableOperation() { return true; } /** * Separates into a reusable method the subpart of {@link * #resolveType(BlockScope)} that needs to be executed while climbing up the * chain of expressions of this' leftmost branch. For use by {@link * CombinedBinaryExpression#resolveType(BlockScope)}. * @param scope the scope within which the resolution occurs */ void nonRecursiveResolveTypeUpwards(BlockScope scope) { // keep implementation in sync with BinaryExpression#resolveType boolean leftIsCast, rightIsCast; TypeBinding leftType = this.left.resolvedType; if ((rightIsCast = this.right instanceof CastExpression) == true) { this.right.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on } TypeBinding rightType = this.right.resolveType(scope); // use the id of the type to navigate into the table if (leftType == null || rightType == null) { this.constant = Constant.NotAConstant; return; } int leftTypeID = leftType.id; int rightTypeID = rightType.id; // autoboxing support boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; if (use15specifics) { if (!leftType.isBaseType() && rightTypeID != TypeIds.T_JavaLangString && rightTypeID != TypeIds.T_null) { leftTypeID = scope.environment().computeBoxingType(leftType).id; } if (!rightType.isBaseType() && leftTypeID != TypeIds.T_JavaLangString && leftTypeID != TypeIds.T_null) { rightTypeID = scope.environment().computeBoxingType(rightType).id; } } if (leftTypeID > 15 || rightTypeID > 15) { // must convert String + Object || Object + String if (leftTypeID == TypeIds.T_JavaLangString) { rightTypeID = TypeIds.T_JavaLangObject; } else if (rightTypeID == TypeIds.T_JavaLangString) { leftTypeID = TypeIds.T_JavaLangObject; } else { this.constant = Constant.NotAConstant; scope.problemReporter().invalidOperator(this, leftType, rightType); return; } } if (((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) { if (leftTypeID == TypeIds.T_JavaLangString) { this.left.computeConversion(scope, leftType, leftType); if (rightType.isArrayType() && ((ArrayBinding) rightType).elementsType() == TypeBinding.CHAR) { scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.right); } } if (rightTypeID == TypeIds.T_JavaLangString) { this.right.computeConversion(scope, rightType, rightType); if (leftType.isArrayType() && ((ArrayBinding) leftType).elementsType() == TypeBinding.CHAR) { scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.left); } } } // the code is an int // (cast) left Op (cast) right --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 <<0 // 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 = (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT; int operatorSignature = OperatorExpression.OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID]; this.left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), leftType); this.right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), rightType); this.bits |= operatorSignature & 0xF; switch (operatorSignature & 0xF) { // record the current ReturnTypeID // only switch on possible result type..... case T_boolean : this.resolvedType = TypeBinding.BOOLEAN; break; case T_byte : this.resolvedType = TypeBinding.BYTE; break; case T_char : this.resolvedType = TypeBinding.CHAR; break; case T_double : this.resolvedType = TypeBinding.DOUBLE; break; case T_float : this.resolvedType = TypeBinding.FLOAT; break; case T_int : this.resolvedType = TypeBinding.INT; break; case T_long : this.resolvedType = TypeBinding.LONG; break; case T_JavaLangString : this.resolvedType = scope.getJavaLangString(); break; default : //error........ this.constant = Constant.NotAConstant; scope.problemReporter().invalidOperator(this, leftType, rightType); return; } // check need for operand cast if ((leftIsCast = (this.left instanceof CastExpression)) == true || rightIsCast) { CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, this.left, leftTypeID, leftIsCast, this.right, rightTypeID, rightIsCast); } // compute the constant when valid computeConstant(scope, leftTypeID, rightTypeID); } public void optimizedBooleanConstant(int leftId, int operator, int rightId) { switch (operator) { case AND : if ((leftId != TypeIds.T_boolean) || (rightId != TypeIds.T_boolean)) return; //$FALL-THROUGH$ case AND_AND : Constant cst; if ((cst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (cst.booleanValue() == false) { // left is equivalent to false this.optimizedBooleanConstant = cst; // constant(false) return; } else { //left is equivalent to true if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { this.optimizedBooleanConstant = cst; // the conditional result is equivalent to the right conditional value } return; } } if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (cst.booleanValue() == false) { // right is equivalent to false this.optimizedBooleanConstant = cst; // constant(false) } } return; case OR : if ((leftId != TypeIds.T_boolean) || (rightId != TypeIds.T_boolean)) return; //$FALL-THROUGH$ case OR_OR : if ((cst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) { if (cst.booleanValue() == true) { // left is equivalent to true this.optimizedBooleanConstant = cst; // constant(true) return; } else { //left is equivalent to false if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { this.optimizedBooleanConstant = cst; } return; } } if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) { if (cst.booleanValue() == true) { // right is equivalent to true this.optimizedBooleanConstant = cst; // constant(true) } } } } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { // keep implementation in sync with // CombinedBinaryExpression#printExpressionNoParenthesis this.left.printExpression(indent, output).append(' ').append(operatorToString()).append(' '); return this.right.printExpression(0, output); } public TypeBinding resolveType(BlockScope scope) { // keep implementation in sync with CombinedBinaryExpression#resolveType // and nonRecursiveResolveTypeUpwards boolean leftIsCast, rightIsCast; if ((leftIsCast = this.left instanceof CastExpression) == true) this.left.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on TypeBinding leftType = this.left.resolveType(scope); if ((rightIsCast = this.right instanceof CastExpression) == true) this.right.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on TypeBinding rightType = this.right.resolveType(scope); // use the id of the type to navigate into the table if (leftType == null || rightType == null) { this.constant = Constant.NotAConstant; return null; } int leftTypeID = leftType.id; int rightTypeID = rightType.id; // autoboxing support boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; if (use15specifics) { if (!leftType.isBaseType() && rightTypeID != TypeIds.T_JavaLangString && rightTypeID != TypeIds.T_null) { leftTypeID = scope.environment().computeBoxingType(leftType).id; } if (!rightType.isBaseType() && leftTypeID != TypeIds.T_JavaLangString && leftTypeID != TypeIds.T_null) { rightTypeID = scope.environment().computeBoxingType(rightType).id; } } if (leftTypeID > 15 || rightTypeID > 15) { // must convert String + Object || Object + String if (leftTypeID == TypeIds.T_JavaLangString) { rightTypeID = TypeIds.T_JavaLangObject; } else if (rightTypeID == TypeIds.T_JavaLangString) { leftTypeID = TypeIds.T_JavaLangObject; } else { this.constant = Constant.NotAConstant; scope.problemReporter().invalidOperator(this, leftType, rightType); return null; } } if (((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) { if (leftTypeID == TypeIds.T_JavaLangString) { this.left.computeConversion(scope, leftType, leftType); if (rightType.isArrayType() && ((ArrayBinding) rightType).elementsType() == TypeBinding.CHAR) { scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.right); } } if (rightTypeID == TypeIds.T_JavaLangString) { this.right.computeConversion(scope, rightType, rightType); if (leftType.isArrayType() && ((ArrayBinding) leftType).elementsType() == TypeBinding.CHAR) { scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(this.left); } } } // the code is an int // (cast) left Op (cast) right --> result // 0000 0000 0000 0000 0000 // <<16 <<12 <<8 <<4 <<0 // 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 = (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT; int operatorSignature = OperatorExpression.OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID]; this.left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), leftType); this.right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), rightType); this.bits |= operatorSignature & 0xF; switch (operatorSignature & 0xF) { // record the current ReturnTypeID // only switch on possible result type..... case T_boolean : this.resolvedType = TypeBinding.BOOLEAN; break; case T_byte : this.resolvedType = TypeBinding.BYTE; break; case T_char : this.resolvedType = TypeBinding.CHAR; break; case T_double : this.resolvedType = TypeBinding.DOUBLE; break; case T_float : this.resolvedType = TypeBinding.FLOAT; break; case T_int : this.resolvedType = TypeBinding.INT; break; case T_long : this.resolvedType = TypeBinding.LONG; break; case T_JavaLangString : this.resolvedType = scope.getJavaLangString(); break; default : //error........ this.constant = Constant.NotAConstant; scope.problemReporter().invalidOperator(this, leftType, rightType); return null; } // check need for operand cast if (leftIsCast || rightIsCast) { CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, this.left, leftTypeID, leftIsCast, this.right, rightTypeID, rightIsCast); } // compute the constant when valid computeConstant(scope, leftTypeID, rightTypeID); return this.resolvedType; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.left.traverse(visitor, scope); this.right.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.j0000644000175000001440000001167412212041344032367 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class JavadocArgumentExpression extends Expression { public char[] token; public Argument argument; public JavadocArgumentExpression(char[] name, int startPos, int endPos, TypeReference typeRef) { this.token = name; this.sourceStart = startPos; this.sourceEnd = endPos; long pos = (((long) startPos) << 32) + endPos; this.argument = new Argument(name, pos, typeRef, ClassFileConstants.AccDefault); this.bits |= InsideJavadoc; } /* * Resolves type on a Block or Class scope. */ private TypeBinding internalResolveType(Scope scope) { this.constant = 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 if (this.argument != null) { TypeReference typeRef = this.argument.type; if (typeRef != null) { this.resolvedType = typeRef.getTypeBinding(scope); typeRef.resolvedType = this.resolvedType; // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=195374 // reproduce javadoc 1.3.1 / 1.4.2 behavior if (this.resolvedType == null) { return null; } if (typeRef instanceof SingleTypeReference && this.resolvedType.leafComponentType().enclosingType() != null && scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_4) { scope.problemReporter().javadocInvalidMemberTypeQualification(this.sourceStart, this.sourceEnd, scope.getDeclarationModifiers()); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=228648 // do not return now but report unresolved reference as expected depending on compliance settings } else if (typeRef instanceof QualifiedTypeReference) { TypeBinding enclosingType = this.resolvedType.leafComponentType().enclosingType(); if (enclosingType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=233187 // inner type references should be fully qualified int compoundLength = 2; while ((enclosingType = enclosingType.enclosingType()) != null) compoundLength++; int typeNameLength = typeRef.getTypeName().length; if (typeNameLength != compoundLength && typeNameLength != (compoundLength+this.resolvedType.getPackage().compoundName.length)) { scope.problemReporter().javadocInvalidMemberTypeQualification(typeRef.sourceStart, typeRef.sourceEnd, scope.getDeclarationModifiers()); } } } if (!this.resolvedType.isValidBinding()) { scope.problemReporter().javadocInvalidType(typeRef, this.resolvedType, scope.getDeclarationModifiers()); return null; } if (isTypeUseDeprecated(this.resolvedType, scope)) { scope.problemReporter().javadocDeprecatedType(this.resolvedType, typeRef, scope.getDeclarationModifiers()); } return this.resolvedType = scope.environment().convertToRawType(this.resolvedType, true /*force the conversion of enclosing types*/); } } return null; } public StringBuffer printExpression(int indent, StringBuffer output) { if (this.argument == null) { if (this.token != null) { output.append(this.token); } } else { this.argument.print(indent, output); } return output; } public void resolve(BlockScope scope) { if (this.argument != null) { this.argument.resolve(scope); } } public TypeBinding resolveType(BlockScope scope) { return internalResolveType(scope); } public TypeBinding resolveType(ClassScope scope) { return internalResolveType(scope); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { if (this.argument != null) { this.argument.traverse(visitor, blockScope); } } visitor.endVisit(this, blockScope); } public void traverse(ASTVisitor visitor, ClassScope blockScope) { if (visitor.visit(this, blockScope)) { if (this.argument != null) { this.argument.traverse(visitor, blockScope); } } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java0000644000175000001440000000527212212041344031461 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.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. * @param source char[] * @param dimensions int * @param pos int */ public ArrayTypeReference(char[] source, int dimensions, long pos) { super(source, pos); this.originalSourceEnd = this.sourceEnd; this.dimensions = dimensions ; } public int dimensions() { return this.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] = ']'; } return new char[][]{ CharOperation.concat(this.token, dimChars) }; } protected TypeBinding getTypeBinding(Scope scope) { if (this.resolvedType != null) { return this.resolvedType; } if (this.dimensions > 255) { scope.problemReporter().tooManyDimensions(this); } TypeBinding leafComponentType = scope.getType(this.token); return scope.createArrayType(leafComponentType, this.dimensions); } public StringBuffer printExpression(int indent, StringBuffer output){ super.printExpression(indent, output); if ((this.bits & IsVarArgs) != 0) { for (int i= 0 ; i < this.dimensions - 1; i++) { output.append("[]"); //$NON-NLS-1$ } output.append("..."); //$NON-NLS-1$ } else { for (int i= 0 ; i < this.dimensions; i++) { output.append("[]"); //$NON-NLS-1$ } } return output; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java0000644000175000001440000006101412212041344031152 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 349326 - [1.7] new warning for missing try-with-resources * bug 370930 - NonNull annotation not considered for enhanced for loops * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 393719 - [compiler] inconsistent warnings on iteration variables * Jesper S Moller - Contribution for * bug 401853 - Eclipse Java compiler creates invalid bytecode (java.lang.VerifyError) *******************************************************************************/ 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.BranchLabel; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; 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.flow.UnconditionalFlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; 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 iteratorReceiverType; private TypeBinding collectionElementType; // loop labels private BranchLabel breakLabel; private BranchLabel 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[] SecretIteratorVariableName = " iterator".toCharArray(); //$NON-NLS-1$ 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, int start) { this.elementVariable = elementVariable; this.sourceStart = start; this.kind = -1; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // initialize break and continue labels this.breakLabel = new BranchLabel(); this.continueLabel = new BranchLabel(); int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; // process the element variable and collection this.collection.checkNPE(currentScope, flowContext, flowInfo); flowInfo = this.elementVariable.analyseCode(this.scope, flowContext, flowInfo); FlowInfo condInfo = this.collection.analyseCode(this.scope, flowContext, flowInfo.copy()); LocalVariableBinding elementVarBinding = this.elementVariable.binding; // element variable will be assigned when iterating condInfo.markAsDefinitelyAssigned(elementVarBinding); this.postCollectionInitStateIndex = currentScope.methodScope().recordInitializationStates(condInfo); // process the action LoopingFlowContext loopingContext = new LoopingFlowContext(flowContext, flowInfo, this, this.breakLabel, this.continueLabel, this.scope, true); UnconditionalFlowInfo actionInfo = condInfo.nullInfoLessUnconditionalCopy(); actionInfo.markAsDefinitelyUnknown(elementVarBinding); if (currentScope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) { // this currently produces an unavoidable warning against all @NonNull element vars: int nullStatus = this.elementVariable.checkAssignmentAgainstNullAnnotation(currentScope, flowContext, elementVarBinding, FlowInfo.UNKNOWN, this.collection, this.collectionElementType); // TODO (stephan): once we have JSR 308 fetch nullStatus from the collection element type // and feed the result into the above check (instead of FlowInfo.UNKNOWN) if ((elementVarBinding.type.tagBits & TagBits.IsBaseType) == 0) { actionInfo.markNullStatus(elementVarBinding, nullStatus); } } FlowInfo exitBranch; if (!(this.action == null || (this.action.isEmptyBlock() && currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3))) { if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalCopy(); } // code generation can be optimized when no need to continue in the loop exitBranch = flowInfo.unconditionalCopy(). addInitializationsFrom(condInfo.initsWhenFalse()); // TODO (maxime) no need to test when false: can optimize (same for action being unreachable above) if ((actionInfo.tagBits & loopingContext.initsOnContinue.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) { this.continueLabel = null; } else { actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue); loopingContext.complainOnDeferredFinalChecks(this.scope, actionInfo); exitBranch.addPotentialInitializationsFrom(actionInfo); } } else { exitBranch = condInfo.initsWhenFalse(); } // we need the variable to iterate the collection even if the // element variable is not used final boolean hasEmptyAction = this.action == null || this.action.isEmptyBlock() || ((this.action.bits & IsUsefulEmptyStatement) != 0); switch(this.kind) { case ARRAY : if (!hasEmptyAction || elementVarBinding.resolvedPosition != -1) { this.collectionVariable.useFlag = LocalVariableBinding.USED; if (this.continueLabel != null) { 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 loopingContext.complainOnDeferredNullChecks(currentScope, actionInfo); FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( (loopingContext.initsOnBreak.tagBits & FlowInfo.UNREACHABLE) != 0 ? loopingContext.initsOnBreak : flowInfo.addInitializationsFrom(loopingContext.initsOnBreak), // recover upstream null info false, exitBranch, false, true /*for(;;){}while(true); unreachable(); */); mergedInfo.resetAssignmentInfo(this.elementVariable.binding); this.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 ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; final boolean hasEmptyAction = this.action == null || this.action.isEmptyBlock() || ((this.action.bits & IsUsefulEmptyStatement) != 0); if (hasEmptyAction && this.elementVariable.binding.resolvedPosition == -1 && this.kind == ARRAY) { this.collection.generateCode(this.scope, codeStream, false); codeStream.exitUserScope(this.scope); if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } // generate the initializations switch(this.kind) { case ARRAY : this.collection.generateCode(this.scope, codeStream, true); codeStream.store(this.collectionVariable, true); codeStream.addVariable(this.collectionVariable); if (this.continueLabel != null) { // int length = (collectionVariable = [collection]).length; codeStream.arraylength(); codeStream.store(this.maxVariable, false); codeStream.addVariable(this.maxVariable); codeStream.iconst_0(); codeStream.store(this.indexVariable, false); codeStream.addVariable(this.indexVariable); } else { // leave collectionVariable on execution stack (will be consumed when swapping condition further down) } break; case RAW_ITERABLE : case GENERIC_ITERABLE : this.collection.generateCode(this.scope, codeStream, true); // declaringClass.iterator(); codeStream.invokeIterableIterator(this.iteratorReceiverType); codeStream.store(this.indexVariable, false); codeStream.addVariable(this.indexVariable); break; } // label management BranchLabel actionLabel = new BranchLabel(codeStream); actionLabel.tagBits |= BranchLabel.USED; BranchLabel conditionLabel = new BranchLabel(codeStream); conditionLabel.tagBits |= BranchLabel.USED; this.breakLabel.initialize(codeStream); if (this.continueLabel == null) { // generate the condition (swapped for optimizing) conditionLabel.place(); int conditionPC = codeStream.position; switch(this.kind) { case ARRAY : // inline the arraylength call // collectionVariable is already on execution stack codeStream.arraylength(); codeStream.ifeq(this.breakLabel); break; case RAW_ITERABLE : case GENERIC_ITERABLE : codeStream.load(this.indexVariable); codeStream.invokeJavaUtilIteratorHasNext(); codeStream.ifeq(this.breakLabel); break; } codeStream.recordPositionsFrom(conditionPC, this.elementVariable.sourceStart); } else { this.continueLabel.initialize(codeStream); this.continueLabel.tagBits |= BranchLabel.USED; // jump over the actionBlock codeStream.goto_(conditionLabel); } // generate the loop action actionLabel.place(); // generate the loop action switch(this.kind) { case ARRAY : if (this.elementVariable.binding.resolvedPosition != -1) { codeStream.load(this.collectionVariable); if (this.continueLabel == null) { codeStream.iconst_0(); // no continue, thus simply hardcode offset 0 } else { codeStream.load(this.indexVariable); } codeStream.arrayAt(this.collectionElementType.id); if (this.elementVariableImplicitWidening != -1) { codeStream.generateImplicitConversion(this.elementVariableImplicitWidening); } codeStream.store(this.elementVariable.binding, false); codeStream.addVisibleLocalVariable(this.elementVariable.binding); if (this.postCollectionInitStateIndex != -1) { codeStream.addDefinitelyAssignedVariables( currentScope, this.postCollectionInitStateIndex); } } 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); } } if (this.elementVariable.binding.resolvedPosition == -1) { switch (this.elementVariable.binding.type.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.pop2(); break; default: codeStream.pop(); break; } } else { codeStream.store(this.elementVariable.binding, false); codeStream.addVisibleLocalVariable(this.elementVariable.binding); if (this.postCollectionInitStateIndex != -1) { codeStream.addDefinitelyAssignedVariables( currentScope, this.postCollectionInitStateIndex); } } break; } if (!hasEmptyAction) { this.action.generateCode(this.scope, codeStream); } codeStream.removeVariable(this.elementVariable.binding); if (this.postCollectionInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postCollectionInitStateIndex); } // continuation point if (this.continueLabel != null) { this.continueLabel.place(); int continuationPC = codeStream.position; // generate the increments for next iteration switch(this.kind) { case ARRAY : if (!hasEmptyAction || this.elementVariable.binding.resolvedPosition >= 0) { codeStream.iinc(this.indexVariable.resolvedPosition, 1); } // generate the condition conditionLabel.place(); codeStream.load(this.indexVariable); codeStream.load(this.maxVariable); codeStream.if_icmplt(actionLabel); break; case RAW_ITERABLE : case GENERIC_ITERABLE : // generate the condition conditionLabel.place(); codeStream.load(this.indexVariable); codeStream.invokeJavaUtilIteratorHasNext(); codeStream.ifne(actionLabel); break; } codeStream.recordPositionsFrom(continuationPC, this.elementVariable.sourceStart); } switch(this.kind) { case ARRAY : codeStream.removeVariable(this.indexVariable); codeStream.removeVariable(this.maxVariable); codeStream.removeVariable(this.collectionVariable); break; case RAW_ITERABLE : case GENERIC_ITERABLE : // generate the condition codeStream.removeVariable(this.indexVariable); break; } codeStream.exitUserScope(this.scope); if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } this.breakLabel.place(); codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output).append("for ("); //$NON-NLS-1$ this.elementVariable.printAsExpression(0, output); output.append(" : ");//$NON-NLS-1$ if (this.collection != null) { this.collection.print(0, output).append(") "); //$NON-NLS-1$ } else { output.append(')'); } //block if (this.action == null) { output.append(';'); } else { output.append('\n'); this.action.printStatement(indent + 1, output); } return output; } public void resolve(BlockScope upperScope) { // use the scope that will hold the init declarations this.scope = new BlockScope(upperScope); this.elementVariable.resolve(this.scope); // collection expression can see itemVariable TypeBinding elementType = this.elementVariable.type.resolvedType; TypeBinding collectionType = this.collection == null ? null : this.collection.resolveType(this.scope); TypeBinding expectedCollectionType = null; if (elementType != null && collectionType != null) { boolean isTargetJsr14 = this.scope.compilerOptions().targetJDK == ClassFileConstants.JDK1_4; if (collectionType.isArrayType()) { // for(E e : E[]) this.kind = ARRAY; this.collectionElementType = ((ArrayBinding) collectionType).elementsType(); if (!this.collectionElementType.isCompatibleWith(elementType) && !this.scope.isBoxingCompatibleWith(this.collectionElementType, elementType)) { this.scope.problemReporter().notCompatibleTypesErrorInForeach(this.collection, this.collectionElementType, elementType); } else if (this.collectionElementType.needsUncheckedConversion(elementType)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321085 this.scope.problemReporter().unsafeElementTypeConversion(this.collection, this.collectionElementType, elementType); } // in case we need to do a conversion int compileTimeTypeID = this.collectionElementType.id; if (elementType.isBaseType()) { this.collection.computeConversion(this.scope, collectionType, collectionType); if (!this.collectionElementType.isBaseType()) { compileTimeTypeID = this.scope.environment().computeBoxingType(this.collectionElementType).id; this.elementVariableImplicitWidening = UNBOXING; if (elementType.isBaseType()) { this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID; this.scope.problemReporter().autoboxing(this.collection, this.collectionElementType, elementType); } } else { this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID; } } else if (this.collectionElementType.isBaseType()) { this.collection.computeConversion(this.scope, collectionType, collectionType); int boxedID = this.scope.environment().computeBoxingType(this.collectionElementType).id; this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion compileTimeTypeID = boxedID; this.scope.problemReporter().autoboxing(this.collection, this.collectionElementType, elementType); } else { expectedCollectionType = upperScope.createArrayType(elementType, 1); this.collection.computeConversion(this.scope, expectedCollectionType, collectionType); } } else if (collectionType instanceof ReferenceBinding) { ReferenceBinding iterableType = ((ReferenceBinding)collectionType).findSuperTypeOriginatingFrom(T_JavaLangIterable, false /*Iterable is not a class*/); if (iterableType == null && isTargetJsr14) { iterableType = ((ReferenceBinding)collectionType).findSuperTypeOriginatingFrom(T_JavaUtilCollection, false /*Iterable is not a class*/); } checkIterable: { if (iterableType == null) break checkIterable; this.iteratorReceiverType = collectionType.erasure(); if (isTargetJsr14) { if (((ReferenceBinding)this.iteratorReceiverType).findSuperTypeOriginatingFrom(T_JavaUtilCollection, false) == null) { this.iteratorReceiverType = iterableType; // handle indirect inheritance thru variable secondary bound this.collection.computeConversion(this.scope, iterableType, collectionType); } else { this.collection.computeConversion(this.scope, collectionType, collectionType); } } else if (((ReferenceBinding)this.iteratorReceiverType).findSuperTypeOriginatingFrom(T_JavaLangIterable, false) == null) { this.iteratorReceiverType = iterableType; // handle indirect inheritance thru variable secondary bound this.collection.computeConversion(this.scope, iterableType, collectionType); } else { this.collection.computeConversion(this.scope, collectionType, collectionType); } TypeBinding[] arguments = null; switch (iterableType.kind()) { case Binding.RAW_TYPE : // for(Object o : Iterable) this.kind = RAW_ITERABLE; this.collectionElementType = this.scope.getJavaLangObject(); if (!this.collectionElementType.isCompatibleWith(elementType) && !this.scope.isBoxingCompatibleWith(this.collectionElementType, elementType)) { this.scope.problemReporter().notCompatibleTypesErrorInForeach(this.collection, this.collectionElementType, elementType); } // no conversion needed as only for reference types break checkIterable; case Binding.GENERIC_TYPE : // for (T t : Iterable) - in case used inside Iterable itself arguments = iterableType.typeVariables(); break; case Binding.PARAMETERIZED_TYPE : // for(E e : Iterable) arguments = ((ParameterizedTypeBinding)iterableType).arguments; break; default: break checkIterable; } // generic or parameterized case if (arguments.length != 1) break checkIterable; // per construction can only be one this.kind = GENERIC_ITERABLE; this.collectionElementType = arguments[0]; if (!this.collectionElementType.isCompatibleWith(elementType) && !this.scope.isBoxingCompatibleWith(this.collectionElementType, elementType)) { this.scope.problemReporter().notCompatibleTypesErrorInForeach(this.collection, this.collectionElementType, elementType); } else if (this.collectionElementType.needsUncheckedConversion(elementType)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=393719 this.scope.problemReporter().unsafeElementTypeConversion(this.collection, this.collectionElementType, elementType); } int compileTimeTypeID = this.collectionElementType.id; // no conversion needed as only for reference types if (elementType.isBaseType()) { if (!this.collectionElementType.isBaseType()) { compileTimeTypeID = this.scope.environment().computeBoxingType(this.collectionElementType).id; this.elementVariableImplicitWidening = UNBOXING; if (elementType.isBaseType()) { this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID; } } else { this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID; } } else { if (this.collectionElementType.isBaseType()) { this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion } } } } switch(this.kind) { case ARRAY : // allocate #index secret variable (of type int) this.indexVariable = new LocalVariableBinding(SecretIndexVariableName, TypeBinding.INT, ClassFileConstants.AccDefault, false); this.scope.addLocalVariable(this.indexVariable); this.indexVariable.setConstant(Constant.NotAConstant); // not inlinable // allocate #max secret variable this.maxVariable = new LocalVariableBinding(SecretMaxVariableName, TypeBinding.INT, ClassFileConstants.AccDefault, false); this.scope.addLocalVariable(this.maxVariable); this.maxVariable.setConstant(Constant.NotAConstant); // not inlinable // add #array secret variable (of collection type) if (expectedCollectionType == null) { this.collectionVariable = new LocalVariableBinding(SecretCollectionVariableName, collectionType, ClassFileConstants.AccDefault, false); } else { this.collectionVariable = new LocalVariableBinding(SecretCollectionVariableName, expectedCollectionType, ClassFileConstants.AccDefault, false); } this.scope.addLocalVariable(this.collectionVariable); this.collectionVariable.setConstant(Constant.NotAConstant); // not inlinable break; case RAW_ITERABLE : case GENERIC_ITERABLE : // allocate #index secret variable (of type Iterator) this.indexVariable = new LocalVariableBinding(SecretIteratorVariableName, this.scope.getJavaUtilIterator(), ClassFileConstants.AccDefault, false); this.scope.addLocalVariable(this.indexVariable); this.indexVariable.setConstant(Constant.NotAConstant); // not inlinable break; default : if (isTargetJsr14) { this.scope.problemReporter().invalidTypeForCollectionTarget14(this.collection); } else { this.scope.problemReporter().invalidTypeForCollection(this.collection); } } } if (this.action != null) { this.action.resolve(this.scope); } } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.elementVariable.traverse(visitor, this.scope); if (this.collection != null) { this.collection.traverse(visitor, this.scope); } if (this.action != null) { this.action.traverse(visitor, this.scope); } } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java0000644000175000001440000013215112212041344031560 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 292478 - Report potentially null across variable assignment, * bug 185682 - Increment/decrement operators mark local variables as read * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * Bug 412203 - [compiler] Internal compiler error: java.lang.IllegalArgumentException: info cannot be null * Jesper S Moller - Contributions for * bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class SingleNameReference extends NameReference implements OperatorIds { public static final int READ = 0; public static final int WRITE = 1; public char[] token; public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor public TypeBinding genericCast; public SingleNameReference(char[] source, long pos) { super(); this.token = source; this.sourceStart = (int) (pos >>> 32); this.sourceEnd = (int) pos; } public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0; // compound assignment extra work if (isCompound) { // check the variable part is initialized if blank final switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field FieldBinding fieldBinding = (FieldBinding) this.binding; if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo); if (!fieldInits.isDefinitelyAssigned(fieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); } } manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); break; case Binding.LOCAL : // reading a local variable // check if assigning a final blank field LocalVariableBinding localBinding; if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); // we could improve error msg here telling "cannot use compound assignment on final local variable" } if (localBinding.useFlag != LocalVariableBinding.USED) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 // access from compound assignment does not prevent "unused" warning, unless unboxing is involved: if (isReachable && (this.implicitConversion & TypeIds.UNBOXING) != 0) { localBinding.useFlag = LocalVariableBinding.USED; } else { // use values < 0 to count the number of compound uses: if (localBinding.useFlag <= LocalVariableBinding.UNUSED) localBinding.useFlag--; } } } } if (assignment.expression != null) { flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); } switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); // check if assigning a final field FieldBinding fieldBinding = (FieldBinding) this.binding; if (fieldBinding.isFinal()) { // inside a context where allowed if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { if (flowInfo.isPotentiallyAssigned(fieldBinding)) { currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this); } else { flowContext.recordSettingFinal(fieldBinding, this, flowInfo); } flowInfo.markAsDefinitelyAssigned(fieldBinding); } else { currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this); } } else if (!isCompound && fieldBinding.isNonNull() && fieldBinding.declaringClass == currentScope.enclosingReceiverType()) { // inherited fields are not tracked here // record assignment for detecting uninitialized non-null fields: flowInfo.markAsDefinitelyAssigned(fieldBinding); } break; case Binding.LOCAL : // assigning to a local variable LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes this.bits |= ASTNode.FirstAssignmentToLocal; } else { this.bits &= ~ASTNode.FirstAssignmentToLocal; } if (localBinding.isFinal()) { if ((this.bits & ASTNode.DepthMASK) == 0) { // tolerate assignment to final local in unreachable code (45674) if ((isReachable && isCompound) || !localBinding.isBlankFinal()){ currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this); } else if (flowInfo.isPotentiallyAssigned(localBinding)) { currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this); } else { flowContext.recordSettingFinal(localBinding, this, flowInfo); } } else { currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this); } } else /* avoid double diagnostic */ if ((localBinding.tagBits & TagBits.IsArgument) != 0) { currentScope.problemReporter().parameterAssignment(localBinding, this); } flowInfo.markAsDefinitelyAssigned(localBinding); } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); return flowInfo; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return analyseCode(currentScope, flowContext, flowInfo, true); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); } // check if reading a final blank field FieldBinding fieldBinding = (FieldBinding) this.binding; if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo); if (!fieldInits.isDefinitelyAssigned(fieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); } } break; case Binding.LOCAL : // reading a local variable LocalVariableBinding localBinding; if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); } if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { localBinding.useFlag = LocalVariableBinding.USED; } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { localBinding.useFlag = LocalVariableBinding.FAKE_USED; } } if (valueRequired) { manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); } return flowInfo; } public TypeBinding checkFieldAccess(BlockScope scope) { FieldBinding fieldBinding = (FieldBinding) this.binding; this.constant = fieldBinding.constant(); this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits this.bits |= Binding.FIELD; MethodScope methodScope = scope.methodScope(); if (fieldBinding.isStatic()) { // check if accessing enum static field in initializer ReferenceBinding declaringClass = fieldBinding.declaringClass; if (declaringClass.isEnum()) { SourceTypeBinding sourceType = scope.enclosingSourceType(); if (this.constant == Constant.NotAConstant && !methodScope.isStatic && (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body && methodScope.isInsideInitializerOrConstructor()) { scope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this); } } } else { if (scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) { scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding); } // must check for the static status.... if (methodScope.isStatic) { scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding); return fieldBinding.type; } } if (isFieldUseDeprecated(fieldBinding, scope, this.bits)) scope.problemReporter().deprecatedField(fieldBinding, this); if ((this.bits & ASTNode.IsStrictlyAssigned) == 0 && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass && methodScope.lastVisibleFieldID >= 0 && fieldBinding.id >= methodScope.lastVisibleFieldID && (!fieldBinding.isStatic() || methodScope.isStatic)) { scope.problemReporter().forwardReference(this, 0, fieldBinding); this.bits |= ASTNode.IgnoreNoEffectAssignCheck; } return fieldBinding.type; } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { if (!super.checkNPE(scope, flowContext, flowInfo)) { VariableBinding var = nullAnnotatedVariableBinding(); if (var instanceof FieldBinding) { checkNullableFieldDereference(scope, (FieldBinding) var, ((long)this.sourceStart<<32)+this.sourceEnd); return true; } } return false; } /** * @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 ((this.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 field = (FieldBinding) this.binding; FieldBinding originalBinding = field.original(); TypeBinding originalType = originalBinding.type; // extra cast needed if field type is type variable if (originalType.leafComponentType().isTypeVariable()) { TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) ? compileTimeType // unboxing: checkcast before conversion : runtimeTimeType; this.genericCast = originalType.genericCast(scope.boxing(targetType)); if (this.genericCast instanceof ReferenceBinding) { ReferenceBinding referenceCast = (ReferenceBinding) this.genericCast; if (!referenceCast.canBeSeenBy(scope)) { scope.problemReporter().invalidType(this, new ProblemReferenceBinding( CharOperation.splitOn('.', referenceCast.shortReadableName()), referenceCast, ProblemReasons.NotVisible)); } } } } 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 if (assignment.expression.isCompactableOperation()) { BinaryExpression operation = (BinaryExpression) assignment.expression; int operator = (operation.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT; SingleNameReference variableReference; if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == this.binding)) { // i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.right, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } return; } if ((operation.right instanceof SingleNameReference) && ((operator == OperatorIds.PLUS) || (operator == OperatorIds.MULTIPLY)) // only commutative operations && ((variableReference = (SingleNameReference) operation.right).binding == this.binding) && (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect && (((operation.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) != TypeIds.T_JavaLangString) // exclude string concatenation which would occur backwards && (((operation.right.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) != TypeIds.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, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.left, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } return; } } switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field int pc = codeStream.position; FieldBinding codegenBinding = ((FieldBinding) this.binding).original(); if (!codegenBinding.isStatic()) { // need a receiver? if ((this.bits & ASTNode.DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { generateReceiver(codeStream); } } codeStream.recordPositionsFrom(pc, this.sourceStart); assignment.expression.generateCode(currentScope, codeStream, true); fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } // no need for generic cast as value got dupped return; case Binding.LOCAL : // assigning to a local variable LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (localBinding.resolvedPosition != -1) { assignment.expression.generateCode(currentScope, codeStream, true); } else { if (assignment.expression.constant != Constant.NotAConstant) { // assigning an unused local to a constant value = no actual assignment is necessary if (valueRequired) { codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion); } } else { assignment.expression.generateCode(currentScope, codeStream, true); /* Even though the value may not be required, we force it to be produced, and discard it later on if it was actually not necessary, so as to provide the same behavior as JDK1.2beta3. */ if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion } else { switch(localBinding.type.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.pop2(); break; default : codeStream.pop(); break; } } } return; } // 26903, need extra cast to store null in array local var if (localBinding.type.isArrayType() && ((assignment.expression instanceof CastExpression) // arrayLoc = (type[])null && (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == TypeBinding.NULL))){ codeStream.checkcast(localBinding.type); } // normal local assignment (since cannot store in outer local which are final locations) codeStream.store(localBinding, valueRequired); if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) { // for local variable debug attributes localBinding.recordInitializationStartPC(codeStream.position); } // implicit conversion if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } } } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { if (valueRequired) { codeStream.generateConstant(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } else { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field FieldBinding codegenField = ((FieldBinding) this.binding).original(); Constant fieldConstant = codegenField.constant(); if (fieldConstant != Constant.NotAConstant) { // directly use inlined value for constant fields if (valueRequired) { codeStream.generateConstant(fieldConstant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } if (codegenField.isStatic()) { if (!valueRequired // if no valueRequired, still need possible side-effects of invocation, if field belongs to different class && ((FieldBinding)this.binding).original().declaringClass == this.actualReceiverType.erasure() && ((this.implicitConversion & TypeIds.UNBOXING) == 0) && this.genericCast == null) { // if no valueRequired, optimize out entire gen codeStream.recordPositionsFrom(pc, this.sourceStart); return; } // managing private access if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } else { if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0 && this.genericCast == null) { // if no valueRequired, optimize out entire gen codeStream.recordPositionsFrom(pc, this.sourceStart); return; } // managing enclosing instance access if ((this.bits & ASTNode.DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { generateReceiver(codeStream); } // managing private access if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } break; case Binding.LOCAL : // reading a local LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (localBinding.resolvedPosition == -1) { if (valueRequired) { // restart code gen localBinding.useFlag = LocalVariableBinding.USED; throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) { // if no valueRequired, optimize out entire gen codeStream.recordPositionsFrom(pc, this.sourceStart); return; } // outer local? if ((this.bits & ASTNode.DepthMASK) != 0) { // outer local can be reached either through a synthetic arg or a synthetic field VariableBinding[] path = currentScope.getEmulationPath(localBinding); codeStream.generateOuterAccess(path, this, localBinding, currentScope); } else { // regular local variable read codeStream.load(localBinding); } break; default: // type codeStream.recordPositionsFrom(pc, this.sourceStart); return; } } // required cast must occur even if no value is required if (this.genericCast != null) codeStream.checkcast(this.genericCast); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; // conversion only generated if unboxing if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); switch (isUnboxing ? postConversionType(currentScope).id : this.resolvedType.id) { case T_long : case T_double : codeStream.pop2(); break; default : codeStream.pop(); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } /* * Regular API for compound assignment, relies on the fact that there is only one reference to the * variable, which carries both synthetic read/write accessors. * The APIs with an extra argument is used whenever there are two references to the same variable which * are optimized in one access: e.g "a = a + 1" optimized into "a++". */ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.LOCAL: LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // check if compound assignment is the only usage of this local Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired); break; case Binding.FIELD: // check if compound assignment is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, (FieldBinding)this.binding, valueRequired); } this.generateCompoundAssignment( currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], expression, operator, assignmentImplicitConversion, valueRequired); } /* * The APIs with an extra argument is used whenever there are two references to the same variable which * are optimized in one access: e.g "a = a + 1" optimized into "a++". */ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field FieldBinding codegenField = ((FieldBinding) this.binding).original(); if (codegenField.isStatic()) { if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } else { if ((this.bits & ASTNode.DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { codeStream.aload_0(); } codeStream.dup(); if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } break; case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local) LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // using incr bytecode if possible Constant assignConstant; switch (localBinding.type.id) { case T_JavaLangString : codeStream.generateStringConcatenationAppend(currentScope, this, expression); if (valueRequired) { codeStream.dup(); } codeStream.store(localBinding, false); return; case T_int : assignConstant = expression.constant; if (localBinding.resolvedPosition == -1) { if (valueRequired) { /* * restart code gen because we either: * - need the value * - the constant can have potential side-effect */ localBinding.useFlag = LocalVariableBinding.USED; throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); } else if (assignConstant == Constant.NotAConstant) { // we only need to generate the value of the expression's constant if it is not a constant expression expression.generateCode(currentScope, codeStream, false); } return; } if ((assignConstant != Constant.NotAConstant) && (assignConstant.typeID() != TypeIds.T_float) // only for integral types && (assignConstant.typeID() != TypeIds.T_double)) { // TODO (philippe) is this test needed ? switch (operator) { case PLUS : int increment = assignConstant.intValue(); if (increment != (short) increment) break; // not representable as a 16-bits value codeStream.iinc(localBinding.resolvedPosition, increment); if (valueRequired) { codeStream.load(localBinding); } return; case MINUS : increment = -assignConstant.intValue(); if (increment != (short) increment) break; // not representable as a 16-bits value codeStream.iinc(localBinding.resolvedPosition, increment); if (valueRequired) { codeStream.load(localBinding); } return; } } //$FALL-THROUGH$ default : if (localBinding.resolvedPosition == -1) { assignConstant = expression.constant; if (valueRequired) { /* * restart code gen because we either: * - need the value * - the constant can have potential side-effect */ localBinding.useFlag = LocalVariableBinding.USED; throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); } else if (assignConstant == Constant.NotAConstant) { // we only need to generate the value of the expression's constant if it is not a constant expression expression.generateCode(currentScope, codeStream, false); } return; } codeStream.load(localBinding); } } // perform the actual compound operation int operationTypeID; switch(operationTypeID = (this.implicitConversion & TypeIds.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 if (this.genericCast != null) codeStream.checkcast(this.genericCast); codeStream.generateImplicitConversion(this.implicitConversion); // generate the increment value (will by itself be promoted to the operation value) if (expression == IntLiteral.One){ // prefix operation codeStream.generateConstant(expression.constant, this.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 (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field FieldBinding codegenField = ((FieldBinding) this.binding).original(); fieldStore(currentScope, codeStream, codegenField, writeAccessor, this.actualReceiverType, true /* implicit this*/, valueRequired); // no need for generic cast as value got dupped return; case Binding.LOCAL : // assigning to a local variable LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (valueRequired) { switch (localBinding.type.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2(); break; default: codeStream.dup(); break; } } codeStream.store(localBinding, false); } } public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field FieldBinding fieldBinding = (FieldBinding)this.binding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 // check if postIncrement is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, fieldBinding, valueRequired); FieldBinding codegenField = fieldBinding.original(); if (codegenField.isStatic()) { if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } else { if ((this.bits & ASTNode.DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { codeStream.aload_0(); } codeStream.dup(); if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } TypeBinding operandType; if (this.genericCast != null) { codeStream.checkcast(this.genericCast); operandType = this.genericCast; } else { operandType = codegenField.type; } if (valueRequired) { if (codegenField.isStatic()) { switch (operandType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2(); break; default: codeStream.dup(); break; } } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] switch (operandType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2_x1(); break; default: codeStream.dup_x1(); break; } } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); fieldStore(currentScope, codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, false); // no need for generic cast return; case Binding.LOCAL : // assigning to a local variable LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 // check if postIncrement is the only usage of this local Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired); if (localBinding.resolvedPosition == -1) { if (valueRequired) { // restart code gen localBinding.useFlag = LocalVariableBinding.USED; throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); } return; } // using incr bytecode if possible if (localBinding.type == TypeBinding.INT) { if (valueRequired) { codeStream.load(localBinding); } if (postIncrement.operator == OperatorIds.PLUS) { codeStream.iinc(localBinding.resolvedPosition, 1); } else { codeStream.iinc(localBinding.resolvedPosition, -1); } } else { codeStream.load(localBinding); if (valueRequired){ switch (localBinding.type.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2(); break; default: codeStream.dup(); break; } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); codeStream.store(localBinding, false); } } } public void generateReceiver(CodeStream codeStream) { codeStream.aload_0(); } /** * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments() */ public TypeBinding[] genericTypeArguments() { return null; } public boolean isEquivalent(Reference reference) { char[] otherToken = null; if (reference instanceof SingleNameReference) { otherToken = ((SingleNameReference) reference).token; } else if (reference instanceof FieldReference) { // test for comparison "f1" vs. "this.f1": FieldReference fr = (FieldReference) reference; if (fr.receiver.isThis() && !(fr.receiver instanceof QualifiedThisReference)) otherToken = fr.token; } return otherToken != null && CharOperation.equals(this.token, otherToken); } /** * Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference) * or thru a cast expression etc... */ public LocalVariableBinding localVariableBinding() { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field break; case Binding.LOCAL : // reading a local variable return (LocalVariableBinding) this.binding; } return null; } public VariableBinding nullAnnotatedVariableBinding() { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field case Binding.LOCAL : // reading a local variable if ((((VariableBinding)this.binding).tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0) return (VariableBinding) this.binding; } return null; } public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { //If inlinable field, forget the access emulation, the code gen will directly target it if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) { return; } if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) { LocalVariableBinding localVariableBinding = (LocalVariableBinding) this.binding; if (localVariableBinding != null) { if ((localVariableBinding.tagBits & TagBits.NotInitialized) != 0) { // local was tagged as uninitialized return; } switch(localVariableBinding.useFlag) { case LocalVariableBinding.FAKE_USED : case LocalVariableBinding.USED : currentScope.emulateOuterAccess(localVariableBinding); } } } } public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return; //If inlinable field, forget the access emulation, the code gen will directly target it if (this.constant != Constant.NotAConstant) return; if ((this.bits & Binding.FIELD) != 0) { FieldBinding fieldBinding = (FieldBinding) this.binding; FieldBinding codegenField = fieldBinding.original(); if (((this.bits & ASTNode.DepthMASK) != 0) && (codegenField.isPrivate() // private access || (codegenField.isProtected() // implicit protected access && codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) { if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2]; this.syntheticAccessors[isReadAccess ? SingleNameReference.READ : SingleNameReference.WRITE] = ((SourceTypeBinding)currentScope.enclosingSourceType(). enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess, false /*not super access*/); currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess); return; } } } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope) */ public TypeBinding postConversionType(Scope scope) { TypeBinding convertedType = this.resolvedType; if (this.genericCast != null) convertedType = this.genericCast; int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; switch (runtimeType) { case T_boolean : convertedType = TypeBinding.BOOLEAN; break; case T_byte : convertedType = TypeBinding.BYTE; break; case T_short : convertedType = TypeBinding.SHORT; break; case T_char : convertedType = TypeBinding.CHAR; break; case T_int : convertedType = TypeBinding.INT; break; case T_float : convertedType = TypeBinding.FLOAT; break; case T_long : convertedType = TypeBinding.LONG; break; case T_double : convertedType = TypeBinding.DOUBLE; break; default : } if ((this.implicitConversion & TypeIds.BOXING) != 0) { convertedType = scope.environment().computeBoxingType(convertedType); } return convertedType; } public StringBuffer printExpression(int indent, StringBuffer output){ return output.append(this.token); } public TypeBinding reportError(BlockScope scope) { //=====error cases======= this.constant = Constant.NotAConstant; if (this.binding instanceof ProblemFieldBinding) { scope.problemReporter().invalidField(this, (FieldBinding) this.binding); } else if (this.binding instanceof ProblemReferenceBinding || this.binding instanceof MissingTypeBinding) { scope.problemReporter().invalidType(this, (TypeBinding) this.binding); } else { scope.problemReporter().unresolvableReference(this, this.binding); } return null; } public TypeBinding resolveType(BlockScope scope) { // for code gen, harm the restrictiveFlag if (this.actualReceiverType != null) { this.binding = scope.getField(this.actualReceiverType, this.token, this); } else { this.actualReceiverType = scope.enclosingSourceType(); this.binding = scope.getBinding(this.token, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/); } if (this.binding.isValidBinding()) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.VARIABLE : // =========only variable============ case Binding.VARIABLE | Binding.TYPE : //====both variable and type============ if (this.binding instanceof VariableBinding) { VariableBinding variable = (VariableBinding) this.binding; TypeBinding variableType; if (this.binding instanceof LocalVariableBinding) { this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits this.bits |= Binding.LOCAL; if (!variable.isFinal() && (this.bits & ASTNode.DepthMASK) != 0) { scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)variable, this); } variableType = variable.type; this.constant = (this.bits & ASTNode.IsStrictlyAssigned) == 0 ? variable.constant() : Constant.NotAConstant; } else { // a field variableType = checkFieldAccess(scope); } // perform capture conversion if read access if (variableType != null) { this.resolvedType = variableType = (((this.bits & ASTNode.IsStrictlyAssigned) == 0) ? variableType.capture(scope, this.sourceEnd) : variableType); if ((variableType.tagBits & TagBits.HasMissingType) != 0) { if ((this.bits & Binding.LOCAL) == 0) { // only complain if field reference (for local, its type got flagged already) scope.problemReporter().invalidType(this, variableType); } return null; } } return variableType; } // thus it was a type this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits this.bits |= Binding.TYPE; //$FALL-THROUGH$ case Binding.TYPE : //========only type============== this.constant = Constant.NotAConstant; //deprecated test TypeBinding type = (TypeBinding)this.binding; if (isTypeUseDeprecated(type, scope)) scope.problemReporter().deprecatedType(type, this); type = scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/); return this.resolvedType = type; } } // error scenario return this.resolvedType = reportError(scope); } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public String unboundReferenceErrorName(){ return new String(this.token); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java0000644000175000001440000001440012212041344032277 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; public class QualifiedTypeReference extends TypeReference { public char[][] tokens; public long[] sourcePositions; public QualifiedTypeReference(char[][] sources , long[] poss) { this.tokens = sources ; this.sourcePositions = poss ; this.sourceStart = (int) (this.sourcePositions[0]>>>32) ; this.sourceEnd = (int)(this.sourcePositions[this.sourcePositions.length-1] & 0x00000000FFFFFFFFL ) ; } 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(this.tokens, dim, this.sourcePositions); } protected TypeBinding findNextTypeBinding(int tokenIndex, Scope scope, PackageBinding packageBinding) { LookupEnvironment env = scope.environment(); try { env.missingClassFileLocation = this; 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.isValidBinding()) { this.resolvedType = new ProblemReferenceBinding( CharOperation.subarray(this.tokens, 0, tokenIndex + 1), (ReferenceBinding)this.resolvedType.closestMatch(), this.resolvedType.problemId()); } } return this.resolvedType; } catch (AbortCompilation e) { e.updateContext(this, scope.referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } } public char[] getLastToken() { return this.tokens[this.tokens.length-1]; } protected TypeBinding getTypeBinding(Scope scope) { if (this.resolvedType != null) { return this.resolvedType; } Binding binding = scope.getPackage(this.tokens); if (binding != null && !binding.isValidBinding()) { if (binding instanceof ProblemReferenceBinding && binding.problemId() == ProblemReasons.NotFound) { ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) binding; Binding pkg = scope.getTypeOrPackage(this.tokens); return new ProblemReferenceBinding(problemBinding.compoundName, pkg instanceof PackageBinding ? null : scope.environment().createMissingType(null, this.tokens), ProblemReasons.NotFound); } 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, last = max-1; i < max; i++) { findNextTypeBinding(i, scope, packageBinding); if (!this.resolvedType.isValidBinding()) return this.resolvedType; if (i == 0 && this.resolvedType.isTypeVariable() && ((TypeVariableBinding) this.resolvedType).firstBound == null) { // cannot select from a type variable scope.problemReporter().illegalAccessFromTypeVariable((TypeVariableBinding) this.resolvedType, this); return null; } if (i <= last && isTypeUseDeprecated(this.resolvedType, scope)) { reportDeprecatedType(this.resolvedType, scope, i); } if (isClassScope) if (((ClassScope) scope).detectHierarchyCycle(this.resolvedType, this)) // must connect hierarchy to find inherited member types return null; ReferenceBinding currentType = (ReferenceBinding) this.resolvedType; if (qualifiedType != null) { ReferenceBinding enclosingType = currentType.enclosingType(); if (enclosingType != null && enclosingType.erasure() != qualifiedType.erasure()) { qualifiedType = enclosingType; // inherited member type, leave it associated with its enclosing rather than subtype } boolean rawQualified; if (currentType.isGenericType()) { qualifiedType = scope.environment().createRawType(currentType, qualifiedType); } else if ((rawQualified = qualifiedType.isRawType()) && !currentType.isStatic()) { qualifiedType = scope.environment().createRawType((ReferenceBinding)currentType.erasure(), qualifiedType); } else if ((rawQualified || qualifiedType.isParameterizedType()) && qualifiedType.erasure() == currentType.enclosingType().erasure()) { qualifiedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType); } else { qualifiedType = currentType; } } else { qualifiedType = currentType.isGenericType() ? (ReferenceBinding)scope.environment().convertToRawType(currentType, false /*do not force conversion of enclosing types*/) : currentType; } recordResolution(scope.environment(), qualifiedType); } this.resolvedType = qualifiedType; return this.resolvedType; } void recordResolution(LookupEnvironment env, TypeBinding typeFound) { if (typeFound != null && typeFound.isValidBinding()) for (int i = 0; i < env.resolutionListeners.length; i++) { env.resolutionListeners[i].recordResolution(this, typeFound); } } public char[][] getTypeName(){ return this.tokens; } public StringBuffer printExpression(int indent, StringBuffer output) { for (int i = 0; i < this.tokens.length; i++) { if (i > 0) output.append('.'); output.append(this.tokens[i]); } return output; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java0000644000175000001440000011447612212041344032074 0ustar dokousers/******************************************************************************* * Copyright (c) 2011, 2013 GK Software AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stephan Herrmann - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.flow.FinallyFlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; 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.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.util.Util; /** * A faked local variable declaration used for keeping track of data flows of a * special variable. Certain events will be recorded by changing the null info * for this variable. * * See bug 349326 - [1.7] new warning for missing try-with-resources */ public class FakedTrackingVariable extends LocalDeclaration { private static final char[] UNASSIGNED_CLOSEABLE_NAME = "".toCharArray(); //$NON-NLS-1$ private static final char[] UNASSIGNED_CLOSEABLE_NAME_TEMPLATE = "".toCharArray(); //$NON-NLS-1$ private static final char[] TEMPLATE_ARGUMENT = "{0}".toCharArray(); //$NON-NLS-1$ // a call to close() was seen at least on one path: private static final int CLOSE_SEEN = 1; // the resource is shared with outside code either by // - passing as an arg in a method call or // - obtaining this from a method call or array reference // Interpret that we may or may not be responsible for closing private static final int SHARED_WITH_OUTSIDE = 2; // the resource is likely owned by outside code (owner has responsibility to close): // - obtained as argument of the current method, or via a field read // - stored into a field // - returned as the result of this method private static final int OWNED_BY_OUTSIDE = 4; // If close() is invoked from a nested method (inside a local type) report remaining problems only as potential: private static final int CLOSED_IN_NESTED_METHOD = 8; // explicit closing has been reported already against this resource: private static final int REPORTED_EXPLICIT_CLOSE = 16; // a location independent potential problem has been reported against this resource: private static final int REPORTED_POTENTIAL_LEAK = 32; // a location independent definitive problem has been reported against this resource: private static final int REPORTED_DEFINITIVE_LEAK = 64; public static boolean TEST_372319 = false; // see https://bugs.eclipse.org/372319 /** * Bitset of {@link #CLOSE_SEEN}, {@link #SHARED_WITH_OUTSIDE}, {@link #OWNED_BY_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD}, {@link #REPORTED_EXPLICIT_CLOSE}, {@link #REPORTED_POTENTIAL_LEAK} and {@link #REPORTED_DEFINITIVE_LEAK}. */ private int globalClosingState = 0; public LocalVariableBinding originalBinding; // the real local being tracked, can be null for preliminary track vars for allocation expressions public FakedTrackingVariable innerTracker; // chained tracking variable of a chained (wrapped) resource public FakedTrackingVariable outerTracker; // inverse of 'innerTracker' MethodScope methodScope; // designates the method declaring this variable private HashMap recordedLocations; // initially null, ASTNode -> Integer // temporary storage while analyzing "res = new Res();": private ASTNode currentAssignment; // temporarily store the assignment as the location for error reporting // if tracking var was allocated from a finally context, record here the flow context of the corresponding try block private FlowContext tryContext; public FakedTrackingVariable(LocalVariableBinding original, ASTNode location, FlowInfo flowInfo, FlowContext flowContext, int nullStatus) { super(original.name, location.sourceStart, location.sourceEnd); this.type = new SingleTypeReference( TypeConstants.OBJECT, ((long)this.sourceStart <<32)+this.sourceEnd); this.methodScope = original.declaringScope.methodScope(); this.originalBinding = original; // inside a finally block? while (flowContext != null) { if (flowContext instanceof FinallyFlowContext) { // yes -> connect to the corresponding try block: this.tryContext = ((FinallyFlowContext) flowContext).tryContext; break; } flowContext = flowContext.parent; } resolve(original.declaringScope); if (nullStatus != 0) flowInfo.markNullStatus(this.binding, nullStatus); // mark that this flow has seen the resource } /* Create an unassigned tracking variable while analyzing an allocation expression: */ private FakedTrackingVariable(BlockScope scope, ASTNode location, FlowInfo flowInfo, int nullStatus) { super(UNASSIGNED_CLOSEABLE_NAME, location.sourceStart, location.sourceEnd); this.type = new SingleTypeReference( TypeConstants.OBJECT, ((long)this.sourceStart <<32)+this.sourceEnd); this.methodScope = scope.methodScope(); this.originalBinding = null; resolve(scope); if (nullStatus != 0) flowInfo.markNullStatus(this.binding, nullStatus); // mark that this flow has seen the resource } public void generateCode(BlockScope currentScope, CodeStream codeStream) { /* NOP - this variable is completely dummy, ie. for analysis only. */ } public void resolve (BlockScope scope) { // only need the binding, which is used as reference in FlowInfo methods. this.binding = new LocalVariableBinding( this.name, scope.getJavaLangObject(), // dummy, just needs to be a reference type 0, false); this.binding.closeTracker = this; this.binding.declaringScope = scope; this.binding.setConstant(Constant.NotAConstant); this.binding.useFlag = LocalVariableBinding.USED; // use a free slot without assigning it: this.binding.id = scope.registerTrackingVariable(this); } /** * If expression resolves to a value of type AutoCloseable answer the variable that tracks closing of that local. * Covers two cases: *
    *
  • value is a local variable reference, create tracking variable it if needed. *
  • value is an allocation expression, return a preliminary tracking variable if set. *
* @param expression * @return a new {@link FakedTrackingVariable} or null. */ public static FakedTrackingVariable getCloseTrackingVariable(Expression expression, FlowInfo flowInfo, FlowContext flowContext) { while (true) { if (expression instanceof CastExpression) expression = ((CastExpression) expression).expression; else if (expression instanceof Assignment) expression = ((Assignment) expression).expression; else break; } if (expression instanceof SingleNameReference) { SingleNameReference name = (SingleNameReference) expression; if (name.binding instanceof LocalVariableBinding) { LocalVariableBinding local = (LocalVariableBinding)name.binding; if (local.closeTracker != null) return local.closeTracker; if (!isAnyCloseable(expression.resolvedType)) return null; // tracking var doesn't yet exist. This happens in finally block // which is analyzed before the corresponding try block Statement location = local.declaration; local.closeTracker = new FakedTrackingVariable(local, location, flowInfo, flowContext, FlowInfo.UNKNOWN); if (local.isParameter()) { local.closeTracker.globalClosingState |= OWNED_BY_OUTSIDE; // status of this tracker is now UNKNOWN } return local.closeTracker; } } else if (expression instanceof AllocationExpression) { // return any preliminary tracking variable from analyseCloseableAllocation return ((AllocationExpression) expression).closeTracker; } return null; } /** * Before analyzing an assignment of this shape: singleName = new Allocation() * connect any tracking variable of the LHS with the allocation on the RHS. * Also the assignment is temporarily stored in the tracking variable in case we need to * report errors because the assignment leaves the old LHS value unclosed. * In this case the assignment should be used as the error location. * * @param location the assignment/local declaration being analyzed * @param local the local variable being assigned to * @param rhs the rhs of the assignment resp. the initialization of the local variable declaration. * Precondition: client has already checked that the resolved type of this expression is either a closeable type or NULL. */ public static void preConnectTrackerAcrossAssignment(ASTNode location, LocalVariableBinding local, Expression rhs, FlowInfo flowInfo) { FakedTrackingVariable closeTracker = null; if (rhs instanceof AllocationExpression) { closeTracker = local.closeTracker; if (closeTracker == null) { if (rhs.resolvedType != TypeBinding.NULL) { // not NULL means valid closeable as per method precondition closeTracker = new FakedTrackingVariable(local, location, flowInfo, null, FlowInfo.UNKNOWN); if (local.isParameter()) { closeTracker.globalClosingState |= OWNED_BY_OUTSIDE; } } } if (closeTracker != null) { closeTracker.currentAssignment = location; AllocationExpression allocation = (AllocationExpression)rhs; allocation.closeTracker = closeTracker; if (allocation.arguments != null && allocation.arguments.length > 0) { // also push into nested allocations, see https://bugs.eclipse.org/368709 preConnectTrackerAcrossAssignment(location, local, allocation.arguments[0], flowInfo); } } } } /** * Compute/assign a tracking variable for a freshly allocated closeable value, using information from our white lists. * See Bug 358903 - Filter practically unimportant resource leak warnings */ public static void analyseCloseableAllocation(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) { // client has checked that the resolvedType is an AutoCloseable, hence the following cast is safe: if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitResourceFreeCloseable)) { // remove unnecessary attempts (closeable is not relevant) if (allocation.closeTracker != null) { scope.removeTrackingVar(allocation.closeTracker); allocation.closeTracker = null; } } else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) { boolean isWrapper = true; if (allocation.arguments != null && allocation.arguments.length > 0) { // find the wrapped resource represented by its tracking var: FakedTrackingVariable innerTracker = findCloseTracker(scope, flowInfo, allocation.arguments[0]); if (innerTracker != null) { FakedTrackingVariable currentInner = innerTracker; do { if (currentInner == allocation.closeTracker) return; // self wrap (res = new Res(res)) -> neither change (here) nor remove (below) // also check for indirect cycles, see https://bugs.eclipse.org/368709 currentInner = currentInner.innerTracker; } while (currentInner != null); int newStatus = FlowInfo.NULL; if (allocation.closeTracker == null) { allocation.closeTracker = new FakedTrackingVariable(scope, allocation, flowInfo, FlowInfo.UNKNOWN); // no local available, closeable is unassigned } else { if (scope.finallyInfo != null) { // inject results from analysing a finally block onto the newly connected wrapper int finallyStatus = scope.finallyInfo.nullStatus(allocation.closeTracker.binding); if (finallyStatus != FlowInfo.UNKNOWN) newStatus = finallyStatus; } } allocation.closeTracker.innerTracker = innerTracker; innerTracker.outerTracker = allocation.closeTracker; flowInfo.markNullStatus(allocation.closeTracker.binding, newStatus); if (newStatus != FlowInfo.NULL) { // propagate results from a finally block also into nested resources: FakedTrackingVariable currentTracker = innerTracker; while (currentTracker != null) { flowInfo.markNullStatus(currentTracker.binding, newStatus); currentTracker.globalClosingState |= allocation.closeTracker.globalClosingState; currentTracker = currentTracker.innerTracker; } } return; // keep chaining wrapper (by avoiding to fall through to removeTrackingVar below) } else { if (!isAnyCloseable(allocation.arguments[0].resolvedType)) { isWrapper = false; // argument is not closeable } } } else { isWrapper = false; // no argument } // successful wrapper detection has exited above, let's see why that failed if (isWrapper) { // remove unnecessary attempts (wrapper has no relevant inner) if (allocation.closeTracker != null) { scope.removeTrackingVar(allocation.closeTracker); allocation.closeTracker = null; } } else { // allocation does not provide a resource as the first argument -> don't treat as a wrapper handleRegularResource(scope, flowInfo, allocation); } } else { // regular resource handleRegularResource(scope, flowInfo, allocation); } } private static void handleRegularResource(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) { FakedTrackingVariable presetTracker = allocation.closeTracker; if (presetTracker != null && presetTracker.originalBinding != null) { // the current assignment forgets a previous resource in the LHS, may cause a leak // report now because handleResourceAssignment can't distinguish this from a self-wrap situation int closeStatus = flowInfo.nullStatus(presetTracker.binding); if (closeStatus != FlowInfo.NON_NULL // old resource was not closed && closeStatus != FlowInfo.UNKNOWN // old resource had some flow information && !flowInfo.isDefinitelyNull(presetTracker.originalBinding) // old resource was not null && !(presetTracker.currentAssignment instanceof LocalDeclaration)) // forgetting old val in local decl is syntactically impossible allocation.closeTracker.recordErrorLocation(presetTracker.currentAssignment, closeStatus); } else { allocation.closeTracker = new FakedTrackingVariable(scope, allocation, flowInfo, FlowInfo.UNKNOWN); // no local available, closeable is unassigned } flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding); } /** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */ private static FakedTrackingVariable findCloseTracker(BlockScope scope, FlowInfo flowInfo, Expression arg) { while (arg instanceof Assignment) { Assignment assign = (Assignment)arg; LocalVariableBinding innerLocal = assign.localVariableBinding(); if (innerLocal != null) { // nested assignment has already been processed return innerLocal.closeTracker; } else { arg = assign.expression; // unwrap assignment and fall through } } if (arg instanceof SingleNameReference) { // is allocation arg a reference to an existing closeable? LocalVariableBinding local = arg.localVariableBinding(); if (local != null) { return local.closeTracker; } } else if (arg instanceof AllocationExpression) { // nested allocation return ((AllocationExpression)arg).closeTracker; } return null; // not a tracked expression } /** * Check if the rhs of an assignment or local declaration is an (Auto)Closeable. * If so create or re-use a tracking variable, and wire and initialize everything. * @param scope scope containing the assignment * @param upstreamInfo info without analysis of the rhs, use this to determine the status of a resource being disconnected * @param flowInfo info with analysis of the rhs, use this for recording resource status because this will be passed downstream * @param flowContext * @param location where to report warnigs/errors against * @param rhs the right hand side of the assignment, this expression is to be analyzed. * The caller has already checked that the rhs is either of a closeable type or null. * @param local the local variable into which the rhs is being assigned */ public static void handleResourceAssignment(BlockScope scope, FlowInfo upstreamInfo, FlowInfo flowInfo, FlowContext flowContext, ASTNode location, Expression rhs, LocalVariableBinding local) { // does the LHS (local) already have a tracker, indicating we may leak a resource by the assignment? FakedTrackingVariable previousTracker = null; FakedTrackingVariable disconnectedTracker = null; if (local.closeTracker != null) { // assigning to a variable already holding an AutoCloseable, has it been closed before? previousTracker = local.closeTracker; int nullStatus = upstreamInfo.nullStatus(local); if (nullStatus != FlowInfo.NULL && nullStatus != FlowInfo.UNKNOWN) // only if previous value may be relevant disconnectedTracker = previousTracker; // report error below, unless we have a self-wrap assignment } rhsAnalyis: if (rhs.resolvedType != TypeBinding.NULL) { // new value is AutoCloseable, start tracking, possibly re-using existing tracker var: FakedTrackingVariable rhsTrackVar = getCloseTrackingVariable(rhs, flowInfo, flowContext); if (rhsTrackVar != null) { // 1. if RHS has a tracking variable... if (local.closeTracker == null) { // null shouldn't occur but let's play safe: if (rhsTrackVar.originalBinding != null) local.closeTracker = rhsTrackVar; // a.: let fresh LHS share it if (rhsTrackVar.currentAssignment == location) { // pre-set tracker from lhs - passed from outside? // now it's a fresh resource rhsTrackVar.globalClosingState &= ~(SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE); } } else { if (rhs instanceof AllocationExpression) { if (rhsTrackVar == disconnectedTracker) return; // b.: self wrapper: res = new Wrap(res); -> done! if (local.closeTracker == rhsTrackVar && ((rhsTrackVar.globalClosingState & OWNED_BY_OUTSIDE) != 0)) { // c.: assigning a fresh resource (pre-connected alloc) // to a local previously holding an alien resource -> start over local.closeTracker = new FakedTrackingVariable(local, location, flowInfo, flowContext, FlowInfo.NULL); // still check disconnectedTracker below break rhsAnalyis; } } local.closeTracker = rhsTrackVar; // d.: conflicting LHS and RHS, proceed with recordErrorLocation below } // keep close-status of RHS unchanged across this assignment } else if (previousTracker != null) { // 2. re-use tracking variable from the LHS? FlowContext currentFlowContext = flowContext; checkReuseTracker : { if (previousTracker.tryContext != null) { while (currentFlowContext != null) { if (previousTracker.tryContext == currentFlowContext) { // "previous" location was the finally block of the current try statement. // -> This is not a re-assignment. // see https://bugs.eclipse.org/388996 break checkReuseTracker; } currentFlowContext = currentFlowContext.parent; } } // re-assigning from a fresh value, mark as not-closed again: if ((previousTracker.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0 && flowInfo.hasNullInfoFor(previousTracker.binding)) // avoid spilling info into a branch that doesn't see the corresponding resource flowInfo.markAsDefinitelyNull(previousTracker.binding); local.closeTracker = analyseCloseableExpression(flowInfo, flowContext, local, location, rhs, previousTracker); } } else { // 3. no re-use, create a fresh tracking variable: rhsTrackVar = analyseCloseableExpression(flowInfo, flowContext, local, location, rhs, null); if (rhsTrackVar != null) { local.closeTracker = rhsTrackVar; // a fresh resource, mark as not-closed: if ((rhsTrackVar.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0) flowInfo.markAsDefinitelyNull(rhsTrackVar.binding); // TODO(stephan): this might be useful, but I could not find a test case for it: // if (flowContext.initsOnFinally != null) // flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding); } } } if (disconnectedTracker != null) { if (disconnectedTracker.innerTracker != null && disconnectedTracker.innerTracker.binding.declaringScope == scope) { // discard tracker for the wrapper but keep the inner: disconnectedTracker.innerTracker.outerTracker = null; scope.pruneWrapperTrackingVar(disconnectedTracker); } else { int upstreamStatus = upstreamInfo.nullStatus(disconnectedTracker.binding); if (upstreamStatus != FlowInfo.NON_NULL) disconnectedTracker.recordErrorLocation(location, upstreamStatus); } } } /** * Analyze structure of a closeable expression, matching (chained) resources against our white lists. * @param flowInfo where to record close status * @param local local variable to which the closeable is being assigned * @param location where to flag errors/warnings against * @param expression expression to be analyzed * @param previousTracker when analyzing a re-assignment we may already have a tracking variable for local, * which we should then re-use * @return a tracking variable associated with local or null if no need to track */ private static FakedTrackingVariable analyseCloseableExpression(FlowInfo flowInfo, FlowContext flowContext, LocalVariableBinding local, ASTNode location, Expression expression, FakedTrackingVariable previousTracker) { // unwrap uninteresting nodes: while (true) { if (expression instanceof Assignment) expression = ((Assignment)expression).expression; else if (expression instanceof CastExpression) expression = ((CastExpression) expression).expression; else break; } // analyze by node type: if (expression instanceof AllocationExpression) { // allocation expressions already have their tracking variables analyzed by analyseCloseableAllocation(..) FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker; if (tracker != null && tracker.originalBinding == null) { // tracker without original binding (unassigned closeable) shouldn't reach here but let's play safe return null; } return tracker; } else if (expression instanceof MessageSend || expression instanceof ArrayReference) { // we *might* be responsible for the resource obtained FakedTrackingVariable tracker = new FakedTrackingVariable(local, location, flowInfo, flowContext, FlowInfo.POTENTIALLY_NULL); // shed some doubt tracker.globalClosingState |= SHARED_WITH_OUTSIDE; return tracker; } else if ( (expression.bits & RestrictiveFlagMASK) == Binding.FIELD ||((expression instanceof QualifiedNameReference) && ((QualifiedNameReference) expression).isFieldAccess())) { // responsibility for this resource probably lies at a higher level FakedTrackingVariable tracker = new FakedTrackingVariable(local, location, flowInfo, flowContext, FlowInfo.UNKNOWN); tracker.globalClosingState |= OWNED_BY_OUTSIDE; // leave state as UNKNOWN, the bit OWNED_BY_OUTSIDE will prevent spurious warnings return tracker; } if (expression.resolvedType instanceof ReferenceBinding) { ReferenceBinding resourceType = (ReferenceBinding) expression.resolvedType; if (resourceType.hasTypeBit(TypeIds.BitResourceFreeCloseable)) { // (a) resource-free closeable: -> null return null; } } if (local.closeTracker != null) // (c): inner has already been analyzed: -> re-use track var return local.closeTracker; FakedTrackingVariable newTracker = new FakedTrackingVariable(local, location, flowInfo, flowContext, FlowInfo.UNKNOWN); LocalVariableBinding rhsLocal = expression.localVariableBinding(); if (rhsLocal != null && rhsLocal.isParameter()) { newTracker.globalClosingState |= OWNED_BY_OUTSIDE; } return newTracker; } public static void cleanUpAfterAssignment(BlockScope currentScope, int lhsBits, Expression expression) { // remove all remaining track vars with no original binding // unwrap uninteresting nodes: while (true) { if (expression instanceof Assignment) expression = ((Assignment)expression).expression; else if (expression instanceof CastExpression) expression = ((CastExpression) expression).expression; else break; } if (expression instanceof AllocationExpression) { FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker; if (tracker != null && tracker.originalBinding == null) { currentScope.removeTrackingVar(tracker); ((AllocationExpression) expression).closeTracker = null; } } else { // assignment passing a local into a field? LocalVariableBinding local = expression.localVariableBinding(); if (local != null && local.closeTracker != null && ((lhsBits & Binding.FIELD) != 0)) currentScope.removeTrackingVar(local.closeTracker); // TODO: may want to use local.closeTracker.markPassedToOutside(..,true) } } /** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */ public static boolean isAnyCloseable(TypeBinding typeBinding) { return typeBinding instanceof ReferenceBinding && ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable); } public int findMostSpecificStatus(FlowInfo flowInfo, BlockScope currentScope, BlockScope locationScope) { int status = FlowInfo.UNKNOWN; FakedTrackingVariable currentTracker = this; // loop as to consider wrappers (per white list) encapsulating an inner resource. while (currentTracker != null) { LocalVariableBinding currentVar = currentTracker.binding; int currentStatus = getNullStatusAggressively(currentVar, flowInfo); if (locationScope != null) // only check at method exit points currentStatus = mergeCloseStatus(locationScope, currentStatus, currentVar, currentScope); if (currentStatus == FlowInfo.NON_NULL) { status = currentStatus; break; // closed -> stop searching } else if (status == FlowInfo.NULL || status == FlowInfo.UNKNOWN) { status = currentStatus; // improved although not yet safe -> keep searching for better } currentTracker = currentTracker.innerTracker; } return status; } /** * Get the null status looking even into unreachable flows * @param local * @param flowInfo * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}. */ private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) { if (flowInfo == FlowInfo.DEAD_END) { return FlowInfo.UNKNOWN; } int reachMode = flowInfo.reachMode(); int status = 0; try { // unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability: if (reachMode != FlowInfo.REACHABLE) flowInfo.tagBits &= ~FlowInfo.UNREACHABLE; status = flowInfo.nullStatus(local); if (TEST_372319) { // see https://bugs.eclipse.org/372319 try { Thread.sleep(5); // increase probability of concurrency bug } catch (InterruptedException e) { /* nop */ } } } finally { // reset flowInfo.tagBits |= reachMode; } // at this point some combinations are not useful so flatten to a single bit: if ((status & FlowInfo.NULL) != 0) { if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0) return FlowInfo.POTENTIALLY_NULL; // null + doubt = pot null return FlowInfo.NULL; } else if ((status & FlowInfo.NON_NULL) != 0) { if ((status & FlowInfo.POTENTIALLY_NULL) != 0) return FlowInfo.POTENTIALLY_NULL; // non-null + doubt = pot null return FlowInfo.NON_NULL; } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0) return FlowInfo.POTENTIALLY_NULL; return status; } public int mergeCloseStatus(BlockScope currentScope, int status, LocalVariableBinding local, BlockScope outerScope) { // get the most suitable null status representing whether resource 'binding' has been closed // start at 'currentScope' and potentially travel out until 'outerScope' // at each scope consult any recorded 'finallyInfo'. if (status != FlowInfo.NON_NULL) { if (currentScope.finallyInfo != null) { int finallyStatus = currentScope.finallyInfo.nullStatus(local); if (finallyStatus == FlowInfo.NON_NULL) return finallyStatus; if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL status = FlowInfo.POTENTIALLY_NULL; } if (currentScope != outerScope && currentScope.parent instanceof BlockScope) return mergeCloseStatus(((BlockScope) currentScope.parent), status, local, outerScope); } return status; } /** Mark that this resource is closed locally. */ public void markClose(FlowInfo flowInfo, FlowContext flowContext) { FakedTrackingVariable current = this; do { flowInfo.markAsDefinitelyNonNull(current.binding); current.globalClosingState |= CLOSE_SEEN; flowContext.markFinallyNullStatus(this.binding, FlowInfo.NON_NULL); current = current.innerTracker; } while (current != null); } /** Mark that this resource is closed from a nested method (inside a local class). */ public void markClosedInNestedMethod() { this.globalClosingState |= CLOSED_IN_NESTED_METHOD; } /** * Mark that this resource is passed to some outside code * (as argument to a method/ctor call or as a return value from the current method), * and thus should be considered as potentially closed. * @param owned should the resource be considered owned by some outside? */ public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo, FlowContext flowContext, boolean owned) { FakedTrackingVariable trackVar = getCloseTrackingVariable(expression, flowInfo, flowContext); if (trackVar != null) { // insert info that the tracked resource *may* be closed (by the target method, i.e.) FlowInfo infoResourceIsClosed = owned ? flowInfo : flowInfo.copy(); int flag = owned ? OWNED_BY_OUTSIDE : SHARED_WITH_OUTSIDE; do { trackVar.globalClosingState |= flag; if (scope.methodScope() != trackVar.methodScope) trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD; infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding); } while ((trackVar = trackVar.innerTracker) != null); if (owned) { return infoResourceIsClosed; // don't let downstream signal any problems on this flow } else { return FlowInfo.conditional(flowInfo, infoResourceIsClosed); // only report potential problems on this flow } } return flowInfo; } /** * Pick tracking variables from 'varsOfScope' to establish a proper order of processing: * As much as possible pick wrapper resources before their inner resources. * Also consider cases of wrappers and their inners being declared at different scopes. */ public static FakedTrackingVariable pickVarForReporting(Set varsOfScope, BlockScope scope, boolean atExit) { if (varsOfScope.isEmpty()) return null; FakedTrackingVariable trackingVar = (FakedTrackingVariable) varsOfScope.iterator().next(); while (trackingVar.outerTracker != null) { // resource is wrapped, is wrapper defined in this scope? if (varsOfScope.contains(trackingVar.outerTracker)) { // resource from same scope, travel up the wrapper chain trackingVar = trackingVar.outerTracker; } else if (atExit) { // at an exit point we report against inner despite a wrapper that may/may not be closed later break; } else { BlockScope outerTrackerScope = trackingVar.outerTracker.binding.declaringScope; if (outerTrackerScope == scope) { // outerTracker is from same scope and already processed -> pick trackingVar now break; } else { // outer resource is from other (outer?) scope Scope currentScope = scope; while ((currentScope = currentScope.parent) instanceof BlockScope) { if (outerTrackerScope == currentScope) { // at end of block pass responsibility for inner resource to outer scope holding a wrapper varsOfScope.remove(trackingVar); // drop this one // pick a next candidate: return pickVarForReporting(varsOfScope, scope, atExit); } } break; // not parent owned -> pick this var } } } varsOfScope.remove(trackingVar); return trackingVar; } /** * Answer true if we know for sure that no resource is bound to this variable * at the point of 'flowInfo'. */ public boolean hasDefinitelyNoResource(FlowInfo flowInfo) { if (this.originalBinding == null) return false; // shouldn't happen but keep quiet. if (flowInfo.isDefinitelyNull(this.originalBinding)) { return true; } if (!(flowInfo.isDefinitelyAssigned(this.originalBinding) || flowInfo.isPotentiallyAssigned(this.originalBinding))) { return true; } return false; } public boolean isClosedInFinallyOfEnclosing(BlockScope scope) { BlockScope currentScope = scope; while (true) { if (currentScope.finallyInfo != null && currentScope.finallyInfo.isDefinitelyNonNull(this.binding)) { return true; // closed in enclosing finally } if (!(currentScope.parent instanceof BlockScope)) { return false; } currentScope = (BlockScope) currentScope.parent; } } /** * If current is the same as 'returnedResource' or a wrapper thereof, * mark as reported and return true, otherwise false. */ public boolean isResourceBeingReturned(FakedTrackingVariable returnedResource) { FakedTrackingVariable current = this; do { if (current == returnedResource) { this.globalClosingState |= REPORTED_DEFINITIVE_LEAK; return true; } current = current.innerTracker; } while (current != null); return false; } public void recordErrorLocation(ASTNode location, int nullStatus) { if ((this.globalClosingState & OWNED_BY_OUTSIDE) != 0) { return; } if (this.recordedLocations == null) this.recordedLocations = new HashMap(); this.recordedLocations.put(location, new Integer(nullStatus)); } public boolean reportRecordedErrors(Scope scope, int mergedStatus) { FakedTrackingVariable current = this; while (current.globalClosingState == 0) { current = current.innerTracker; if (current == null) { // no relevant state found -> report: reportError(scope.problemReporter(), null, mergedStatus); return true; } } boolean hasReported = false; if (this.recordedLocations != null) { Iterator locations = this.recordedLocations.entrySet().iterator(); int reportFlags = 0; while (locations.hasNext()) { Map.Entry entry = (Entry) locations.next(); reportFlags |= reportError(scope.problemReporter(), (ASTNode)entry.getKey(), ((Integer)entry.getValue()).intValue()); hasReported = true; } if (reportFlags != 0) { // after all locations have been reported, mark as reported to prevent duplicate report via an outer wrapper current = this; do { current.globalClosingState |= reportFlags; } while ((current = current.innerTracker) != null); } } return hasReported; } public int reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) { if ((this.globalClosingState & OWNED_BY_OUTSIDE) != 0) { return 0; // TODO: should we still propagate some flags?? } // which degree of problem? boolean isPotentialProblem = false; if (nullStatus == FlowInfo.NULL) { if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0) isPotentialProblem = true; } else if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL)) != 0) { isPotentialProblem = true; } // report: if (isPotentialProblem) { if ((this.globalClosingState & (REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK)) != 0) return 0; problemReporter.potentiallyUnclosedCloseable(this, location); } else { if ((this.globalClosingState & (REPORTED_DEFINITIVE_LEAK)) != 0) return 0; problemReporter.unclosedCloseable(this, location); } // propagate flag to inners: int reportFlag = isPotentialProblem ? REPORTED_POTENTIAL_LEAK : REPORTED_DEFINITIVE_LEAK; if (location == null) { // if location != null flags will be set after the loop over locations FakedTrackingVariable current = this; do { current.globalClosingState |= reportFlag; } while ((current = current.innerTracker) != null); } return reportFlag; } public void reportExplicitClosing(ProblemReporter problemReporter) { if ((this.globalClosingState & (OWNED_BY_OUTSIDE|REPORTED_EXPLICIT_CLOSE)) == 0) { // can't use t-w-r for OWNED_BY_OUTSIDE this.globalClosingState |= REPORTED_EXPLICIT_CLOSE; problemReporter.explicitlyClosedAutoCloseable(this); } } public void resetReportingBits() { FakedTrackingVariable current = this; do { current.globalClosingState &= ~(REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK); current = current.innerTracker; } while (current != null); } public String nameForReporting(ASTNode location, ReferenceContext referenceContext) { if (this.name == UNASSIGNED_CLOSEABLE_NAME) { if (location != null && referenceContext != null) { CompilationResult compResult = referenceContext.compilationResult(); if (compResult != null) { int[] lineEnds = compResult.getLineSeparatorPositions(); int resourceLine = Util.getLineNumber(this.sourceStart, lineEnds , 0, lineEnds.length-1); int reportLine = Util.getLineNumber(location.sourceStart, lineEnds , 0, lineEnds.length-1); if (resourceLine != reportLine) { char[] replacement = Integer.toString(resourceLine).toCharArray(); return String.valueOf(CharOperation.replace(UNASSIGNED_CLOSEABLE_NAME_TEMPLATE, TEMPLATE_ARGUMENT, replacement)); } } } } return String.valueOf(this.name); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Statement.java0000644000175000001440000003011312212041344027656 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 335093 - [compiler][null] minimal hook for future null annotation support * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 365983 - [compiler][null] AIOOB with null annotation analysis and varargs * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370930 - NonNull annotation not considered for enhanced for loops * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; 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 { /** * Answers true if the if is identified as a known coding pattern which * should be tolerated by dead code analysis. * e.g. if (DEBUG) print(); // no complaint * Only invoked when overall condition is known to be optimizeable into false/true. */ protected static boolean isKnowDeadCodePattern(Expression expression) { // if (!DEBUG) print(); - tolerated if (expression instanceof UnaryExpression) { expression = ((UnaryExpression) expression).expression; } // if (DEBUG) print(); - tolerated if (expression instanceof Reference) return true; // if (expression instanceof BinaryExpression) { // BinaryExpression binary = (BinaryExpression) expression; // switch ((binary.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT/* operator */) { // case OperatorIds.AND_AND : // case OperatorIds.OR_OR : // break; // default: // // if (DEBUG_LEVEL > 0) print(); - tolerated // if ((binary.left instanceof Reference) && binary.right.constant != Constant.NotAConstant) // return true; // // if (0 < DEBUG_LEVEL) print(); - tolerated // if ((binary.right instanceof Reference) && binary.left.constant != Constant.NotAConstant) // return true; // } // } return false; } public abstract FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo); public static final int NOT_COMPLAINED = 0; public static final int COMPLAINED_FAKE_REACHABLE = 1; public static final int COMPLAINED_UNREACHABLE = 2; /** Analysing arguments of MessageSend, ExplicitConstructorCall, AllocationExpression. */ protected void analyseArguments(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, MethodBinding methodBinding, Expression[] arguments) { // compare actual null-status against parameter annotations of the called method: if (arguments != null && methodBinding.parameterNonNullness != null) { // check if varargs need special treatment: int numParamsToCheck = methodBinding.parameters.length; boolean passThrough = false; if (methodBinding.isVarargs()) { int varArgPos = numParamsToCheck-1; // this if-block essentially copied from generateArguments(..): if (numParamsToCheck == arguments.length) { TypeBinding varArgsType = methodBinding.parameters[varArgPos]; TypeBinding lastType = arguments[varArgPos].resolvedType; if (lastType == TypeBinding.NULL || (varArgsType.dimensions() == lastType.dimensions() && lastType.isCompatibleWith(varArgsType))) passThrough = true; // pass directly as-is } if (!passThrough) numParamsToCheck--; // with non-passthrough varargs last param is fed from individual args -> don't check } for (int i = 0; i < numParamsToCheck; i++) { if (methodBinding.parameterNonNullness[i] == Boolean.TRUE) { TypeBinding expectedType = methodBinding.parameters[i]; Expression argument = arguments[i]; int nullStatus = argument.nullStatus(flowInfo, flowContext); // slight loss of precision: should also use the null info from the receiver. if (nullStatus != FlowInfo.NON_NULL) // if required non-null is not provided flowContext.recordNullityMismatch(currentScope, argument, argument.resolvedType, expectedType, nullStatus); } } } } /** Check null-ness of 'var' against a possible null annotation */ protected int checkAssignmentAgainstNullAnnotation(BlockScope currentScope, FlowContext flowContext, VariableBinding var, int nullStatus, Expression expression, TypeBinding providedType) { if ((var.tagBits & TagBits.AnnotationNonNull) != 0 && nullStatus != FlowInfo.NON_NULL) { flowContext.recordNullityMismatch(currentScope, expression, providedType, var.type, nullStatus); return FlowInfo.NON_NULL; } else if ((var.tagBits & TagBits.AnnotationNullable) != 0 && nullStatus == FlowInfo.UNKNOWN) { // provided a legacy type? return FlowInfo.POTENTIALLY_NULL; // -> use more specific info from the annotation } return nullStatus; } /** * INTERNAL USE ONLY. * This is used to redirect inter-statements jumps. */ public void branchChainTo(BranchLabel label) { // do nothing by default } // Report an error if necessary (if even more unreachable than previously reported // complaintLevel = 0 if was reachable up until now, 1 if fake reachable (deadcode), 2 if fatal unreachable (error) public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previousComplaintLevel, boolean endOfBlock) { if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) { if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE_OR_DEAD) != 0) this.bits &= ~ASTNode.IsReachable; if (flowInfo == FlowInfo.DEAD_END) { if (previousComplaintLevel < COMPLAINED_UNREACHABLE) { scope.problemReporter().unreachableCode(this); if (endOfBlock) scope.checkUnclosedCloseables(flowInfo, null, null, null); } return COMPLAINED_UNREACHABLE; } else { if (previousComplaintLevel < COMPLAINED_FAKE_REACHABLE) { scope.problemReporter().fakeReachable(this); if (endOfBlock) scope.checkUnclosedCloseables(flowInfo, null, null, null); } return COMPLAINED_FAKE_REACHABLE; } } return previousComplaintLevel; } /** * 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 ArrayBinding codeGenVarArgsType = (ArrayBinding) binding.parameters[varArgIndex].erasure(); int elementsTypeID = varArgsType.elementsType().id; int argLength = arguments == null ? 0 : arguments.length; if (argLength > paramLength) { // 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(codeGenVarArgsType); // create a mono-dimensional array for (int i = varArgIndex; i < argLength; i++) { codeStream.dup(); codeStream.generateInlinedValue(i - varArgIndex); arguments[i].generateCode(currentScope, codeStream, true); codeStream.arrayAtPut(elementsTypeID, false); } } else if (argLength == paramLength) { // right number of arguments - could be inexact - pass argument as is TypeBinding lastType = arguments[varArgIndex].resolvedType; if (lastType == TypeBinding.NULL || (varArgsType.dimensions() == lastType.dimensions() && lastType.isCompatibleWith(varArgsType))) { // foo(1, new int[]{2, 3}) or foo(1, null) --> last arg is passed as-is arguments[varArgIndex].generateCode(currentScope, codeStream, true); } else { // right number but not directly compatible or too many arguments - wrap extra into array // need to gen elements into an array, then gen each remaining element into created array codeStream.generateInlinedValue(1); codeStream.newArray(codeGenVarArgsType); // create a mono-dimensional array codeStream.dup(); codeStream.generateInlinedValue(0); arguments[varArgIndex].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(codeGenVarArgsType); // 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); protected boolean isBoxingCompatible(TypeBinding expressionType, TypeBinding targetType, Expression expression, Scope scope) { if (scope.isBoxingCompatibleWith(expressionType, targetType)) return true; return expressionType.isBaseType() // narrowing then boxing ? Only allowed for some target types see 362279 && !targetType.isBaseType() && !targetType.isTypeVariable() && scope.compilerOptions().sourceLevel >= org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_5 // autoboxing && (targetType.id == TypeIds.T_JavaLangByte || targetType.id == TypeIds.T_JavaLangShort || targetType.id == TypeIds.T_JavaLangCharacter) && expression.isConstantValueOfTypeAssignableToType(expressionType, scope.environment().computeBoxingType(targetType)); } public boolean isEmptyBlock() { return false; } public boolean isValidJavaStatement() { //the use of this method should be avoid in most cases //and is here mostly for documentation purpose..... //while the parser is responsible for creating //welled formed expression statement, which results //in the fact that java-non-semantic-expression-used-as-statement //should not be parsed...thus not being built. //It sounds like the java grammar as help the compiler job in removing //-by construction- some statement that would have no effect.... //(for example all expression that may do side-effects are valid statement // -this is an approximative idea.....-) return true; } public StringBuffer print(int indent, StringBuffer output) { return printStatement(indent, output); } public abstract StringBuffer printStatement(int indent, StringBuffer output); 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 Constant.NotAConstant; } /** * Implementation of {@link org.eclipse.jdt.internal.compiler.lookup.InvocationSite#expectedType} * suitable at this level. Subclasses should override as necessary. * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#expectedType() */ public TypeBinding expectedType() { return null; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java0000644000175000001440000000432612212041344030150 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 383368 - [compiler][null] syntactic null analysis for field references *******************************************************************************/ 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.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class NullLiteral extends MagicLiteral { static final char[] source = {'n' , 'u' , 'l' , 'l'}; public NullLiteral(int s , int e) { super(s,e); } public void computeConstant() { this.constant = Constant.NotAConstant; } /** * Code generation for the null 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.aconst_null(); codeStream.generateImplicitConversion(this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.NULL; } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { return FlowInfo.NULL; } public Object reusableJSRTarget() { return TypeBinding.NULL; } public char[] source() { return source; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ImportReference.java0000644000175000001440000000476212212041344031016 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.lookup.*; public class ImportReference extends ASTNode { public char[][] tokens; public long[] sourcePositions; //each entry is using the code : (start<<32) + end public int declarationEnd; // doesn't include an potential trailing comment public int declarationSourceStart; public int declarationSourceEnd; public int modifiers; // 1.5 addition for static imports public Annotation[] annotations; // star end position public int trailingStarPosition; public ImportReference( char[][] tokens, long[] sourcePositions, boolean onDemand, int modifiers) { this.tokens = tokens; this.sourcePositions = sourcePositions; if (onDemand) { this.bits |= ASTNode.OnDemand; } this.sourceEnd = (int) (sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFF); this.sourceStart = (int) (sourcePositions[0] >>> 32); this.modifiers = modifiers; } public boolean isStatic() { return (this.modifiers & ClassFileConstants.AccStatic) != 0; } /** * @return char[][] */ public char[][] getImportName() { return this.tokens; } public StringBuffer print(int indent, StringBuffer output) { return print(indent, output, true); } public StringBuffer print(int tab, StringBuffer output, boolean withOnDemand) { /* when withOnDemand is false, only the name is printed */ for (int i = 0; i < this.tokens.length; i++) { if (i > 0) output.append('.'); output.append(this.tokens[i]); } if (withOnDemand && ((this.bits & ASTNode.OnDemand) != 0)) { output.append(".*"); //$NON-NLS-1$ } return output; } public void traverse(ASTVisitor visitor, CompilationUnitScope scope) { // annotations are traversed during the compilation unit traversal using a class scope visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java0000644000175000001440000000634412212041344031625 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class SingleTypeReference extends TypeReference { public char[] token; public SingleTypeReference(char[] source, long pos) { this.token = source; this.sourceStart = (int) (pos>>>32) ; this.sourceEnd = (int) (pos & 0x00000000FFFFFFFFL) ; } 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(this.token, dim,(((long)this.sourceStart)<<32)+this.sourceEnd); } public char[] getLastToken() { return this.token; } protected TypeBinding getTypeBinding(Scope scope) { if (this.resolvedType != null) return this.resolvedType; this.resolvedType = scope.getType(this.token); if (scope.kind == Scope.CLASS_SCOPE && this.resolvedType.isValidBinding()) if (((ClassScope) scope).detectHierarchyCycle(this.resolvedType, this)) return null; return this.resolvedType; } public char [][] getTypeName() { return new char[][] { this.token }; } public StringBuffer printExpression(int indent, StringBuffer output){ return output.append(this.token); } public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) { TypeBinding memberType = this.resolvedType = scope.getMemberType(this.token, enclosingType); boolean hasError = false; if (!memberType.isValidBinding()) { hasError = true; scope.problemReporter().invalidEnclosingType(this, memberType, enclosingType); memberType = ((ReferenceBinding)memberType).closestMatch(); if (memberType == null) { return null; } } if (isTypeUseDeprecated(memberType, scope)) reportDeprecatedType(memberType, scope); memberType = scope.environment().convertToRawType(memberType, false /*do not force conversion of enclosing types*/); if (memberType.isRawType() && (this.bits & IgnoreRawTypeCheck) == 0 && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore){ scope.problemReporter().rawTypeReference(this, memberType); } if (hasError) { // do not store the computed type, keep the problem type instead return memberType; } return this.resolvedType = memberType; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java0000644000175000001440000000732212212041344030447 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.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() { Double computedValue; boolean containsUnderscores = CharOperation.indexOf('_', this.source) > 0; if (containsUnderscores) { // remove all underscores from source this.source = CharOperation.remove(this.source, '_'); } try { computedValue = Double.valueOf(String.valueOf(this.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(this.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; } this.value = v; this.constant = DoubleConstant.fromValue(v); } catch (NumberFormatException e1) { // if the computation of the constant fails } return; } final double doubleValue = computedValue.doubleValue(); if (doubleValue > 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 < this.source.length; i++) { //it is welled formated so just test against '0' and potential . D d switch (this.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; } } } this.value = doubleValue; this.constant = DoubleConstant.fromValue(this.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(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.DOUBLE; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000015412251602427011643 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReferen0000644000175000001440000001012212212041344032334 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class JavadocQualifiedTypeReference extends QualifiedTypeReference { public int tagSourceStart, tagSourceEnd; public PackageBinding packageBinding; public JavadocQualifiedTypeReference(char[][] sources, long[] pos, int tagStart, int tagEnd) { super(sources, pos); this.tagSourceStart = tagStart; this.tagSourceEnd = tagEnd; this.bits |= ASTNode.InsideJavadoc; } /* * We need to modify resolving behavior to handle package references */ private TypeBinding internalResolveType(Scope scope, boolean checkBounds) { // handle the error here this.constant = Constant.NotAConstant; if (this.resolvedType != null) // is a shared type reference which was already resolved return this.resolvedType.isValidBinding() ? this.resolvedType : this.resolvedType.closestMatch(); // already reported error TypeBinding type = this.resolvedType = getTypeBinding(scope); // End resolution when getTypeBinding(scope) returns null. This may happen in // certain circumstances, typically when an illegal access is done on a type // variable (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=204749) if (type == null) return null; if (!type.isValidBinding()) { Binding binding = scope.getTypeOrPackage(this.tokens); if (binding instanceof PackageBinding) { this.packageBinding = (PackageBinding) binding; // Valid package references are allowed in Javadoc (https://bugs.eclipse.org/bugs/show_bug.cgi?id=281609) } else { reportInvalidType(scope); } return null; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=209936 // raw convert all enclosing types when dealing with Javadoc references if (type.isGenericType() || type.isParameterizedType()) { this.resolvedType = scope.environment().convertToRawType(type, true /*force the conversion of enclosing types*/); } return this.resolvedType; } protected void reportDeprecatedType(TypeBinding type, Scope scope) { scope.problemReporter().javadocDeprecatedType(type, this, scope.getDeclarationModifiers()); } protected void reportDeprecatedType(TypeBinding type, Scope scope, int index) { scope.problemReporter().javadocDeprecatedType(type, this, scope.getDeclarationModifiers(), index); } protected void reportInvalidType(Scope scope) { scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers()); } public TypeBinding resolveType(BlockScope blockScope, boolean checkBounds) { return internalResolveType(blockScope, checkBounds); } public TypeBinding resolveType(ClassScope classScope) { return internalResolveType(classScope, false); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Wildcard.java0000644000175000001440000001040012212041344027440 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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, null /*no extra bound*/, 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; } // only invoked for improving resilience when unable to bind generic type from parameterized reference public TypeBinding resolveType(BlockScope scope, boolean checkBounds) { if (this.bound != null) { this.bound.resolveType(scope, checkBounds); } return null; } // only invoked for improving resilience when unable to bind generic type from parameterized reference public TypeBinding resolveType(ClassScope scope) { if (this.bound != null) { this.bound.resolveType(scope); } return null; } 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); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java0000644000175000001440000001143612212041344032032 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 383368 - [compiler][null] syntactic null analysis for field references *******************************************************************************/ 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.*; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class InstanceOfExpression extends OperatorExpression { public Expression expression; public TypeReference type; public InstanceOfExpression(Expression expression, TypeReference type) { this.expression = expression; this.type = type; type.bits |= IgnoreRawTypeCheck; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=282141 this.bits |= INSTANCEOF << OperatorSHIFT; this.sourceStart = expression.sourceStart; this.sourceEnd = type.sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { LocalVariableBinding local = this.expression.localVariableBinding(); if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo). unconditionalInits(); FlowInfo initsWhenTrue = flowInfo.copy(); initsWhenTrue.markAsComparedEqualToNonNull(local); flowContext.recordUsingNullReference(currentScope, local, this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo); // no impact upon enclosing try context return FlowInfo.conditional(initsWhenTrue, flowInfo.copy()); } if (this.expression instanceof Reference && currentScope.compilerOptions().enableSyntacticNullAnalysisForFields) { FieldBinding field = ((Reference)this.expression).lastFieldBinding(); if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) { flowContext.recordNullCheckedFieldReference((Reference) this.expression, 1); } } return this.expression.analyseCode(currentScope, flowContext, flowInfo). unconditionalInits(); } /** * Code generation for instanceOfExpression * * @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; this.expression.generateCode(currentScope, codeStream, true); codeStream.instance_of(this.type.resolvedType); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { codeStream.pop(); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { this.expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$ return this.type.print(0, output); } public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; TypeBinding expressionType = this.expression.resolveType(scope); TypeBinding checkedType = this.type.resolveType(scope, true /* check bounds*/); if (expressionType == null || checkedType == null) return null; if (!checkedType.isReifiable()) { scope.problemReporter().illegalInstanceOfGenericType(checkedType, this); } else if (checkedType.isValidBinding()) { // if not a valid binding, an error has already been reported for unresolved type if ((expressionType != TypeBinding.NULL && expressionType.isBaseType()) // disallow autoboxing || !checkCastTypesCompatibility(scope, checkedType, expressionType, null)) { scope.problemReporter().notCompatibleTypesError(this, expressionType, checkedType); } } return this.resolvedType = TypeBinding.BOOLEAN; } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding) */ public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) { // null is not instanceof Type, recognize direct scenario if (this.expression.resolvedType != TypeBinding.NULL) scope.problemReporter().unnecessaryInstanceof(this, castType); } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.expression.traverse(visitor, scope); this.type.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java0000644000175000001440000001610212212041344032260 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class SynchronizedStatement extends SubRoutineStatement { public Expression expression; public Block block; public BlockScope scope; public LocalVariableBinding synchroVariable; static final char[] SecretLocalDeclarationName = " syncValue".toCharArray(); //$NON-NLS-1$ // for local variables table attributes int preSynchronizedInitStateIndex = -1; int mergedSynchronizedInitStateIndex = -1; public SynchronizedStatement( Expression expression, Block statement, int s, int e) { this.expression = expression; this.block = statement; this.sourceEnd = e; this.sourceStart = s; } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.preSynchronizedInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); // TODO (philippe) shouldn't it be protected by a check whether reachable statement ? // mark the synthetic variable as being used this.synchroVariable.useFlag = LocalVariableBinding.USED; // simple propagation to subnodes flowInfo = this.block.analyseCode( this.scope, new InsideSubRoutineFlowContext(flowContext, this), this.expression.analyseCode(this.scope, flowContext, flowInfo)); this.mergedSynchronizedInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); // optimizing code gen if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) { this.bits |= ASTNode.BlockExit; } return flowInfo; } public boolean isSubRoutineEscaping() { return false; } /** * Synchronized 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 ((this.bits & IsReachable) == 0) { return; } // in case the labels needs to be reinitialized // when the code generation is restarted in wide mode this.anyExceptionLabel = null; int pc = codeStream.position; // generate the synchronization expression this.expression.generateCode(this.scope, codeStream, true); if (this.block.isEmptyBlock()) { switch(this.synchroVariable.type.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2(); break; default : codeStream.dup(); break; } // only take the lock codeStream.monitorenter(); codeStream.monitorexit(); if (this.scope != currentScope) { codeStream.exitUserScope(this.scope); } } else { // enter the monitor codeStream.store(this.synchroVariable, true); codeStream.addVariable(this.synchroVariable); codeStream.monitorenter(); // generate the body of the synchronized block enterAnyExceptionHandler(codeStream); this.block.generateCode(this.scope, codeStream); if (this.scope != currentScope) { // close all locals defined in the synchronized block except the secret local codeStream.exitUserScope(this.scope, this.synchroVariable); } BranchLabel endLabel = new BranchLabel(codeStream); if ((this.bits & ASTNode.BlockExit) == 0) { codeStream.load(this.synchroVariable); codeStream.monitorexit(); exitAnyExceptionHandler(); codeStream.goto_(endLabel); enterAnyExceptionHandler(codeStream); } // generate the body of the exception handler codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable()); if (this.preSynchronizedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSynchronizedInitStateIndex); } placeAllAnyExceptionHandler(); codeStream.load(this.synchroVariable); codeStream.monitorexit(); exitAnyExceptionHandler(); codeStream.athrow(); // May loose some local variable initializations : affecting the local variable attributes if (this.mergedSynchronizedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedSynchronizedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedSynchronizedInitStateIndex); } if (this.scope != currentScope) { codeStream.removeVariable(this.synchroVariable); } if ((this.bits & ASTNode.BlockExit) == 0) { endLabel.place(); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding) */ public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) { codeStream.load(this.synchroVariable); codeStream.monitorexit(); exitAnyExceptionHandler(); return false; } public void resolve(BlockScope upperScope) { // special scope for secret locals optimization. this.scope = new BlockScope(upperScope); TypeBinding type = this.expression.resolveType(this.scope); if (type == null) return; switch (type.id) { case T_boolean : case T_char : case T_float : case T_double : case T_byte : case T_short : case T_int : case T_long : this.scope.problemReporter().invalidTypeToSynchronize(this.expression, type); break; case T_void : this.scope.problemReporter().illegalVoidExpression(this.expression); break; case T_null : this.scope.problemReporter().invalidNullToSynchronize(this.expression); break; } //continue even on errors in order to have the TC done into the statements this.synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, ClassFileConstants.AccDefault, false); this.scope.addLocalVariable(this.synchroVariable); this.synchroVariable.setConstant(Constant.NotAConstant); // not inlinable this.expression.computeConversion(this.scope, type, type); this.block.resolveUsing(this.scope); } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output); output.append("synchronized ("); //$NON-NLS-1$ this.expression.printExpression(0, output).append(')'); output.append('\n'); return this.block.printStatement(indent + 1, output); } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.expression.traverse(visitor, this.scope); this.block.traverse(visitor, this.scope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java0000644000175000001440000000740612212041344030713 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" *******************************************************************************/ 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.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public class ThrowStatement extends Statement { public Expression exception; public TypeBinding exceptionType; public ThrowStatement(Expression exception, int sourceStart, int sourceEnd) { this.exception = exception; this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.exception.analyseCode(currentScope, flowContext, flowInfo); this.exception.checkNPE(currentScope, flowContext, flowInfo); // need to check that exception thrown is actually caught somewhere flowContext.checkExceptionHandlers(this.exceptionType, this, flowInfo, currentScope); currentScope.checkUnclosedCloseables(flowInfo, flowContext, this, currentScope); flowContext.recordAbruptExit(); return FlowInfo.DEAD_END; } /** * Throw 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 ((this.bits & ASTNode.IsReachable) == 0) return; int pc = codeStream.position; this.exception.generateCode(currentScope, codeStream, true); codeStream.athrow(); codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output).append("throw "); //$NON-NLS-1$ this.exception.printExpression(0, output); return output.append(';'); } public void resolve(BlockScope scope) { this.exceptionType = this.exception.resolveType(scope); if (this.exceptionType != null && this.exceptionType.isValidBinding()) { if (this.exceptionType == TypeBinding.NULL) { if (scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3){ // if compliant with 1.4, this problem will not be reported scope.problemReporter().cannotThrowNull(this.exception); } } else if (this.exceptionType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null) { scope.problemReporter().cannotThrowType(this.exception, this.exceptionType); } this.exception.computeConversion(scope, this.exceptionType, this.exceptionType); } } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) this.exception.traverse(visitor, blockScope); visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java0000644000175000001440000002771312212041344031065 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; //dedicated treatment for the || public class OR_OR_Expression extends BinaryExpression { int rightInitStateIndex = -1; int mergedInitStateIndex = -1; public OR_OR_Expression(Expression left, Expression right, int operator) { super(left, right, operator); } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { Constant cst = this.left.optimizedBooleanConstant(); boolean isLeftOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isLeftOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; if (isLeftOptimizedFalse) { // FALSE || anything // need to be careful of scenario: // (x || y) || !z, if passing the left info to the right, it would be swapped by the ! FlowInfo mergedInfo = this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); flowContext.expireNullCheckedFieldInfo(); mergedInfo = this.right.analyseCode(currentScope, flowContext, mergedInfo); flowContext.expireNullCheckedFieldInfo(); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } FlowInfo leftInfo = this.left.analyseCode(currentScope, flowContext, flowInfo); if ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) == 0) flowContext.expireNullCheckedFieldInfo(); // need to be careful of scenario: // (x || y) || !z, if passing the left info to the right, it would be swapped by the ! FlowInfo rightInfo = leftInfo.initsWhenFalse().unconditionalCopy(); this.rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo); int previousMode = rightInfo.reachMode(); if (isLeftOptimizedTrue){ if ((rightInfo.reachMode() & FlowInfo.UNREACHABLE) == 0) { currentScope.problemReporter().fakeReachable(this.right); rightInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } } rightInfo = this.right.analyseCode(currentScope, flowContext, rightInfo); if ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) == 0) flowContext.expireNullCheckedFieldInfo(); this.left.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); this.right.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); // The definitely null variables in right info when true should not be missed out while merging // https://bugs.eclipse.org/bugs/show_bug.cgi?id=299900 FlowInfo leftInfoWhenTrueForMerging = leftInfo.initsWhenTrue().unconditionalCopy().addPotentialInitializationsFrom(rightInfo.unconditionalInitsWithoutSideEffect()); FlowInfo mergedInfo = FlowInfo.conditional( // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b; // b may not have been initialized leftInfoWhenTrueForMerging.unconditionalInits().mergedWith( rightInfo.safeInitsWhenTrue().setReachMode(previousMode).unconditionalInits()), rightInfo.initsWhenFalse()); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } /** * Code generation for a binary operation */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { // inlined value if (valueRequired) codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); return; } Constant cst = this.right.constant; if (cst != Constant.NotAConstant) { // || true --> true if (cst.booleanValue() == true) { this.left.generateCode(currentScope, codeStream, false); if (valueRequired) codeStream.iconst_1(); } else { // || false --> this.left.generateCode(currentScope, codeStream, valueRequired); } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.recordPositionsFrom(pc, this.sourceStart); return; } BranchLabel trueLabel = new BranchLabel(codeStream), endLabel; cst = this.left.optimizedBooleanConstant(); boolean leftIsConst = cst != Constant.NotAConstant; boolean leftIsTrue = leftIsConst && cst.booleanValue() == true; cst = this.right.optimizedBooleanConstant(); boolean rightIsConst = cst != Constant.NotAConstant; boolean rightIsTrue = rightIsConst && cst.booleanValue() == true; generateOperands : { if (leftIsConst) { this.left.generateCode(currentScope, codeStream, false); if (leftIsTrue) { break generateOperands; // no need to generate right operand } } else { this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true); // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1 } if (this.rightInitStateIndex != -1) { codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } if (rightIsConst) { this.right.generateCode(currentScope, codeStream, false); } else { this.right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired); } } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } /* * improving code gen for such a case: boolean b = i < 0 || true since * the label has never been used, we have the inlined value on the * stack. */ if (valueRequired) { if (leftIsConst && leftIsTrue) { codeStream.iconst_1(); codeStream.recordPositionsFrom(codeStream.position, this.left.sourceEnd); } else { if (rightIsConst && rightIsTrue) { codeStream.iconst_1(); codeStream.recordPositionsFrom(codeStream.position, this.left.sourceEnd); } else { codeStream.iconst_0(); } if (trueLabel.forwardReferenceCount() > 0) { if ((this.bits & IsReturnedValue) != 0) { codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateReturnBytecode(this); trueLabel.place(); codeStream.iconst_1(); } else { codeStream.goto_(endLabel = new BranchLabel(codeStream)); codeStream.decrStackSize(1); trueLabel.place(); codeStream.iconst_1(); endLabel.place(); } } else { trueLabel.place(); } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } else { trueLabel.place(); } } /** * Boolean operator code generation Optimized operations are: || */ public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { if (this.constant != Constant.NotAConstant) { super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } // || false --> Constant cst = this.right.constant; if (cst != Constant.NotAConstant && cst.booleanValue() == false) { int pc = codeStream.position; this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } cst = this.left.optimizedBooleanConstant(); boolean leftIsConst = cst != Constant.NotAConstant; boolean leftIsTrue = leftIsConst && cst.booleanValue() == true; cst = this.right.optimizedBooleanConstant(); boolean rightIsConst = cst != Constant.NotAConstant; boolean rightIsTrue = rightIsConst && cst.booleanValue() == true; // default case generateOperands : { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, !leftIsConst); // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1 if (leftIsTrue) { if (valueRequired) codeStream.goto_(trueLabel); codeStream.recordPositionsFrom(codeStream.position, this.left.sourceEnd); break generateOperands; // no need to generate right operand } if (this.rightInitStateIndex != -1) { codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } this.right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired && !rightIsConst); if (valueRequired && rightIsTrue) { codeStream.goto_(trueLabel); codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } } } else { // implicit falling through the TRUE case if (trueLabel == null) { BranchLabel internalTrueLabel = new BranchLabel(codeStream); this.left.generateOptimizedBoolean(currentScope, codeStream, internalTrueLabel, null, !leftIsConst); // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1 if (leftIsTrue) { internalTrueLabel.place(); break generateOperands; // no need to generate right operand } if (this.rightInitStateIndex != -1) { codeStream .addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } this.right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired && !rightIsConst); int pc = codeStream.position; if (valueRequired && rightIsConst && !rightIsTrue) { codeStream.goto_(falseLabel); codeStream.recordPositionsFrom(pc, this.sourceEnd); } internalTrueLabel.place(); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } } public boolean isCompactableOperation() { return false; } /** * @see org.eclipse.jdt.internal.compiler.ast.BinaryExpression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public TypeBinding resolveType(BlockScope scope) { TypeBinding result = super.resolveType(scope); // check whether comparing identical expressions Binding leftDirect = Expression.getDirectBinding(this.left); if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) { if (!(this.right instanceof Assignment)) scope.problemReporter().comparingIdenticalExpressions(this); } return result; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.left.traverse(visitor, scope); this.right.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Argument.java0000644000175000001440000001656412212041344027512 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; 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); this.declarationSourceEnd = (int) posNom; this.modifiers = modifiers; this.type = tr; this.bits |= (IsLocalDeclarationReachable | IsArgument); } public void createBinding(MethodScope scope, TypeBinding typeBinding) { if (this.binding == null) { // for default constructors and fake implementation of abstract methods this.binding = new LocalVariableBinding(this, typeBinding, this.modifiers, true /*isArgument*/); } else if (!this.binding.type.isValidBinding()) { AbstractMethodDeclaration methodDecl = scope.referenceMethod(); if (methodDecl != null) { MethodBinding methodBinding = methodDecl.binding; if (methodBinding != null) { methodBinding.tagBits |= TagBits.HasUnresolvedArguments; } } } resolveAnnotations(scope, this.annotations, this.binding); this.binding.declaration = this; } public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) { createBinding(scope, typeBinding); // basically a no-op if createBinding() was called before // record the resolved type into the type reference Binding existingVariable = scope.getBinding(this.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); } else { boolean isSpecialArgument = false; if (existingVariable instanceof FieldBinding) { if (scope.isInsideConstructor()) { isSpecialArgument = true; // constructor argument } else { AbstractMethodDeclaration methodDecl = scope.referenceMethod(); if (methodDecl != null && CharOperation.prefixEquals(SET, methodDecl.selector)) { isSpecialArgument = true; // setter argument } } } scope.problemReporter().localVariableHiding(this, existingVariable, isSpecialArgument); } } scope.addLocalVariable(this.binding); this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED; } /** * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind() */ public int getKind() { return (this.bits & ASTNode.IsArgument) != 0 ? PARAMETER : LOCAL_VARIABLE; } public boolean isVarArgs() { return this.type != null && (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 (this.type == null) { output.append(" "); //$NON-NLS-1$ } else { this.type.print(0, output).append(' '); } return output.append(this.name); } public StringBuffer printStatement(int indent, StringBuffer output) { return print(indent, output).append(';'); } public TypeBinding resolveForCatch(BlockScope scope) { // resolution on an argument of a catch clause // provide the scope with a side effect : insertion of a LOCAL // that represents the argument. The type must be from JavaThrowable TypeBinding exceptionType = this.type.resolveType(scope, true /* check bounds*/); boolean hasError; if (exceptionType == null) { hasError = true; } else { hasError = false; switch(exceptionType.kind()) { case Binding.PARAMETERIZED_TYPE : if (exceptionType.isBoundParameterizedType()) { hasError = true; scope.problemReporter().invalidParameterizedExceptionType(exceptionType, this); // fall thru to create the variable - avoids additional errors because the variable is missing } break; case Binding.TYPE_PARAMETER : scope.problemReporter().invalidTypeVariableAsException(exceptionType, this); hasError = true; // fall thru to create the variable - avoids additional errors because the variable is missing break; } if (exceptionType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null && exceptionType.isValidBinding()) { scope.problemReporter().cannotThrowType(this.type, exceptionType); hasError = true; // fall thru to create the variable - avoids additional errors because the variable is missing } } Binding existingVariable = scope.getBinding(this.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); } else { scope.problemReporter().localVariableHiding(this, existingVariable, false); } } if ((this.type.bits & ASTNode.IsUnionType) != 0) { this.binding = new CatchParameterBinding(this, exceptionType, this.modifiers | ClassFileConstants.AccFinal, false); // argument decl, but local var (where isArgument = false) this.binding.tagBits |= TagBits.MultiCatchParameter; } else { this.binding = new CatchParameterBinding(this, exceptionType, this.modifiers, false); // argument decl, but local var (where isArgument = false) } resolveAnnotations(scope, this.annotations, this.binding); scope.addLocalVariable(this.binding); this.binding.setConstant(Constant.NotAConstant); if (hasError) return null; return exceptionType; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (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); } if (this.type != null) this.type.traverse(visitor, scope); } visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { if (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); } if (this.type != null) this.type.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/DoStatement.java0000644000175000001440000002161412212041344030147 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class DoStatement extends Statement { public Expression condition; public Statement action; private BranchLabel breakLabel, continueLabel; // for local variables table attributes int mergedInitStateIndex = -1; int preConditionInitStateIndex = -1; public DoStatement(Expression condition, Statement action, int sourceStart, int sourceEnd) { this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; this.condition = condition; this.action = action; // remember useful empty statement if (action instanceof EmptyStatement) action.bits |= ASTNode.IsUsefulEmptyStatement; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.breakLabel = new BranchLabel(); this.continueLabel = new BranchLabel(); LoopingFlowContext loopingContext = new LoopingFlowContext( flowContext, flowInfo, this, this.breakLabel, this.continueLabel, currentScope, false); Constant cst = this.condition.constant; boolean isConditionTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; cst = this.condition.optimizedBooleanConstant(); boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; int previousMode = flowInfo.reachMode(); FlowInfo initsOnCondition = flowInfo; UnconditionalFlowInfo actionInfo = flowInfo.nullInfoLessUnconditionalCopy(); // we need to collect the contribution to nulls of the coming paths through the // loop, be they falling through normally or branched to break, continue labels // or catch blocks if ((this.action != null) && !this.action.isEmptyBlock()) { actionInfo = this.action. analyseCode(currentScope, loopingContext, actionInfo). unconditionalInits(); // code generation can be optimized when no need to continue in the loop if ((actionInfo.tagBits & loopingContext.initsOnContinue.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) { this.continueLabel = null; } if ((this.condition.implicitConversion & TypeIds.UNBOXING) != 0) { initsOnCondition = flowInfo.unconditionalInits(). addInitializationsFrom( actionInfo.mergedWith(loopingContext.initsOnContinue)); } } this.condition.checkNPEbyUnboxing(currentScope, flowContext, initsOnCondition); /* Reset reach mode, to address following scenario. * final blank; * do { if (true) break; else blank = 0; } while(false); * blank = 1; // may be initialized already */ actionInfo.setReachMode(previousMode); LoopingFlowContext condLoopContext; FlowInfo condInfo = this.condition.analyseCode( currentScope, (condLoopContext = new LoopingFlowContext(flowContext, flowInfo, this, null, null, currentScope, true)), (this.action == null ? actionInfo : (actionInfo.mergedWith(loopingContext.initsOnContinue))).copy()); /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=367023, we reach the condition at the bottom via two arcs, one by free fall and another by continuing... Merge initializations propagated through the two pathways, cf, while and for loops. */ this.preConditionInitStateIndex = currentScope.methodScope().recordInitializationStates(actionInfo.mergedWith(loopingContext.initsOnContinue)); if (!isConditionOptimizedFalse && this.continueLabel != null) { loopingContext.complainOnDeferredFinalChecks(currentScope, condInfo); condLoopContext.complainOnDeferredFinalChecks(currentScope, condInfo); loopingContext.complainOnDeferredNullChecks(currentScope, flowInfo.unconditionalCopy().addPotentialNullInfoFrom( condInfo.initsWhenTrue().unconditionalInits())); condLoopContext.complainOnDeferredNullChecks(currentScope, actionInfo.addPotentialNullInfoFrom( condInfo.initsWhenTrue().unconditionalInits())); } if (loopingContext.hasEscapingExceptions()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321926 FlowInfo loopbackFlowInfo = flowInfo.copy(); loopbackFlowInfo.mergedWith(condInfo.initsWhenTrue().unconditionalCopy()); loopingContext.simulateThrowAfterLoopBack(loopbackFlowInfo); } // end of loop FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( (loopingContext.initsOnBreak.tagBits & FlowInfo.UNREACHABLE) != 0 ? loopingContext.initsOnBreak : flowInfo.unconditionalCopy().addInitializationsFrom(loopingContext.initsOnBreak), // recover upstream null info isConditionOptimizedTrue, (condInfo.tagBits & FlowInfo.UNREACHABLE) == 0 ? flowInfo.copy().addInitializationsFrom(condInfo.initsWhenFalse()) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=380927 : condInfo, // 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(); */); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } /** * Do statement code generation * */ public void generateCode(BlockScope currentScope, CodeStream codeStream) { if ((this.bits & ASTNode.IsReachable) == 0) { return; } int pc = codeStream.position; // labels management BranchLabel actionLabel = new BranchLabel(codeStream); if (this.action != null) actionLabel.tagBits |= BranchLabel.USED; actionLabel.place(); this.breakLabel.initialize(codeStream); boolean hasContinueLabel = this.continueLabel != null; if (hasContinueLabel) { this.continueLabel.initialize(codeStream); } // generate action if (this.action != null) { this.action.generateCode(currentScope, codeStream); } // continue label (135602) if (hasContinueLabel) { this.continueLabel.place(); // May loose some local variable initializations : affecting the local variable attributes if (this.preConditionInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preConditionInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.preConditionInitStateIndex); } // generate condition Constant cst = this.condition.optimizedBooleanConstant(); boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; if (isConditionOptimizedFalse){ this.condition.generateCode(currentScope, codeStream, false); } else { this.condition.generateOptimizedBoolean( currentScope, codeStream, actionLabel, null, true); } } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } if (this.breakLabel.forwardReferenceCount() > 0) { this.breakLabel.place(); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output).append("do"); //$NON-NLS-1$ if (this.action == null) output.append(" ;\n"); //$NON-NLS-1$ else { output.append('\n'); this.action.printStatement(indent + 1, output).append('\n'); } output.append("while ("); //$NON-NLS-1$ return this.condition.printExpression(0, output).append(");"); //$NON-NLS-1$ } public void resolve(BlockScope scope) { TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); this.condition.computeConversion(scope, type, type); if (this.action != null) this.action.resolve(scope); } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { if (this.action != null) { this.action.traverse(visitor, scope); } this.condition.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/TryStatement.java0000644000175000001440000015224212212041344030365 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 332637 - Dead Code detection removing code that isn't dead * bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis * bug 349326 - [1.7] new warning for missing try-with-resources * bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points * bug 358903 - Filter practically unimportant resource leak warnings * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 401088 - [compiler][null] Wrong warning "Redundant null check" inside nested try statement * bug 401092 - [compiler][null] Wrong warning "Redundant null check" in outer catch of nested try * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check * bug 384380 - False positive on a ?? Potential null pointer access ?? after a continue * Jesper Steen Moller - Contributions for * bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.*; import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class TryStatement extends SubRoutineStatement { static final char[] SECRET_RETURN_ADDRESS_NAME = " returnAddress".toCharArray(); //$NON-NLS-1$ static final char[] SECRET_ANY_HANDLER_NAME = " anyExceptionHandler".toCharArray(); //$NON-NLS-1$ static final char[] SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME = " primaryException".toCharArray(); //$NON-NLS-1$ static final char[] SECRET_CAUGHT_THROWABLE_VARIABLE_NAME = " caughtThrowable".toCharArray(); //$NON-NLS-1$; static final char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); //$NON-NLS-1$ private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0]; public LocalDeclaration[] resources = NO_RESOURCES; public Block tryBlock; public Block[] catchBlocks; public Argument[] catchArguments; public Block finallyBlock; BlockScope scope; public UnconditionalFlowInfo subRoutineInits; ReferenceBinding[] caughtExceptionTypes; boolean[] catchExits; BranchLabel subRoutineStartLabel; public LocalVariableBinding anyExceptionVariable, returnAddressVariable, secretReturnValue; ExceptionLabel[] declaredExceptionLabels; // only set while generating code // for inlining/optimizing JSR instructions private Object[] reusableJSRTargets; private BranchLabel[] reusableJSRSequenceStartLabels; private int[] reusableJSRStateIndexes; private int reusableJSRTargetsCount = 0; private static final int NO_FINALLY = 0; // no finally block private static final int FINALLY_SUBROUTINE = 1; // finally is generated as a subroutine (using jsr/ret bytecodes) private static final int FINALLY_DOES_NOT_COMPLETE = 2; // non returning finally is optimized with only one instance of finally block private static final int FINALLY_INLINE = 3; // finally block must be inlined since cannot use jsr/ret bytecodes >1.5 // for local variables table attributes int mergedInitStateIndex = -1; int preTryInitStateIndex = -1; int postTryInitStateIndex = -1; int[] postResourcesInitStateIndexes; int naturalExitMergeInitStateIndex = -1; int[] catchExitInitStateIndexes; private LocalVariableBinding primaryExceptionVariable; private LocalVariableBinding caughtThrowableVariable; private ExceptionLabel[] resourceExceptionLabels; private int[] caughtExceptionsCatchBlocks; public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // Consider the try block and catch block so as to compute the intersection of initializations and // the minimum exit relative depth amongst all of them. Then consider the subroutine, and append its // initialization to the try/catch ones, if the subroutine completes normally. If the subroutine does not // complete, then only keep this result for the rest of the analysis // process the finally block (subroutine) - create a context for the subroutine this.preTryInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); if (this.anyExceptionVariable != null) { this.anyExceptionVariable.useFlag = LocalVariableBinding.USED; } if (this.primaryExceptionVariable != null) { this.primaryExceptionVariable.useFlag = LocalVariableBinding.USED; } if (this.caughtThrowableVariable != null) { this.caughtThrowableVariable.useFlag = LocalVariableBinding.USED; } if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused this.returnAddressVariable.useFlag = LocalVariableBinding.USED; } int resourcesLength = this.resources.length; if (resourcesLength > 0) { this.postResourcesInitStateIndexes = new int[resourcesLength]; } if (this.subRoutineStartLabel == null) { // no finally block -- this is a simplified copy of the else part if (flowContext instanceof FinallyFlowContext) { // if this TryStatement sits inside another TryStatement, establish the wiring so that // FlowContext.markFinallyNullStatus can report into initsOnFinally of the outer try context: FinallyFlowContext finallyContext = (FinallyFlowContext) flowContext; finallyContext.outerTryContext = finallyContext.tryContext; } // process the try block in a context handling the local exceptions. ExceptionHandlingFlowContext handlingContext = new ExceptionHandlingFlowContext( flowContext, this, this.caughtExceptionTypes, this.caughtExceptionsCatchBlocks, null, this.scope, flowInfo); handlingContext.conditionalLevel = 0; // start collection initsOnFinally // only try blocks initialize that member - may consider creating a // separate class if needed FlowInfo tryInfo = flowInfo.copy(); for (int i = 0; i < resourcesLength; i++) { final LocalDeclaration resource = this.resources[i]; tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo); LocalVariableBinding resourceBinding = resource.binding; resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. if (resourceBinding.closeTracker != null) { // this was false alarm, we don't need to track the resource this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker); // keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block } MethodBinding closeMethod = findCloseMethod(resource, resourceBinding); if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) { ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions; for (int j = 0, length = thrownExceptions.length; j < length; j++) { handlingContext.checkExceptionHandlers(thrownExceptions[j], this.resources[i], tryInfo, currentScope, true); } } } if (!this.tryBlock.isEmptyBlock()) { tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, tryInfo); if ((tryInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) this.bits |= ASTNode.IsTryBlockExiting; } if (resourcesLength > 0) { this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); // the resources are not in scope after the try block, so remove their assignment info // to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since // it is used to add or remove assigned resources during code gen for (int i = 0; i < resourcesLength; i++) { tryInfo.resetAssignmentInfo(this.resources[i].binding); } } // check unreachable catch blocks handlingContext.complainIfUnusedExceptionHandlers(this.scope, this); // process the catch blocks - computing the minimal exit depth amongst try/catch if (this.catchArguments != null) { int catchCount; this.catchExits = new boolean[catchCount = this.catchBlocks.length]; this.catchExitInitStateIndexes = new int[catchCount]; for (int i = 0; i < catchCount; i++) { // keep track of the inits that could potentially have led to this exception handler (for final assignments diagnosis) FlowInfo catchInfo = prepareCatchInfo(flowInfo, handlingContext, tryInfo, i); flowContext.conditionalLevel++; catchInfo = this.catchBlocks[i].analyseCode( currentScope, flowContext, catchInfo); flowContext.conditionalLevel--; this.catchExitInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(catchInfo); this.catchExits[i] = (catchInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0; tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits()); } } this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); // chain up null info registry flowContext.mergeFinallyNullInfo(handlingContext.initsOnFinally); return tryInfo; } else { InsideSubRoutineFlowContext insideSubContext; FinallyFlowContext finallyContext; UnconditionalFlowInfo subInfo; // analyse finally block first insideSubContext = new InsideSubRoutineFlowContext(flowContext, this); if (flowContext instanceof FinallyFlowContext) { // if this TryStatement sits inside another TryStatement, establish the wiring so that // FlowContext.markFinallyNullStatus can report into initsOnFinally of the outer try context: insideSubContext.outerTryContext = ((FinallyFlowContext)flowContext).tryContext; } // process the try block in a context handling the local exceptions. // (advance instantiation so we can wire this into the FinallyFlowContext) ExceptionHandlingFlowContext handlingContext = new ExceptionHandlingFlowContext( insideSubContext, this, this.caughtExceptionTypes, this.caughtExceptionsCatchBlocks, null, this.scope, flowInfo); insideSubContext.initsOnFinally = handlingContext.initsOnFinally; subInfo = this.finallyBlock .analyseCode( currentScope, finallyContext = new FinallyFlowContext(flowContext, this.finallyBlock, handlingContext), flowInfo.nullInfoLessUnconditionalCopy()) .unconditionalInits(); handlingContext.conditionalLevel = 0; // start collection initsOnFinally only after analysing the finally block if (subInfo == FlowInfo.DEAD_END) { this.bits |= ASTNode.IsSubRoutineEscaping; this.scope.problemReporter().finallyMustCompleteNormally(this.finallyBlock); } else { // for resource analysis we need the finallyInfo in these nested scopes: FlowInfo finallyInfo = subInfo.copy(); this.tryBlock.scope.finallyInfo = finallyInfo; if (this.catchBlocks != null) { for (int i = 0; i < this.catchBlocks.length; i++) this.catchBlocks[i].scope.finallyInfo = finallyInfo; } } this.subRoutineInits = subInfo; // only try blocks initialize that member - may consider creating a // separate class if needed FlowInfo tryInfo = flowInfo.copy(); for (int i = 0; i < resourcesLength; i++) { final LocalDeclaration resource = this.resources[i]; tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo); LocalVariableBinding resourceBinding = resource.binding; resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. if (resourceBinding.closeTracker != null) { // this was false alarm, we don't need to track the resource this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker); // keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block } MethodBinding closeMethod = findCloseMethod(resource, resourceBinding); if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) { ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions; for (int j = 0, length = thrownExceptions.length; j < length; j++) { handlingContext.checkExceptionHandlers(thrownExceptions[j], this.resources[i], tryInfo, currentScope, true); } } } if (!this.tryBlock.isEmptyBlock()) { tryInfo = this.tryBlock.analyseCode(currentScope, handlingContext, tryInfo); if ((tryInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) this.bits |= ASTNode.IsTryBlockExiting; } if (resourcesLength > 0) { this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); // the resources are not in scope after the try block, so remove their assignment info // to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since // it is used to add or remove assigned resources during code gen for (int i = 0; i < resourcesLength; i++) { tryInfo.resetAssignmentInfo(this.resources[i].binding); } } // check unreachable catch blocks handlingContext.complainIfUnusedExceptionHandlers(this.scope, this); // process the catch blocks - computing the minimal exit depth amongst try/catch if (this.catchArguments != null) { int catchCount; this.catchExits = new boolean[catchCount = this.catchBlocks.length]; this.catchExitInitStateIndexes = new int[catchCount]; for (int i = 0; i < catchCount; i++) { // keep track of the inits that could potentially have led to this exception handler (for final assignments diagnosis) FlowInfo catchInfo = prepareCatchInfo(flowInfo, handlingContext, tryInfo, i); insideSubContext.conditionalLevel = 1; catchInfo = this.catchBlocks[i].analyseCode( currentScope, insideSubContext, catchInfo); this.catchExitInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(catchInfo); this.catchExits[i] = (catchInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0; tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits()); } } // 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.complainOnDeferredChecks( ((tryInfo.tagBits & FlowInfo.UNREACHABLE) == 0 ? flowInfo.unconditionalCopy(). addPotentialInitializationsFrom(tryInfo). // lighten the influence of the try block, which may have // exited at any point addPotentialInitializationsFrom(insideSubContext.initsOnReturn) : insideSubContext.initsOnReturn). addNullInfoFrom( handlingContext.initsOnFinally), currentScope); // chain up null info registry flowContext.mergeFinallyNullInfo(handlingContext.initsOnFinally); this.naturalExitMergeInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); if (subInfo == FlowInfo.DEAD_END) { this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(subInfo); return subInfo; } else { FlowInfo mergedInfo = tryInfo.addInitializationsFrom(subInfo); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } } } private MethodBinding findCloseMethod(final LocalDeclaration resource, LocalVariableBinding resourceBinding) { MethodBinding closeMethod = null; TypeBinding type = resourceBinding.type; if (type != null && type.isValidBinding()) { ReferenceBinding binding = (ReferenceBinding) type; closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter if(closeMethod == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 // closeMethod could be null if the binding is from an interface // extending from multiple interfaces. InvocationSite site = new InvocationSite.EmptyWithAstNode(resource); closeMethod = this.scope.compilationUnitScope().findMethod(binding, ConstantPool.Close, new TypeBinding[0], site, false); } } return closeMethod; } private FlowInfo prepareCatchInfo(FlowInfo flowInfo, ExceptionHandlingFlowContext handlingContext, FlowInfo tryInfo, int i) { FlowInfo catchInfo; if (isUncheckedCatchBlock(i)) { catchInfo = flowInfo.unconditionalCopy(). addPotentialInitializationsFrom( handlingContext.initsOnException(i)). addPotentialInitializationsFrom(tryInfo). addPotentialInitializationsFrom( handlingContext.initsOnReturn). addNullInfoFrom(handlingContext.initsOnFinally); } else { FlowInfo initsOnException = handlingContext.initsOnException(i); if ((handlingContext.tagBits & (FlowContext.DEFER_NULL_DIAGNOSTIC | FlowContext.PREEMPT_NULL_DIAGNOSTIC)) == FlowContext.DEFER_NULL_DIAGNOSTIC) { // if null diagnostics are being deferred, initsOnException are incomplete, // need to start with the more accurate upstream flowInfo catchInfo = flowInfo.unconditionalCopy() .addPotentialInitializationsFrom(initsOnException) .addPotentialInitializationsFrom( tryInfo.unconditionalCopy()) .addPotentialInitializationsFrom( handlingContext.initsOnReturn.nullInfoLessUnconditionalCopy()); } else { // here initsOnException are precise, so use them as the only source for null information into the catch block: catchInfo = flowInfo.nullInfoLessUnconditionalCopy() .addPotentialInitializationsFrom(initsOnException) .addNullInfoFrom(initsOnException) .addPotentialInitializationsFrom( tryInfo.nullInfoLessUnconditionalCopy()) .addPotentialInitializationsFrom( handlingContext.initsOnReturn.nullInfoLessUnconditionalCopy()); } } // catch var is always set LocalVariableBinding catchArg = this.catchArguments[i].binding; 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. try { x = 1; throwSomething();} catch(Exception e){ x = 2} " "(uncheckedExceptionTypes notNil and: [uncheckedExceptionTypes at: index]) ifTrue: [catchInits addPotentialInitializationsFrom: tryInits]." */ if (this.tryBlock.statements == null && this.resources == NO_RESOURCES) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350579 catchInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } return catchInfo; } // Return true if the catch block corresponds to an unchecked exception making allowance for multi-catch blocks. private boolean isUncheckedCatchBlock(int catchBlock) { if (this.caughtExceptionsCatchBlocks == null) { return this.caughtExceptionTypes[catchBlock].isUncheckedException(true); } for (int i = 0, length = this.caughtExceptionsCatchBlocks.length; i < length; i++) { if (this.caughtExceptionsCatchBlocks[i] == catchBlock) { if (this.caughtExceptionTypes[i].isUncheckedException(true)) { return true; } } } return false; } public ExceptionLabel enterAnyExceptionHandler(CodeStream codeStream) { if (this.subRoutineStartLabel == null) return null; return super.enterAnyExceptionHandler(codeStream); } public void enterDeclaredExceptionHandlers(CodeStream codeStream) { for (int i = 0, length = this.declaredExceptionLabels == null ? 0 : this.declaredExceptionLabels.length; i < length; i++) { this.declaredExceptionLabels[i].placeStart(); } } public void exitAnyExceptionHandler() { if (this.subRoutineStartLabel == null) return; super.exitAnyExceptionHandler(); } public void exitDeclaredExceptionHandlers(CodeStream codeStream) { for (int i = 0, length = this.declaredExceptionLabels == null ? 0 : this.declaredExceptionLabels.length; i < length; i++) { this.declaredExceptionLabels[i].placeEnd(); } } private int finallyMode() { if (this.subRoutineStartLabel == null) { return NO_FINALLY; } else if (isSubRoutineEscaping()) { return FINALLY_DOES_NOT_COMPLETE; } else if (this.scope.compilerOptions().inlineJsrBytecode) { return FINALLY_INLINE; } else { return FINALLY_SUBROUTINE; } } /** * Try statement code generation with or without jsr bytecode use * post 1.5 target level, cannot use jsr bytecode, must instead inline finally block * returnAddress is only allocated if jsr is allowed */ public void generateCode(BlockScope currentScope, CodeStream codeStream) { if ((this.bits & ASTNode.IsReachable) == 0) { return; } boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; // in case the labels needs to be reinitialized // when the code generation is restarted in wide mode this.anyExceptionLabel = null; this.reusableJSRTargets = null; this.reusableJSRSequenceStartLabels = null; this.reusableJSRTargetsCount = 0; int pc = codeStream.position; int finallyMode = finallyMode(); boolean requiresNaturalExit = false; // preparing exception labels int maxCatches = this.catchArguments == null ? 0 : this.catchArguments.length; ExceptionLabel[] exceptionLabels; if (maxCatches > 0) { exceptionLabels = new ExceptionLabel[maxCatches]; for (int i = 0; i < maxCatches; i++) { Argument argument = this.catchArguments[i]; ExceptionLabel exceptionLabel = null; if ((argument.binding.tagBits & TagBits.MultiCatchParameter) != 0) { MultiCatchExceptionLabel multiCatchExceptionLabel = new MultiCatchExceptionLabel(codeStream, argument.binding.type); multiCatchExceptionLabel.initialize((UnionTypeReference) argument.type); exceptionLabel = multiCatchExceptionLabel; } else { exceptionLabel = new ExceptionLabel(codeStream, argument.binding.type); } exceptionLabel.placeStart(); exceptionLabels[i] = exceptionLabel; } } else { exceptionLabels = null; } if (this.subRoutineStartLabel != null) { this.subRoutineStartLabel.initialize(codeStream); enterAnyExceptionHandler(codeStream); } // generate the try block try { this.declaredExceptionLabels = exceptionLabels; int resourceCount = this.resources.length; if (resourceCount > 0) { // Please see https://bugs.eclipse.org/bugs/show_bug.cgi?id=338402#c16 this.resourceExceptionLabels = new ExceptionLabel[resourceCount + 1]; codeStream.aconst_null(); codeStream.store(this.primaryExceptionVariable, false /* value not required */); codeStream.addVariable(this.primaryExceptionVariable); codeStream.aconst_null(); codeStream.store(this.caughtThrowableVariable, false /* value not required */); codeStream.addVariable(this.caughtThrowableVariable); for (int i = 0; i <= resourceCount; i++) { // put null for the exception type to treat them as any exception handlers (equivalent to a try/finally) this.resourceExceptionLabels[i] = new ExceptionLabel(codeStream, null); this.resourceExceptionLabels[i].placeStart(); if (i < resourceCount) { this.resources[i].generateCode(this.scope, codeStream); // Initialize resources ... } } } this.tryBlock.generateCode(this.scope, codeStream); if (resourceCount > 0) { for (int i = resourceCount; i >= 0; i--) { BranchLabel exitLabel = new BranchLabel(codeStream); this.resourceExceptionLabels[i].placeEnd(); // outer handler if any is the one that should catch exceptions out of close() LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null; if ((this.bits & ASTNode.IsTryBlockExiting) == 0) { // inline resource closure if (i > 0) { int invokeCloseStartPc = codeStream.position; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343785 if (this.postTryInitStateIndex != -1) { /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=361053, we are just past a synthetic instance of try-catch-finally. Our initialization type state is the same as it was at the end of the just concluded try (catch rethrows) */ codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); } codeStream.load(localVariable); codeStream.ifnull(exitLabel); codeStream.load(localVariable); codeStream.invokeAutoCloseableClose(localVariable.type); codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); } codeStream.goto_(exitLabel); // skip over the catch block. } if (i > 0) { // i is off by one codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postResourcesInitStateIndexes[i - 1]); codeStream.addDefinitelyAssignedVariables(currentScope, this.postResourcesInitStateIndexes[i - 1]); } else { // For the first resource, its preset state is the preTryInitStateIndex codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); } codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable()); this.resourceExceptionLabels[i].place(); if (i == resourceCount) { // inner most try's catch/finally can be a lot simpler. codeStream.store(this.primaryExceptionVariable, false); // fall through, invoke close() and re-throw. } else { BranchLabel elseLabel = new BranchLabel(codeStream), postElseLabel = new BranchLabel(codeStream); codeStream.store(this.caughtThrowableVariable, false); codeStream.load(this.primaryExceptionVariable); codeStream.ifnonnull(elseLabel); codeStream.load(this.caughtThrowableVariable); codeStream.store(this.primaryExceptionVariable, false); codeStream.goto_(postElseLabel); elseLabel.place(); codeStream.load(this.primaryExceptionVariable); codeStream.load(this.caughtThrowableVariable); codeStream.if_acmpeq(postElseLabel); codeStream.load(this.primaryExceptionVariable); codeStream.load(this.caughtThrowableVariable); codeStream.invokeThrowableAddSuppressed(); postElseLabel.place(); } if (i > 0) { // inline resource close here rather than bracketing the current catch block with a try region. BranchLabel postCloseLabel = new BranchLabel(codeStream); int invokeCloseStartPc = codeStream.position; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343785 codeStream.load(localVariable); codeStream.ifnull(postCloseLabel); codeStream.load(localVariable); codeStream.invokeAutoCloseableClose(localVariable.type); codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); codeStream.removeVariable(localVariable); postCloseLabel.place(); } codeStream.load(this.primaryExceptionVariable); codeStream.athrow(); exitLabel.place(); } codeStream.removeVariable(this.primaryExceptionVariable); codeStream.removeVariable(this.caughtThrowableVariable); } } finally { this.declaredExceptionLabels = null; this.resourceExceptionLabels = null; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=375248 } boolean tryBlockHasSomeCode = codeStream.position != pc; // flag telling if some bytecodes were issued inside the try block // place end positions of user-defined exception labels if (tryBlockHasSomeCode) { // natural exit may require subroutine invocation (if finally != null) BranchLabel naturalExitLabel = new BranchLabel(codeStream); BranchLabel postCatchesFinallyLabel = null; for (int i = 0; i < maxCatches; i++) { exceptionLabels[i].placeEnd(); } if ((this.bits & ASTNode.IsTryBlockExiting) == 0) { int position = codeStream.position; switch(finallyMode) { case FINALLY_SUBROUTINE : case FINALLY_INLINE : requiresNaturalExit = true; if (this.naturalExitMergeInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); } codeStream.goto_(naturalExitLabel); break; case NO_FINALLY : if (this.naturalExitMergeInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); } codeStream.goto_(naturalExitLabel); break; case FINALLY_DOES_NOT_COMPLETE : codeStream.goto_(this.subRoutineStartLabel); break; } codeStream.recordPositionsFrom(position, this.tryBlock.sourceEnd); //goto is tagged as part of the try block } /* generate sequence of handler, all starting by storing the TOS (exception thrown) into their own catch variables, the one specified in the source that must denote the handled exception. */ exitAnyExceptionHandler(); if (this.catchArguments != null) { postCatchesFinallyLabel = new BranchLabel(codeStream); for (int i = 0; i < maxCatches; i++) { /* * This should not happen. For consistency purpose, if the exception label is never used * we also don't generate the corresponding catch block, otherwise we have some * unreachable bytecodes */ if (exceptionLabels[i].getCount() == 0) continue; enterAnyExceptionHandler(codeStream); // May loose some local variable initializations : affecting the local variable attributes if (this.preTryInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); } codeStream.pushExceptionOnStack(exceptionLabels[i].exceptionType); exceptionLabels[i].place(); // optimizing the case where the exception variable is not actually used LocalVariableBinding catchVar; int varPC = codeStream.position; if ((catchVar = this.catchArguments[i].binding).resolvedPosition != -1) { codeStream.store(catchVar, false); catchVar.recordInitializationStartPC(codeStream.position); codeStream.addVisibleLocalVariable(catchVar); } else { codeStream.pop(); } codeStream.recordPositionsFrom(varPC, this.catchArguments[i].sourceStart); // Keep track of the pcs at diverging point for computing the local attribute // since not passing the catchScope, the block generation will exitUserScope(catchScope) this.catchBlocks[i].generateCode(this.scope, codeStream); exitAnyExceptionHandler(); if (!this.catchExits[i]) { switch(finallyMode) { case FINALLY_INLINE : // inlined finally here can see all merged variables if (isStackMapFrameCodeStream) { ((StackMapFrameCodeStream) codeStream).pushStateIndex(this.naturalExitMergeInitStateIndex); } if (this.catchExitInitStateIndexes[i] != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.catchExitInitStateIndexes[i]); codeStream.addDefinitelyAssignedVariables(currentScope, this.catchExitInitStateIndexes[i]); } // entire sequence for finally is associated to finally block this.finallyBlock.generateCode(this.scope, codeStream); codeStream.goto_(postCatchesFinallyLabel); if (isStackMapFrameCodeStream) { ((StackMapFrameCodeStream) codeStream).popStateIndex(); } break; case FINALLY_SUBROUTINE : requiresNaturalExit = true; //$FALL-THROUGH$ case NO_FINALLY : if (this.naturalExitMergeInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); } codeStream.goto_(naturalExitLabel); break; case FINALLY_DOES_NOT_COMPLETE : codeStream.goto_(this.subRoutineStartLabel); break; } } } } // extra handler for trailing natural exit (will be fixed up later on when natural exit is generated below) ExceptionLabel naturalExitExceptionHandler = requiresNaturalExit && (finallyMode == FINALLY_SUBROUTINE) ? 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 (this.subRoutineStartLabel != null && this.anyExceptionLabel.getCount() != 0) { codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable()); if (this.preTryInitStateIndex != -1) { // reset initialization state, as for a normal catch block codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); } placeAllAnyExceptionHandler(); if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place(); switch(finallyMode) { case FINALLY_SUBROUTINE : // any exception handler codeStream.store(this.anyExceptionVariable, false); codeStream.jsr(this.subRoutineStartLabel); codeStream.recordPositionsFrom(finallySequenceStartPC, this.finallyBlock.sourceStart); int position = codeStream.position; codeStream.throwAnyException(this.anyExceptionVariable); codeStream.recordPositionsFrom(position, this.finallyBlock.sourceEnd); // subroutine this.subRoutineStartLabel.place(); codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable()); position = codeStream.position; codeStream.store(this.returnAddressVariable, false); codeStream.recordPositionsFrom(position, this.finallyBlock.sourceStart); this.finallyBlock.generateCode(this.scope, codeStream); position = codeStream.position; codeStream.ret(this.returnAddressVariable.resolvedPosition); codeStream.recordPositionsFrom( position, this.finallyBlock.sourceEnd); // the ret bytecode is part of the subroutine break; case FINALLY_INLINE : // any exception handler codeStream.store(this.anyExceptionVariable, false); codeStream.addVariable(this.anyExceptionVariable); codeStream.recordPositionsFrom(finallySequenceStartPC, this.finallyBlock.sourceStart); // subroutine this.finallyBlock.generateCode(currentScope, codeStream); position = codeStream.position; codeStream.throwAnyException(this.anyExceptionVariable); codeStream.removeVariable(this.anyExceptionVariable); if (this.preTryInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preTryInitStateIndex); } this.subRoutineStartLabel.place(); codeStream.recordPositionsFrom(position, this.finallyBlock.sourceEnd); break; case FINALLY_DOES_NOT_COMPLETE : // any exception handler codeStream.pop(); this.subRoutineStartLabel.place(); codeStream.recordPositionsFrom(finallySequenceStartPC, this.finallyBlock.sourceStart); // subroutine this.finallyBlock.generateCode(this.scope, codeStream); break; } // will naturally fall into subsequent code after subroutine invocation if (requiresNaturalExit) { switch(finallyMode) { case FINALLY_SUBROUTINE : naturalExitLabel.place(); int position = codeStream.position; naturalExitExceptionHandler.placeStart(); codeStream.jsr(this.subRoutineStartLabel); naturalExitExceptionHandler.placeEnd(); codeStream.recordPositionsFrom( position, this.finallyBlock.sourceEnd); break; case FINALLY_INLINE : // inlined finally here can see all merged variables if (isStackMapFrameCodeStream) { ((StackMapFrameCodeStream) codeStream).pushStateIndex(this.naturalExitMergeInitStateIndex); } if (this.naturalExitMergeInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.naturalExitMergeInitStateIndex); } naturalExitLabel.place(); // entire sequence for finally is associated to finally block this.finallyBlock.generateCode(this.scope, codeStream); if (postCatchesFinallyLabel != null) { position = codeStream.position; // entire sequence for finally is associated to finally block codeStream.goto_(postCatchesFinallyLabel); codeStream.recordPositionsFrom( position, this.finallyBlock.sourceEnd); } if (isStackMapFrameCodeStream) { ((StackMapFrameCodeStream) codeStream).popStateIndex(); } break; case FINALLY_DOES_NOT_COMPLETE : break; default : naturalExitLabel.place(); break; } } if (postCatchesFinallyLabel != null) { postCatchesFinallyLabel.place(); } } else { // no subroutine, simply position end label (natural exit == end) naturalExitLabel.place(); } } else { // try block had no effect, only generate the body of the finally block if any if (this.subRoutineStartLabel != null) { this.finallyBlock.generateCode(this.scope, codeStream); } } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding) */ public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) { int resourceCount = this.resources.length; if (resourceCount > 0 && this.resourceExceptionLabels != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=375248 for (int i = resourceCount; i > 0; --i) { // Disarm the handlers and take care of resource closure. this.resourceExceptionLabels[i].placeEnd(); LocalVariableBinding localVariable = this.resources[i-1].binding; BranchLabel exitLabel = new BranchLabel(codeStream); int invokeCloseStartPc = codeStream.position; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343785 codeStream.load(localVariable); codeStream.ifnull(exitLabel); codeStream.load(localVariable); codeStream.invokeAutoCloseableClose(localVariable.type); codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); exitLabel.place(); } // Reinstall handlers for (int i = resourceCount; i > 0; --i) { this.resourceExceptionLabels[i].placeStart(); } } boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream; int finallyMode = finallyMode(); switch(finallyMode) { case FINALLY_DOES_NOT_COMPLETE : codeStream.goto_(this.subRoutineStartLabel); return true; case NO_FINALLY : exitDeclaredExceptionHandlers(codeStream); return false; } // optimize subroutine invocation sequences, using the targetLocation (if any) CompilerOptions options = this.scope.compilerOptions(); if (options.shareCommonFinallyBlocks && targetLocation != null) { boolean reuseTargetLocation = true; if (this.reusableJSRTargetsCount > 0) { nextReusableTarget: for (int i = 0, count = this.reusableJSRTargetsCount; i < count; i++) { Object reusableJSRTarget = this.reusableJSRTargets[i]; differentTarget: { if (targetLocation == reusableJSRTarget) break differentTarget; if (targetLocation instanceof Constant && reusableJSRTarget instanceof Constant && ((Constant)targetLocation).hasSameValue((Constant) reusableJSRTarget)) { break differentTarget; } // cannot reuse current target continue nextReusableTarget; } // current target has been used in the past, simply branch to its label if ((this.reusableJSRStateIndexes[i] != stateIndex) && finallyMode == FINALLY_INLINE) { reuseTargetLocation = false; break nextReusableTarget; } else { codeStream.goto_(this.reusableJSRSequenceStartLabels[i]); return true; } } } else { this.reusableJSRTargets = new Object[3]; this.reusableJSRSequenceStartLabels = new BranchLabel[3]; this.reusableJSRStateIndexes = new int[3]; } if (reuseTargetLocation) { if (this.reusableJSRTargetsCount == this.reusableJSRTargets.length) { System.arraycopy(this.reusableJSRTargets, 0, this.reusableJSRTargets = new Object[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount); System.arraycopy(this.reusableJSRSequenceStartLabels, 0, this.reusableJSRSequenceStartLabels = new BranchLabel[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount); System.arraycopy(this.reusableJSRStateIndexes, 0, this.reusableJSRStateIndexes = new int[2*this.reusableJSRTargetsCount], 0, this.reusableJSRTargetsCount); } this.reusableJSRTargets[this.reusableJSRTargetsCount] = targetLocation; BranchLabel reusableJSRSequenceStartLabel = new BranchLabel(codeStream); reusableJSRSequenceStartLabel.place(); this.reusableJSRStateIndexes[this.reusableJSRTargetsCount] = stateIndex; this.reusableJSRSequenceStartLabels[this.reusableJSRTargetsCount++] = reusableJSRSequenceStartLabel; } } if (finallyMode == FINALLY_INLINE) { if (isStackMapFrameCodeStream) { ((StackMapFrameCodeStream) codeStream).pushStateIndex(stateIndex); } // cannot use jsr bytecode, then simply inline the subroutine // inside try block, ensure to deactivate all catch block exception handlers while inlining finally block exitAnyExceptionHandler(); exitDeclaredExceptionHandlers(codeStream); this.finallyBlock.generateCode(currentScope, codeStream); if (isStackMapFrameCodeStream) { ((StackMapFrameCodeStream) codeStream).popStateIndex(); } } else { // classic subroutine invocation, distinguish case of non-returning subroutine codeStream.jsr(this.subRoutineStartLabel); exitAnyExceptionHandler(); exitDeclaredExceptionHandlers(codeStream); } return false; } public boolean isSubRoutineEscaping() { return (this.bits & ASTNode.IsSubRoutineEscaping) != 0; } public StringBuffer printStatement(int indent, StringBuffer output) { int length = this.resources.length; printIndent(indent, output).append("try" + (length == 0 ? "\n" : " (")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ for (int i = 0; i < length; i++) { this.resources[i].printAsExpression(0, output); if (i != length - 1) { output.append(";\n"); //$NON-NLS-1$ printIndent(indent + 2, output); } } if (length > 0) { output.append(")\n"); //$NON-NLS-1$ } this.tryBlock.printStatement(indent + 1, output); //catches if (this.catchBlocks != null) for (int i = 0; i < this.catchBlocks.length; i++) { output.append('\n'); printIndent(indent, output).append("catch ("); //$NON-NLS-1$ this.catchArguments[i].print(0, output).append(")\n"); //$NON-NLS-1$ this.catchBlocks[i].printStatement(indent + 1, output); } //finally if (this.finallyBlock != null) { output.append('\n'); printIndent(indent, output).append("finally\n"); //$NON-NLS-1$ this.finallyBlock.printStatement(indent + 1, output); } return output; } public void resolve(BlockScope upperScope) { // special scope for secret locals optimization. this.scope = new BlockScope(upperScope); BlockScope finallyScope = null; BlockScope resourceManagementScope = null; // Single scope to hold all resources and additional secret variables. int resourceCount = this.resources.length; if (resourceCount > 0) { resourceManagementScope = new BlockScope(this.scope); this.primaryExceptionVariable = new LocalVariableBinding(TryStatement.SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); resourceManagementScope.addLocalVariable(this.primaryExceptionVariable); this.primaryExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable this.caughtThrowableVariable = new LocalVariableBinding(TryStatement.SECRET_CAUGHT_THROWABLE_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); resourceManagementScope.addLocalVariable(this.caughtThrowableVariable); this.caughtThrowableVariable.setConstant(Constant.NotAConstant); // not inlinable } for (int i = 0; i < resourceCount; i++) { this.resources[i].resolve(resourceManagementScope); LocalVariableBinding localVariableBinding = this.resources[i].binding; if (localVariableBinding != null && localVariableBinding.isValidBinding()) { localVariableBinding.modifiers |= ClassFileConstants.AccFinal; localVariableBinding.tagBits |= TagBits.IsResource; TypeBinding resourceType = localVariableBinding.type; if (resourceType instanceof ReferenceBinding) { if (resourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangAutoCloseable, false /*AutoCloseable is not a class*/) == null && resourceType.isValidBinding()) { upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, this.resources[i].type); localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); } } else if (resourceType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=349862, avoid secondary error in problematic null case upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, this.resources[i].type); localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); } } } BlockScope tryScope = new BlockScope(resourceManagementScope != null ? resourceManagementScope : this.scope); if (this.finallyBlock != null) { if (this.finallyBlock.isEmptyBlock()) { if ((this.finallyBlock.bits & ASTNode.UndocumentedEmptyBlock) != 0) { this.scope.problemReporter().undocumentedEmptyBlock(this.finallyBlock.sourceStart, this.finallyBlock.sourceEnd); } } else { finallyScope = new BlockScope(this.scope, false); // don't add it yet to parent scope // provision for returning and forcing the finally block to run MethodScope methodScope = this.scope.methodScope(); // the type does not matter as long as it is not a base type if (!upperScope.compilerOptions().inlineJsrBytecode) { this.returnAddressVariable = new LocalVariableBinding(TryStatement.SECRET_RETURN_ADDRESS_NAME, upperScope.getJavaLangObject(), ClassFileConstants.AccDefault, false); finallyScope.addLocalVariable(this.returnAddressVariable); this.returnAddressVariable.setConstant(Constant.NotAConstant); // not inlinable } this.subRoutineStartLabel = new BranchLabel(); this.anyExceptionVariable = new LocalVariableBinding(TryStatement.SECRET_ANY_HANDLER_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false); finallyScope.addLocalVariable(this.anyExceptionVariable); this.anyExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable if (!methodScope.isInsideInitializer()) { MethodBinding methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding; if (methodBinding != null) { TypeBinding methodReturnType = methodBinding.returnType; if (methodReturnType.id != TypeIds.T_void) { this.secretReturnValue = new LocalVariableBinding( TryStatement.SECRET_RETURN_VALUE_NAME, methodReturnType, ClassFileConstants.AccDefault, false); finallyScope.addLocalVariable(this.secretReturnValue); this.secretReturnValue.setConstant(Constant.NotAConstant); // not inlinable } } } this.finallyBlock.resolveUsing(finallyScope); // force the finally scope to have variable positions shifted after its try scope and catch ones int shiftScopesLength = this.catchArguments == null ? 1 : this.catchArguments.length + 1; finallyScope.shiftScopes = new BlockScope[shiftScopesLength]; finallyScope.shiftScopes[0] = tryScope; } } this.tryBlock.resolveUsing(tryScope); // arguments type are checked against JavaLangThrowable in resolveForCatch(..) if (this.catchBlocks != null) { int length = this.catchArguments.length; TypeBinding[] argumentTypes = new TypeBinding[length]; boolean containsUnionTypes = false; boolean catchHasError = false; for (int i = 0; i < length; i++) { BlockScope catchScope = new BlockScope(this.scope); if (finallyScope != null){ finallyScope.shiftScopes[i+1] = catchScope; } // side effect on catchScope in resolveForCatch(..) Argument catchArgument = this.catchArguments[i]; containsUnionTypes |= (catchArgument.type.bits & ASTNode.IsUnionType) != 0; if ((argumentTypes[i] = catchArgument.resolveForCatch(catchScope)) == null) { catchHasError = true; } this.catchBlocks[i].resolveUsing(catchScope); } if (catchHasError) { return; } // Verify that the catch clause are ordered in the right way: // more specialized first. verifyDuplicationAndOrder(length, argumentTypes, containsUnionTypes); } else { this.caughtExceptionTypes = new ReferenceBinding[0]; } if (finallyScope != null){ // add finallyScope as last subscope, so it can be shifted behind try/catch subscopes. // the shifting is necessary to achieve no overlay in between the finally scope and its // sibling in term of local variable positions. this.scope.addSubscope(finallyScope); } } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { LocalDeclaration[] localDeclarations = this.resources; for (int i = 0, max = localDeclarations.length; i < max; i++) { localDeclarations[i].traverse(visitor, this.scope); } this.tryBlock.traverse(visitor, this.scope); if (this.catchArguments != null) { for (int i = 0, max = this.catchBlocks.length; i < max; i++) { this.catchArguments[i].traverse(visitor, this.scope); this.catchBlocks[i].traverse(visitor, this.scope); } } if (this.finallyBlock != null) this.finallyBlock.traverse(visitor, this.scope); } visitor.endVisit(this, blockScope); } protected void verifyDuplicationAndOrder(int length, TypeBinding[] argumentTypes, boolean containsUnionTypes) { // Verify that the catch clause are ordered in the right way: // more specialized first. if (containsUnionTypes) { int totalCount = 0; ReferenceBinding[][] allExceptionTypes = new ReferenceBinding[length][]; for (int i = 0; i < length; i++) { ReferenceBinding currentExceptionType = (ReferenceBinding) argumentTypes[i]; TypeReference catchArgumentType = this.catchArguments[i].type; if ((catchArgumentType.bits & ASTNode.IsUnionType) != 0) { TypeReference[] typeReferences = ((UnionTypeReference) catchArgumentType).typeReferences; int typeReferencesLength = typeReferences.length; ReferenceBinding[] unionExceptionTypes = new ReferenceBinding[typeReferencesLength]; for (int j = 0; j < typeReferencesLength; j++) { unionExceptionTypes[j] = (ReferenceBinding) typeReferences[j].resolvedType; } totalCount += typeReferencesLength; allExceptionTypes[i] = unionExceptionTypes; } else { allExceptionTypes[i] = new ReferenceBinding[] { currentExceptionType }; totalCount++; } } this.caughtExceptionTypes = new ReferenceBinding[totalCount]; this.caughtExceptionsCatchBlocks = new int[totalCount]; for (int i = 0, l = 0; i < length; i++) { ReferenceBinding[] currentExceptions = allExceptionTypes[i]; loop: for (int j = 0, max = currentExceptions.length; j < max; j++) { ReferenceBinding exception = currentExceptions[j]; this.caughtExceptionTypes[l] = exception; this.caughtExceptionsCatchBlocks[l++] = i; // now iterate over all previous exceptions for (int k = 0; k < i; k++) { ReferenceBinding[] exceptions = allExceptionTypes[k]; for (int n = 0, max2 = exceptions.length; n < max2; n++) { ReferenceBinding currentException = exceptions[n]; if (exception.isCompatibleWith(currentException)) { TypeReference catchArgumentType = this.catchArguments[i].type; if ((catchArgumentType.bits & ASTNode.IsUnionType) != 0) { catchArgumentType = ((UnionTypeReference) catchArgumentType).typeReferences[j]; } this.scope.problemReporter().wrongSequenceOfExceptionTypesError( catchArgumentType, exception, currentException); break loop; } } } } } } else { this.caughtExceptionTypes = new ReferenceBinding[length]; for (int i = 0; i < length; i++) { this.caughtExceptionTypes[i] = (ReferenceBinding) argumentTypes[i]; for (int j = 0; j < i; j++) { if (this.caughtExceptionTypes[i].isCompatibleWith(argumentTypes[j])) { this.scope.problemReporter().wrongSequenceOfExceptionTypesError( this.catchArguments[i].type, this.caughtExceptionTypes[i], argumentTypes[j]); } } } } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java0000644000175000001440000002571012212041344030656 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.*; public class WhileStatement extends Statement { public Expression condition; public Statement action; private BranchLabel breakLabel, continueLabel; int preCondInitStateIndex = -1; int condIfTrueInitStateIndex = -1; int mergedInitStateIndex = -1; public WhileStatement(Expression condition, Statement action, int s, int e) { this.condition = condition; this.action = action; // remember useful empty statement if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatement; this.sourceStart = s; this.sourceEnd = e; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.breakLabel = new BranchLabel(); this.continueLabel = new BranchLabel(); int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; Constant cst = this.condition.constant; boolean isConditionTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isConditionFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; cst = this.condition.optimizedBooleanConstant(); boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; this.preCondInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); LoopingFlowContext condLoopContext; FlowInfo condInfo = flowInfo.nullInfoLessUnconditionalCopy(); // we need to collect the contribution to nulls of the coming paths through the // loop, be they falling through normally or branched to break, continue labels // or catch blocks condInfo = this.condition.analyseCode( currentScope, (condLoopContext = new LoopingFlowContext(flowContext, flowInfo, this, null, null, currentScope, true)), condInfo); this.condition.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); LoopingFlowContext loopingContext; FlowInfo actionInfo; FlowInfo exitBranch; if (this.action == null || (this.action.isEmptyBlock() && currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3)) { condLoopContext.complainOnDeferredFinalChecks(currentScope, condInfo); condLoopContext.complainOnDeferredNullChecks(currentScope, condInfo.unconditionalInits()); if (isConditionTrue) { return FlowInfo.DEAD_END; } else { FlowInfo mergedInfo = flowInfo.copy().addInitializationsFrom(condInfo.initsWhenFalse()); if (isConditionOptimizedTrue){ mergedInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } } else { // in case the condition was inlined to false, record the fact that there is no way to reach any // statement inside the looping action loopingContext = new LoopingFlowContext( flowContext, flowInfo, this, this.breakLabel, this.continueLabel, currentScope, true); if (isConditionFalse) { actionInfo = FlowInfo.DEAD_END; } else { actionInfo = condInfo.initsWhenTrue().copy(); if (isConditionOptimizedFalse){ actionInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } } // for computing local var attributes this.condIfTrueInitStateIndex = currentScope.methodScope().recordInitializationStates( condInfo.initsWhenTrue()); if (this.action.complainIfUnreachable(actionInfo, currentScope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) { actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo); } // code generation can be optimized when no need to continue in the loop exitBranch = flowInfo.copy(); // need to start over from flowInfo so as to get null inits int combinedTagBits = actionInfo.tagBits & loopingContext.initsOnContinue.tagBits; if ((combinedTagBits & FlowInfo.UNREACHABLE) != 0) { if ((combinedTagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) this.continueLabel = null; exitBranch.addInitializationsFrom(condInfo.initsWhenFalse()); } else { condLoopContext.complainOnDeferredFinalChecks(currentScope, condInfo); actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits()); condLoopContext.complainOnDeferredNullChecks(currentScope, actionInfo); loopingContext.complainOnDeferredFinalChecks(currentScope, actionInfo); loopingContext.complainOnDeferredNullChecks(currentScope, actionInfo); exitBranch. addPotentialInitializationsFrom( actionInfo.unconditionalInits()). addInitializationsFrom(condInfo.initsWhenFalse()); } if (loopingContext.hasEscapingExceptions()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321926 FlowInfo loopbackFlowInfo = flowInfo.copy(); if (this.continueLabel != null) { // we do get to the bottom loopbackFlowInfo.mergedWith(actionInfo.unconditionalCopy()); } loopingContext.simulateThrowAfterLoopBack(loopbackFlowInfo); } } // end of loop FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( (loopingContext.initsOnBreak.tagBits & FlowInfo.UNREACHABLE) != 0 ? loopingContext.initsOnBreak : flowInfo.addInitializationsFrom(loopingContext.initsOnBreak), // recover upstream null info isConditionOptimizedTrue, exitBranch, isConditionOptimizedFalse, !isConditionTrue /*while(true); unreachable(); */); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } /** * While 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 ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; Constant cst = this.condition.optimizedBooleanConstant(); boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; if (isConditionOptimizedFalse) { this.condition.generateCode(currentScope, codeStream, false); // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } this.breakLabel.initialize(codeStream); // generate condition if (this.continueLabel == null) { // no need to reverse condition if (this.condition.constant == Constant.NotAConstant) { this.condition.generateOptimizedBoolean( currentScope, codeStream, null, this.breakLabel, true); } } else { this.continueLabel.initialize(codeStream); if (!(((this.condition.constant != Constant.NotAConstant) && (this.condition.constant.booleanValue() == true)) || (this.action == null) || this.action.isEmptyBlock())) { int jumpPC = codeStream.position; codeStream.goto_(this.continueLabel); codeStream.recordPositionsFrom(jumpPC, this.condition.sourceStart); } } // generate the action BranchLabel actionLabel = new BranchLabel(codeStream); if (this.action != null) { actionLabel.tagBits |= BranchLabel.USED; // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect if (this.condIfTrueInitStateIndex != -1) { // insert all locals initialized inside the condition into the action generated prior to the condition codeStream.addDefinitelyAssignedVariables( currentScope, this.condIfTrueInitStateIndex); } actionLabel.place(); this.action.generateCode(currentScope, codeStream); // May loose some local variable initializations : affecting the local variable attributes if (this.preCondInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preCondInitStateIndex); } } else { actionLabel.place(); } // output condition and branch back to the beginning of the repeated action if (this.continueLabel != null) { this.continueLabel.place(); this.condition.generateOptimizedBoolean( currentScope, codeStream, actionLabel, null, true); } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } this.breakLabel.place(); codeStream.recordPositionsFrom(pc, this.sourceStart); } public void resolve(BlockScope scope) { TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); this.condition.computeConversion(scope, type, type); if (this.action != null) this.action.resolve(scope); } public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output).append("while ("); //$NON-NLS-1$ this.condition.printExpression(0, output).append(')'); if (this.action == null) output.append(';'); else this.action.printStatement(tab + 1, output); return output; } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.condition.traverse(visitor, blockScope); if (this.action != null) this.action.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ././@LongLink0000644000000000000000000000015312251602427011642 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReferenc0000644000175000001440000001037112212041344032354 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class JavadocImplicitTypeReference extends TypeReference { public char[] token; public JavadocImplicitTypeReference(char[] name, int pos) { super(); this.token = name; this.sourceStart = pos; this.sourceEnd = pos; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int) */ public TypeReference copyDims(int dim) { return null; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope) */ protected TypeBinding getTypeBinding(Scope scope) { this.constant = Constant.NotAConstant; return this.resolvedType = scope.enclosingReceiverType(); } public char[] getLastToken() { return this.token; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeName() */ public char[][] getTypeName() { if (this.token != null) { char[][] tokens = { this.token }; return tokens; } return null; } public boolean isThis() { return true; } /* * Resolves type on a Block, Class or CompilationUnit scope. * We need to modify resoling behavior to avoid raw type creation. */ protected TypeBinding internalResolveType(Scope scope) { // handle the error here this.constant = Constant.NotAConstant; if (this.resolvedType != null) { // is a shared type reference which was already resolved if (this.resolvedType.isValidBinding()) { return this.resolvedType; } else { switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : TypeBinding type = this.resolvedType.closestMatch(); return type; default : return null; } } } boolean hasError; TypeBinding type = this.resolvedType = getTypeBinding(scope); if (type == null) { return null; // detected cycle while resolving hierarchy } else if ((hasError = !type.isValidBinding())== true) { reportInvalidType(scope); switch (type.problemId()) { case ProblemReasons.NotFound : case ProblemReasons.NotVisible : type = type.closestMatch(); if (type == null) return null; break; default : return null; } } if (type.isArrayType() && ((ArrayBinding) type).leafComponentType == TypeBinding.VOID) { scope.problemReporter().cannotAllocateVoidArray(this); return null; } if (isTypeUseDeprecated(type, scope)) { reportDeprecatedType(type, scope); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=209936 // raw convert all enclosing types when dealing with Javadoc references if (type.isGenericType() || type.isParameterizedType()) { type = scope.environment().convertToRawType(type, true /*force the conversion of enclosing types*/); } if (hasError) { // do not store the computed type, keep the problem type instead return type; } return this.resolvedType = type; } protected void reportInvalidType(Scope scope) { scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers()); } protected void reportDeprecatedType(TypeBinding type, Scope scope) { scope.problemReporter().javadocDeprecatedType(type, this, scope.getDeclarationModifiers()); } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public StringBuffer printExpression(int indent, StringBuffer output) { return new StringBuffer(); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java0000644000175000001440000003413012212041344031106 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * bug 331649 - [compiler][null] consider null annotations for fields * bug 400761 - [compiler][null] null may be return as boolean without a diagnostic *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.core.compiler.IProblem; 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.*; 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 FieldDeclaration extends AbstractVariableDeclaration { public FieldBinding binding; public Javadoc javadoc; //allows to retrieve both the "type" part of the declaration (part1) //and also the part that decribe the name and the init and optionally //some other dimension ! .... //public int[] a, b[] = X, c ; //for b that would give for // - part1 : public int[] // - part2 : b[] = X, public int endPart1Position; public int endPart2Position; public FieldDeclaration() { // for subtypes or conversion } public FieldDeclaration( char[] name, int sourceStart, int sourceEnd) { this.name = name; //due to some declaration like // int x, y = 3, z , x ; //the sourceStart and the sourceEnd is ONLY on the name this.sourceStart = sourceStart; this.sourceEnd = sourceEnd; } public FlowInfo analyseCode(MethodScope initializationScope, FlowContext flowContext, FlowInfo flowInfo) { if (this.binding != null && !this.binding.isUsed() && this.binding.isOrEnclosedByPrivateType()) { if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError) { initializationScope.problemReporter().unusedPrivateField(this); } } // cannot define static non-constant field inside nested class if (this.binding != null && this.binding.isValidBinding() && this.binding.isStatic() && this.binding.constant() == Constant.NotAConstant && this.binding.declaringClass.isNestedType() && !this.binding.declaringClass.isStatic()) { initializationScope.problemReporter().unexpectedStaticModifierForField( (SourceTypeBinding) this.binding.declaringClass, this); } if (this.initialization != null) { flowInfo = this.initialization .analyseCode(initializationScope, flowContext, flowInfo) .unconditionalInits(); flowInfo.markAsDefinitelyAssigned(this.binding); } if (this.initialization != null) { if (this.binding.isNonNull()) { int nullStatus = this.initialization.nullStatus(flowInfo, flowContext); // check against annotation @NonNull: if (nullStatus != FlowInfo.NON_NULL) { char[][] annotationName = initializationScope.environment().getNonNullAnnotationName(); initializationScope.problemReporter().nullityMismatch(this.initialization, this.initialization.resolvedType, this.binding.type, nullStatus, annotationName); } } this.initialization.checkNPEbyUnboxing(initializationScope, flowContext, flowInfo); } return flowInfo; } /** * Code generation for a field declaration: * standard assignment to a field * * @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 ((this.bits & IsReachable) == 0) { return; } // do not generate initialization code if final and static (constant is then // recorded inside the field itself). int pc = codeStream.position; boolean isStatic; if (this.initialization != null && !((isStatic = this.binding.isStatic()) && this.binding.constant() != Constant.NotAConstant)) { // non-static field, need receiver if (!isStatic) codeStream.aload_0(); // generate initialization value this.initialization.generateCode(currentScope, codeStream, true); // store into field if (isStatic) { codeStream.fieldAccess(Opcodes.OPC_putstatic, this.binding, null /* default declaringClass */); } else { codeStream.fieldAccess(Opcodes.OPC_putfield, this.binding, null /* default declaringClass */); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * @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) return this.binding.isStatic(); return (this.modifiers & ClassFileConstants.AccStatic) != 0; } public boolean isFinal() { if (this.binding != null) return this.binding.isFinal(); return (this.modifiers & ClassFileConstants.AccFinal) != 0; } public StringBuffer printStatement(int indent, StringBuffer output) { if (this.javadoc != null) { this.javadoc.print(indent, output); } return super.printStatement(indent, output); } public void resolve(MethodScope initializationScope) { // the two could be regrouped into // a single line but it is clearer to have two lines while the reason of their // existence is not at all the same. See comment for the second one. //-------------------------------------------------------- if ((this.bits & ASTNode.HasBeenResolved) != 0) return; if (this.binding == null || !this.binding.isValidBinding()) return; this.bits |= ASTNode.HasBeenResolved; // 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(); if (classScope != null) { checkHiding: { SourceTypeBinding declaringType = classScope.enclosingSourceType(); checkHidingSuperField: { if (declaringType.superclass == null) break checkHidingSuperField; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318171, find field skipping visibility checks // we do the checks below ourselves, using the appropriate conditions for access check of // protected members from superclasses. FieldBinding existingVariable = classScope.findField(declaringType.superclass, this.name, this, false /*do not resolve hidden field*/, true /* no visibility checks please */); if (existingVariable == null) break checkHidingSuperField; // keep checking outer scenario if (!existingVariable.isValidBinding()) break checkHidingSuperField; // keep checking outer scenario if (existingVariable.original() == this.binding) break checkHidingSuperField; // keep checking outer scenario if (!existingVariable.canBeSeenBy(declaringType, this, initializationScope)) break checkHidingSuperField; // keep checking outer scenario // collision with supertype field initializationScope.problemReporter().fieldHiding(this, existingVariable); break checkHiding; // already found a matching field } // 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. Scope outerScope = classScope.parent; if (outerScope.kind == Scope.COMPILATION_UNIT_SCOPE) break checkHiding; Binding existingVariable = outerScope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/); if (existingVariable == null) break checkHiding; if (!existingVariable.isValidBinding()) break checkHiding; if (existingVariable == this.binding) break checkHiding; if (existingVariable instanceof FieldBinding) { FieldBinding existingField = (FieldBinding) existingVariable; if (existingField.original() == this.binding) break checkHiding; if (!existingField.isStatic() && declaringType.isStatic()) break checkHiding; } // collision with outer field or local variable initializationScope.problemReporter().fieldHiding(this, existingVariable); } } 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; try { initializationScope.initializedField = this.binding; initializationScope.lastVisibleFieldID = this.binding.id; resolveAnnotations(initializationScope, this.annotations, this.binding); // check @Deprecated annotation presence if ((this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0 && (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0 && initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { initializationScope.problemReporter().missingDeprecatedAnnotationForField(this); } // the resolution of the initialization hasn't been done if (this.initialization == null) { this.binding.setConstant(Constant.NotAConstant); } else { // break dead-lock cycles by forcing constant to NotAConstant 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 ((initializationType = this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) { ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType; this.initialization.computeConversion(initializationScope, fieldType, initializationType); } } 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) || initializationType.isCompatibleWith(fieldType, classScope)) { this.initialization.computeConversion(initializationScope, fieldType, initializationType); if (initializationType.needsUncheckedConversion(fieldType)) { initializationScope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, fieldType); } if (this.initialization instanceof CastExpression && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) { CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization); } } else if (isBoxingCompatible(initializationType, fieldType, this.initialization, initializationScope)) { this.initialization.computeConversion(initializationScope, fieldType, initializationType); if (this.initialization instanceof CastExpression && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) { CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization); } } else { if ((fieldType.tagBits & TagBits.HasMissingType) == 0) { // if problem already got signaled on type, do not report secondary problem initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this.initialization, null); } } if (this.binding.isFinal()){ // cast from constant actual type to variable type this.binding.setConstant(this.initialization.constant.castTo((this.binding.type.id << 4) + this.initialization.constant.typeID())); } } else { this.binding.setConstant(Constant.NotAConstant); } // check for assignment with no effect if (this.binding == Expression.getDirectBinding(this.initialization)) { initializationScope.problemReporter().assignmentHasNoEffect(this, this.name); } } // Resolve Javadoc comment if one is present if (this.javadoc != null) { this.javadoc.resolve(initializationScope); } else if (this.binding != null && this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) { // Set javadoc visibility int javadocVisibility = this.binding.modifiers & ExtraCompilerModifiers.AccVisibilityMASK; ProblemReporter reporter = initializationScope.problemReporter(); int severity = reporter.computeSeverity(IProblem.JavadocMissing); if (severity != ProblemSeverities.Ignore) { if (classScope != null) { javadocVisibility = Util.computeOuterMostVisibility(classScope.referenceType(), javadocVisibility); } int javadocModifiers = (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK) | javadocVisibility; reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers); } } } finally { initializationScope.initializedField = previousField; initializationScope.lastVisibleFieldID = previousFieldID; if (this.binding.constant() == null) this.binding.setConstant(Constant.NotAConstant); } } public void traverse(ASTVisitor visitor, MethodScope scope) { if (visitor.visit(this, scope)) { if (this.javadoc != null) { this.javadoc.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); } visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000015612251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeRefer0000644000175000001440000000356512212041344032343 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class JavadocArraySingleTypeReference extends ArrayTypeReference { public JavadocArraySingleTypeReference(char[] name, int dim, long pos) { super(name, dim, pos); this.bits |= InsideJavadoc; } protected void reportInvalidType(Scope scope) { scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers()); } protected void reportDeprecatedType(TypeBinding type, Scope scope) { scope.problemReporter().javadocDeprecatedType(type, this, scope.getDeclarationModifiers()); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java0000644000175000001440000000747412212041344031401 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class ContinueStatement extends BranchStatement { public ContinueStatement(char[] label, int sourceStart, int sourceEnd) { super(label, sourceStart, sourceEnd); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // here requires to generate a sequence of finally blocks invocations depending corresponding // to each of the traversed try statements, so that execution will terminate properly. // lookup the label, this should answer the returnContext FlowContext targetContext = (this.label == null) ? flowContext.getTargetContextForDefaultContinue() : flowContext.getTargetContextForContinueLabel(this.label); if (targetContext == null) { if (this.label == null) { currentScope.problemReporter().invalidContinue(this); } else { currentScope.problemReporter().undefinedLabel(this); } return flowInfo; // pretend it did not continue since no actual target } targetContext.recordAbruptExit(); if (targetContext == FlowContext.NotContinuableContext) { currentScope.problemReporter().invalidContinue(this); return flowInfo; // pretend it did not continue since no actual target } this.initStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); this.targetLabel = targetContext.continueLabel(); FlowContext traversedContext = flowContext; int subCount = 0; this.subroutines = new SubRoutineStatement[5]; do { SubRoutineStatement sub; if ((sub = traversedContext.subroutine()) != null) { if (subCount == this.subroutines.length) { System.arraycopy(this.subroutines, 0, this.subroutines = new SubRoutineStatement[subCount*2], 0, subCount); // grow } this.subroutines[subCount++] = sub; if (sub.isSubRoutineEscaping()) { break; } } traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); if (traversedContext instanceof InsideSubRoutineFlowContext) { ASTNode node = traversedContext.associatedNode; if (node instanceof TryStatement) { TryStatement tryStatement = (TryStatement) node; flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits } } else if (traversedContext == targetContext) { // only record continue info once accumulated through subroutines, and only against target context targetContext.recordContinueFrom(flowContext, flowInfo); break; } } while ((traversedContext = traversedContext.getLocalParent()) != null); // resize subroutines if (subCount != this.subroutines.length) { System.arraycopy(this.subroutines, 0, this.subroutines = new SubRoutineStatement[subCount], 0, subCount); } return FlowInfo.DEAD_END; } public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output).append("continue "); //$NON-NLS-1$ if (this.label != null) output.append(this.label); return output.append(';'); } public void traverse(ASTVisitor visitor, BlockScope blockScope) { visitor.visit(this, blockScope); visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java0000644000175000001440000002177712212041344031060 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.ASTVisitor; public class AssertStatement extends Statement { public Expression assertExpression, exceptionArgument; // for local variable attribute int preAssertInitStateIndex = -1; private FieldBinding assertionSyntheticFieldBinding; public AssertStatement( Expression exceptionArgument, Expression assertExpression, int startPosition) { this.assertExpression = assertExpression; this.exceptionArgument = exceptionArgument; this.sourceStart = startPosition; this.sourceEnd = exceptionArgument.sourceEnd; } public AssertStatement(Expression assertExpression, int startPosition) { this.assertExpression = assertExpression; this.sourceStart = startPosition; this.sourceEnd = assertExpression.sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { this.preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); Constant cst = this.assertExpression.optimizedBooleanConstant(); this.assertExpression.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); boolean isOptimizedTrueAssertion = cst != Constant.NotAConstant && cst.booleanValue() == true; boolean isOptimizedFalseAssertion = cst != Constant.NotAConstant && cst.booleanValue() == false; flowContext.tagBits |= FlowContext.HIDE_NULL_COMPARISON_WARNING; FlowInfo conditionFlowInfo = this.assertExpression.analyseCode(currentScope, flowContext, flowInfo.copy()); flowContext.extendTimeToLiveForNullCheckedField(1); // survive this assert as a Statement flowContext.tagBits &= ~FlowContext.HIDE_NULL_COMPARISON_WARNING; UnconditionalFlowInfo assertWhenTrueInfo = conditionFlowInfo.initsWhenTrue().unconditionalInits(); FlowInfo assertInfo = conditionFlowInfo.initsWhenFalse(); if (isOptimizedTrueAssertion) { assertInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } if (this.exceptionArgument != null) { // only gets evaluated when escaping - results are not taken into account FlowInfo exceptionInfo = this.exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy()); if (isOptimizedTrueAssertion){ currentScope.problemReporter().fakeReachable(this.exceptionArgument); } else { flowContext.checkExceptionHandlers( currentScope.getJavaLangAssertionError(), this, exceptionInfo, currentScope); } } if (!isOptimizedTrueAssertion){ // add the assert support in the clinit manageSyntheticAccessIfNecessary(currentScope, flowInfo); } // account for potential AssertionError: flowContext.recordAbruptExit(); if (isOptimizedFalseAssertion) { return flowInfo; // if assertions are enabled, the following code will be unreachable // change this if we need to carry null analysis results of the assert // expression downstream } else { CompilerOptions compilerOptions = currentScope.compilerOptions(); if (!compilerOptions.includeNullInfoFromAsserts) { // keep just the initializations info, don't include assert's null info // merge initialization info's and then add back the null info from flowInfo to // make sure that the empty null info of assertInfo doesnt change flowInfo's null info. return ((flowInfo.nullInfoLessUnconditionalCopy()).mergedWith(assertInfo.nullInfoLessUnconditionalCopy())).addNullInfoFrom(flowInfo); } return flowInfo.mergedWith(assertInfo.nullInfoLessUnconditionalCopy()). addInitializationsFrom(assertWhenTrueInfo.discardInitializationInfo()); // keep the merge from the initial code for the definite assignment // analysis, tweak the null part to influence nulls downstream } } public void generateCode(BlockScope currentScope, CodeStream codeStream) { if ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; if (this.assertionSyntheticFieldBinding != null) { BranchLabel assertionActivationLabel = new BranchLabel(codeStream); codeStream.fieldAccess(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */); codeStream.ifne(assertionActivationLabel); BranchLabel falseLabel; this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new BranchLabel(codeStream)), null , true); codeStream.newJavaLangAssertionError(); codeStream.dup(); if (this.exceptionArgument != null) { this.exceptionArgument.generateCode(currentScope, codeStream, true); codeStream.invokeJavaLangAssertionErrorConstructor(this.exceptionArgument.implicitConversion & 0xF); } else { codeStream.invokeJavaLangAssertionErrorDefaultConstructor(); } codeStream.athrow(); // May loose some local variable initializations : affecting the local variable attributes if (this.preAssertInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex); } falseLabel.place(); assertionActivationLabel.place(); } else { // May loose some local variable initializations : affecting the local variable attributes if (this.preAssertInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } public void resolve(BlockScope scope) { this.assertExpression.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); if (this.exceptionArgument != null) { TypeBinding exceptionArgumentType = this.exceptionArgument.resolveType(scope); if (exceptionArgumentType != null){ int id = exceptionArgumentType.id; switch(id) { case T_void : scope.problemReporter().illegalVoidExpression(this.exceptionArgument); //$FALL-THROUGH$ default: id = T_JavaLangObject; //$FALL-THROUGH$ case T_boolean : case T_byte : case T_char : case T_short : case T_double : case T_float : case T_int : case T_long : case T_JavaLangString : this.exceptionArgument.implicitConversion = (id << 4) + id; } } } } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.assertExpression.traverse(visitor, scope); if (this.exceptionArgument != null) { this.exceptionArgument.traverse(visitor, scope); } } visitor.endVisit(this, scope); } public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { // need assertion flag: $assertionsDisabled on outer most source clas // (in case of static member of interface, will use the outermost static member - bug 22334) SourceTypeBinding outerMostClass = currentScope.enclosingSourceType(); while (outerMostClass.isLocalType()) { ReferenceBinding enclosing = outerMostClass.enclosingType(); if (enclosing == null || enclosing.isInterface()) break; outerMostClass = (SourceTypeBinding) enclosing; } this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope); // find and enable assertion support TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType(); AbstractMethodDeclaration[] methods = typeDeclaration.methods; for (int i = 0, max = methods.length; i < max; i++) { AbstractMethodDeclaration method = methods[i]; if (method.isClinit()) { ((Clinit) method).setAssertionSupport(this.assertionSyntheticFieldBinding, currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5); break; } } } } public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output); output.append("assert "); //$NON-NLS-1$ this.assertExpression.printExpression(0, output); if (this.exceptionArgument != null) { output.append(": "); //$NON-NLS-1$ this.exceptionArgument.printExpression(0, output); } return output.append(';'); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java0000644000175000001440000006401512212041344031050 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 265744 - Enum switch should warn about missing default * bug 374605 - Unreasonable warning for enum-based switch statements * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import java.util.Arrays; 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.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class SwitchStatement extends Statement { public Expression expression; public Statement[] statements; public BlockScope scope; public int explicitDeclarations; public BranchLabel breakLabel; public CaseStatement[] cases; public CaseStatement defaultCase; public int blockStart; public int caseCount; int[] constants; String[] stringConstants; // fallthrough public final static int CASE = 0; public final static int FALLTHROUGH = 1; public final static int ESCAPING = 2; // for switch on strings private static final char[] SecretStringVariableName = " switchDispatchString".toCharArray(); //$NON-NLS-1$ public SyntheticMethodBinding synthetic; // use for switch on enums types // for local variables table attributes int preSwitchInitStateIndex = -1; int mergedInitStateIndex = -1; CaseStatement[] duplicateCaseStatements = null; int duplicateCaseStatementsCounter = 0; private LocalVariableBinding dispatchStringCopy = null; public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { try { flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo); if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0 || (this.expression.resolvedType != null && this.expression.resolvedType.id == T_JavaLangString)) { this.expression.checkNPE(currentScope, flowContext, flowInfo); } SwitchFlowContext switchContext = new SwitchFlowContext(flowContext, this, (this.breakLabel = new BranchLabel()), true); // analyse the block by considering specially the case/default statements (need to bind them // to the entry point) FlowInfo caseInits = FlowInfo.DEAD_END; // in case of statements before the first case this.preSwitchInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); int caseIndex = 0; if (this.statements != null) { int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED; int complaintLevel = initialComplaintLevel; int fallThroughState = CASE; for (int i = 0, max = this.statements.length; i < max; i++) { Statement statement = this.statements[i]; if ((caseIndex < this.caseCount) && (statement == this.cases[caseIndex])) { // statement is a case this.scope.enclosingCase = this.cases[caseIndex]; // record entering in a switch case block caseIndex++; if (fallThroughState == FALLTHROUGH && (statement.bits & ASTNode.DocumentedFallthrough) == 0) { // the case is not fall-through protected by a line comment this.scope.problemReporter().possibleFallThroughCase(this.scope.enclosingCase); } caseInits = caseInits.mergedWith(flowInfo.unconditionalInits()); complaintLevel = initialComplaintLevel; // reset complaint fallThroughState = CASE; } else if (statement == this.defaultCase) { // statement is the default case this.scope.enclosingCase = this.defaultCase; // record entering in a switch case block if (fallThroughState == FALLTHROUGH && (statement.bits & ASTNode.DocumentedFallthrough) == 0) { this.scope.problemReporter().possibleFallThroughCase(this.scope.enclosingCase); } caseInits = caseInits.mergedWith(flowInfo.unconditionalInits()); complaintLevel = initialComplaintLevel; // reset complaint fallThroughState = CASE; } else { fallThroughState = FALLTHROUGH; // reset below if needed } if ((complaintLevel = statement.complainIfUnreachable(caseInits, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { caseInits = statement.analyseCode(this.scope, switchContext, caseInits); if (caseInits == FlowInfo.DEAD_END) { fallThroughState = ESCAPING; } } } } final TypeBinding resolvedTypeBinding = this.expression.resolvedType; if (resolvedTypeBinding.isEnum()) { final SourceTypeBinding sourceTypeBinding = currentScope.classScope().referenceContext.binding; this.synthetic = sourceTypeBinding.addSyntheticMethodForSwitchEnum(resolvedTypeBinding); } // if no default case, then record it may jump over the block directly to the end if (this.defaultCase == null) { // only retain the potential initializations flowInfo.addPotentialInitializationsFrom(caseInits.mergedWith(switchContext.initsOnBreak)); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); return flowInfo; } // merge all branches inits FlowInfo mergedInfo = caseInits.mergedWith(switchContext.initsOnBreak); this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; } finally { if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block } } /** * Switch on String code generation * This assumes that hashCode() specification for java.lang.String is API * and is stable. * * @see "http://download.oracle.com/javase/6/docs/api/java/lang/String.html" * * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream */ public void generateCodeForStringSwitch(BlockScope currentScope, CodeStream codeStream) { try { if ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; class StringSwitchCase implements Comparable { int hashCode; String string; BranchLabel label; public StringSwitchCase(int hashCode, String string, BranchLabel label) { this.hashCode = hashCode; this.string = string; this.label = label; } public int compareTo(Object o) { StringSwitchCase that = (StringSwitchCase) o; if (this.hashCode == that.hashCode) { return 0; } if (this.hashCode > that.hashCode) { return 1; } return -1; } public String toString() { return "StringSwitchCase :\n" + //$NON-NLS-1$ "case " + this.hashCode + ":(" + this.string + ")\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } final boolean hasCases = this.caseCount != 0; StringSwitchCase [] stringCases = new StringSwitchCase[this.caseCount]; // may have to shrink later if multiple strings hash to same code. BranchLabel[] sourceCaseLabels = new BranchLabel[this.caseCount]; CaseLabel [] hashCodeCaseLabels = new CaseLabel[this.caseCount]; this.constants = new int[this.caseCount]; // hashCode() values. for (int i = 0, max = this.caseCount; i < max; i++) { this.cases[i].targetLabel = (sourceCaseLabels[i] = new BranchLabel(codeStream)); // A branch label, not a case label. sourceCaseLabels[i].tagBits |= BranchLabel.USED; stringCases[i] = new StringSwitchCase(this.stringConstants[i].hashCode(), this.stringConstants[i], sourceCaseLabels[i]); hashCodeCaseLabels[i] = new CaseLabel(codeStream); hashCodeCaseLabels[i].tagBits |= BranchLabel.USED; } Arrays.sort(stringCases); int uniqHashCount = 0; int lastHashCode = 0; for (int i = 0, length = this.caseCount; i < length; ++i) { int hashCode = stringCases[i].hashCode; if (i == 0 || hashCode != lastHashCode) { lastHashCode = this.constants[uniqHashCount++] = hashCode; } } if (uniqHashCount != this.caseCount) { // multiple keys hashed to the same value. System.arraycopy(this.constants, 0, this.constants = new int[uniqHashCount], 0, uniqHashCount); System.arraycopy(hashCodeCaseLabels, 0, hashCodeCaseLabels = new CaseLabel[uniqHashCount], 0, uniqHashCount); } int[] sortedIndexes = new int[uniqHashCount]; // hash code are sorted already anyways. for (int i = 0; i < uniqHashCount; i++) { sortedIndexes[i] = i; } CaseLabel defaultCaseLabel = new CaseLabel(codeStream); defaultCaseLabel.tagBits |= BranchLabel.USED; // prepare the labels and constants this.breakLabel.initialize(codeStream); BranchLabel defaultBranchLabel = new BranchLabel(codeStream); if (hasCases) defaultBranchLabel.tagBits |= BranchLabel.USED; if (this.defaultCase != null) { this.defaultCase.targetLabel = defaultBranchLabel; } // generate expression this.expression.generateCode(currentScope, codeStream, true); codeStream.store(this.dispatchStringCopy, true); // leaves string on operand stack codeStream.addVariable(this.dispatchStringCopy); codeStream.invokeStringHashCode(); if (hasCases) { codeStream.lookupswitch(defaultCaseLabel, this.constants, sortedIndexes, hashCodeCaseLabels); for (int i = 0, j = 0, max = this.caseCount; i < max; i++) { int hashCode = stringCases[i].hashCode; if (i == 0 || hashCode != lastHashCode) { lastHashCode = hashCode; if (i != 0) { codeStream.goto_(defaultBranchLabel); } hashCodeCaseLabels[j++].place(); } codeStream.load(this.dispatchStringCopy); codeStream.ldc(stringCases[i].string); codeStream.invokeStringEquals(); codeStream.ifne(stringCases[i].label); } codeStream.goto_(defaultBranchLabel); } else { codeStream.pop(); } // generate the switch block statements int caseIndex = 0; 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.enclosingCase = this.cases[caseIndex]; // record entering in a switch case block if (this.preSwitchInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSwitchInitStateIndex); } caseIndex++; } else { if (statement == this.defaultCase) { // statements[i] is a case or a default case defaultCaseLabel.place(); // branch label gets placed by generateCode below. this.scope.enclosingCase = this.defaultCase; // record entering in a switch case block if (this.preSwitchInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSwitchInitStateIndex); } } } statement.generateCode(this.scope, codeStream); } } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.removeVariable(this.dispatchStringCopy); if (this.scope != currentScope) { codeStream.exitUserScope(this.scope); } // place the trailing labels (for break and default case) this.breakLabel.place(); if (this.defaultCase == null) { // we want to force an line number entry to get an end position after the switch statement codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd, true); defaultCaseLabel.place(); defaultBranchLabel.place(); } codeStream.recordPositionsFrom(pc, this.sourceStart); } catch (Throwable e) { e.printStackTrace(); } finally { if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block } } /** * Switch 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 (this.expression.resolvedType.id == TypeIds.T_JavaLangString) { generateCodeForStringSwitch(currentScope, codeStream); return; } try { if ((this.bits & IsReachable) == 0) { return; } int pc = codeStream.position; // prepare the labels and constants this.breakLabel.initialize(codeStream); CaseLabel[] caseLabels = new CaseLabel[this.caseCount]; for (int i = 0, max = this.caseCount; i < max; i++) { this.cases[i].targetLabel = (caseLabels[i] = new CaseLabel(codeStream)); caseLabels[i].tagBits |= BranchLabel.USED; } CaseLabel defaultLabel = new CaseLabel(codeStream); final boolean hasCases = this.caseCount != 0; if (hasCases) defaultLabel.tagBits |= BranchLabel.USED; if (this.defaultCase != null) { this.defaultCase.targetLabel = defaultLabel; } final TypeBinding resolvedType = this.expression.resolvedType; boolean valueRequired = false; if (resolvedType.isEnum()) { // go through the translation table codeStream.invoke(Opcodes.OPC_invokestatic, this.synthetic, null /* default declaringClass */); this.expression.generateCode(currentScope, codeStream, true); // get enum constant ordinal() codeStream.invokeEnumOrdinal(resolvedType.constantPoolName()); codeStream.iaload(); if (!hasCases) { // we can get rid of the generated ordinal value codeStream.pop(); } } else { valueRequired = this.expression.constant == Constant.NotAConstant || hasCases; // generate expression this.expression.generateCode(currentScope, codeStream, valueRequired); } // generate the appropriate switch table/lookup bytecode if (hasCases) { 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 < this.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); int max = localKeysCopy[this.caseCount - 1]; int min = localKeysCopy[0]; if ((long) (this.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.compilerOptions().complianceLevel < ClassFileConstants.JDK1_4) { codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels); } else { codeStream.tableswitch( defaultLabel, min, max, this.constants, sortedIndexes, caseLabels); } } else { codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels); } codeStream.recordPositionsFrom(codeStream.position, this.expression.sourceEnd); } else if (valueRequired) { codeStream.pop(); } // generate the switch block statements int caseIndex = 0; 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.enclosingCase = this.cases[caseIndex]; // record entering in a switch case block if (this.preSwitchInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSwitchInitStateIndex); } caseIndex++; } else { if (statement == this.defaultCase) { // statements[i] is a case or a default case this.scope.enclosingCase = this.defaultCase; // record entering in a switch case block if (this.preSwitchInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSwitchInitStateIndex); } } } statement.generateCode(this.scope, codeStream); } } // May loose some local variable initializations : affecting the local variable attributes if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } if (this.scope != currentScope) { codeStream.exitUserScope(this.scope); } // place the trailing labels (for break and default case) this.breakLabel.place(); if (this.defaultCase == null) { // we want to force an line number entry to get an end position after the switch statement codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd, true); defaultLabel.place(); } codeStream.recordPositionsFrom(pc, this.sourceStart); } finally { if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block } } public StringBuffer printStatement(int indent, StringBuffer output) { printIndent(indent, output).append("switch ("); //$NON-NLS-1$ this.expression.printExpression(0, output).append(") {"); //$NON-NLS-1$ if (this.statements != null) { for (int i = 0; i < this.statements.length; i++) { output.append('\n'); if (this.statements[i] instanceof CaseStatement) { this.statements[i].printStatement(indent, output); } else { this.statements[i].printStatement(indent+2, output); } } } output.append("\n"); //$NON-NLS-1$ return printIndent(indent, output).append('}'); } public void resolve(BlockScope upperScope) { try { boolean isEnumSwitch = false; boolean isStringSwitch = false; TypeBinding expressionType = this.expression.resolveType(upperScope); CompilerOptions compilerOptions = upperScope.compilerOptions(); if (expressionType != null) { this.expression.computeConversion(upperScope, expressionType, expressionType); checkType: { if (!expressionType.isValidBinding()) { expressionType = null; // fault-tolerance: ignore type mismatch from constants from hereon break checkType; } else if (expressionType.isBaseType()) { if (this.expression.isConstantValueOfTypeAssignableToType(expressionType, TypeBinding.INT)) break checkType; if (expressionType.isCompatibleWith(TypeBinding.INT)) break checkType; } else if (expressionType.isEnum()) { isEnumSwitch = true; if (compilerOptions.complianceLevel < ClassFileConstants.JDK1_5) { upperScope.problemReporter().incorrectSwitchType(this.expression, expressionType); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317 } break checkType; } else if (upperScope.isBoxingCompatibleWith(expressionType, TypeBinding.INT)) { this.expression.computeConversion(upperScope, TypeBinding.INT, expressionType); break checkType; } else if (compilerOptions.complianceLevel >= ClassFileConstants.JDK1_7 && expressionType.id == TypeIds.T_JavaLangString) { isStringSwitch = true; break checkType; } upperScope.problemReporter().incorrectSwitchType(this.expression, expressionType); expressionType = null; // fault-tolerance: ignore type mismatch from constants from hereon } } if (isStringSwitch) { // the secret variable should be created before iterating over the switch's statements that could // create more locals. This must be done to prevent overlapping of locals // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=356002 this.dispatchStringCopy = new LocalVariableBinding(SecretStringVariableName, upperScope.getJavaLangString(), ClassFileConstants.AccDefault, false); upperScope.addLocalVariable(this.dispatchStringCopy); this.dispatchStringCopy.setConstant(Constant.NotAConstant); this.dispatchStringCopy.useFlag = LocalVariableBinding.USED; } if (this.statements != null) { this.scope = new BlockScope(upperScope); int length; // collection of cases is too big but we will only iterate until caseCount this.cases = new CaseStatement[length = this.statements.length]; if (!isStringSwitch) { this.constants = new int[length]; } else { this.stringConstants = new String[length]; } int counter = 0; for (int i = 0; i < length; i++) { Constant constant; final Statement statement = this.statements[i]; if ((constant = statement.resolveCase(this.scope, expressionType, this)) != Constant.NotAConstant) { if (!isStringSwitch) { int key = constant.intValue(); //----check for duplicate case statement------------ for (int j = 0; j < counter; j++) { if (this.constants[j] == key) { reportDuplicateCase((CaseStatement) statement, this.cases[j], length); } } this.constants[counter++] = key; } else { String key = constant.stringValue(); //----check for duplicate case statement------------ for (int j = 0; j < counter; j++) { if (this.stringConstants[j].equals(key)) { reportDuplicateCase((CaseStatement) statement, this.cases[j], length); } } this.stringConstants[counter++] = key; } } } if (length != counter) { // resize constants array if (!isStringSwitch) { System.arraycopy(this.constants, 0, this.constants = new int[counter], 0, counter); } else { System.arraycopy(this.stringConstants, 0, this.stringConstants = new String[counter], 0, counter); } } } else { if ((this.bits & UndocumentedEmptyBlock) != 0) { upperScope.problemReporter().undocumentedEmptyBlock(this.blockStart, this.sourceEnd); } } // check default case for all kinds of switch: if (this.defaultCase == null) { if (compilerOptions.getSeverity(CompilerOptions.MissingDefaultCase) == ProblemSeverities.Ignore) { if (isEnumSwitch) { upperScope.methodScope().hasMissingSwitchDefault = true; } } else { upperScope.problemReporter().missingDefaultCase(this, isEnumSwitch, expressionType); } } // for enum switch, check if all constants are accounted for (perhaps depending on existence of a default case) if (isEnumSwitch && compilerOptions.complianceLevel >= ClassFileConstants.JDK1_5) { if (this.defaultCase == null || compilerOptions.reportMissingEnumCaseDespiteDefault) { int constantCount = this.constants == null ? 0 : this.constants.length; // could be null if no case statement if (constantCount == this.caseCount && this.caseCount != ((ReferenceBinding)expressionType).enumConstantCount()) { FieldBinding[] enumFields = ((ReferenceBinding)expressionType.erasure()).fields(); for (int i = 0, max = enumFields.length; i 0) { label.becomeDelegateFor(this.breakLabel); } } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java0000644000175000001440000002335312212041344031410 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class JavadocMessageSend extends MessageSend { public int tagSourceStart, tagSourceEnd; public int tagValue; public JavadocMessageSend(char[] name, long pos) { this.selector = name; this.nameSourcePosition = pos; this.sourceStart = (int) (this.nameSourcePosition >>> 32); this.sourceEnd = (int) this.nameSourcePosition; this.bits |= InsideJavadoc; } public JavadocMessageSend(char[] name, long pos, JavadocArgumentExpression[] arguments) { this(name, pos); this.arguments = arguments; } /* * Resolves type on a Block or Class scope. */ private TypeBinding internalResolveType(Scope scope) { // Answer the signature return type // Base type promotion this.constant = Constant.NotAConstant; if (this.receiver == null) { this.actualReceiverType = scope.enclosingReceiverType(); } else if (scope.kind == Scope.CLASS_SCOPE) { this.actualReceiverType = this.receiver.resolveType((ClassScope) scope); } else { this.actualReceiverType = this.receiver.resolveType((BlockScope) scope); } // will check for null after args are resolved TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; boolean hasArgsTypeVar = false; if (this.arguments != null) { boolean argHasError = false; // typeChecks all arguments int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++){ Expression argument = this.arguments[i]; if (scope.kind == Scope.CLASS_SCOPE) { argumentTypes[i] = argument.resolveType((ClassScope)scope); } else { argumentTypes[i] = argument.resolveType((BlockScope)scope); } if (argumentTypes[i] == null) { argHasError = true; } else if (!hasArgsTypeVar) { hasArgsTypeVar = argumentTypes[i].isTypeVariable(); } } if (argHasError) { return null; } } // check receiver type if (this.actualReceiverType == null) { return null; } this.actualReceiverType = scope.environment().convertToRawType(this.receiver.resolvedType, true /*force the conversion of enclosing types*/); ReferenceBinding enclosingType = scope.enclosingReceiverType(); if (enclosingType==null ? false : enclosingType.isCompatibleWith(this.actualReceiverType)) { this.bits |= ASTNode.SuperAccess; } // base type cannot receive any message if (this.actualReceiverType.isBaseType()) { scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, argumentTypes, scope.getDeclarationModifiers()); return null; } this.binding = scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); if (!this.binding.isValidBinding()) { // Try method in enclosing types TypeBinding enclosingTypeBinding = this.actualReceiverType; MethodBinding methodBinding = this.binding; while (!methodBinding.isValidBinding() && (enclosingTypeBinding.isMemberType() || enclosingTypeBinding.isLocalType())) { enclosingTypeBinding = enclosingTypeBinding.enclosingType(); methodBinding = scope.getMethod(enclosingTypeBinding, this.selector, argumentTypes, this); } if (methodBinding.isValidBinding()) { this.binding = methodBinding; } else { // Try to search a constructor instead enclosingTypeBinding = this.actualReceiverType; MethodBinding contructorBinding = this.binding; if (!contructorBinding.isValidBinding() && CharOperation.equals(this.selector, enclosingTypeBinding.shortReadableName())) { contructorBinding = scope.getConstructor((ReferenceBinding)enclosingTypeBinding, argumentTypes, this); } while (!contructorBinding.isValidBinding() && (enclosingTypeBinding.isMemberType() || enclosingTypeBinding.isLocalType())) { enclosingTypeBinding = enclosingTypeBinding.enclosingType(); if (CharOperation.equals(this.selector, enclosingTypeBinding.shortReadableName())) { contructorBinding = scope.getConstructor((ReferenceBinding)enclosingTypeBinding, argumentTypes, this); } } if (contructorBinding.isValidBinding()) { this.binding = contructorBinding; } } } if (!this.binding.isValidBinding()) { // implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient switch (this.binding.problemId()) { case ProblemReasons.NonStaticReferenceInConstructorInvocation: case ProblemReasons.NonStaticReferenceInStaticContext: case ProblemReasons.InheritedNameHidesEnclosingName : case ProblemReasons.Ambiguous: MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; if (closestMatch != null) { this.binding = closestMatch; // ignore problem if can reach target method through it } } } if (!this.binding.isValidBinding()) { if (this.receiver.resolvedType instanceof ProblemReferenceBinding) { // problem already got signaled on receiver, do not report secondary problem return null; } if (this.binding.declaringClass == null) { if (this.actualReceiverType instanceof ReferenceBinding) { this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType; } else { scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, argumentTypes, scope.getDeclarationModifiers()); return null; } } scope.problemReporter().javadocInvalidMethod(this, this.binding, scope.getDeclarationModifiers()); // record the closest match, for clients who may still need hint about possible method match if (this.binding instanceof ProblemMethodBinding) { MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; if (closestMatch != null) this.binding = closestMatch; } return this.resolvedType = this.binding == null ? null : this.binding.returnType; } else if (hasArgsTypeVar) { MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, argumentTypes, ProblemReasons.NotFound); scope.problemReporter().javadocInvalidMethod(this, problem, scope.getDeclarationModifiers()); } else if (this.binding.isVarargs()) { int length = argumentTypes.length; if (!(this.binding.parameters.length == length && argumentTypes[length-1].isArrayType())) { MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, argumentTypes, ProblemReasons.NotFound); scope.problemReporter().javadocInvalidMethod(this, problem, scope.getDeclarationModifiers()); } } else { int length = argumentTypes.length; for (int i=0; i 0) output.append(", "); //$NON-NLS-1$ this.arguments[i].printExpression(0, output); } } return output.append(')'); } public TypeBinding resolveType(BlockScope scope) { return internalResolveType(scope); } public TypeBinding resolveType(ClassScope scope) { return internalResolveType(scope); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { if (this.receiver != null) { this.receiver.traverse(visitor, blockScope); } if (this.arguments != null) { int argumentsLength = this.arguments.length; for (int i = 0; i < argumentsLength; i++) this.arguments[i].traverse(visitor, blockScope); } } visitor.endVisit(this, blockScope); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, ClassScope scope) { if (visitor.visit(this, scope)) { if (this.receiver != null) { this.receiver.traverse(visitor, scope); } if (this.arguments != null) { int argumentsLength = this.arguments.length; for (int i = 0; i < argumentsLength; i++) this.arguments[i].traverse(visitor, scope); } } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java0000644000175000001440000000146612212041344030260 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; public abstract class MagicLiteral extends Literal { public MagicLiteral(int start , int end) { super(start,end); } public boolean isValidJavaStatement(){ return false ; } public char[] source() { return null; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/SuperReference.java0000644000175000001440000000415512212041344030636 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Jesper S Moller - Contributions for * Bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class SuperReference extends ThisReference { public SuperReference(int sourceStart, int sourceEnd) { super(sourceStart, sourceEnd); } public static ExplicitConstructorCall implicitSuperConstructorCall() { return new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); } public boolean isImplicitThis() { return false; } public boolean isSuper() { return true; } public boolean isThis() { return false ; } public StringBuffer printExpression(int indent, StringBuffer output){ return output.append("super"); //$NON-NLS-1$ } public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; if (!checkAccess(scope.methodScope())) return null; ReferenceBinding enclosingReceiverType = scope.enclosingReceiverType(); if (enclosingReceiverType.id == T_JavaLangObject) { scope.problemReporter().cannotUseSuperInJavaLangObject(this); return null; } return this.resolvedType = enclosingReceiverType.superclass(); } public void traverse(ASTVisitor visitor, BlockScope blockScope) { visitor.visit(this, blockScope); visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/FieldReference.java0000644000175000001440000007560612212041344030574 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 185682 - Increment/decrement operators mark local variables as read * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * Bug 412203 - [compiler] Internal compiler error: java.lang.IllegalArgumentException: info cannot be null * Jesper S Moller - Contributions for * Bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; public class FieldReference extends Reference implements InvocationSite { public static final int READ = 0; public static final int WRITE = 1; public Expression receiver; public char[] token; public FieldBinding binding; // exact binding resulting from lookup public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor public long nameSourcePosition; //(start<<32)+end public TypeBinding actualReceiverType; public TypeBinding genericCast; public FieldReference(char[] source, long pos) { this.token = source; this.nameSourcePosition = pos; //by default the position are the one of the field (not true for super access) this.sourceStart = (int) (pos >>> 32); this.sourceEnd = (int) (pos & 0x00000000FFFFFFFFL); this.bits |= Binding.FIELD; } public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { // compound assignment extra work if (isCompound) { // check the variable part is initialized if blank final if (this.binding.isBlankFinal() && this.receiver.isThis() && currentScope.needBlankFinalFieldInitializationCheck(this.binding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(this.binding.declaringClass.original(), flowInfo); if (!fieldInits.isDefinitelyAssigned(this.binding)) { currentScope.problemReporter().uninitializedBlankFinalField(this.binding, this); // we could improve error msg here telling "cannot use compound assignment on final blank field" } } manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); } flowInfo = this.receiver .analyseCode(currentScope, flowContext, flowInfo, !this.binding.isStatic()) .unconditionalInits(); if (assignment.expression != null) { flowInfo = assignment .expression .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); } manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); // check if assigning a final field if (this.binding.isFinal()) { // in a context where it can be assigned? if (this.binding.isBlankFinal() && !isCompound && this.receiver.isThis() && !(this.receiver instanceof QualifiedThisReference) && ((this.receiver.bits & ASTNode.ParenthesizedMASK) == 0) // (this).x is forbidden && currentScope.allowBlankFinalFieldAssignment(this.binding)) { if (flowInfo.isPotentiallyAssigned(this.binding)) { currentScope.problemReporter().duplicateInitializationOfBlankFinalField( this.binding, this); } else { flowContext.recordSettingFinal(this.binding, this, flowInfo); } flowInfo.markAsDefinitelyAssigned(this.binding); } else { // assigning a final field outside an initializer or constructor or wrong reference currentScope.problemReporter().cannotAssignToFinalField(this.binding, this); } } else if (this.binding.isNonNull()) { // in a context where it can be assigned? if ( !isCompound && this.receiver.isThis() && !(this.receiver instanceof QualifiedThisReference) && this.receiver.resolvedType == this.binding.declaringClass // inherited fields are not tracked here && ((this.receiver.bits & ASTNode.ParenthesizedMASK) == 0)) { // (this).x is forbidden flowInfo.markAsDefinitelyAssigned(this.binding); } } return flowInfo; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return analyseCode(currentScope, flowContext, flowInfo, true); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { boolean nonStatic = !this.binding.isStatic(); this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic); if (nonStatic) { this.receiver.checkNPE(currentScope, flowContext, flowInfo); } if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); } return flowInfo; } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { if (flowContext.isNullcheckedFieldAccess(this)) { return true; // enough seen } return checkNullableFieldDereference(scope, this.binding, this.nameSourcePosition); } /** * @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(); TypeBinding originalType = originalBinding.type; // extra cast needed if field type is type variable if (originalType.leafComponentType().isTypeVariable()) { TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) ? compileTimeType // unboxing: checkcast before conversion : runtimeTimeType; this.genericCast = originalBinding.type.genericCast(targetType); if (this.genericCast instanceof ReferenceBinding) { ReferenceBinding referenceCast = (ReferenceBinding) this.genericCast; if (!referenceCast.canBeSeenBy(scope)) { scope.problemReporter().invalidType(this, new ProblemReferenceBinding( CharOperation.splitOn('.', referenceCast.shortReadableName()), referenceCast, ProblemReasons.NotVisible)); } } } } super.computeConversion(scope, runtimeTimeType, compileTimeType); } public FieldBinding fieldBinding() { return this.binding; } public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { int pc = codeStream.position; FieldBinding codegenBinding = this.binding.original(); this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic()); codeStream.recordPositionsFrom(pc, this.sourceStart); assignment.expression.generateCode(currentScope, codeStream, true); fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } // no need for generic cast as value got dupped } /** * Field reference 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) { int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { if (valueRequired) { codeStream.generateConstant(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } FieldBinding codegenBinding = this.binding.original(); boolean isStatic = codegenBinding.isStatic(); boolean isThisReceiver = this.receiver instanceof ThisReference; Constant fieldConstant = codegenBinding.constant(); if (fieldConstant != Constant.NotAConstant) { if (!isThisReceiver) { this.receiver.generateCode(currentScope, codeStream, !isStatic); if (!isStatic){ codeStream.invokeObjectGetClass(); codeStream.pop(); } } if (valueRequired) { codeStream.generateConstant(fieldConstant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } if (valueRequired || (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) || ((this.implicitConversion & TypeIds.UNBOXING) != 0) || (this.genericCast != null)) { this.receiver.generateCode(currentScope, codeStream, !isStatic); if ((this.bits & NeedReceiverGenericCast) != 0) { codeStream.checkcast(this.actualReceiverType); } pc = codeStream.position; if (codegenBinding.declaringClass == null) { // array length codeStream.arraylength(); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { // could occur if !valueRequired but compliance >= 1.4 codeStream.pop(); } } else { if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); if (isStatic) { codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } // required cast must occur even if no value is required if (this.genericCast != null) codeStream.checkcast(this.genericCast); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else { boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; // conversion only generated if unboxing if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.type.id) { case T_long : case T_double : codeStream.pop2(); break; default : codeStream.pop(); } } } } else { if (isThisReceiver) { if (isStatic){ // if no valueRequired, still need possible side-effects of invocation, if field belongs to different class if (this.binding.original().declaringClass != this.actualReceiverType.erasure()) { MethodBinding accessor = this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.READ]; if (accessor == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } switch (codegenBinding.type.id) { case T_long : case T_double : codeStream.pop2(); break; default : codeStream.pop(); } } } } else { this.receiver.generateCode(currentScope, codeStream, !isStatic); if (!isStatic){ codeStream.invokeObjectGetClass(); // perform null check codeStream.pop(); } } } codeStream.recordPositionsFrom(pc, this.sourceEnd); } public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { boolean isStatic; // check if compound assignment is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, this.binding, valueRequired); FieldBinding codegenBinding = this.binding.original(); this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic())); if (isStatic) { if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } else { codeStream.dup(); if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } int operationTypeID; switch(operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) { case T_JavaLangString : case T_JavaLangObject : case T_undefined : codeStream.generateStringConcatenationAppend(currentScope, null, expression); break; default : if (this.genericCast != null) codeStream.checkcast(this.genericCast); // promote the array reference to the suitable operation type codeStream.generateImplicitConversion(this.implicitConversion); // generate the increment value (will by itself be promoted to the operation value) if (expression == IntLiteral.One) { // prefix operation codeStream.generateConstant(expression.constant, this.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(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), valueRequired); // no need for generic cast as value got dupped } public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { boolean isStatic; // check if postIncrement is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, this.binding, valueRequired); FieldBinding codegenBinding = this.binding.original(); this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic())); if (isStatic) { if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } else { codeStream.dup(); if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } TypeBinding operandType; if (this.genericCast != null) { codeStream.checkcast(this.genericCast); operandType = this.genericCast; } else { operandType = codegenBinding.type; } if (valueRequired) { if (isStatic) { switch (operandType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2(); break; default : codeStream.dup(); break; } } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] switch (operandType.id) { case TypeIds.T_long : case TypeIds.T_double : codeStream.dup2_x1(); break; default : codeStream.dup_x1(); break; } } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateConstant( postIncrement.expression.constant, this.implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion( postIncrement.preAssignImplicitConversion); fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), false); } /** * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments() */ public TypeBinding[] genericTypeArguments() { return null; } public boolean isEquivalent(Reference reference) { // only consider field references relative to "this": if (this.receiver.isThis() && !(this.receiver instanceof QualifiedThisReference)) { // current is a simple "this.f1" char[] otherToken = null; // matching 'reference' could be "f1" or "this.f1": if (reference instanceof SingleNameReference) { otherToken = ((SingleNameReference) reference).token; } else if (reference instanceof FieldReference) { FieldReference fr = (FieldReference) reference; if (fr.receiver.isThis() && !(fr.receiver instanceof QualifiedThisReference)) { otherToken = fr.token; } } return otherToken != null && CharOperation.equals(this.token, otherToken); } else { // search deeper for "this" inside: char[][] thisTokens = getThisFieldTokens(1); if (thisTokens == null) { return false; } // other can be "this.f1.f2", too, or "f1.f2": char[][] otherTokens = null; if (reference instanceof FieldReference) { otherTokens = ((FieldReference) reference).getThisFieldTokens(1); } else if (reference instanceof QualifiedNameReference) { if (((QualifiedNameReference)reference).binding instanceof LocalVariableBinding) return false; // initial variable mismatch: local (from f1.f2) vs. field (from this.f1.f2) otherTokens = ((QualifiedNameReference) reference).tokens; } return CharOperation.equals(thisTokens, otherTokens); } } private char[][] getThisFieldTokens(int nestingCount) { char[][] result = null; if (this.receiver.isThis() && ! (this.receiver instanceof QualifiedThisReference)) { // found an inner-most this-reference, start building the token array: result = new char[nestingCount][]; // fill it front to tail while traveling back out: result[0] = this.token; } else if (this.receiver instanceof FieldReference) { result = ((FieldReference)this.receiver).getThisFieldTokens(nestingCount+1); if (result != null) { // front to tail: outermost is last: result[result.length-nestingCount] = this.token; } } return result; } public boolean isSuperAccess() { return this.receiver.isSuper(); } public boolean isTypeAccess() { return this.receiver != null && this.receiver.isTypeReference(); } public FieldBinding lastFieldBinding() { return this.binding; } /* * No need to emulate access to protected fields since not implicitly accessed */ public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return; // if field from parameterized type got found, use the original field at codegen time FieldBinding codegenBinding = this.binding.original(); if (this.binding.isPrivate()) { if ((currentScope.enclosingSourceType() != codegenBinding.declaringClass) && this.binding.constant() == Constant.NotAConstant) { if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2]; this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = ((SourceTypeBinding) codegenBinding.declaringClass).addSyntheticMethod(codegenBinding, isReadAccess, false /* not super ref in remote type*/); currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess); return; } } else if (this.receiver instanceof QualifiedSuperReference) { // qualified super // qualified super need emulation always SourceTypeBinding destinationType = (SourceTypeBinding) (((QualifiedSuperReference) this.receiver).currentCompatibleType); if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2]; this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(codegenBinding, isReadAccess, isSuperAccess()); currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess); return; } else if (this.binding.isProtected()) { SourceTypeBinding enclosingSourceType; if (((this.bits & ASTNode.DepthMASK) != 0) && this.binding.declaringClass.getPackage() != (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()) { SourceTypeBinding currentCompatibleType = (SourceTypeBinding) enclosingSourceType.enclosingTypeAt( (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2]; this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(codegenBinding, isReadAccess, isSuperAccess()); currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess); return; } } } public Constant optimizedBooleanConstant() { switch (this.resolvedType.id) { case T_boolean : case T_JavaLangBoolean : return this.constant != Constant.NotAConstant ? this.constant : this.binding.constant(); default : return Constant.NotAConstant; } } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope) */ public TypeBinding postConversionType(Scope scope) { TypeBinding convertedType = this.resolvedType; if (this.genericCast != null) convertedType = this.genericCast; int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; switch (runtimeType) { case T_boolean : convertedType = TypeBinding.BOOLEAN; break; case T_byte : convertedType = TypeBinding.BYTE; break; case T_short : convertedType = TypeBinding.SHORT; break; case T_char : convertedType = TypeBinding.CHAR; break; case T_int : convertedType = TypeBinding.INT; break; case T_float : convertedType = TypeBinding.FLOAT; break; case T_long : convertedType = TypeBinding.LONG; break; case T_double : convertedType = TypeBinding.DOUBLE; break; default : } if ((this.implicitConversion & TypeIds.BOXING) != 0) { convertedType = scope.environment().computeBoxingType(convertedType); } return convertedType; } public StringBuffer printExpression(int indent, StringBuffer output) { return this.receiver.printExpression(0, output).append('.').append(this.token); } public TypeBinding resolveType(BlockScope scope) { // Answer the signature type of the field. // constants are propaged when the field is final // and initialized with a (compile time) constant //always ignore receiver cast, since may affect constant pool reference boolean receiverCast = false; if (this.receiver instanceof CastExpression) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on receiverCast = true; } this.actualReceiverType = this.receiver.resolveType(scope); if (this.actualReceiverType == null) { this.constant = Constant.NotAConstant; return null; } if (receiverCast) { // due to change of declaring class with receiver type, only identity cast should be notified if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { scope.problemReporter().unnecessaryCast((CastExpression)this.receiver); } } // the case receiverType.isArrayType and token = 'length' is handled by the scope API FieldBinding fieldBinding = this.binding = scope.getField(this.actualReceiverType, this.token, this); if (!fieldBinding.isValidBinding()) { this.constant = Constant.NotAConstant; if (this.receiver.resolvedType instanceof ProblemReferenceBinding) { // problem already got signaled on receiver, do not report secondary problem return null; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=245007 avoid secondary errors in case of // missing super type for anonymous classes ... ReferenceBinding declaringClass = fieldBinding.declaringClass; boolean avoidSecondary = declaringClass != null && declaringClass.isAnonymousType() && declaringClass.superclass() instanceof MissingTypeBinding; if (!avoidSecondary) { scope.problemReporter().invalidField(this, this.actualReceiverType); } if (fieldBinding instanceof ProblemFieldBinding) { ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) fieldBinding; FieldBinding closestMatch = problemFieldBinding.closestMatch; switch(problemFieldBinding.problemId()) { case ProblemReasons.InheritedNameHidesEnclosingName : case ProblemReasons.NotVisible : case ProblemReasons.NonStaticReferenceInConstructorInvocation : case ProblemReasons.NonStaticReferenceInStaticContext : if (closestMatch != null) { fieldBinding = closestMatch; } } } if (!fieldBinding.isValidBinding()) { return null; } } // handle indirect inheritance thru variable secondary bound // receiver may receive generic cast, as part of implicit conversion TypeBinding oldReceiverType = this.actualReceiverType; this.actualReceiverType = this.actualReceiverType.getErasureCompatibleType(fieldBinding.declaringClass); this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); if (this.actualReceiverType != oldReceiverType && this.receiver.postConversionType(scope) != this.actualReceiverType) { // record need for explicit cast at codegen since receiver could not handle it this.bits |= NeedReceiverGenericCast; } if (isFieldUseDeprecated(fieldBinding, scope, this.bits)) { scope.problemReporter().deprecatedField(fieldBinding, this); } boolean isImplicitThisRcv = this.receiver.isImplicitThis(); this.constant = isImplicitThisRcv ? fieldBinding.constant() : Constant.NotAConstant; if (fieldBinding.isStatic()) { // static field accessed through receiver? legal but unoptimal (optional warning) if (!(isImplicitThisRcv || (this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0))) { scope.problemReporter().nonStaticAccessToStaticField(this, fieldBinding); } ReferenceBinding declaringClass = this.binding.declaringClass; if (!isImplicitThisRcv && declaringClass != this.actualReceiverType && declaringClass.canBeSeenBy(scope)) { scope.problemReporter().indirectAccessToStaticField(this, fieldBinding); } // check if accessing enum static field in initializer if (declaringClass.isEnum()) { MethodScope methodScope = scope.methodScope(); SourceTypeBinding sourceType = scope.enclosingSourceType(); if (this.constant == Constant.NotAConstant && !methodScope.isStatic && (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body && methodScope.isInsideInitializerOrConstructor()) { scope.problemReporter().enumStaticFieldUsedDuringInitialization(this.binding, this); } } } TypeBinding fieldType = fieldBinding.type; if (fieldType != null) { if ((this.bits & ASTNode.IsStrictlyAssigned) == 0) { fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access } this.resolvedType = fieldType; if ((fieldType.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().invalidType(this, fieldType); return null; } } return fieldType; } public void setActualReceiverType(ReferenceBinding receiverType) { this.actualReceiverType = receiverType; } public void setDepth(int depth) { this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any if (depth > 0) { this.bits |= (depth & 0xFF) << ASTNode.DepthSHIFT; // encoded on 8 bits } } public void setFieldIndex(int index) { // ignored } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.receiver.traverse(visitor, scope); } visitor.endVisit(this, scope); } public VariableBinding nullAnnotatedVariableBinding() { if (this.binding != null && ((this.binding.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0)) { return this.binding; } return null; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Clinit.java0000644000175000001440000003435712212041344027152 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Patrick Wienands - Contribution for bug 393749 * Stephan Herrmann - Contribution for * bug 331649 - [compiler][null] consider null annotations for fields *******************************************************************************/ 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.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; public class Clinit extends AbstractMethodDeclaration { private static int ENUM_CONSTANTS_THRESHOLD = 2000; private FieldBinding assertionSyntheticFieldBinding = null; private FieldBinding classLiteralSyntheticField = null; public Clinit(CompilationResult compilationResult) { super(compilationResult); this.modifiers = 0; this.selector = TypeConstants.CLINIT; } public void analyseCode( ClassScope classScope, InitializationFlowContext staticInitializerFlowContext, FlowInfo flowInfo) { if (this.ignoreFurtherInvestigation) return; try { ExceptionHandlingFlowContext clinitContext = new ExceptionHandlingFlowContext( staticInitializerFlowContext.parent, this, Binding.NO_EXCEPTIONS, staticInitializerFlowContext, this.scope, FlowInfo.DEAD_END); // check for missing returning path if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.bits |= ASTNode.NeedFreeReturn; } // check missing blank final field initializations flowInfo = flowInfo.mergedWith(staticInitializerFlowContext.initsOnReturn); FieldBinding[] fields = this.scope.enclosingSourceType().fields(); for (int i = 0, count = fields.length; i < count; i++) { FieldBinding field = fields[i]; if (field.isStatic()) { if (!flowInfo.isDefinitelyAssigned(field)) { if (field.isFinal()) { this.scope.problemReporter().uninitializedBlankFinalField( field, this.scope.referenceType().declarationOf(field.original())); // can complain against the field decl, since only one } else if (field.isNonNull()) { this.scope.problemReporter().uninitializedNonNullField( field, this.scope.referenceType().declarationOf(field.original())); } } } } // check static initializers thrown exceptions staticInitializerFlowContext.checkInitializerExceptions( this.scope, clinitContext, flowInfo); } catch (AbortMethod e) { this.ignoreFurtherInvestigation = true; } } /** * Bytecode generation for a method * * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile */ public void generateCode(ClassScope classScope, ClassFile classFile) { int clinitOffset = 0; if (this.ignoreFurtherInvestigation) { // should never have to add any problem method return; } boolean restart = false; do { try { clinitOffset = classFile.contentsOffset; this.generateCode(classScope, classFile, clinitOffset); restart = false; } catch (AbortMethod e) { // should never occur // the clinit referenceContext is the type declaration // All clinit problems will be reported against the type: AbortType instead of AbortMethod // reset the contentsOffset to the value before generating the clinit code // decrement the number of method info as well. // This is done in the addProblemMethod and addProblemConstructor for other // cases. if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { // a branch target required a goto_w, restart code gen in wide mode. classFile.contentsOffset = clinitOffset; classFile.methodCount--; classFile.codeStream.resetInWideMode(); // request wide mode // restart method generation restart = true; } else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) { classFile.contentsOffset = clinitOffset; classFile.methodCount--; classFile.codeStream.resetForCodeGenUnusedLocals(); // restart method generation restart = true; } else { // produce a problem method accounting for this fatal error classFile.contentsOffset = clinitOffset; classFile.methodCount--; restart = false; } } } while (restart); } /** * Bytecode generation for a method * * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile */ private void generateCode( ClassScope classScope, ClassFile classFile, int clinitOffset) { ConstantPool constantPool = classFile.constantPool; int constantPoolOffset = constantPool.currentOffset; int constantPoolIndex = constantPool.currentIndex; classFile.generateMethodInfoHeaderForClinit(); int codeAttributeOffset = classFile.contentsOffset; classFile.generateCodeAttributeHeader(); CodeStream codeStream = classFile.codeStream; resolve(classScope); codeStream.reset(this, classFile); TypeDeclaration declaringType = classScope.referenceContext; // initialize local positions - including initializer scope. MethodScope staticInitializerScope = declaringType.staticInitializerScope; staticInitializerScope.computeLocalVariablePositions(0, codeStream); // 1.4 feature // This has to be done before any other initialization if (this.assertionSyntheticFieldBinding != null) { // generate code related to the activation of assertion for this class codeStream.generateClassLiteralAccessForType( classScope.outerMostClassScope().enclosingSourceType(), this.classLiteralSyntheticField); codeStream.invokeJavaLangClassDesiredAssertionStatus(); BranchLabel falseLabel = new BranchLabel(codeStream); codeStream.ifne(falseLabel); codeStream.iconst_1(); BranchLabel jumpLabel = new BranchLabel(codeStream); codeStream.decrStackSize(1); codeStream.goto_(jumpLabel); falseLabel.place(); codeStream.iconst_0(); jumpLabel.place(); codeStream.fieldAccess(Opcodes.OPC_putstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */); } // generate static fields/initializers/enum constants final FieldDeclaration[] fieldDeclarations = declaringType.fields; int sourcePosition = -1; int remainingFieldCount = 0; if (TypeDeclaration.kind(declaringType.modifiers) == TypeDeclaration.ENUM_DECL) { int enumCount = declaringType.enumConstantsCounter; if (enumCount > ENUM_CONSTANTS_THRESHOLD) { // generate synthetic methods to initialize all the enum constants int begin = -1; int count = 0; if (fieldDeclarations != null) { int max = fieldDeclarations.length; for (int i = 0; i < max; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; if (fieldDecl.isStatic()) { if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { if (begin == -1) { begin = i; } count++; if (count > ENUM_CONSTANTS_THRESHOLD) { SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, i); codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null /* default declaringClass */); begin = i; count = 1; } } else { remainingFieldCount++; } } } if (count != 0) { // add last synthetic method SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, max); codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null /* default declaringClass */); } } } else 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); } else { remainingFieldCount++; } } } } // enum need to initialize $VALUES synthetic cache of enum constants // $VALUES := new [] codeStream.generateInlinedValue(enumCount); codeStream.anewarray(declaringType.binding); if (enumCount > 0) { if (fieldDeclarations != null) { 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.fieldAccess(Opcodes.OPC_getstatic, fieldDecl.binding, null /* default declaringClass */); codeStream.aastore(); } } } } codeStream.fieldAccess(Opcodes.OPC_putstatic, declaringType.enumValuesSyntheticfield, null /* default declaringClass */); if (remainingFieldCount != 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 && remainingFieldCount >= 0; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; switch (fieldDecl.getKind()) { case AbstractVariableDeclaration.ENUM_CONSTANT : break; case AbstractVariableDeclaration.INITIALIZER : if (!fieldDecl.isStatic()) { break; } remainingFieldCount--; sourcePosition = ((Initializer) fieldDecl).block.sourceEnd; fieldDecl.generateCode(staticInitializerScope, codeStream); break; case AbstractVariableDeclaration.FIELD : if (!fieldDecl.binding.isStatic()) { break; } remainingFieldCount--; sourcePosition = fieldDecl.declarationEnd; fieldDecl.generateCode(staticInitializerScope, codeStream); break; } } } } else { if (fieldDeclarations != null) { for (int i = 0, max = fieldDeclarations.length; i < max; i++) { FieldDeclaration fieldDecl = fieldDeclarations[i]; switch (fieldDecl.getKind()) { case AbstractVariableDeclaration.INITIALIZER : if (!fieldDecl.isStatic()) break; sourcePosition = ((Initializer) fieldDecl).block.sourceEnd; fieldDecl.generateCode(staticInitializerScope, codeStream); break; case AbstractVariableDeclaration.FIELD : if (!fieldDecl.binding.isStatic()) break; sourcePosition = fieldDecl.declarationEnd; fieldDecl.generateCode(staticInitializerScope, codeStream); break; } } } } if (codeStream.position == 0) { // do not need to output a Clinit if no bytecodes // so we reset the offset inside the byte array contents. classFile.contentsOffset = clinitOffset; // like we don't addd a method we need to undo the increment on the method count classFile.methodCount--; // reset the constant pool to its state before the clinit constantPool.resetForClinit(constantPoolIndex, constantPoolOffset); } else { if ((this.bits & ASTNode.NeedFreeReturn) != 0) { int before = codeStream.position; codeStream.return_(); if (sourcePosition != -1) { // expand the last initializer variables to include the trailing return codeStream.recordPositionsFrom(before, sourcePosition); } } // Record the end of the clinit: point to the declaration of the class codeStream.recordPositionsFrom(0, declaringType.sourceStart); classFile.completeCodeAttributeForClinit(codeAttributeOffset); } } public boolean isClinit() { return true; } public boolean isInitializationMethod() { return true; } public boolean isStatic() { return true; } public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { //the clinit is filled by hand .... } public StringBuffer print(int tab, StringBuffer output) { printIndent(tab, output).append("()"); //$NON-NLS-1$ printBody(tab + 1, output); return output; } public void resolve(ClassScope classScope) { this.scope = new MethodScope(classScope, classScope.referenceContext, true); } public void traverse( ASTVisitor visitor, ClassScope classScope) { visitor.visit(this, classScope); visitor.endVisit(this, classScope); } 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 if (needClassLiteralField) { SourceTypeBinding sourceType = this.scope.outerMostClassScope().enclosingSourceType(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=22334 if (!sourceType.isInterface() && !sourceType.isBaseType()) { this.classLiteralSyntheticField = sourceType.addSyntheticFieldForClassLiteral(sourceType, this.scope); } } } } ././@LongLink0000644000000000000000000000015412251602427011643 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpressi0000644000175000001440000006526312212041344032444 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 395977 - [compiler][resource] Resource leak warning behavior possibly incorrect for anonymous inner class * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking * Jesper S Moller - Contributions for * bug 378674 - "The method can be declared as static" is wrong * Till Brychcy - Contributions for * bug 413460 - NonNullByDefault is not inherited to Constructors when accessed via Class File ******************************************************************************/ 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.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.ImplicitNullAnnotationVerifier; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; /** * 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 { //qualification may be on both side public Expression enclosingInstance; public TypeDeclaration anonymousType; public QualifiedAllocationExpression() { // for subtypes } public QualifiedAllocationExpression(TypeDeclaration anonymousType) { this.anonymousType = anonymousType; anonymousType.allocation = this; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // analyse the enclosing instance if (this.enclosingInstance != null) { flowInfo = this.enclosingInstance.analyseCode(currentScope, flowContext, flowInfo); } else { if (this.binding != null && this.binding.declaringClass != null) { ReferenceBinding superclass = this.binding.declaringClass.superclass(); if (superclass != null && superclass.isMemberType() && !superclass.isStatic()) { // creating an anonymous type of a non-static member type without an enclosing instance of parent type currentScope.resetDeclaringClassMethodStaticFlag(superclass.enclosingType()); // Reviewed for https://bugs.eclipse.org/bugs/show_bug.cgi?id=378674 : // The corresponding problem (when called from static) is not produced until during code generation } } } // check captured variables are initialized in current context (26134) checkCapturedLocalInitializationIfNecessary( (ReferenceBinding)(this.anonymousType == null ? this.binding.declaringClass.erasure() : this.binding.declaringClass.superclass().erasure()), currentScope, flowInfo); // process arguments if (this.arguments != null) { boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks; boolean hasResourceWrapperType = analyseResources && this.resolvedType instanceof ReferenceBinding && ((ReferenceBinding)this.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable); for (int i = 0, count = this.arguments.length; i < count; i++) { flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo); if (analyseResources && !hasResourceWrapperType) { // allocation of wrapped closeables is analyzed specially // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.) flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, flowContext, false); } this.arguments[i].checkNPEbyUnboxing(currentScope, flowContext, flowInfo); } analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments); } // analyse the anonymous nested type if (this.anonymousType != null) { flowInfo = this.anonymousType.analyseCode(currentScope, flowContext, flowInfo); } // record some dependency information for exception types ReferenceBinding[] thrownExceptions; if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) { if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6 thrownExceptions = currentScope.environment().convertToRawTypes(this.binding.thrownExceptions, true, true); } // check exception handling flowContext.checkExceptionHandlers( thrownExceptions, this, flowInfo.unconditionalCopy(), currentScope); } // after having analysed exceptions above start tracking newly allocated resource: if (currentScope.compilerOptions().analyseResourceLeaks && FakedTrackingVariable.isAnyCloseable(this.resolvedType)) { FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this); } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); manageSyntheticAccessIfNecessary(currentScope, flowInfo); // account for possible exceptions thrown by constructor execution: flowContext.recordAbruptExit(); return flowInfo; } public Expression enclosingInstance() { return this.enclosingInstance; } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { if (!valueRequired) currentScope.problemReporter().unusedObjectAllocation(this); int pc = codeStream.position; MethodBinding codegenBinding = this.binding.original(); ReferenceBinding allocatedType = codegenBinding.declaringClass; codeStream.new_(allocatedType); boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; if (valueRequired || isUnboxing) { codeStream.dup(); } // better highlight for allocation: display the type individually 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(this.enumConstant.name)); codeStream.generateInlinedValue(this.enumConstant.binding.id); } // handling innerclass instance allocation - enclosing instance arguments if (allocatedType.isNestedType()) { codeStream.generateSyntheticEnclosingInstanceValues( currentScope, allocatedType, enclosingInstance(), this); } // generate the arguments for constructor generateArguments(this.binding, this.arguments, currentScope, codeStream); // handling innerclass instance allocation - outer local arguments if (allocatedType.isNestedType()) { codeStream.generateSyntheticOuterArgumentValues( currentScope, allocatedType, this); } // invoke constructor if (this.syntheticAccessor == null) { codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, null /* default declaringClass */); } else { // synthetic accessor got some extra arguments appended to its signature, which need values for (int i = 0, max = this.syntheticAccessor.parameters.length - codegenBinding.parameters.length; i < max; i++) { codeStream.aconst_null(); } codeStream.invoke(Opcodes.OPC_invokespecial, this.syntheticAccessor, null /* default declaringClass */); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else if (isUnboxing) { // conversion only generated if unboxing codeStream.generateImplicitConversion(this.implicitConversion); switch (postConversionType(currentScope).id) { case T_long : case T_double : codeStream.pop2(); break; default : codeStream.pop(); } } codeStream.recordPositionsFrom(pc, this.sourceStart); if (this.anonymousType != null) { this.anonymousType.generateCode(currentScope, codeStream); } } public boolean isSuperAccess() { // necessary to lookup super constructor of anonymous type return this.anonymousType != null; } /* Inner emulation consists in either recording a dependency * link only, or performing one level of propagation. * * Dependency mechanism is used whenever dealing with source target * types, since by the time we reach them, we might not yet know their * exact need. */ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { ReferenceBinding allocatedTypeErasure = (ReferenceBinding) this.binding.declaringClass.erasure(); // perform some extra emulation work in case there is some and we are inside a local type only if (allocatedTypeErasure.isNestedType() && currentScope.enclosingSourceType().isLocalType()) { if (allocatedTypeErasure.isLocalType()) { ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, this.enclosingInstance != null); } else { // locally propagate, since we already now the desired shape for sure currentScope.propagateInnerEmulation(allocatedTypeErasure, this.enclosingInstance != null); } } } } public StringBuffer printExpression(int indent, StringBuffer output) { if (this.enclosingInstance != null) this.enclosingInstance.printExpression(0, output).append('.'); super.printExpression(0, output); if (this.anonymousType != null) { this.anonymousType.print(indent, output); } return output; } public TypeBinding resolveType(BlockScope scope) { // added for code assist...cannot occur with 'normal' code if (this.anonymousType == null && this.enclosingInstance == null) { return super.resolveType(scope); } TypeBinding result=resolveTypeForQualifiedAllocationExpression(scope); if(result != null) { final CompilerOptions compilerOptions = scope.compilerOptions(); if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) { new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations) .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope); } } return result; } private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope 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 this.constant = Constant.NotAConstant; TypeBinding enclosingInstanceType = null; ReferenceBinding enclosingInstanceReference = null; TypeBinding receiverType = null; boolean hasError = false; boolean enclosingInstanceContainsCast = false; boolean argsContainCast = false; if (this.enclosingInstance != null) { if (this.enclosingInstance instanceof CastExpression) { this.enclosingInstance.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on enclosingInstanceContainsCast = true; } if ((enclosingInstanceType = this.enclosingInstance.resolveType(scope)) == null){ hasError = true; } else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) { scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance( enclosingInstanceType, this.enclosingInstance); hasError = true; } else if (this.type instanceof QualifiedTypeReference) { scope.problemReporter().illegalUsageOfQualifiedTypeReference((QualifiedTypeReference)this.type); hasError = true; } else if (!(enclosingInstanceReference = (ReferenceBinding) enclosingInstanceType).canBeSeenBy(scope)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317212 enclosingInstanceType = new ProblemReferenceBinding( enclosingInstanceReference.compoundName, enclosingInstanceReference, ProblemReasons.NotVisible); scope.problemReporter().invalidType(this.enclosingInstance, enclosingInstanceType); hasError = true; } else { receiverType = ((SingleTypeReference) this.type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType); if (receiverType != null && enclosingInstanceContainsCast) { CastExpression.checkNeedForEnclosingInstanceCast(scope, this.enclosingInstance, enclosingInstanceType, receiverType); } } } else { if (this.type == null) { // initialization of an enum constant receiverType = scope.enclosingSourceType(); } else { receiverType = this.type.resolveType(scope, true /* check bounds*/); checkParameterizedAllocation: { if (receiverType == null || !receiverType.isValidBinding()) break checkParameterizedAllocation; if (this.type instanceof ParameterizedQualifiedTypeReference) { // disallow new X.Y() ReferenceBinding currentType = (ReferenceBinding)receiverType; do { // isStatic() is answering true for toplevel types if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0) break checkParameterizedAllocation; if (currentType.isRawType()) break checkParameterizedAllocation; } while ((currentType = currentType.enclosingType())!= null); ParameterizedQualifiedTypeReference qRef = (ParameterizedQualifiedTypeReference) this.type; for (int i = qRef.typeArguments.length - 2; i >= 0; i--) { if (qRef.typeArguments[i] != null) { scope.problemReporter().illegalQualifiedParameterizedTypeAllocation(this.type, receiverType); break; } } } } } } if (receiverType == null || !receiverType.isValidBinding()) { hasError = true; } // resolve type arguments (for generic constructor call) final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0; if (this.typeArguments != null) { int length = this.typeArguments.length; boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5; this.genericTypeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeReference typeReference = this.typeArguments[i]; if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) { argHasError = true; } if (argHasError && typeReference instanceof Wildcard) { scope.problemReporter().illegalUsageOfWildcard(typeReference); } } if (isDiamond) { scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments); return null; } if (argHasError) { if (this.arguments != null) { // still attempt to resolve arguments for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return null; } } // will check for null after args are resolved TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; if (this.arguments != null) { int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++) { Expression argument = this.arguments[i]; if (argument instanceof CastExpression) { argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on argsContainCast = true; } if ((argumentTypes[i] = argument.resolveType(scope)) == null){ hasError = true; } } } // limit of fault-tolerance if (hasError) { /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case. No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do not return the partially resolved type. */ if (isDiamond) { return null; // not the partially cooked this.resolvedType } if (receiverType instanceof ReferenceBinding) { ReferenceBinding referenceReceiver = (ReferenceBinding) receiverType; if (receiverType.isValidBinding()) { // record a best guess, for clients who need hint about possible contructor match int length = this.arguments == null ? 0 : this.arguments.length; TypeBinding[] pseudoArgs = new TypeBinding[length]; for (int i = length; --i >= 0;) { pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type } this.binding = scope.findMethod(referenceReceiver, TypeConstants.INIT, pseudoArgs, this); if (this.binding != null && !this.binding.isValidBinding()) { MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; // record the closest match, for clients who may still need hint about possible method match if (closestMatch != null) { if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method // shouldn't return generic method outside its context, rather convert it to raw method (175409) closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null); } this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } } if (this.anonymousType != null) { // insert anonymous type in scope (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=210070) scope.addAnonymousType(this.anonymousType, referenceReceiver); this.anonymousType.resolve(scope); return this.resolvedType = this.anonymousType.binding; } } return this.resolvedType = receiverType; } if (this.anonymousType == null) { // qualified allocation with no anonymous type if (!receiverType.canBeInstantiated()) { scope.problemReporter().cannotInstantiate(this.type, receiverType); return this.resolvedType = receiverType; } if (isDiamond) { TypeBinding [] inferredTypes = inferElidedTypes(((ParameterizedTypeBinding) receiverType).genericType(), receiverType.enclosingType(), argumentTypes, scope); if (inferredTypes == null) { scope.problemReporter().cannotInferElidedTypes(this); return this.resolvedType = null; } receiverType = this.type.resolvedType = scope.environment().createParameterizedType(((ParameterizedTypeBinding) receiverType).genericType(), inferredTypes, ((ParameterizedTypeBinding) receiverType).enclosingType()); } ReferenceBinding allocationType = (ReferenceBinding) receiverType; if ((this.binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) { if (isMethodUseDeprecated(this.binding, scope, true)) { scope.problemReporter().deprecatedMethod(this.binding, this); } if (checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments); } } else { if (this.binding.declaringClass == null) { this.binding.declaringClass = allocationType; } if (this.type != null && !this.type.resolvedType.isValidBinding()) { // problem already got signaled on type reference, do not report secondary problem return null; } scope.problemReporter().invalidConstructor(this, this.binding); return this.resolvedType = receiverType; } if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInConstructor(this, this.binding); } if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments()) { checkTypeArgumentRedundancy((ParameterizedTypeBinding)receiverType, receiverType.enclosingType(), argumentTypes , scope); } // The enclosing instance must be compatible with the innermost enclosing type ReferenceBinding expectedType = this.binding.declaringClass.enclosingType(); if (expectedType != enclosingInstanceType) // must call before computeConversion() and typeMismatchError() scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType); if (enclosingInstanceType.isCompatibleWith(expectedType) || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) { this.enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType); return this.resolvedType = receiverType; } scope.problemReporter().typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance, null); return this.resolvedType = receiverType; } else { if (isDiamond) { scope.problemReporter().diamondNotWithAnoymousClasses(this.type); return null; } } ReferenceBinding superType = (ReferenceBinding) receiverType; if (superType.isTypeVariable()) { superType = new ProblemReferenceBinding(new char[][]{superType.sourceName()}, superType, ProblemReasons.IllegalSuperTypeVariable); scope.problemReporter().invalidType(this, superType); return null; } else if (this.type != null && superType.isEnum()) { // tolerate enum constant body scope.problemReporter().cannotInstantiate(this.type, superType); return this.resolvedType = superType; } // anonymous type scenario // an anonymous class inherits from java.lang.Object when declared "after" an interface ReferenceBinding anonymousSuperclass = superType.isInterface() ? scope.getJavaLangObject() : superType; // insert anonymous type in scope scope.addAnonymousType(this.anonymousType, superType); this.anonymousType.resolve(scope); // find anonymous super constructor this.resolvedType = this.anonymousType.binding; // 1.2 change if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) { return null; // stop secondary errors } MethodBinding inheritedBinding = scope.getConstructor(anonymousSuperclass, argumentTypes, this); if (!inheritedBinding.isValidBinding()) { if (inheritedBinding.declaringClass == null) { inheritedBinding.declaringClass = anonymousSuperclass; } if (this.type != null && !this.type.resolvedType.isValidBinding()) { // problem already got signaled on type reference, do not report secondary problem return null; } scope.problemReporter().invalidConstructor(this, inheritedBinding); return this.resolvedType; } if ((inheritedBinding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInConstructor(this, inheritedBinding); } if (this.enclosingInstance != null) { ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType(); if (targetEnclosing == null) { scope.problemReporter().unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, superType); return this.resolvedType; } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) { scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, this.enclosingInstance, null); return this.resolvedType; } this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType); } if (this.arguments != null) { if (checkInvocationArguments(scope, null, anonymousSuperclass, inheritedBinding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } } if (this.typeArguments != null && inheritedBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(inheritedBinding, this.genericTypeArguments, this.typeArguments); } // Update the anonymous inner class : superclass, interface this.binding = this.anonymousType.createDefaultConstructorWithBinding(inheritedBinding, (this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null); return this.resolvedType; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { if (this.enclosingInstance != null) this.enclosingInstance.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 (this.arguments != null) { int argumentsLength = this.arguments.length; for (int i = 0; i < argumentsLength; i++) this.arguments[i].traverse(visitor, scope); } if (this.anonymousType != null) this.anonymousType.traverse(visitor, scope); } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java0000644000175000001440000001346412212041344032056 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 185682 - Increment/decrement operators mark local variables as read *******************************************************************************/ 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.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class JavadocFieldReference extends FieldReference { public int tagSourceStart, tagSourceEnd; public int tagValue; public MethodBinding methodBinding; public JavadocFieldReference(char[] source, long pos) { super(source, pos); this.bits |= InsideJavadoc; } /* public Binding getBinding() { if (this.methodBinding != null) { return this.methodBinding; } return this.binding; } */ /* * Resolves type on a Block or Class scope. */ protected TypeBinding internalResolveType(Scope scope) { this.constant = Constant.NotAConstant; if (this.receiver == null) { this.actualReceiverType = scope.enclosingReceiverType(); } else if (scope.kind == Scope.CLASS_SCOPE) { this.actualReceiverType = this.receiver.resolveType((ClassScope) scope); } else { this.actualReceiverType = this.receiver.resolveType((BlockScope)scope); } if (this.actualReceiverType == null) { return null; } Binding fieldBinding = (this.receiver != null && this.receiver.isThis()) ? scope.classScope().getBinding(this.token, this.bits & RestrictiveFlagMASK, this, true /*resolve*/) : scope.getField(this.actualReceiverType, this.token, this); if (!fieldBinding.isValidBinding()) { // implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient switch (fieldBinding.problemId()) { case ProblemReasons.NonStaticReferenceInConstructorInvocation: case ProblemReasons.NonStaticReferenceInStaticContext: case ProblemReasons.InheritedNameHidesEnclosingName : FieldBinding closestMatch = ((ProblemFieldBinding)fieldBinding).closestMatch; if (closestMatch != null) { fieldBinding = closestMatch; // ignore problem if can reach target field through it } } } // When there's no valid field binding, try to resolve possible method reference without parenthesis if (!fieldBinding.isValidBinding() || !(fieldBinding instanceof FieldBinding)) { if (this.receiver.resolvedType instanceof ProblemReferenceBinding) { // problem already got signaled on receiver, do not report secondary problem return null; } if (this.actualReceiverType instanceof ReferenceBinding) { ReferenceBinding refBinding = (ReferenceBinding) this.actualReceiverType; char[] selector = this.token; MethodBinding possibleMethod = null; if (CharOperation.equals(this.actualReceiverType.sourceName(), selector)) { possibleMethod = scope.getConstructor(refBinding, Binding.NO_TYPES, this); } else { possibleMethod = this.receiver.isThis() ? scope.getImplicitMethod(selector, Binding.NO_TYPES, this) : scope.getMethod(refBinding, selector, Binding.NO_TYPES, this); } if (possibleMethod.isValidBinding()) { this.methodBinding = possibleMethod; } else { ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) possibleMethod; if (problemMethodBinding.closestMatch == null) { if (fieldBinding.isValidBinding()) { // When the binding is not on a field (e.g. local variable), we need to create a problem field binding to report the correct problem // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=254825 fieldBinding = new ProblemFieldBinding(refBinding, fieldBinding.readableName(), ProblemReasons.NotFound); } scope.problemReporter().javadocInvalidField(this, fieldBinding, this.actualReceiverType, scope.getDeclarationModifiers()); } else { this.methodBinding = problemMethodBinding.closestMatch; } } } return null; } this.binding = (FieldBinding) fieldBinding; if (isFieldUseDeprecated(this.binding, scope, this.bits)) { scope.problemReporter().javadocDeprecatedField(this.binding, this, scope.getDeclarationModifiers()); } return this.resolvedType = this.binding.type; } public boolean isSuperAccess() { return (this.bits & ASTNode.SuperAccess) != 0; } public StringBuffer printExpression(int indent, StringBuffer output) { if (this.receiver != null) { this.receiver.printExpression(0, output); } output.append('#').append(this.token); return output; } public TypeBinding resolveType(BlockScope scope) { return internalResolveType(scope); } public TypeBinding resolveType(ClassScope scope) { return internalResolveType(scope); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { if (this.receiver != null) { this.receiver.traverse(visitor, scope); } } visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { if (visitor.visit(this, scope)) { if (this.receiver != null) { this.receiver.traverse(visitor, scope); } } visitor.endVisit(this, scope); } } ././@LongLink0000644000000000000000000000015112251602427011640 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.0000644000175000001440000006605612212041344032353 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 295551 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import java.util.Arrays; import java.util.Comparator; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.IrritantSet; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; import org.eclipse.jdt.internal.compiler.lookup.ImportBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.parser.NLSTag; import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; import org.eclipse.jdt.internal.compiler.problem.AbortType; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.HashSetOfInt; public class CompilationUnitDeclaration extends ASTNode implements ProblemSeverities, ReferenceContext { private static final Comparator STRING_LITERAL_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { StringLiteral literal1 = (StringLiteral) o1; StringLiteral literal2 = (StringLiteral) o2; return literal1.sourceStart - literal2.sourceStart; } }; private static final int STRING_LITERALS_INCREMENT = 10; public ImportReference currentPackage; public ImportReference[] imports; public TypeDeclaration[] types; public int[][] comments; public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors public boolean ignoreMethodBodies = false; public CompilationUnitScope scope; public ProblemReporter problemReporter; public CompilationResult compilationResult; public LocalTypeBinding[] localTypes; public int localTypeCount = 0; public boolean isPropagatingInnerClassEmulation; public Javadoc javadoc; // 1.5 addition for package-info.java public NLSTag[] nlsTags; private StringLiteral[] stringLiterals; private int stringLiteralsPtr; private HashSetOfInt stringLiteralsStart; IrritantSet[] suppressWarningIrritants; // irritant for suppressed warnings Annotation[] suppressWarningAnnotations; long[] suppressWarningScopePositions; // (start << 32) + end int suppressWarningsCount; public CompilationUnitDeclaration(ProblemReporter problemReporter, CompilationResult compilationResult, int sourceLength) { this.problemReporter = problemReporter; this.compilationResult = compilationResult; //by definition of a compilation unit.... this.sourceStart = 0; this.sourceEnd = sourceLength - 1; } /* * We cause the compilation task to abort to a given extent. */ public void abort(int abortLevel, CategorizedProblem problem) { switch (abortLevel) { case AbortType : throw new AbortType(this.compilationResult, problem); case AbortMethod : throw new AbortMethod(this.compilationResult, problem); default : throw new AbortCompilationUnit(this.compilationResult, problem); } } /* * Dispatch code analysis AND request saturation of inner emulation */ public void analyseCode() { if (this.ignoreFurtherInvestigation) return; try { if (this.types != null) { for (int i = 0, count = this.types.length; i < count; i++) { this.types[i].analyseCode(this.scope); } } // request inner emulation propagation propagateInnerEmulationForAllLocalTypes(); } catch (AbortCompilationUnit e) { this.ignoreFurtherInvestigation = true; return; } } /* * When unit result is about to be accepted, removed back pointers * to compiler structures. */ public void cleanUp() { if (this.types != null) { for (int i = 0, max = this.types.length; i < max; i++) { cleanUp(this.types[i]); } for (int i = 0, max = this.localTypeCount; i < max; i++) { LocalTypeBinding localType = this.localTypes[i]; // null out the type's scope backpointers localType.scope = null; // local members are already in the list localType.enclosingCase = null; } } this.compilationResult.recoveryScannerData = null; // recovery is already done ClassFile[] classFiles = this.compilationResult.getClassFiles(); for (int i = 0, max = classFiles.length; i < max; i++) { // clear the classFile back pointer to the bindings ClassFile classFile = classFiles[i]; // null out the classfile backpointer to a type binding classFile.referenceBinding = null; classFile.innerClassesBindings = null; classFile.missingTypes = null; classFile.visitedTypes = null; } this.suppressWarningAnnotations = null; } private void cleanUp(TypeDeclaration type) { if (type.memberTypes != null) { for (int i = 0, max = type.memberTypes.length; i < max; i++){ cleanUp(type.memberTypes[i]); } } if (type.binding != null && type.binding.isAnnotationType()) this.compilationResult.hasAnnotations = true; if (type.binding != null) { // null out the type's scope backpointers type.binding.scope = null; } } public void checkUnusedImports(){ if (this.scope.imports != null){ for (int i = 0, max = this.scope.imports.length; i < max; i++){ ImportBinding importBinding = this.scope.imports[i]; ImportReference importReference = importBinding.reference; if (importReference != null && ((importReference.bits & ASTNode.Used) == 0)){ this.scope.problemReporter().unusedImport(importReference); } } } } public CompilationResult compilationResult() { return this.compilationResult; } public void createPackageInfoType() { TypeDeclaration declaration = new TypeDeclaration(this.compilationResult); declaration.name = TypeConstants.PACKAGE_INFO_NAME; declaration.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccInterface; declaration.javadoc = this.javadoc; this.types[0] = declaration; // Assumes the first slot is meant for this type } /* * Finds the matching type amoung this compilation unit types. * Returns null if no type with this name is found. * The type name is a compound name * e.g. if we're looking for X.A.B then a type name would be {X, A, B} */ public TypeDeclaration declarationOfType(char[][] typeName) { for (int i = 0; i < this.types.length; i++) { TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName); if (typeDecl != null) { return typeDecl; } } return null; } public void finalizeProblems() { if (this.suppressWarningsCount == 0) return; int removed = 0; CategorizedProblem[] problems = this.compilationResult.problems; int problemCount = this.compilationResult.problemCount; IrritantSet[] foundIrritants = new IrritantSet[this.suppressWarningsCount]; CompilerOptions options = this.scope.compilerOptions(); boolean hasMandatoryErrors = false; nextProblem: for (int iProblem = 0, length = problemCount; iProblem < length; iProblem++) { CategorizedProblem problem = problems[iProblem]; int problemID = problem.getID(); int irritant = ProblemReporter.getIrritant(problemID); boolean isError = problem.isError(); if (isError) { if (irritant == 0) { // tolerate unused warning tokens when mandatory errors hasMandatoryErrors = true; continue; } if (!options.suppressOptionalErrors) { continue; } } int start = problem.getSourceStart(); int end = problem.getSourceEnd(); nextSuppress: for (int iSuppress = 0, suppressCount = this.suppressWarningsCount; iSuppress < suppressCount; iSuppress++) { long position = this.suppressWarningScopePositions[iSuppress]; int startSuppress = (int) (position >>> 32); int endSuppress = (int) position; if (start < startSuppress) continue nextSuppress; if (end > endSuppress) continue nextSuppress; if (!this.suppressWarningIrritants[iSuppress].isSet(irritant)) continue nextSuppress; // discard suppressed warning removed++; problems[iProblem] = null; this.compilationResult.removeProblem(problem); if (foundIrritants[iSuppress] == null){ foundIrritants[iSuppress] = new IrritantSet(irritant); } else { foundIrritants[iSuppress].set(irritant); } continue nextProblem; } } // compact remaining problems if (removed > 0) { for (int i = 0, index = 0; i < problemCount; i++) { CategorizedProblem problem; if ((problem = problems[i]) != null) { if (i > index) { problems[index++] = problem; } else { index++; } } } } // flag SuppressWarnings which had no effect (only if no (mandatory) error got detected within unit if (!hasMandatoryErrors) { int severity = options.getSeverity(CompilerOptions.UnusedWarningToken); if (severity != ProblemSeverities.Ignore) { boolean unusedWarningTokenIsWarning = (severity & ProblemSeverities.Error) == 0; for (int iSuppress = 0, suppressCount = this.suppressWarningsCount; iSuppress < suppressCount; iSuppress++) { Annotation annotation = this.suppressWarningAnnotations[iSuppress]; if (annotation == null) continue; // implicit annotation IrritantSet irritants = this.suppressWarningIrritants[iSuppress]; if (unusedWarningTokenIsWarning && irritants.areAllSet()) continue; // @SuppressWarnings("all") also suppresses unused warning token if (irritants != foundIrritants[iSuppress]) { // mismatch, some warning tokens were unused MemberValuePair[] pairs = annotation.memberValuePairs(); pairLoop: for (int iPair = 0, pairCount = pairs.length; iPair < pairCount; iPair++) { MemberValuePair pair = pairs[iPair]; if (CharOperation.equals(pair.name, TypeConstants.VALUE)) { Expression value = pair.value; if (value instanceof ArrayInitializer) { ArrayInitializer initializer = (ArrayInitializer) value; Expression[] inits = initializer.expressions; if (inits != null) { for (int iToken = 0, tokenCount = inits.length; iToken < tokenCount; iToken++) { Constant cst = inits[iToken].constant; if (cst != Constant.NotAConstant && cst.typeID() == TypeIds.T_JavaLangString) { IrritantSet tokenIrritants = CompilerOptions.warningTokenToIrritants(cst.stringValue()); if (tokenIrritants != null && !tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all") && options.isAnyEnabled(tokenIrritants) // if irritant is effectively enabled && (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem if (unusedWarningTokenIsWarning) { int start = value.sourceStart, end = value.sourceEnd; nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) { long position = this.suppressWarningScopePositions[jSuppress]; int startSuppress = (int) (position >>> 32); int endSuppress = (int) position; if (start < startSuppress) continue nextSuppress; if (end > endSuppress) continue nextSuppress; if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all? } } this.scope.problemReporter().unusedWarningToken(inits[iToken]); } } } } } else { Constant cst = value.constant; if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) { IrritantSet tokenIrritants = CompilerOptions.warningTokenToIrritants(cst.stringValue()); if (tokenIrritants != null && !tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all") && options.isAnyEnabled(tokenIrritants) // if irritant is effectively enabled && (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem if (unusedWarningTokenIsWarning) { int start = value.sourceStart, end = value.sourceEnd; nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) { long position = this.suppressWarningScopePositions[jSuppress]; int startSuppress = (int) (position >>> 32); int endSuppress = (int) position; if (start < startSuppress) continue nextSuppress; if (end > endSuppress) continue nextSuppress; if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all? } } this.scope.problemReporter().unusedWarningToken(value); } } } break pairLoop; } } } } } } } /** * Bytecode generation */ public void generateCode() { if (this.ignoreFurtherInvestigation) { if (this.types != null) { for (int i = 0, count = this.types.length; i < count; i++) { this.types[i].ignoreFurtherInvestigation = true; // propagate the flag to request problem type creation this.types[i].generateCode(this.scope); } } return; } try { if (this.types != null) { for (int i = 0, count = this.types.length; i < count; i++) this.types[i].generateCode(this.scope); } } catch (AbortCompilationUnit e) { // ignore } } public CompilationUnitDeclaration getCompilationUnitDeclaration() { return this; } public char[] getFileName() { return this.compilationResult.getFileName(); } public char[] getMainTypeName() { if (this.compilationResult.compilationUnit == null) { char[] fileName = this.compilationResult.getFileName(); int start = CharOperation.lastIndexOf('/', fileName) + 1; if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName)) start = CharOperation.lastIndexOf('\\', fileName) + 1; int end = CharOperation.lastIndexOf('.', fileName); if (end == -1) end = fileName.length; return CharOperation.subarray(fileName, start, end); } else { return this.compilationResult.compilationUnit.getMainTypeName(); } } public boolean isEmpty() { return (this.currentPackage == null) && (this.imports == null) && (this.types == null); } public boolean isPackageInfo() { return CharOperation.equals(getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME); } public boolean isSuppressed(CategorizedProblem problem) { if (this.suppressWarningsCount == 0) return false; int irritant = ProblemReporter.getIrritant(problem.getID()); if (irritant == 0) return false; int start = problem.getSourceStart(); int end = problem.getSourceEnd(); nextSuppress: for (int iSuppress = 0, suppressCount = this.suppressWarningsCount; iSuppress < suppressCount; iSuppress++) { long position = this.suppressWarningScopePositions[iSuppress]; int startSuppress = (int) (position >>> 32); int endSuppress = (int) position; if (start < startSuppress) continue nextSuppress; if (end > endSuppress) continue nextSuppress; if (this.suppressWarningIrritants[iSuppress].isSet(irritant)) return true; } return false; } public boolean hasErrors() { return this.ignoreFurtherInvestigation; } public StringBuffer print(int indent, StringBuffer output) { if (this.currentPackage != null) { printIndent(indent, output).append("package "); //$NON-NLS-1$ this.currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$ } if (this.imports != null) for (int i = 0; i < this.imports.length; i++) { printIndent(indent, output).append("import "); //$NON-NLS-1$ ImportReference currentImport = this.imports[i]; if (currentImport.isStatic()) { output.append("static "); //$NON-NLS-1$ } currentImport.print(0, output).append(";\n"); //$NON-NLS-1$ } if (this.types != null) { for (int i = 0; i < this.types.length; i++) { this.types[i].print(indent, output).append("\n"); //$NON-NLS-1$ } } return output; } /* * Force inner local types to update their innerclass emulation */ public void propagateInnerEmulationForAllLocalTypes() { this.isPropagatingInnerClassEmulation = true; for (int i = 0, max = this.localTypeCount; i < max; i++) { LocalTypeBinding localType = this.localTypes[i]; // only propagate for reachable local types if ((localType.scope.referenceType().bits & IsReachable) != 0) { localType.updateInnerEmulationDependents(); } } } public void recordStringLiteral(StringLiteral literal, boolean fromRecovery) { if (this.stringLiteralsStart != null) { if (this.stringLiteralsStart.contains(literal.sourceStart)) return; this.stringLiteralsStart.add(literal.sourceStart); } else if (fromRecovery) { this.stringLiteralsStart = new HashSetOfInt(this.stringLiteralsPtr + STRING_LITERALS_INCREMENT); for (int i = 0; i < this.stringLiteralsPtr; i++) { this.stringLiteralsStart.add(this.stringLiterals[i].sourceStart); } if (this.stringLiteralsStart.contains(literal.sourceStart)) return; this.stringLiteralsStart.add(literal.sourceStart); } if (this.stringLiterals == null) { this.stringLiterals = new StringLiteral[STRING_LITERALS_INCREMENT]; this.stringLiteralsPtr = 0; } else { int stackLength = this.stringLiterals.length; if (this.stringLiteralsPtr == stackLength) { System.arraycopy( this.stringLiterals, 0, this.stringLiterals = new StringLiteral[stackLength + STRING_LITERALS_INCREMENT], 0, stackLength); } } this.stringLiterals[this.stringLiteralsPtr++] = literal; } public void recordSuppressWarnings(IrritantSet irritants, Annotation annotation, int scopeStart, int scopeEnd) { if (this.suppressWarningIrritants == null) { this.suppressWarningIrritants = new IrritantSet[3]; this.suppressWarningAnnotations = new Annotation[3]; this.suppressWarningScopePositions = new long[3]; } else if (this.suppressWarningIrritants.length == this.suppressWarningsCount) { System.arraycopy(this.suppressWarningIrritants, 0,this.suppressWarningIrritants = new IrritantSet[2*this.suppressWarningsCount], 0, this.suppressWarningsCount); System.arraycopy(this.suppressWarningAnnotations, 0,this.suppressWarningAnnotations = new Annotation[2*this.suppressWarningsCount], 0, this.suppressWarningsCount); System.arraycopy(this.suppressWarningScopePositions, 0,this.suppressWarningScopePositions = new long[2*this.suppressWarningsCount], 0, this.suppressWarningsCount); } final long scopePositions = ((long)scopeStart<<32) + scopeEnd; for (int i = 0, max = this.suppressWarningsCount; i < max; i++) { if (this.suppressWarningAnnotations[i] == annotation && this.suppressWarningScopePositions[i] == scopePositions && this.suppressWarningIrritants[i].hasSameIrritants(irritants)) { // annotation data already recorded return; } } this.suppressWarningIrritants[this.suppressWarningsCount] = irritants; this.suppressWarningAnnotations[this.suppressWarningsCount] = annotation; this.suppressWarningScopePositions[this.suppressWarningsCount++] = scopePositions; } /* * Keep track of all local types, so as to update their innerclass * emulation later on. */ public void record(LocalTypeBinding localType) { if (this.localTypeCount == 0) { this.localTypes = new LocalTypeBinding[5]; } else if (this.localTypeCount == this.localTypes.length) { System.arraycopy(this.localTypes, 0, (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]), 0, this.localTypeCount); } this.localTypes[this.localTypeCount++] = localType; } public void resolve() { int startingTypeIndex = 0; boolean isPackageInfo = isPackageInfo(); if (this.types != null && isPackageInfo) { // resolve synthetic type declaration final TypeDeclaration syntheticTypeDeclaration = this.types[0]; // set empty javadoc to avoid missing warning (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=95286) if (syntheticTypeDeclaration.javadoc == null) { syntheticTypeDeclaration.javadoc = new Javadoc(syntheticTypeDeclaration.declarationSourceStart, syntheticTypeDeclaration.declarationSourceStart); } syntheticTypeDeclaration.resolve(this.scope); /* * resolve javadoc package if any, skip this step if we don't have a valid scope due to an earlier error (bug 252555) * we do it now as the javadoc in the fake type won't be resolved. The peculiar usage of MethodScope to resolve the * package level javadoc is because the CU level resolve method is a NOP to mimic Javadoc's behavior and can't be used * as such. */ if (this.javadoc != null && syntheticTypeDeclaration.staticInitializerScope != null) { this.javadoc.resolve(syntheticTypeDeclaration.staticInitializerScope); } startingTypeIndex = 1; } else { // resolve compilation unit javadoc package if any if (this.javadoc != null) { this.javadoc.resolve(this.scope); } } if (this.currentPackage != null && this.currentPackage.annotations != null && !isPackageInfo) { this.scope.problemReporter().invalidFileNameForPackageAnnotations(this.currentPackage.annotations[0]); } try { if (this.types != null) { for (int i = startingTypeIndex, count = this.types.length; i < count; i++) { this.types[i].resolve(this.scope); } } if (!this.compilationResult.hasMandatoryErrors()) checkUnusedImports(); reportNLSProblems(); } catch (AbortCompilationUnit e) { this.ignoreFurtherInvestigation = true; return; } } private void reportNLSProblems() { if (this.nlsTags != null || this.stringLiterals != null) { final int stringLiteralsLength = this.stringLiteralsPtr; final int nlsTagsLength = this.nlsTags == null ? 0 : this.nlsTags.length; if (stringLiteralsLength == 0) { if (nlsTagsLength != 0) { for (int i = 0; i < nlsTagsLength; i++) { NLSTag tag = this.nlsTags[i]; if (tag != null) { this.scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end); } } } } else if (nlsTagsLength == 0) { // resize string literals if (this.stringLiterals.length != stringLiteralsLength) { System.arraycopy(this.stringLiterals, 0, (this.stringLiterals = new StringLiteral[stringLiteralsLength]), 0, stringLiteralsLength); } Arrays.sort(this.stringLiterals, STRING_LITERAL_COMPARATOR); for (int i = 0; i < stringLiteralsLength; i++) { this.scope.problemReporter().nonExternalizedStringLiteral(this.stringLiterals[i]); } } else { // need to iterate both arrays to find non matching elements if (this.stringLiterals.length != stringLiteralsLength) { System.arraycopy(this.stringLiterals, 0, (this.stringLiterals = new StringLiteral[stringLiteralsLength]), 0, stringLiteralsLength); } Arrays.sort(this.stringLiterals, STRING_LITERAL_COMPARATOR); int indexInLine = 1; int lastLineNumber = -1; StringLiteral literal = null; int index = 0; int i = 0; stringLiteralsLoop: for (; i < stringLiteralsLength; i++) { literal = this.stringLiterals[i]; final int literalLineNumber = literal.lineNumber; if (lastLineNumber != literalLineNumber) { indexInLine = 1; lastLineNumber = literalLineNumber; } else { indexInLine++; } if (index < nlsTagsLength) { nlsTagsLoop: for (; index < nlsTagsLength; index++) { NLSTag tag = this.nlsTags[index]; if (tag == null) continue nlsTagsLoop; int tagLineNumber = tag.lineNumber; if (literalLineNumber < tagLineNumber) { this.scope.problemReporter().nonExternalizedStringLiteral(literal); continue stringLiteralsLoop; } else if (literalLineNumber == tagLineNumber) { if (tag.index == indexInLine) { this.nlsTags[index] = null; index++; continue stringLiteralsLoop; } else { nlsTagsLoop2: for (int index2 = index + 1; index2 < nlsTagsLength; index2++) { NLSTag tag2 = this.nlsTags[index2]; if (tag2 == null) continue nlsTagsLoop2; int tagLineNumber2 = tag2.lineNumber; if (literalLineNumber == tagLineNumber2) { if (tag2.index == indexInLine) { this.nlsTags[index2] = null; continue stringLiteralsLoop; } else { continue nlsTagsLoop2; } } else { this.scope.problemReporter().nonExternalizedStringLiteral(literal); continue stringLiteralsLoop; } } this.scope.problemReporter().nonExternalizedStringLiteral(literal); continue stringLiteralsLoop; } } else { this.scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end); continue nlsTagsLoop; } } } // all nls tags have been processed, so remaining string literals are not externalized break stringLiteralsLoop; } for (; i < stringLiteralsLength; i++) { this.scope.problemReporter().nonExternalizedStringLiteral(this.stringLiterals[i]); } if (index < nlsTagsLength) { for (; index < nlsTagsLength; index++) { NLSTag tag = this.nlsTags[index]; if (tag != null) { this.scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end); } } } } } } public void tagAsHavingErrors() { this.ignoreFurtherInvestigation = true; } public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) { if (this.ignoreFurtherInvestigation) return; try { if (visitor.visit(this, this.scope)) { if (this.types != null && isPackageInfo()) { // resolve synthetic type declaration final TypeDeclaration syntheticTypeDeclaration = this.types[0]; // resolve javadoc package if any final MethodScope methodScope = syntheticTypeDeclaration.staticInitializerScope; // Don't traverse in null scope and invite trouble a la bug 252555. if (this.javadoc != null && methodScope != null) { this.javadoc.traverse(visitor, methodScope); } // Don't traverse in null scope and invite trouble a la bug 252555. if (this.currentPackage != null && methodScope != null) { final Annotation[] annotations = this.currentPackage.annotations; if (annotations != null) { int annotationsLength = annotations.length; for (int i = 0; i < annotationsLength; i++) { annotations[i].traverse(visitor, methodScope); } } } } if (this.currentPackage != null) { this.currentPackage.traverse(visitor, this.scope); } if (this.imports != null) { int importLength = this.imports.length; for (int i = 0; i < importLength; i++) { this.imports[i].traverse(visitor, this.scope); } } if (this.types != null) { int typesLength = this.types.length; for (int i = 0; i < typesLength; i++) { this.types[i].traverse(visitor, this.scope); } } } visitor.endVisit(this, this.scope); } catch (AbortCompilationUnit e) { // ignore } } } ././@LongLink0000644000000000000000000000016112251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeRe0000644000175000001440000000370012212041344032317 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class JavadocArrayQualifiedTypeReference extends ArrayQualifiedTypeReference { public int tagSourceStart, tagSourceEnd; public JavadocArrayQualifiedTypeReference(JavadocQualifiedTypeReference typeRef, int dim) { super(typeRef.tokens, dim, typeRef.sourcePositions); } protected void reportInvalidType(Scope scope) { scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers()); } protected void reportDeprecatedType(TypeBinding type, Scope scope) { scope.problemReporter().javadocDeprecatedType(type, this, scope.getDeclarationModifiers()); } /* (non-Javadoc) * Redefine to capture javadoc specific signatures * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CastExpression.java0000644000175000001440000006355612212041344030705 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752) * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 401017 - [compiler][null] casted reference to @Nullable field lacks a warning * bug 400761 - [compiler][null] null may be return as boolean without a diagnostic *******************************************************************************/ 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.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class CastExpression extends Expression { public Expression expression; public TypeReference 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, TypeReference type) { this.expression = expression; this.type = type; type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { FlowInfo result = this.expression .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); this.expression.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); // account for pot. CCE: flowContext.recordAbruptExit(); return result; } /** * Complain if assigned expression is cast, but not actually used as such, e.g. Object o = (List) object; */ public static void checkNeedForAssignedCast(BlockScope scope, TypeBinding expectedType, CastExpression rhs) { if (scope.compilerOptions().getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; TypeBinding castedExpressionType = rhs.expression.resolvedType; // int i = (byte) n; // cast still had side effect // double d = (float) n; // cast to float is unnecessary if (castedExpressionType == null || rhs.resolvedType.isBaseType()) return; //if (castedExpressionType.id == T_null) return; // tolerate null expression cast if (castedExpressionType.isCompatibleWith(expectedType, scope)) { scope.problemReporter().unnecessaryCast(rhs); } } /** * Complain if cast expression is cast, but not actually needed, int i = (int)(Integer) 12; * Note that this (int) cast is however needed: Integer i = 0; char c = (char)((int) i); */ public static void checkNeedForCastCast(BlockScope scope, CastExpression enclosingCast) { if (scope.compilerOptions().getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; CastExpression nestedCast = (CastExpression) enclosingCast.expression; if ((nestedCast.bits & ASTNode.UnnecessaryCast) == 0) return; // check if could cast directly to enclosing cast type, without intermediate type cast CastExpression alternateCast = new CastExpression(null, enclosingCast.type); alternateCast.resolvedType = enclosingCast.resolvedType; if (!alternateCast.checkCastTypesCompatibility(scope, enclosingCast.resolvedType, nestedCast.expression.resolvedType, null /* no expr to avoid side-effects*/)) return; scope.problemReporter().unnecessaryCast(nestedCast); } /** * 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) { if (scope.compilerOptions().getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; TypeBinding castedExpressionType = ((CastExpression)enclosingInstance).expression.resolvedType; if (castedExpressionType == null) return; // cannot do better // obvious identity cast if (castedExpressionType == enclosingInstanceType) { scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance); } else if (castedExpressionType == TypeBinding.NULL){ return; // tolerate null enclosing instance cast } else { TypeBinding alternateEnclosingInstanceType = castedExpressionType; if (castedExpressionType.isBaseType() || castedExpressionType.isArrayType()) return; // error case if (memberType == scope.getMemberType(memberType.sourceName(), (ReferenceBinding) alternateEnclosingInstanceType)) { scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance); } } } /** * Only complain for identity cast, since other type of casts may be useful: e.g. ~((~(long) 0) << 32) is different from: ~((~0) << 32) */ public static void checkNeedForArgumentCast(BlockScope scope, int operator, int operatorSignature, Expression expression, int expressionTypeId) { if (scope.compilerOptions().getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; // check need for left operand cast if ((expression.bits & ASTNode.UnnecessaryCast) == 0 && expression.resolvedType.isBaseType()) { // narrowing conversion on base type may change value, thus necessary return; } else { TypeBinding alternateLeftType = ((CastExpression)expression).expression.resolvedType; if (alternateLeftType == null) return; // cannot do better if (alternateLeftType.id == expressionTypeId) { // obvious identity cast scope.problemReporter().unnecessaryCast((CastExpression)expression); return; } } } /** * Cast expressions will considered as useful if removing them all would actually bind to a different method * (no fine grain analysis on per casted argument basis, simply separate widening cast from narrowing ones) */ public static void checkNeedForArgumentCasts(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] argumentTypes, final InvocationSite invocationSite) { if (scope.compilerOptions().getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; int length = argumentTypes.length; // iterate over arguments, and retrieve original argument types (before cast) TypeBinding[] rawArgumentTypes = argumentTypes; for (int i = 0; i < length; i++) { Expression argument = arguments[i]; if (argument instanceof CastExpression) { // narrowing conversion on base type may change value, thus necessary if ((argument.bits & ASTNode.UnnecessaryCast) == 0 && argument.resolvedType.isBaseType()) { continue; } TypeBinding castedExpressionType = ((CastExpression)argument).expression.resolvedType; if (castedExpressionType == null) return; // cannot do better // obvious identity cast if (castedExpressionType == argumentTypes[i]) { scope.problemReporter().unnecessaryCast((CastExpression)argument); } else if (castedExpressionType == TypeBinding.NULL){ continue; // tolerate null argument cast } else if ((argument.implicitConversion & TypeIds.BOXING) != 0) { continue; // boxing has a side effect: (int) char is not boxed as simple char } else { if (rawArgumentTypes == argumentTypes) { System.arraycopy(rawArgumentTypes, 0, rawArgumentTypes = new TypeBinding[length], 0, length); } // retain original argument type rawArgumentTypes[i] = castedExpressionType; } } } // perform alternate lookup with original types if (rawArgumentTypes != argumentTypes) { checkAlternateBinding(scope, receiver, receiverType, binding, arguments, argumentTypes, rawArgumentTypes, invocationSite); } } /** * Check binary operator casted arguments */ public static void checkNeedForArgumentCasts(BlockScope scope, int operator, int operatorSignature, Expression left, int leftTypeId, boolean leftIsCast, Expression right, int rightTypeId, boolean rightIsCast) { if (scope.compilerOptions().getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; // check need for left operand cast int alternateLeftTypeId = leftTypeId; if (leftIsCast) { if ((left.bits & ASTNode.UnnecessaryCast) == 0 && left.resolvedType.isBaseType()) { // narrowing conversion on base type may change value, thus necessary leftIsCast = false; } else { TypeBinding alternateLeftType = ((CastExpression)left).expression.resolvedType; if (alternateLeftType == null) return; // cannot do better if ((alternateLeftTypeId = alternateLeftType.id) == leftTypeId || scope.environment().computeBoxingType(alternateLeftType).id == leftTypeId) { // obvious identity cast scope.problemReporter().unnecessaryCast((CastExpression)left); leftIsCast = false; } else if (alternateLeftTypeId == TypeIds.T_null) { alternateLeftTypeId = leftTypeId; // tolerate null argument cast leftIsCast = false; } } } // check need for right operand cast int alternateRightTypeId = rightTypeId; if (rightIsCast) { if ((right.bits & ASTNode.UnnecessaryCast) == 0 && right.resolvedType.isBaseType()) { // narrowing conversion on base type may change value, thus necessary rightIsCast = false; } else { TypeBinding alternateRightType = ((CastExpression)right).expression.resolvedType; if (alternateRightType == null) return; // cannot do better if ((alternateRightTypeId = alternateRightType.id) == rightTypeId || scope.environment().computeBoxingType(alternateRightType).id == rightTypeId) { // obvious identity cast scope.problemReporter().unnecessaryCast((CastExpression)right); rightIsCast = false; } else if (alternateRightTypeId == TypeIds.T_null) { alternateRightTypeId = rightTypeId; // tolerate null argument cast rightIsCast = false; } } } if (leftIsCast || rightIsCast) { if (alternateLeftTypeId > 15 || alternateRightTypeId > 15) { // must convert String + Object || Object + String if (alternateLeftTypeId == TypeIds.T_JavaLangString) { alternateRightTypeId = TypeIds.T_JavaLangObject; } else if (alternateRightTypeId == TypeIds.T_JavaLangString) { alternateLeftTypeId = TypeIds.T_JavaLangObject; } else { return; // invalid operator } } int alternateOperatorSignature = OperatorExpression.OperatorSignatures[operator][(alternateLeftTypeId << 4) + alternateRightTypeId]; // (cast) left Op (cast) right --> result // 1111 0000 1111 0000 1111 // <<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().unnecessaryCast((CastExpression)left); if (rightIsCast) scope.problemReporter().unnecessaryCast((CastExpression)right); } } } public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { checkNPEbyUnboxing(scope, flowContext, flowInfo); return this.expression.checkNPE(scope, flowContext, flowInfo); } 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 */} public void setDepth(int depth) { /* ignore */} public void setFieldIndex(int depth){ /* ignore */} public int sourceStart() { return 0; } public int sourceEnd() { return 0; } public TypeBinding expectedType() { return invocationSite.expectedType(); } }; MethodBinding bindingIfNoCast; if (binding.isConstructor()) { bindingIfNoCast = scope.getConstructor((ReferenceBinding)receiverType, alternateArgumentTypes, fakeInvocationSite); } else { bindingIfNoCast = receiver.isImplicitThis() ? scope.getImplicitMethod(binding.selector, alternateArgumentTypes, fakeInvocationSite) : scope.getMethod(receiverType, binding.selector, alternateArgumentTypes, fakeInvocationSite); } if (bindingIfNoCast == binding) { int argumentLength = originalArgumentTypes.length; if (binding.isVarargs()) { int paramLength = binding.parameters.length; if (paramLength == argumentLength) { int varargsIndex = paramLength - 1; ArrayBinding varargsType = (ArrayBinding) binding.parameters[varargsIndex]; TypeBinding lastArgType = alternateArgumentTypes[varargsIndex]; // originalType may be compatible already, but cast mandated // to clarify between varargs/non-varargs call if (varargsType.dimensions != lastArgType.dimensions()) { return; } if (lastArgType.isCompatibleWith(varargsType.elementsType()) && lastArgType.isCompatibleWith(varargsType)) { return; } } } for (int i = 0; i < argumentLength; i++) { if (originalArgumentTypes[i] != alternateArgumentTypes[i] /*&& !originalArgumentTypes[i].needsUncheckedConversion(alternateArgumentTypes[i])*/) { scope.problemReporter().unnecessaryCast((CastExpression)arguments[i]); } } } } public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) { if (match == castType) { if (!isNarrowing && match == this.resolvedType.leafComponentType()) { // do not tag as unnecessary when recursing through upper bounds tagAsUnnecessaryCast(scope, castType); } return true; } if (match != null) { if (isNarrowing ? match.isProvablyDistinct(expressionType) : castType.isProvablyDistinct(match)) { return false; } } switch (castType.kind()) { case Binding.PARAMETERIZED_TYPE : if (!castType.isReifiable()) { if (match == null) { // unrelated types this.bits |= ASTNode.UnsafeCast; return true; } switch (match.kind()) { case Binding.PARAMETERIZED_TYPE : if (isNarrowing) { // [JLS 5.5] T <: S if (expressionType.isRawType() || !expressionType.isEquivalentTo(match)) { this.bits |= ASTNode.UnsafeCast; return true; } // [JLS 5.5] S has no subtype X != T, such that |X| == |T| // if I2 extends I1, then cast from I1 to I2 is unchecked ParameterizedTypeBinding paramCastType = (ParameterizedTypeBinding) castType; ParameterizedTypeBinding paramMatch = (ParameterizedTypeBinding) match; // easy case if less parameters on match TypeBinding[] castArguments = paramCastType.arguments; int length = castArguments == null ? 0 : castArguments.length; if (paramMatch.arguments == null || length > paramMatch.arguments.length) { this.bits |= ASTNode.UnsafeCast; } else if ((paramCastType.tagBits & (TagBits.HasDirectWildcard|TagBits.HasTypeVariable)) != 0) { // verify alternate cast type, substituting different type arguments nextAlternateArgument: for (int i = 0; i < length; i++) { switch (castArguments[i].kind()) { case Binding.WILDCARD_TYPE : case Binding.TYPE_PARAMETER : break; // check substituting with other default: continue nextAlternateArgument; // no alternative possible } TypeBinding[] alternateArguments; // need to clone for each iteration to avoid env paramtype cache interference System.arraycopy(paramCastType.arguments, 0, alternateArguments = new TypeBinding[length], 0, length); alternateArguments[i] = scope.getJavaLangObject(); LookupEnvironment environment = scope.environment(); ParameterizedTypeBinding alternateCastType = environment.createParameterizedType((ReferenceBinding)castType.erasure(), alternateArguments, castType.enclosingType()); if (alternateCastType.findSuperTypeOriginatingFrom(expressionType) == match) { this.bits |= ASTNode.UnsafeCast; break; } } } return true; } else { // [JLS 5.5] T >: S if (!match.isEquivalentTo(castType)) { this.bits |= ASTNode.UnsafeCast; return true; } } break; case Binding.RAW_TYPE : this.bits |= ASTNode.UnsafeCast; // upcast since castType is known to be bound paramType return true; default : if (isNarrowing){ // match is not parameterized or raw, then any other subtype of match will erase to |T| this.bits |= ASTNode.UnsafeCast; return true; } break; } } break; case Binding.ARRAY_TYPE : TypeBinding leafType = castType.leafComponentType(); if (isNarrowing && (!leafType.isReifiable() || leafType.isTypeVariable())) { this.bits |= ASTNode.UnsafeCast; return true; } break; case Binding.TYPE_PARAMETER : this.bits |= ASTNode.UnsafeCast; return true; // (disabled) https://bugs.eclipse.org/bugs/show_bug.cgi?id=240807 // case Binding.TYPE : // if (isNarrowing && match == null && expressionType.isParameterizedType()) { // this.bits |= ASTNode.UnsafeCast; // return true; // } // break; } if (!isNarrowing && match == this.resolvedType.leafComponentType()) { // do not tag as unnecessary when recursing through upper bounds tagAsUnnecessaryCast(scope, castType); } return true; } /** * Cast expression 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) { int pc = codeStream.position; boolean needRuntimeCheckcast = (this.bits & ASTNode.GenerateCheckcast) != 0; if (this.constant != Constant.NotAConstant) { if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check codeStream.generateConstant(this.constant, this.implicitConversion); if (needRuntimeCheckcast) { codeStream.checkcast(this.resolvedType); } if (!valueRequired) { // the resolveType cannot be double or long codeStream.pop(); } } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } this.expression.generateCode(currentScope, codeStream, valueRequired || needRuntimeCheckcast); if (needRuntimeCheckcast && this.expression.postConversionType(currentScope) != this.resolvedType.erasure()) { // no need to issue a checkcast if already done as genericCast codeStream.checkcast(this.resolvedType); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); } else if (needRuntimeCheckcast) { codeStream.pop(); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public Expression innermostCastedExpression(){ Expression current = this.expression; while (current instanceof CastExpression) { current = ((CastExpression) current).expression; } return current; } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#localVariableBinding() */ public LocalVariableBinding localVariableBinding() { return this.expression.localVariableBinding(); } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { return this.expression.nullStatus(flowInfo, flowContext); } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#optimizedBooleanConstant() */ public Constant optimizedBooleanConstant() { switch(this.resolvedType.id) { case T_boolean : case T_JavaLangBoolean : return this.expression.optimizedBooleanConstant(); } return Constant.NotAConstant; } public StringBuffer printExpression(int indent, StringBuffer output) { output.append('('); this.type.print(0, output).append(") "); //$NON-NLS-1$ return this.expression.printExpression(0, output); } public TypeBinding resolveType(BlockScope scope) { // compute a new constant if the cast is effective // due to the fact an expression may start with ( and that a cast can also start with ( // the field is an expression....it can be a TypeReference OR a NameReference Or // any kind of Expression <-- this last one is invalid....... this.constant = Constant.NotAConstant; this.implicitConversion = TypeIds.T_undefined; boolean exprContainCast = false; TypeBinding castType = this.resolvedType = this.type.resolveType(scope); //expression.setExpectedType(this.resolvedType); // needed in case of generic method invocation if (this.expression instanceof CastExpression) { this.expression.bits |= ASTNode.DisableUnnecessaryCastCheck; exprContainCast = true; } TypeBinding expressionType = this.expression.resolveType(scope); if (this.expression instanceof MessageSend) { MessageSend messageSend = (MessageSend) this.expression; MethodBinding methodBinding = messageSend.binding; if (methodBinding != null && methodBinding.isPolymorphic()) { messageSend.binding = scope.environment().updatePolymorphicMethodReturnType((PolymorphicMethodBinding) methodBinding, castType); if (expressionType != castType) { expressionType = castType; this.bits |= ASTNode.DisableUnnecessaryCastCheck; } } } if (castType != null) { if (expressionType != null) { boolean isLegal = checkCastTypesCompatibility(scope, castType, expressionType, this.expression); if (isLegal) { this.expression.computeConversion(scope, castType, expressionType); if ((this.bits & ASTNode.UnsafeCast) != 0) { // unsafe cast if (scope.compilerOptions().reportUnavoidableGenericTypeProblems || !this.expression.forcedToBeRaw(scope.referenceContext())) { scope.problemReporter().unsafeCast(this, scope); } } else { if (castType.isRawType() && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore){ scope.problemReporter().rawTypeReference(this.type, castType); } if ((this.bits & (ASTNode.UnnecessaryCast|ASTNode.DisableUnnecessaryCastCheck)) == ASTNode.UnnecessaryCast) { // unnecessary cast if (!isIndirectlyUsed()) // used for generic type inference or boxing ? scope.problemReporter().unnecessaryCast(this); } } } else { // illegal cast if ((castType.tagBits & TagBits.HasMissingType) == 0) { // no complaint if secondary error scope.problemReporter().typeCastError(this, castType, expressionType); } this.bits |= ASTNode.DisableUnnecessaryCastCheck; // disable further secondary diagnosis } } this.resolvedType = castType.capture(scope, this.sourceEnd); if (exprContainCast) { checkNeedForCastCast(scope, this); } } return this.resolvedType; } /** * @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 or boxing. */ private boolean isIndirectlyUsed() { 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; } } if (this.expectedType != null && this.resolvedType.isBaseType() && !this.resolvedType.isCompatibleWith(this.expectedType)) { // boxing: Short s = (short) _byte return true; } return false; } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsNeedCheckCast() */ public void tagAsNeedCheckCast() { this.bits |= ASTNode.GenerateCheckcast; } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope, TypeBinding) */ public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) { this.bits |= ASTNode.UnnecessaryCast; } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.type.traverse(visitor, blockScope); this.expression.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration0000644000175000001440000001250512212041344032420 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.generateMethodInfoAttributes(this.binding, this); classFile.completeMethodInfo(this.binding, 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('<'); 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) { this.scope.problemReporter().annotationMembersCannotHaveParameters(this); } if (this.typeParameters != null) { this.scope.problemReporter().annotationMembersCannotHaveTypeParameters(this); } if (this.extendedDimensions != 0) { this.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(); if (returnTypeBinding.dimensions() <= 1) { // only 1-dimensional array permitted 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 : break checkAnnotationMethodType; } if (leafReturnType.isEnum() || leafReturnType.isAnnotationType()) break checkAnnotationMethodType; } this.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(this.scope, returnTypeBinding); this.binding.setDefaultValue(org.eclipse.jdt.internal.compiler.lookup.ElementValuePair.getValue(this.defaultValue)); } else { // let it know it does not have a default value so it won't try to find it this.binding.setDefaultValue(null); } } } 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, this.scope); } if (this.returnType != null) { this.returnType.traverse(visitor, this.scope); } if (this.defaultValue != null) { this.defaultValue.traverse(visitor, this.scope); } } visitor.endVisit(this, classScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/Assignment.java0000644000175000001440000003017712212041344030034 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Genady Beriozkin - added support for reporting assignment with no effect * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 292478 - Report potentially null across variable assignment * bug 335093 - [compiler][null] minimal hook for future null annotation support * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 358903 - Filter practically unimportant resource leak warnings * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking *******************************************************************************/ 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.*; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class Assignment extends Expression { public Expression lhs; public Expression expression; public Assignment(Expression lhs, Expression expression, int sourceEnd) { //lhs is always a reference by construction , //but is build as an expression ==> the checkcast cannot fail this.lhs = lhs; lhs.bits |= IsStrictlyAssigned; // tag lhs as assigned this.expression = expression; this.sourceStart = lhs.sourceStart; this.sourceEnd = sourceEnd; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // record setting a variable: various scenarii are possible, setting an array reference, // a field reference, a blank final field reference, a field of an enclosing instance or // just a local variable. LocalVariableBinding local = this.lhs.localVariableBinding(); this.expression.checkNPEbyUnboxing(currentScope, flowContext, flowInfo); FlowInfo preInitInfo = null; CompilerOptions compilerOptions = currentScope.compilerOptions(); boolean shouldAnalyseResource = local != null && flowInfo.reachMode() == FlowInfo.REACHABLE && compilerOptions.analyseResourceLeaks && (FakedTrackingVariable.isAnyCloseable(this.expression.resolvedType) || this.expression.resolvedType == TypeBinding.NULL); if (shouldAnalyseResource) { preInitInfo = flowInfo.unconditionalCopy(); // analysis of resource leaks needs additional context while analyzing the RHS: FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, local, this.expression, flowInfo); } flowInfo = ((Reference) this.lhs) .analyseAssignment(currentScope, flowContext, flowInfo, this, false) .unconditionalInits(); if (shouldAnalyseResource) FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, flowContext, this, this.expression, local); else FakedTrackingVariable.cleanUpAfterAssignment(currentScope, this.lhs.bits, this.expression); int nullStatus = this.expression.nullStatus(flowInfo, flowContext); if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { if (nullStatus == FlowInfo.NULL) { flowContext.recordUsingNullReference(currentScope, local, this.lhs, FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo); } } if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) { VariableBinding var = this.lhs.nullAnnotatedVariableBinding(); if (var != null) { nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, var, nullStatus, this.expression, this.expression.resolvedType); if (nullStatus == FlowInfo.NON_NULL && var instanceof FieldBinding && this.lhs instanceof Reference && compilerOptions.enableSyntacticNullAnalysisForFields) { int timeToLive = (this.bits & InsideExpressionStatement) != 0 ? 2 // assignment is statement: make info survives the end of this statement : 1; // assignment is expression: expire on next event. flowContext.recordNullCheckedFieldReference((Reference) this.lhs, timeToLive); } } } if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { flowInfo.markNullStatus(local, nullStatus); flowContext.markFinallyNullStatus(local, nullStatus); } return flowInfo; } void checkAssignment(BlockScope scope, TypeBinding lhsType, TypeBinding rhsType) { FieldBinding leftField = getLastField(this.lhs); if (leftField != null && rhsType != TypeBinding.NULL && (lhsType.kind() == Binding.WILDCARD_TYPE) && ((WildcardBinding)lhsType).boundKind != Wildcard.SUPER) { scope.problemReporter().wildcardAssignment(lhsType, rhsType, this.expression); } else if (leftField != null && !leftField.isStatic() && leftField.declaringClass != null /*length pseudo field*/&& leftField.declaringClass.isRawType()) { scope.problemReporter().unsafeRawFieldAssignment(leftField, rhsType, this.lhs); } else if (rhsType.needsUncheckedConversion(lhsType)) { scope.problemReporter().unsafeTypeConversion(this.expression, rhsType, lhsType); } } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { // various scenarii are possible, setting an array reference, // a field reference, a blank final field reference, a field of an enclosing instance or // just a local variable. int pc = codeStream.position; ((Reference) this.lhs).generateAssignment(currentScope, codeStream, this, valueRequired); // variable may have been optimized out // the lhs is responsible to perform the implicitConversion generation for the assignment since optimized for unused local assignment. codeStream.recordPositionsFrom(pc, this.sourceStart); } 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) { if ((someExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) { return (FieldBinding)qName.binding; } } else { return qName.otherBindings[qName.otherBindings.length - 1]; } } return null; } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { return this.expression.nullStatus(flowInfo, flowContext); } public StringBuffer print(int indent, StringBuffer output) { //no () when used as a statement printIndent(indent, output); return printExpressionNoParenthesis(indent, output); } public StringBuffer printExpression(int indent, StringBuffer output) { //subclass redefine printExpressionNoParenthesis() output.append('('); return printExpressionNoParenthesis(0, output).append(')'); } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { this.lhs.printExpression(indent, output).append(" = "); //$NON-NLS-1$ return this.expression.printExpression(0, output); } public StringBuffer printStatement(int indent, StringBuffer output) { //no () when used as a statement return print(indent, output).append(';'); } public TypeBinding resolveType(BlockScope scope) { // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference this.constant = Constant.NotAConstant; if (!(this.lhs instanceof Reference) || this.lhs.isThis()) { scope.problemReporter().expressionShouldBeAVariable(this.lhs); return null; } TypeBinding lhsType = this.lhs.resolveType(scope); this.expression.setExpectedType(lhsType); // needed in case of generic method invocation if (lhsType != null) { this.resolvedType = lhsType.capture(scope, this.sourceEnd); } LocalVariableBinding localVariableBinding = this.lhs.localVariableBinding(); if (localVariableBinding != null) { localVariableBinding.tagBits &= ~TagBits.IsEffectivelyFinal; } TypeBinding rhsType = this.expression.resolveType(scope); if (lhsType == null || rhsType == null) { return null; } // check for assignment with no effect Binding left = getDirectBinding(this.lhs); if (left != null && !left.isVolatile() && left == getDirectBinding(this.expression)) { scope.problemReporter().assignmentHasNoEffect(this, left.shortReadableName()); } // Compile-time conversion of base-types : implicit narrowing integer into byte/short/character // may require to widen the rhs expression at runtime if (lhsType != rhsType) { // must call before computeConversion() and typeMismatchError() scope.compilationUnitScope().recordTypeConversion(lhsType, rhsType); } if (this.expression.isConstantValueOfTypeAssignableToType(rhsType, lhsType) || rhsType.isCompatibleWith(lhsType, scope)) { this.expression.computeConversion(scope, lhsType, rhsType); checkAssignment(scope, lhsType, rhsType); if (this.expression instanceof CastExpression && (this.expression.bits & ASTNode.UnnecessaryCast) == 0) { CastExpression.checkNeedForAssignedCast(scope, lhsType, (CastExpression) this.expression); } return this.resolvedType; } else if (isBoxingCompatible(rhsType, lhsType, this.expression, scope)) { this.expression.computeConversion(scope, lhsType, rhsType); if (this.expression instanceof CastExpression && (this.expression.bits & ASTNode.UnnecessaryCast) == 0) { CastExpression.checkNeedForAssignedCast(scope, lhsType, (CastExpression) this.expression); } return this.resolvedType; } scope.problemReporter().typeMismatchError(rhsType, lhsType, this.expression, this.lhs); return lhsType; } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveTypeExpecting(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding) */ public TypeBinding resolveTypeExpecting(BlockScope scope, 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 == TypeBinding.BOOLEAN && lhsType == TypeBinding.BOOLEAN && (this.lhs.bits & IsStrictlyAssigned) != 0) { scope.problemReporter().possibleAccidentalBooleanAssignment(this); } checkAssignment(scope, lhsType, rhsType); return type; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { this.lhs.traverse(visitor, scope); this.expression.traverse(visitor, scope); } visitor.endVisit(this, scope); } public LocalVariableBinding localVariableBinding() { return this.lhs.localVariableBinding(); } } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CombinedBinaryExpression.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CombinedBinaryExpression.ja0000644000175000001440000003643612212041344032346 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" *******************************************************************************/ 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.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; 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.lookup.TypeIds; /** * CombinedBinaryExpression is an implementation of BinaryExpression that * specifically attempts to mitigate the issues raised by expressions which * have a very deep leftmost branch. It does so by maintaining a table of * direct references to its subexpressions, and implementing non-recursive * variants of the most significant recursive algorithms of its ancestors. * The subexpressions table only holds intermediate binary expressions. Its * role is to provide the reversed navigation through the left relationship * of BinaryExpression to Expression. To cope with potentially very deep * left branches, an instance of CombinedBinaryExpression is created once in * a while, using variable thresholds held by {@link #arityMax}. * As a specific case, the topmost node of all binary expressions that are * deeper than one is a CombinedBinaryExpression, but it has no references * table.
* Notes: *
    *
  • CombinedBinaryExpression is not meant to behave in other ways than * BinaryExpression in any observable respect;
  • *
  • visitors that implement their own traversal upon binary expressions * should consider taking advantage of combined binary expressions, or * else face a risk of StackOverflowError upon deep instances;
  • *
  • callers that need to change the operator should rebuild the expression * from scratch, or else amend the references table as needed to cope with * the resulting, separated expressions.
  • *
*/ public class CombinedBinaryExpression extends BinaryExpression { /** * The number of consecutive binary expressions of this' left branch that * bear the same operator as this.
* Notes: *
  • the presence of a CombinedBinaryExpression instance resets * arity, even when its operator is compatible;
  • *
  • this property is maintained by the parser.
  • *
*/ public int arity; /** * The threshold that will trigger the creation of the next full-fledged * CombinedBinaryExpression. This field is only maintained for the * topmost binary expression (it is 0 otherwise). It enables a variable * policy, which scales better with very large expressions. */ public int arityMax; /** * Upper limit for {@link #arityMax}. */ public static final int ARITY_MAX_MAX = 160; /** * Default lower limit for {@link #arityMax}. */ public static final int ARITY_MAX_MIN = 20; /** * Default value for the first term of the series of {@link #arityMax} * values. Changing this allows for experimentation. Not meant to be * changed during a parse operation. */ public static int defaultArityMaxStartingValue = ARITY_MAX_MIN; /** * A table of references to the binary expressions of this' left branch. * Instances of CombinedBinaryExpression are not repeated here. Instead, * the left subexpression of referencesTable[0] may be a combined binary * expression, if appropriate. Null when this only cares about tracking * the expression's arity. */ public BinaryExpression referencesTable[]; /** * Make a new CombinedBinaryExpression. If arity is strictly greater than one, * a references table is built and initialized with the reverse relationship of * the one defined by {@link BinaryExpression#left}. arity and left must be * compatible with each other (that is, there must be at least arity - 1 * consecutive compatible binary expressions into the leftmost branch of left, * the topmost of which being left's immediate left expression). * @param left the left branch expression * @param right the right branch expression * @param operator the operator for this binary expression - only PLUS for now * @param arity the number of binary expressions of a compatible operator that * already exist into the leftmost branch of left (including left); must * be strictly greater than 0 */ public CombinedBinaryExpression(Expression left, Expression right, int operator, int arity) { super(left, right, operator); initArity(left, arity); } public CombinedBinaryExpression(CombinedBinaryExpression expression) { super(expression); initArity(expression.left, expression.arity); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // keep implementation in sync with BinaryExpression#analyseCode if (this.referencesTable == null) { return super.analyseCode(currentScope, flowContext, flowInfo); } try { BinaryExpression cursor; if ((cursor = this.referencesTable[0]).resolvedType.id != TypeIds.T_JavaLangString) { cursor.left.checkNPE(currentScope, flowContext, flowInfo); } flowInfo = cursor.left.analyseCode(currentScope, flowContext, flowInfo). unconditionalInits(); for (int i = 0, end = this.arity; i < end; i ++) { if ((cursor = this.referencesTable[i]).resolvedType.id != TypeIds.T_JavaLangString) { cursor.right.checkNPE(currentScope, flowContext, flowInfo); } flowInfo = cursor.right. analyseCode(currentScope, flowContext, flowInfo). unconditionalInits(); } if (this.resolvedType.id != TypeIds.T_JavaLangString) { this.right.checkNPE(currentScope, flowContext, flowInfo); } return this.right.analyseCode(currentScope, flowContext, flowInfo). unconditionalInits(); } finally { // account for exception possibly thrown by arithmetics flowContext.recordAbruptExit(); } } public void generateOptimizedStringConcatenation(BlockScope blockScope, CodeStream codeStream, int typeID) { // keep implementation in sync with BinaryExpression and Expression // #generateOptimizedStringConcatenation if (this.referencesTable == null) { super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID); } else { if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { if (this.constant != Constant.NotAConstant) { codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.invokeStringConcatenationAppendForType( this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); } else { BinaryExpression cursor = this.referencesTable[0]; int restart = 0; // int cursorTypeID; int pc = codeStream.position; for (restart = this.arity - 1; restart >= 0; restart--) { if ((cursor = this.referencesTable[restart]).constant != Constant.NotAConstant) { codeStream.generateConstant(cursor.constant, cursor.implicitConversion); codeStream.invokeStringConcatenationAppendForType( cursor.implicitConversion & TypeIds.COMPILE_TYPE_MASK); break; } // never happens for now - may reconsider if we decide to // cover more than string concatenation // if (!((((cursor = this.referencesTable[restart]).bits & // ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == // OperatorIds.PLUS) & // ((cursorTypeID = cursor.bits & ASTNode.ReturnTypeIDMASK) == // TypeIds.T_JavaLangString)) { // if (cursorTypeID == T_JavaLangString && // cursor.constant != Constant.NotAConstant && // cursor.constant.stringValue().length() == 0) { // break; // optimize str + "" // } // cursor.generateCode(blockScope, codeStream, true); // codeStream.invokeStringConcatenationAppendForType( // cursorTypeID); // break; // } } restart++; if (restart == 0) { // reached the leftmost expression cursor.left.generateOptimizedStringConcatenation( blockScope, codeStream, cursor.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); } int pcAux; for (int i = restart; i < this.arity; i++) { codeStream.recordPositionsFrom(pc, (cursor = this.referencesTable[i]).left.sourceStart); pcAux = codeStream.position; cursor.right.generateOptimizedStringConcatenation(blockScope, codeStream, cursor.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pcAux, cursor.right.sourceStart); } codeStream.recordPositionsFrom(pc, this.left.sourceStart); pc = codeStream.position; this.right.generateOptimizedStringConcatenation( blockScope, codeStream, this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.right.sourceStart); } } else { super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID); } } } public void generateOptimizedStringConcatenationCreation(BlockScope blockScope, CodeStream codeStream, int typeID) { // keep implementation in sync with BinaryExpression // #generateOptimizedStringConcatenationCreation if (this.referencesTable == null) { super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID); } else { if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString) && this.constant == Constant.NotAConstant) { int pc = codeStream.position; BinaryExpression cursor = this.referencesTable[this.arity - 1]; // silence warnings int restart = 0; for (restart = this.arity - 1; restart >= 0; restart--) { if (((((cursor = this.referencesTable[restart]).bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((cursor.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { if (cursor.constant != Constant.NotAConstant) { codeStream.newStringContatenation(); // new: java.lang.StringBuffer codeStream.dup(); codeStream.ldc(cursor.constant.stringValue()); codeStream.invokeStringConcatenationStringConstructor(); // invokespecial: java.lang.StringBuffer.(Ljava.lang.String;)V break; } } else { cursor.generateOptimizedStringConcatenationCreation(blockScope, codeStream, cursor.implicitConversion & TypeIds.COMPILE_TYPE_MASK); break; } } restart++; if (restart == 0) { // reached the leftmost expression cursor.left.generateOptimizedStringConcatenationCreation( blockScope, codeStream, cursor.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); } int pcAux; for (int i = restart; i < this.arity; i++) { codeStream.recordPositionsFrom(pc, (cursor = this.referencesTable[i]).left.sourceStart); pcAux = codeStream.position; cursor.right.generateOptimizedStringConcatenation(blockScope, codeStream, cursor.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pcAux, cursor.right.sourceStart); } codeStream.recordPositionsFrom(pc, this.left.sourceStart); pc = codeStream.position; this.right.generateOptimizedStringConcatenation( blockScope, codeStream, this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.right.sourceStart); } else { super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID); } } } private void initArity(Expression expression, int value) { this.arity = value; if (value > 1) { this.referencesTable = new BinaryExpression[value]; this.referencesTable[value - 1] = (BinaryExpression) expression; for (int i = value - 1; i > 0; i--) { this.referencesTable[i - 1] = (BinaryExpression) this.referencesTable[i].left; } } else { this.arityMax = defaultArityMaxStartingValue; } } public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { // keep implementation in sync with // BinaryExpression#printExpressionNoParenthesis and // OperatorExpression#printExpression if (this.referencesTable == null) { return super.printExpressionNoParenthesis(indent, output); } String operatorString = operatorToString(); for (int i = this.arity - 1; i >= 0; i--) { output.append('('); } output = this.referencesTable[0].left. printExpression(indent, output); for (int i = 0, end = this.arity; i < end; i++) { output.append(' ').append(operatorString).append(' '); output = this.referencesTable[i].right. printExpression(0, output); output.append(')'); } output.append(' ').append(operatorString).append(' '); return this.right.printExpression(0, output); } public TypeBinding resolveType(BlockScope scope) { // keep implementation in sync with BinaryExpression#resolveType if (this.referencesTable == null) { return super.resolveType(scope); } BinaryExpression cursor; if ((cursor = this.referencesTable[0]).left instanceof CastExpression) { cursor.left.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on } cursor.left.resolveType(scope); for (int i = 0, end = this.arity; i < end; i ++) { this.referencesTable[i].nonRecursiveResolveTypeUpwards(scope); } nonRecursiveResolveTypeUpwards(scope); return this.resolvedType; } public void traverse(ASTVisitor visitor, BlockScope scope) { if (this.referencesTable == null) { super.traverse(visitor, scope); } else { if (visitor.visit(this, scope)) { int restart; for (restart = this.arity - 1; restart >= 0; restart--) { if (!visitor.visit( this.referencesTable[restart], scope)) { visitor.endVisit( this.referencesTable[restart], scope); break; } } restart++; // restart now points to the deepest BE for which // visit returned true, if any if (restart == 0) { this.referencesTable[0].left.traverse(visitor, scope); } for (int i = restart, end = this.arity; i < end; i++) { this.referencesTable[i].right.traverse(visitor, scope); visitor.endVisit(this.referencesTable[i], scope); } this.right.traverse(visitor, scope); } visitor.endVisit(this, scope); } } /** * Change {@link #arityMax} if and as needed. The current policy is to double * arityMax each time this method is called, until it reaches * {@link #ARITY_MAX_MAX}. Other policies may consider incrementing it less * agressively. Call only after an appropriate value has been assigned to * {@link #left}. */ // more sophisticate increment policies would leverage the leftmost expression // to hold an indication of the number of uses of a given arityMax in a row public void tuneArityMax() { if (this.arityMax < ARITY_MAX_MAX) { this.arityMax *= 2; } } } ././@LongLink0000644000000000000000000000014612251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.jav0000644000175000001440000000373512212041344032324 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.*; public class QualifiedSuperReference extends QualifiedThisReference { public QualifiedSuperReference(TypeReference name, int pos, int sourceEnd) { super(name, pos, sourceEnd); } public boolean isSuper() { return true; } public boolean isThis() { return false; } public StringBuffer printExpression(int indent, StringBuffer output) { return this.qualification.print(0, output).append(".super"); //$NON-NLS-1$ } public TypeBinding resolveType(BlockScope scope) { if ((this.bits & ParenthesizedMASK) != 0) { scope.problemReporter().invalidParenthesizedExpression(this); return null; } super.resolveType(scope); if (this.currentCompatibleType == null) return null; // error case if (this.currentCompatibleType.id == T_JavaLangObject) { scope.problemReporter().cannotUseSuperInJavaLangObject(this); return null; } return this.resolvedType = this.currentCompatibleType.superclass(); } public void traverse( ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.qualification.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } public void traverse( ASTVisitor visitor, ClassScope blockScope) { if (visitor.visit(this, blockScope)) { this.qualification.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/MessageSend.java0000644000175000001440000011375012212041344030121 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752) * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 358903 - Filter practically unimportant resource leak warnings * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 379784 - [compiler] "Method can be static" is not getting reported * bug 379834 - Wrong "method can be static" in presence of qualified super and different staticness of nested super class. * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional * bug 381445 - [compiler][resource] Can the resource leak check be made aware of Closeables.closeQuietly? * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking * Jesper S Moller - Contributions for * Bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ 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.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; 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.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ImplicitNullAnnotationVerifier; import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; 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.problem.ProblemSeverities; public class MessageSend extends Expression implements InvocationSite { public Expression receiver; public char[] selector; public Expression[] arguments; public MethodBinding binding; // exact binding resulting from lookup public MethodBinding syntheticAccessor; // synthetic accessor for inner-emulation public TypeBinding expectedType; // for generic method invocation (return type inference) public long nameSourcePosition ; //(start<<32)+end 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) { boolean nonStatic = !this.binding.isStatic(); boolean wasInsideAssert = ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0); flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits(); // recording the closing of AutoCloseable resources: boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks; if (analyseResources) { Expression closeTarget = null; if (nonStatic) { // closeable.close() if (CharOperation.equals(TypeConstants.CLOSE, this.selector)) { closeTarget = this.receiver; } } else if (this.arguments != null && this.arguments.length > 0 && FakedTrackingVariable.isAnyCloseable(this.arguments[0].resolvedType)) { // Helper.closeMethod(closeable, ..) for (int i=0; i= ClassFileConstants.JDK1_5) { // from 1.5 source level on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast this.valueCast = runtimeTimeType; } if (this.valueCast instanceof ReferenceBinding) { ReferenceBinding referenceCast = (ReferenceBinding) this.valueCast; if (!referenceCast.canBeSeenBy(scope)) { scope.problemReporter().invalidType(this, new ProblemReferenceBinding( CharOperation.splitOn('.', referenceCast.shortReadableName()), referenceCast, ProblemReasons.NotVisible)); } } } super.computeConversion(scope, runtimeTimeType, compileTimeType); } /** * MessageSend 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) { int pc = codeStream.position; // generate receiver/enclosing instance access MethodBinding codegenBinding = this.binding instanceof PolymorphicMethodBinding ? this.binding : this.binding.original(); boolean isStatic = codegenBinding.isStatic(); if (isStatic) { this.receiver.generateCode(currentScope, codeStream, false); } else if ((this.bits & ASTNode.DepthMASK) != 0 && this.receiver.isImplicitThis()) { // outer access ? // outer method can be reached through emulation if implicit access ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); Object[] path = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); codeStream.generateOuterAccess(path, this, targetType, currentScope); } else { this.receiver.generateCode(currentScope, codeStream, true); if ((this.bits & NeedReceiverGenericCast) != 0) { codeStream.checkcast(this.actualReceiverType); } } codeStream.recordPositionsFrom(pc, this.sourceStart); // generate arguments generateArguments(this.binding, this.arguments, currentScope, codeStream); pc = codeStream.position; // actual message invocation if (this.syntheticAccessor == null){ TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); if (isStatic){ codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass); } else if((this.receiver.isSuper()) || codegenBinding.isPrivate()){ codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, constantPoolDeclaringClass); } else if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type codeStream.invoke(Opcodes.OPC_invokeinterface, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokevirtual, codegenBinding, constantPoolDeclaringClass); } } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessor, null /* default declaringClass */); } // required cast must occur even if no value is required if (this.valueCast != null) codeStream.checkcast(this.valueCast); if (valueRequired){ // implicit conversion if necessary codeStream.generateImplicitConversion(this.implicitConversion); } else { boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; // conversion only generated if unboxing if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.returnType.id) { case T_long : case T_double : codeStream.pop2(); break; case T_void : break; default : codeStream.pop(); } } 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 this.receiver.isSuper(); } public boolean isTypeAccess() { return this.receiver != null && this.receiver.isTypeReference(); } public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){ if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return; // if method from parameterized type got found, use the original method at codegen time MethodBinding codegenBinding = this.binding.original(); if (this.binding.isPrivate()){ // depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy) if (currentScope.enclosingSourceType() != codegenBinding.declaringClass){ this.syntheticAccessor = ((SourceTypeBinding)codegenBinding.declaringClass).addSyntheticMethod(codegenBinding, false /* not super access there */); currentScope.problemReporter().needToEmulateMethodAccess(codegenBinding, this); return; } } else if (this.receiver instanceof QualifiedSuperReference){ // qualified super // qualified super need emulation always SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)this.receiver).currentCompatibleType); this.syntheticAccessor = destinationType.addSyntheticMethod(codegenBinding, isSuperAccess()); currentScope.problemReporter().needToEmulateMethodAccess(codegenBinding, this); return; } else if (this.binding.isProtected()){ SourceTypeBinding enclosingSourceType; if (((this.bits & ASTNode.DepthMASK) != 0) && codegenBinding.declaringClass.getPackage() != (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()){ SourceTypeBinding currentCompatibleType = (SourceTypeBinding)enclosingSourceType.enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); this.syntheticAccessor = currentCompatibleType.addSyntheticMethod(codegenBinding, isSuperAccess()); currentScope.problemReporter().needToEmulateMethodAccess(codegenBinding, this); return; } } } public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) { if (this.binding.isValidBinding()) { // try to retrieve null status of this message send from an annotation of the called method: long tagBits = this.binding.tagBits; if ((tagBits & TagBits.AnnotationNonNull) != 0) return FlowInfo.NON_NULL; if ((tagBits & TagBits.AnnotationNullable) != 0) return FlowInfo.POTENTIALLY_NULL | FlowInfo.POTENTIALLY_NON_NULL; } return FlowInfo.UNKNOWN; } /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope) */ public TypeBinding postConversionType(Scope scope) { TypeBinding convertedType = this.resolvedType; if (this.valueCast != null) convertedType = this.valueCast; int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; switch (runtimeType) { case T_boolean : convertedType = TypeBinding.BOOLEAN; break; case T_byte : convertedType = TypeBinding.BYTE; break; case T_short : convertedType = TypeBinding.SHORT; break; case T_char : convertedType = TypeBinding.CHAR; break; case T_int : convertedType = TypeBinding.INT; break; case T_float : convertedType = TypeBinding.FLOAT; break; case T_long : convertedType = TypeBinding.LONG; break; case T_double : convertedType = TypeBinding.DOUBLE; break; default : } if ((this.implicitConversion & TypeIds.BOXING) != 0) { convertedType = scope.environment().computeBoxingType(convertedType); } return convertedType; } public StringBuffer printExpression(int indent, StringBuffer output){ if (!this.receiver.isImplicitThis()) this.receiver.printExpression(0, output).append('.'); if (this.typeArguments != null) { output.append('<'); int max = this.typeArguments.length - 1; for (int j = 0; j < max; j++) { this.typeArguments[j].print(0, output); output.append(", ");//$NON-NLS-1$ } this.typeArguments[max].print(0, output); output.append('>'); } 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].printExpression(0, output); } } return output.append(')'); } public TypeBinding resolveType(BlockScope scope) { // Answer the signature return type // Base type promotion this.constant = Constant.NotAConstant; boolean receiverCast = false, argsContainCast = false; if (this.receiver instanceof CastExpression) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on receiverCast = true; } this.actualReceiverType = this.receiver.resolveType(scope); boolean receiverIsType = this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0; 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.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 = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5; // typeChecks all arguments this.genericTypeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeReference typeReference = this.typeArguments[i]; if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) { argHasError = true; } if (argHasError && typeReference instanceof Wildcard) { scope.problemReporter().illegalUsageOfWildcard(typeReference); } } if (argHasError) { if (this.arguments != null) { // still attempt to resolve arguments for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return null; } } // will check for null after args are resolved TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; if (this.arguments != null) { boolean argHasError = false; // typeChecks all arguments int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++){ Expression argument = this.arguments[i]; if (argument instanceof CastExpression) { argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on argsContainCast = true; } if ((argumentTypes[i] = argument.resolveType(scope)) == null){ argHasError = true; } } if (argHasError) { if (this.actualReceiverType instanceof ReferenceBinding) { // record a best guess, for clients who need hint about possible method match TypeBinding[] pseudoArgs = new TypeBinding[length]; for (int i = length; --i >= 0;) pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type this.binding = this.receiver.isImplicitThis() ? scope.getImplicitMethod(this.selector, pseudoArgs, this) : scope.findMethod((ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this); if (this.binding != null && !this.binding.isValidBinding()) { MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; // record the closest match, for clients who may still need hint about possible method match if (closestMatch != null) { if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method // shouldn't return generic method outside its context, rather convert it to raw method (175409) closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null); } this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } } return null; } } if (this.actualReceiverType == null) { return null; } // base type cannot receive any message if (this.actualReceiverType.isBaseType()) { scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); return null; } this.binding = this.receiver.isImplicitThis() ? scope.getImplicitMethod(this.selector, argumentTypes, this) : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); if (!this.binding.isValidBinding()) { if (this.binding.declaringClass == null) { if (this.actualReceiverType instanceof ReferenceBinding) { this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType; } else { scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); return null; } } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=245007 avoid secondary errors in case of // missing super type for anonymous classes ... ReferenceBinding declaringClass = this.binding.declaringClass; boolean avoidSecondary = declaringClass != null && declaringClass.isAnonymousType() && declaringClass.superclass() instanceof MissingTypeBinding; if (!avoidSecondary) scope.problemReporter().invalidMethod(this, this.binding); MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; switch (this.binding.problemId()) { case ProblemReasons.Ambiguous : break; // no resilience on 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; break; } // record the closest match, for clients who may still need hint about possible method match if (closestMatch != null) { this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } return (this.resolvedType != null && (this.resolvedType.tagBits & TagBits.HasMissingType) == 0) ? this.resolvedType : null; } final CompilerOptions compilerOptions = scope.compilerOptions(); if (compilerOptions.complianceLevel <= ClassFileConstants.JDK1_6 && this.binding.isPolymorphic()) { scope.problemReporter().polymorphicMethodNotBelow17(this); return null; } if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) { // not interested in reporting problems against this.binding: new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations) .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope); } if (((this.bits & ASTNode.InsideExpressionStatement) != 0) && this.binding.isPolymorphic()) { // we only set the return type to be void if this method invocation is used inside an expression statement this.binding = scope.environment().updatePolymorphicMethodReturnType((PolymorphicMethodBinding) this.binding, TypeBinding.VOID); } if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInMethod(this, this.binding); } if (!this.binding.isStatic()) { // the "receiver" must not be a type if (receiverIsType) { scope.problemReporter().mustUseAStaticMethod(this, this.binding); if (this.actualReceiverType.isRawType() && (this.receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0 && compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) { scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType); } } else { // handle indirect inheritance thru variable secondary bound // receiver may receive generic cast, as part of implicit conversion TypeBinding oldReceiverType = this.actualReceiverType; this.actualReceiverType = this.actualReceiverType.getErasureCompatibleType(this.binding.declaringClass); this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); if (this.actualReceiverType != oldReceiverType && this.receiver.postConversionType(scope) != this.actualReceiverType) { // record need for explicit cast at codegen since receiver could not handle it this.bits |= NeedReceiverGenericCast; } } } else { // static message invoked through receiver? legal but unoptimal (optional warning). if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || receiverIsType)) { scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding); } if (!this.receiver.isImplicitThis() && this.binding.declaringClass != this.actualReceiverType) { scope.problemReporter().indirectAccessToStaticMethod(this, this.binding); } } if (checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } //-------message send that are known to fail at compile time----------- if (this.binding.isAbstract()) { if (this.receiver.isSuper()) { scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding); } // abstract private methods cannot occur nor abstract static............ } if (isMethodUseDeprecated(this.binding, scope, true)) scope.problemReporter().deprecatedMethod(this.binding, this); // from 1.5 source level on, array#clone() returns the array type (but binding still shows Object) if (this.binding == scope.environment().arrayClone && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) { this.resolvedType = this.actualReceiverType; } else { TypeBinding returnType; if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6 returnType = this.binding.returnType; if (returnType != null) { returnType = scope.environment().convertToRawType(returnType.erasure(), true); } } else { returnType = this.binding.returnType; if (returnType != null) { returnType = returnType.capture(scope, this.sourceEnd); } } this.resolvedType = returnType; } if (this.receiver.isSuper() && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) { final ReferenceContext referenceContext = scope.methodScope().referenceContext; if (referenceContext instanceof AbstractMethodDeclaration) { final AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) referenceContext; MethodBinding enclosingMethodBinding = abstractMethodDeclaration.binding; if (enclosingMethodBinding.isOverriding() && CharOperation.equals(this.binding.selector, enclosingMethodBinding.selector) && this.binding.areParametersEqual(enclosingMethodBinding)) { abstractMethodDeclaration.bits |= ASTNode.OverridingMethodWithSupercall; } } } if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments); } return (this.resolvedType.tagBits & TagBits.HasMissingType) == 0 ? this.resolvedType : null; } public void setActualReceiverType(ReferenceBinding receiverType) { if (receiverType == null) return; // error scenario only this.actualReceiverType = receiverType; } public void setDepth(int depth) { this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any if (depth > 0) { this.bits |= (depth & 0xFF) << ASTNode.DepthSHIFT; // encoded on 8 bits } } /** * @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 setFieldIndex(int depth) { // ignore for here } public TypeBinding expectedType() { return this.expectedType; } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { this.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 (this.arguments != null) { int argumentsLength = this.arguments.length; for (int i = 0; i < argumentsLength; i++) this.arguments[i].traverse(visitor, blockScope); } } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java0000644000175000001440000016030112212041344031004 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop) * Bug 388630 - @NonNull diagnostics at line 0 * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.*; 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.*; import org.eclipse.jdt.internal.compiler.parser.*; import org.eclipse.jdt.internal.compiler.problem.*; import org.eclipse.jdt.internal.compiler.util.Util; public class TypeDeclaration extends Statement implements ProblemSeverities, ReferenceContext { // Type decl kinds public static final int CLASS_DECL = 1; public static final int INTERFACE_DECL = 2; public static final int ENUM_DECL = 3; public static final int ANNOTATION_TYPE_DECL = 4; public int modifiers = ClassFileConstants.AccDefault; public int modifiersSourceStart; public Annotation[] annotations; public char[] name; public TypeReference superclass; public TypeReference[] superInterfaces; public FieldDeclaration[] fields; public AbstractMethodDeclaration[] methods; public TypeDeclaration[] memberTypes; public SourceTypeBinding binding; public ClassScope scope; public MethodScope initializerScope; public MethodScope staticInitializerScope; public boolean ignoreFurtherInvestigation = false; public int maxFieldCount; public int declarationSourceStart; public int declarationSourceEnd; public int bodyStart; public int bodyEnd; // doesn't include the trailing comment if any. public CompilationResult compilationResult; public MethodDeclaration[] missingAbstractMethods; public Javadoc javadoc; public QualifiedAllocationExpression allocation; // for anonymous only public TypeDeclaration enclosingType; // for member types only public FieldBinding enumValuesSyntheticfield; // for enum public int enumConstantsCounter; // 1.5 support public TypeParameter[] typeParameters; public TypeDeclaration(CompilationResult compilationResult){ this.compilationResult = compilationResult; } /* * We cause the compilation task to abort to a given extent. */ public void abort(int abortLevel, CategorizedProblem problem) { switch (abortLevel) { case AbortCompilation : throw new AbortCompilation(this.compilationResult, problem); case AbortCompilationUnit : throw new AbortCompilationUnit(this.compilationResult, problem); case AbortMethod : throw new AbortMethod(this.compilationResult, problem); default : throw new AbortType(this.compilationResult, problem); } } /** * This method is responsible for adding a method declaration to the type method collections. * Note that this implementation is inserting it in first place (as VAJ or javac), and that this * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as * the latter will have to reset the constant pool state accordingly (if it was added first, it does * not need to preserve some of the method specific cached entries since this will be the first method). * inserts the clinit method declaration in the first position. * * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int) */ public final void addClinit() { //see comment on needClassInitMethod if (needClassInitMethod()) { int length; AbstractMethodDeclaration[] methodDeclarations; if ((methodDeclarations = this.methods) == null) { length = 0; methodDeclarations = new AbstractMethodDeclaration[1]; } else { length = methodDeclarations.length; System.arraycopy( methodDeclarations, 0, (methodDeclarations = new AbstractMethodDeclaration[length + 1]), 1, length); } Clinit clinit = new Clinit(this.compilationResult); methodDeclarations[0] = clinit; // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits) clinit.declarationSourceStart = clinit.sourceStart = this.sourceStart; clinit.declarationSourceEnd = clinit.sourceEnd = this.sourceEnd; clinit.bodyEnd = this.sourceEnd; this.methods = methodDeclarations; } } /* * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding. * It is used to report errors for missing abstract methods. */ public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) { TypeBinding[] argumentTypes = methodBinding.parameters; int argumentsLength = argumentTypes.length; //the constructor MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult); methodDeclaration.selector = methodBinding.selector; methodDeclaration.sourceStart = this.sourceStart; methodDeclaration.sourceEnd = this.sourceEnd; methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~ClassFileConstants.AccAbstract; if (argumentsLength > 0) { String baseName = "arg";//$NON-NLS-1$ Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]); for (int i = argumentsLength; --i >= 0;) { arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, ClassFileConstants.AccDefault); } } //adding the constructor in the methods list if (this.missingAbstractMethods == null) { this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration }; } else { MethodDeclaration[] newMethods; System.arraycopy( this.missingAbstractMethods, 0, newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1], 1, this.missingAbstractMethods.length); newMethods[0] = methodDeclaration; this.missingAbstractMethods = newMethods; } //============BINDING UPDATE========================== methodDeclaration.binding = new MethodBinding( methodDeclaration.modifiers | ClassFileConstants.AccSynthetic, //methodDeclaration methodBinding.selector, methodBinding.returnType, argumentsLength == 0 ? Binding.NO_PARAMETERS : argumentTypes, //arguments bindings methodBinding.thrownExceptions, //exceptions this.binding); //declaringClass methodDeclaration.scope = new MethodScope(this.scope, methodDeclaration, true); methodDeclaration.bindArguments(); /* if (binding.methods == null) { binding.methods = new MethodBinding[] { methodDeclaration.binding }; } else { MethodBinding[] newMethods; System.arraycopy( binding.methods, 0, newMethods = new MethodBinding[binding.methods.length + 1], 1, binding.methods.length); newMethods[0] = methodDeclaration.binding; binding.methods = newMethods; }*/ //=================================================== return methodDeclaration; } /** * Flow analysis for a local innertype * */ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { if (this.ignoreFurtherInvestigation) return flowInfo; try { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.bits |= ASTNode.IsReachable; LocalTypeBinding localType = (LocalTypeBinding) this.binding; localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType)); } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); updateMaxFieldCount(); // propagate down the max field count internalAnalyseCode(flowContext, flowInfo); } catch (AbortType e) { this.ignoreFurtherInvestigation = true; } return flowInfo; } /** * Flow analysis for a member innertype * */ public void analyseCode(ClassScope enclosingClassScope) { if (this.ignoreFurtherInvestigation) return; try { // propagate down the max field count updateMaxFieldCount(); internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount)); } catch (AbortType e) { this.ignoreFurtherInvestigation = true; } } /** * Flow analysis for a local member innertype * */ public void analyseCode(ClassScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { if (this.ignoreFurtherInvestigation) return; try { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.bits |= ASTNode.IsReachable; LocalTypeBinding localType = (LocalTypeBinding) this.binding; localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType)); } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); updateMaxFieldCount(); // propagate down the max field count internalAnalyseCode(flowContext, flowInfo); } catch (AbortType e) { this.ignoreFurtherInvestigation = true; } } /** * Flow analysis for a package member type * */ public void analyseCode(CompilationUnitScope unitScope) { if (this.ignoreFurtherInvestigation) return; try { internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount)); } catch (AbortType e) { this.ignoreFurtherInvestigation = true; } } /** * Check for constructor vs. method with no return type. * Answers true if at least one constructor is defined */ public boolean checkConstructors(Parser parser) { //if a constructor has not the name of the type, //convert it into a method with 'null' as its return type boolean hasConstructor = false; if (this.methods != null) { for (int i = this.methods.length; --i >= 0;) { AbstractMethodDeclaration am; if ((am = this.methods[i]).isConstructor()) { if (!CharOperation.equals(am.selector, this.name)) { // the constructor was in fact a method with no return type // unless an explicit constructor call was supplied ConstructorDeclaration c = (ConstructorDeclaration) am; if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult); this.methods[i] = m; } } else { switch (kind(this.modifiers)) { case TypeDeclaration.INTERFACE_DECL : // report the problem and continue the parsing parser.problemReporter().interfaceCannotHaveConstructors((ConstructorDeclaration) am); break; case TypeDeclaration.ANNOTATION_TYPE_DECL : // report the problem and continue the parsing parser.problemReporter().annotationTypeDeclarationCannotHaveConstructor((ConstructorDeclaration) am); break; } hasConstructor = true; } } } } return hasConstructor; } public CompilationResult compilationResult() { return this.compilationResult; } public ConstructorDeclaration createDefaultConstructor( boolean needExplicitConstructorCall, boolean needToInsert) { //Add to method'set, the default constuctor that just recall the //super constructor with no arguments //The arguments' type will be positionned by the TC so just use //the default int instead of just null (consistency purpose) //the constructor ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult); constructor.bits |= ASTNode.IsDefaultConstructor; constructor.selector = this.name; constructor.modifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK; //if you change this setting, please update the //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method constructor.declarationSourceStart = constructor.sourceStart = this.sourceStart; constructor.declarationSourceEnd = constructor.sourceEnd = constructor.bodyEnd = this.sourceEnd; //the super call inside the constructor if (needExplicitConstructorCall) { constructor.constructorCall = SuperReference.implicitSuperConstructorCall(); constructor.constructorCall.sourceStart = this.sourceStart; constructor.constructorCall.sourceEnd = this.sourceEnd; } //adding the constructor in the methods list: rank is not critical since bindings will be sorted if (needToInsert) { if (this.methods == null) { this.methods = new AbstractMethodDeclaration[] { constructor }; } else { AbstractMethodDeclaration[] newMethods; System.arraycopy( this.methods, 0, newMethods = new AbstractMethodDeclaration[this.methods.length + 1], 1, this.methods.length); newMethods[0] = constructor; this.methods = newMethods; } } return constructor; } // anonymous type constructor creation: rank is important since bindings already got sorted public MethodBinding createDefaultConstructorWithBinding(MethodBinding inheritedConstructorBinding, boolean eraseThrownExceptions) { //Add to method'set, the default constuctor that just recall the //super constructor with the same arguments String baseName = "$anonymous"; //$NON-NLS-1$ TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters; int argumentsLength = argumentTypes.length; //the constructor ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult); constructor.selector = new char[] { 'x' }; //no maining constructor.sourceStart = this.sourceStart; constructor.sourceEnd = this.sourceEnd; int newModifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK; if (inheritedConstructorBinding.isVarargs()) { newModifiers |= ClassFileConstants.AccVarargs; } constructor.modifiers = newModifiers; constructor.bits |= ASTNode.IsDefaultConstructor; if (argumentsLength > 0) { Argument[] arguments = (constructor.arguments = new Argument[argumentsLength]); for (int i = argumentsLength; --i >= 0;) { arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, ClassFileConstants.AccDefault); } } //the super call inside the constructor constructor.constructorCall = SuperReference.implicitSuperConstructorCall(); constructor.constructorCall.sourceStart = this.sourceStart; constructor.constructorCall.sourceEnd = this.sourceEnd; if (argumentsLength > 0) { Expression[] args; args = constructor.constructorCall.arguments = new Expression[argumentsLength]; for (int i = argumentsLength; --i >= 0;) { args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L); } } //adding the constructor in the methods list if (this.methods == null) { this.methods = new AbstractMethodDeclaration[] { constructor }; } else { AbstractMethodDeclaration[] newMethods; System.arraycopy(this.methods, 0, newMethods = new AbstractMethodDeclaration[this.methods.length + 1], 1, this.methods.length); newMethods[0] = constructor; this.methods = newMethods; } //============BINDING UPDATE========================== // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6 ReferenceBinding[] thrownExceptions = eraseThrownExceptions ? this.scope.environment().convertToRawTypes(inheritedConstructorBinding.thrownExceptions, true, true) : inheritedConstructorBinding.thrownExceptions; SourceTypeBinding sourceType = this.binding; constructor.binding = new MethodBinding( constructor.modifiers, //methodDeclaration argumentsLength == 0 ? Binding.NO_PARAMETERS : argumentTypes, //arguments bindings thrownExceptions, //exceptions sourceType); //declaringClass constructor.binding.tagBits |= (inheritedConstructorBinding.tagBits & TagBits.HasMissingType); constructor.binding.modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor; if (inheritedConstructorBinding.parameterNonNullness != null // this implies that annotation based null analysis is enabled && argumentsLength > 0) { // copy nullness info from inherited constructor to the new constructor: int len = inheritedConstructorBinding.parameterNonNullness.length; System.arraycopy(inheritedConstructorBinding.parameterNonNullness, 0, constructor.binding.parameterNonNullness = new Boolean[len], 0, len); } constructor.scope = new MethodScope(this.scope, constructor, true); constructor.bindArguments(); constructor.constructorCall.resolve(constructor.scope); MethodBinding[] methodBindings = sourceType.methods(); // trigger sorting int length; System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[(length = methodBindings.length) + 1], 1, length); methodBindings[0] = constructor.binding; if (++length > 1) ReferenceBinding.sortMethods(methodBindings, 0, length); // need to resort, since could be valid methods ahead (140643) - DOM needs eager sorting sourceType.setMethods(methodBindings); //=================================================== return constructor.binding; } /** * Find the matching parse node, answers null if nothing found */ public FieldDeclaration declarationOf(FieldBinding fieldBinding) { if (fieldBinding != null && this.fields != null) { for (int i = 0, max = this.fields.length; i < max; i++) { FieldDeclaration fieldDecl; if ((fieldDecl = this.fields[i]).binding == fieldBinding) return fieldDecl; } } return null; } /** * Find the matching parse node, answers null if nothing found */ public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) { if (memberTypeBinding != null && this.memberTypes != null) { for (int i = 0, max = this.memberTypes.length; i < max; i++) { TypeDeclaration memberTypeDecl; if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding) return memberTypeDecl; } } return null; } /** * Find the matching parse node, answers null if nothing found */ public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) { if (methodBinding != null && this.methods != null) { for (int i = 0, max = this.methods.length; i < max; i++) { AbstractMethodDeclaration methodDecl; if ((methodDecl = this.methods[i]).binding == methodBinding) return methodDecl; } } return null; } /** * Finds the matching type amoung this type's member types. * Returns null if no type with this name is found. * The type name is a compound name relative to this type * e.g. if this type is X and we're looking for Y.X.A.B * then a type name would be {X, A, B} */ public TypeDeclaration declarationOfType(char[][] typeName) { int typeNameLength = typeName.length; if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) { return null; } if (typeNameLength == 1) { return this; } char[][] subTypeName = new char[typeNameLength - 1][]; System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1); for (int i = 0; i < this.memberTypes.length; i++) { TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName); if (typeDecl != null) { return typeDecl; } } return null; } public CompilationUnitDeclaration getCompilationUnitDeclaration() { if (this.scope != null) { return this.scope.compilationUnitScope().referenceContext; } return null; } /** * Generic bytecode generation for type */ public void generateCode(ClassFile enclosingClassFile) { if ((this.bits & ASTNode.HasBeenGenerated) != 0) return; this.bits |= ASTNode.HasBeenGenerated; if (this.ignoreFurtherInvestigation) { if (this.binding == null) return; ClassFile.createProblemType( this, this.scope.referenceCompilationUnit().compilationResult); return; } try { // create the result for a compiled type ClassFile classFile = ClassFile.getNewInstance(this.binding); classFile.initialize(this.binding, enclosingClassFile, false); if (this.binding.isMemberType()) { classFile.recordInnerClasses(this.binding); } else if (this.binding.isLocalType()) { enclosingClassFile.recordInnerClasses(this.binding); classFile.recordInnerClasses(this.binding); } TypeVariableBinding[] typeVariables = this.binding.typeVariables(); for (int i = 0, max = typeVariables.length; i < max; i++) { TypeVariableBinding typeVariableBinding = typeVariables[i]; if ((typeVariableBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(classFile, typeVariableBinding); } } // generate all fiels classFile.addFieldInfos(); if (this.memberTypes != null) { for (int i = 0, max = this.memberTypes.length; i < max; i++) { TypeDeclaration memberType = this.memberTypes[i]; classFile.recordInnerClasses(memberType.binding); memberType.generateCode(this.scope, classFile); } } // generate all methods classFile.setForMethodInfos(); if (this.methods != null) { for (int i = 0, max = this.methods.length; i < max; i++) { this.methods[i].generateCode(this.scope, classFile); } } // generate all synthetic and abstract methods classFile.addSpecialMethods(); if (this.ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors throw new AbortType(this.scope.referenceCompilationUnit().compilationResult, null); } // finalize the compiled type result classFile.addAttributes(); this.scope.referenceCompilationUnit().compilationResult.record( this.binding.constantPoolName(), classFile); } catch (AbortType e) { if (this.binding == null) return; ClassFile.createProblemType( this, this.scope.referenceCompilationUnit().compilationResult); } } /** * Bytecode generation for a local inner type (API as a normal statement code gen) */ public void generateCode(BlockScope blockScope, CodeStream codeStream) { if ((this.bits & ASTNode.IsReachable) == 0) { return; } if ((this.bits & ASTNode.HasBeenGenerated) != 0) return; int pc = codeStream.position; if (this.binding != null) { SyntheticArgumentBinding[] enclosingInstances = ((NestedTypeBinding) this.binding).syntheticEnclosingInstances(); for (int i = 0, slotSize = 0, count = enclosingInstances == null ? 0 : enclosingInstances.length; i < count; i++){ SyntheticArgumentBinding enclosingInstance = enclosingInstances[i]; enclosingInstance.resolvedPosition = ++slotSize; // shift by 1 to leave room for aload0==this if (slotSize > 0xFF) { // no more than 255 words of arguments blockScope.problemReporter().noMoreAvailableSpaceForArgument(enclosingInstance, blockScope.referenceType()); } } } generateCode(codeStream.classFile); codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * Bytecode generation for a member inner type */ public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) { if ((this.bits & ASTNode.HasBeenGenerated) != 0) return; if (this.binding != null) { SyntheticArgumentBinding[] enclosingInstances = ((NestedTypeBinding) this.binding).syntheticEnclosingInstances(); for (int i = 0, slotSize = 0, count = enclosingInstances == null ? 0 : enclosingInstances.length; i < count; i++){ SyntheticArgumentBinding enclosingInstance = enclosingInstances[i]; enclosingInstance.resolvedPosition = ++slotSize; // shift by 1 to leave room for aload0==this if (slotSize > 0xFF) { // no more than 255 words of arguments classScope.problemReporter().noMoreAvailableSpaceForArgument(enclosingInstance, classScope.referenceType()); } } } generateCode(enclosingClassFile); } /** * Bytecode generation for a package member */ public void generateCode(CompilationUnitScope unitScope) { generateCode((ClassFile) null); } public boolean hasErrors() { return this.ignoreFurtherInvestigation; } /** * Common flow analysis for all types */ private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) { if (!this.binding.isUsed() && this.binding.isOrEnclosedByPrivateType()) { if (!this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) { this.scope.problemReporter().unusedPrivateType(this); } } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=385780 if (this.typeParameters != null && !this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) { for (int i = 0, length = this.typeParameters.length; i < length; ++i) { TypeParameter typeParameter = this.typeParameters[i]; if ((typeParameter.binding.modifiers & ExtraCompilerModifiers.AccLocallyUsed) == 0) { this.scope.problemReporter().unusedTypeParameter(typeParameter); } } } // for local classes we use the flowContext as our parent, but never use an initialization context for this purpose // see Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop) FlowContext parentContext = (flowContext instanceof InitializationFlowContext) ? null : flowContext; InitializationFlowContext initializerContext = new InitializationFlowContext(parentContext, this, flowInfo, flowContext, this.initializerScope); // no static initializer in local classes, thus no need to set parent: InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, flowInfo, flowContext, this.staticInitializerScope); FlowInfo nonStaticFieldInfo = flowInfo.unconditionalFieldLessCopy(); FlowInfo staticFieldInfo = flowInfo.unconditionalFieldLessCopy(); if (this.fields != null) { for (int i = 0, count = this.fields.length; i < count; i++) { FieldDeclaration field = this.fields[i]; if (field.isStatic()) { if ((staticFieldInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) field.bits &= ~ASTNode.IsReachable; /*if (field.isField()){ staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 } else {*/ staticInitializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them /*}*/ staticFieldInfo = field.analyseCode(this.staticInitializerScope, staticInitializerContext, staticFieldInfo); // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable // branch, since the previous initializer already got the blame. if (staticFieldInfo == FlowInfo.DEAD_END) { this.staticInitializerScope.problemReporter().initializerMustCompleteNormally(field); staticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } } else { if ((nonStaticFieldInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) field.bits &= ~ASTNode.IsReachable; /*if (field.isField()){ initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 } else {*/ initializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them /*}*/ nonStaticFieldInfo = field.analyseCode(this.initializerScope, initializerContext, nonStaticFieldInfo); // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable // branch, since the previous initializer already got the blame. if (nonStaticFieldInfo == FlowInfo.DEAD_END) { this.initializerScope.problemReporter().initializerMustCompleteNormally(field); nonStaticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } } } } if (this.memberTypes != null) { for (int i = 0, count = this.memberTypes.length; i < count; i++) { if (flowContext != null){ // local type this.memberTypes[i].analyseCode(this.scope, flowContext, nonStaticFieldInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely } else { this.memberTypes[i].analyseCode(this.scope); } } } if (this.methods != null) { UnconditionalFlowInfo outerInfo = flowInfo.unconditionalFieldLessCopy(); FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo); for (int i = 0, count = this.methods.length; i < count; i++) { AbstractMethodDeclaration method = this.methods[i]; if (method.ignoreFurtherInvestigation) continue; if (method.isInitializationMethod()) { // pass down the appropriate initializerContext: if (method.isStatic()) { // ((Clinit)method).analyseCode( this.scope, staticInitializerContext, staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo)); } else { // constructor ((ConstructorDeclaration)method).analyseCode(this.scope, initializerContext, constructorInfo.copy(), flowInfo.reachMode()); } } else { // regular method // pass down the parentContext (NOT an initializer context, see above): ((MethodDeclaration)method).analyseCode(this.scope, parentContext, flowInfo.copy()); } } } // enable enum support ? if (this.binding.isEnum() && !this.binding.isAnonymousType()) { this.enumValuesSyntheticfield = this.binding.addSyntheticFieldForEnumValues(); } } public final static int kind(int flags) { switch (flags & (ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation|ClassFileConstants.AccEnum)) { case ClassFileConstants.AccInterface : return TypeDeclaration.INTERFACE_DECL; case ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation : return TypeDeclaration.ANNOTATION_TYPE_DECL; case ClassFileConstants.AccEnum : return TypeDeclaration.ENUM_DECL; default : return TypeDeclaration.CLASS_DECL; } } /* * Access emulation for a local type * force to emulation of access to direct enclosing instance. * By using the initializer scope, we actually only request an argument emulation, the * field is not added until actually used. However we will force allocations to be qualified * with an enclosing instance. * 15.9.2 */ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return; NestedTypeBinding nestedType = (NestedTypeBinding) this.binding; MethodScope methodScope = currentScope.methodScope(); if (!methodScope.isStatic && !methodScope.isConstructorCall){ nestedType.addSyntheticArgumentAndField(nestedType.enclosingType()); } // add superclass enclosing instance arg for anonymous types (if necessary) if (nestedType.isAnonymousType()) { ReferenceBinding superclassBinding = (ReferenceBinding)nestedType.superclass.erasure(); if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) { if (!superclassBinding.isLocalType() || ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){ nestedType.addSyntheticArgument(superclassBinding.enclosingType()); } } // From 1.5 on, provide access to enclosing instance synthetic constructor argument when declared inside constructor call // only for direct anonymous type //public class X { // void foo() {} // class M { // M(Object o) {} // M() { this(new Object() { void baz() { foo(); }}); } // access to #foo() indirects through constructor synthetic arg: val$this$0 // } //} if (!methodScope.isStatic && methodScope.isConstructorCall && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) { ReferenceBinding enclosing = nestedType.enclosingType(); if (enclosing.isNestedType()) { NestedTypeBinding nestedEnclosing = (NestedTypeBinding)enclosing; // if (nestedEnclosing.findSuperTypeErasingTo(nestedEnclosing.enclosingType()) == null) { // only if not inheriting SyntheticArgumentBinding syntheticEnclosingInstanceArgument = nestedEnclosing.getSyntheticArgument(nestedEnclosing.enclosingType(), true, false); if (syntheticEnclosingInstanceArgument != null) { nestedType.addSyntheticArgumentAndField(syntheticEnclosingInstanceArgument); } } // } } } } /** * Access emulation for a local member type * force to emulation of access to direct enclosing instance. * By using the initializer scope, we actually only request an argument emulation, the * field is not added until actually used. However we will force allocations to be qualified * with an enclosing instance. * * Local member cannot be static. */ public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { NestedTypeBinding nestedType = (NestedTypeBinding) this.binding; nestedType.addSyntheticArgumentAndField(this.binding.enclosingType()); } } /** * A will be requested as soon as static fields or assertions are present. It will be eliminated during * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings. */ public final boolean needClassInitMethod() { // always need a when assertions are present if ((this.bits & ASTNode.ContainsAssertion) != 0) return true; switch (kind(this.modifiers)) { case TypeDeclaration.INTERFACE_DECL: case TypeDeclaration.ANNOTATION_TYPE_DECL: return this.fields != null; // fields are implicitly statics case TypeDeclaration.ENUM_DECL: return true; // even if no enum constants, need to set $VALUES array } if (this.fields != null) { for (int i = this.fields.length; --i >= 0;) { FieldDeclaration field = this.fields[i]; //need to test the modifier directly while there is no binding yet if ((field.modifiers & ClassFileConstants.AccStatic) != 0) return true; // TODO (philippe) shouldn't it check whether field is initializer or has some initial value ? } } return false; } public void parseMethods(Parser parser, CompilationUnitDeclaration unit) { //connect method bodies if (unit.ignoreMethodBodies) return; //members if (this.memberTypes != null) { int length = this.memberTypes.length; for (int i = 0; i < length; i++) { TypeDeclaration typeDeclaration = this.memberTypes[i]; typeDeclaration.parseMethods(parser, unit); this.bits |= (typeDeclaration.bits & ASTNode.HasSyntaxErrors); } } //methods if (this.methods != null) { int length = this.methods.length; for (int i = 0; i < length; i++) { AbstractMethodDeclaration abstractMethodDeclaration = this.methods[i]; abstractMethodDeclaration.parseStatements(parser, unit); this.bits |= (abstractMethodDeclaration.bits & ASTNode.HasSyntaxErrors); } } //initializers if (this.fields != null) { int length = this.fields.length; for (int i = 0; i < length; i++) { final FieldDeclaration fieldDeclaration = this.fields[i]; switch(fieldDeclaration.getKind()) { case AbstractVariableDeclaration.INITIALIZER: ((Initializer) fieldDeclaration).parseStatements(parser, this, unit); this.bits |= (fieldDeclaration.bits & ASTNode.HasSyntaxErrors); break; } } } } public StringBuffer print(int indent, StringBuffer output) { if (this.javadoc != null) { this.javadoc.print(indent, output); } if ((this.bits & ASTNode.IsAnonymousType) == 0) { printIndent(indent, output); printHeader(0, output); } return printBody(indent, output); } public StringBuffer printBody(int indent, StringBuffer output) { output.append(" {"); //$NON-NLS-1$ if (this.memberTypes != null) { for (int i = 0; i < this.memberTypes.length; i++) { if (this.memberTypes[i] != null) { output.append('\n'); this.memberTypes[i].print(indent + 1, output); } } } if (this.fields != null) { for (int fieldI = 0; fieldI < this.fields.length; fieldI++) { if (this.fields[fieldI] != null) { output.append('\n'); this.fields[fieldI].print(indent + 1, output); } } } if (this.methods != null) { for (int i = 0; i < this.methods.length; i++) { if (this.methods[i] != null) { output.append('\n'); this.methods[i].print(indent + 1, output); } } } output.append('\n'); return printIndent(indent, output).append('}'); } public StringBuffer printHeader(int indent, StringBuffer output) { printModifiers(this.modifiers, output); if (this.annotations != null) printAnnotations(this.annotations, output); switch (kind(this.modifiers)) { case TypeDeclaration.CLASS_DECL : output.append("class "); //$NON-NLS-1$ break; case TypeDeclaration.INTERFACE_DECL : output.append("interface "); //$NON-NLS-1$ break; case TypeDeclaration.ENUM_DECL : output.append("enum "); //$NON-NLS-1$ break; case TypeDeclaration.ANNOTATION_TYPE_DECL : output.append("@interface "); //$NON-NLS-1$ break; } output.append(this.name); if (this.typeParameters != null) { output.append("<");//$NON-NLS-1$ for (int i = 0; i < this.typeParameters.length; i++) { if (i > 0) output.append( ", "); //$NON-NLS-1$ this.typeParameters[i].print(0, output); } output.append(">");//$NON-NLS-1$ } if (this.superclass != null) { output.append(" extends "); //$NON-NLS-1$ this.superclass.print(0, output); } if (this.superInterfaces != null && this.superInterfaces.length > 0) { switch (kind(this.modifiers)) { case TypeDeclaration.CLASS_DECL : case TypeDeclaration.ENUM_DECL : output.append(" implements "); //$NON-NLS-1$ break; case TypeDeclaration.INTERFACE_DECL : case TypeDeclaration.ANNOTATION_TYPE_DECL : output.append(" extends "); //$NON-NLS-1$ break; } for (int i = 0; i < this.superInterfaces.length; i++) { if (i > 0) output.append( ", "); //$NON-NLS-1$ this.superInterfaces[i].print(0, output); } } return output; } public StringBuffer printStatement(int tab, StringBuffer output) { return print(tab, output); } public void resolve() { SourceTypeBinding sourceType = this.binding; if (sourceType == null) { this.ignoreFurtherInvestigation = true; return; } try { boolean old = this.staticInitializerScope.insideTypeAnnotation; try { this.staticInitializerScope.insideTypeAnnotation = true; resolveAnnotations(this.staticInitializerScope, this.annotations, sourceType); } finally { this.staticInitializerScope.insideTypeAnnotation = old; } // check @Deprecated annotation if ((sourceType.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0 && (sourceType.modifiers & ClassFileConstants.AccDeprecated) != 0 && this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { this.scope.problemReporter().missingDeprecatedAnnotationForType(this); } if ((this.bits & ASTNode.UndocumentedEmptyBlock) != 0) { this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd); } boolean needSerialVersion = this.scope.compilerOptions().getSeverity(CompilerOptions.MissingSerialVersion) != ProblemSeverities.Ignore && sourceType.isClass() && sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoExternalizable, false /*Externalizable is not a class*/) == null && sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null; if (needSerialVersion) { // if Object writeReplace() throws java.io.ObjectStreamException is present, then no serialVersionUID is needed // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=101476 CompilationUnitScope compilationUnitScope = this.scope.compilationUnitScope(); MethodBinding methodBinding = sourceType.getExactMethod(TypeConstants.WRITEREPLACE, Binding.NO_TYPES, compilationUnitScope); ReferenceBinding[] throwsExceptions; needSerialVersion = methodBinding == null || !methodBinding.isValidBinding() || methodBinding.returnType.id != TypeIds.T_JavaLangObject || (throwsExceptions = methodBinding.thrownExceptions).length != 1 || throwsExceptions[0].id != TypeIds.T_JavaIoObjectStreamException; if (needSerialVersion) { // check the presence of an implementation of the methods // private void writeObject(java.io.ObjectOutputStream out) throws IOException // private void readObject(java.io.ObjectInputStream out) throws IOException boolean hasWriteObjectMethod = false; boolean hasReadObjectMethod = false; TypeBinding argumentTypeBinding = this.scope.getType(TypeConstants.JAVA_IO_OBJECTOUTPUTSTREAM, 3); if (argumentTypeBinding.isValidBinding()) { methodBinding = sourceType.getExactMethod(TypeConstants.WRITEOBJECT, new TypeBinding[] { argumentTypeBinding }, compilationUnitScope); hasWriteObjectMethod = methodBinding != null && methodBinding.isValidBinding() && methodBinding.modifiers == ClassFileConstants.AccPrivate && methodBinding.returnType == TypeBinding.VOID && (throwsExceptions = methodBinding.thrownExceptions).length == 1 && throwsExceptions[0].id == TypeIds.T_JavaIoException; } argumentTypeBinding = this.scope.getType(TypeConstants.JAVA_IO_OBJECTINPUTSTREAM, 3); if (argumentTypeBinding.isValidBinding()) { methodBinding = sourceType.getExactMethod(TypeConstants.READOBJECT, new TypeBinding[] { argumentTypeBinding }, compilationUnitScope); hasReadObjectMethod = methodBinding != null && methodBinding.isValidBinding() && methodBinding.modifiers == ClassFileConstants.AccPrivate && methodBinding.returnType == TypeBinding.VOID && (throwsExceptions = methodBinding.thrownExceptions).length == 1 && throwsExceptions[0].id == TypeIds.T_JavaIoException; } needSerialVersion = !hasWriteObjectMethod || !hasReadObjectMethod; } } // generics (and non static generic members) cannot extend Throwable if (sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) != null) { ReferenceBinding current = sourceType; checkEnclosedInGeneric : do { if (current.isGenericType()) { this.scope.problemReporter().genericTypeCannotExtendThrowable(this); break checkEnclosedInGeneric; } if (current.isStatic()) break checkEnclosedInGeneric; if (current.isLocalType()) { NestedTypeBinding nestedType = (NestedTypeBinding) current.erasure(); if (nestedType.scope.methodScope().isStatic) break checkEnclosedInGeneric; } } while ((current = current.enclosingType()) != null); } // this.maxFieldCount might already be set int localMaxFieldCount = 0; int lastVisibleFieldID = -1; boolean hasEnumConstants = false; FieldDeclaration[] enumConstantsWithoutBody = null; if (this.typeParameters != null) { for (int i = 0, count = this.typeParameters.length; i < count; i++) { this.typeParameters[i].resolve(this.scope); } } 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]; switch(field.getKind()) { case AbstractVariableDeclaration.ENUM_CONSTANT: hasEnumConstants = true; if (!(field.initialization instanceof QualifiedAllocationExpression)) { if (enumConstantsWithoutBody == null) enumConstantsWithoutBody = new FieldDeclaration[count]; enumConstantsWithoutBody[i] = field; } //$FALL-THROUGH$ 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 & (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal)) == (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal)) && CharOperation.equals(TypeConstants.SERIALVERSIONUID, fieldBinding.name) && TypeBinding.LONG == fieldBinding.type) { needSerialVersion = false; } localMaxFieldCount++; lastVisibleFieldID = field.binding.id; break; case AbstractVariableDeclaration.INITIALIZER: ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1; break; } field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope); } } if (this.maxFieldCount < localMaxFieldCount) { this.maxFieldCount = localMaxFieldCount; } if (needSerialVersion) { //check that the current type doesn't extend javax.rmi.CORBA.Stub TypeBinding javaxRmiCorbaStub = this.scope.getType(TypeConstants.JAVAX_RMI_CORBA_STUB, 4); if (javaxRmiCorbaStub.isValidBinding()) { ReferenceBinding superclassBinding = this.binding.superclass; loop: while (superclassBinding != null) { if (superclassBinding == javaxRmiCorbaStub) { needSerialVersion = false; break loop; } superclassBinding = superclassBinding.superclass(); } } if (needSerialVersion) { this.scope.problemReporter().missingSerialVersion(this); } } // check extends/implements for annotation type switch(kind(this.modifiers)) { case TypeDeclaration.ANNOTATION_TYPE_DECL : if (this.superclass != null) { this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperclass(this); } if (this.superInterfaces != null) { this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperinterfaces(this); } break; case TypeDeclaration.ENUM_DECL : // check enum abstract methods if (this.binding.isAbstract()) { if (!hasEnumConstants) { for (int i = 0, count = this.methods.length; i < count; i++) { final AbstractMethodDeclaration methodDeclaration = this.methods[i]; if (methodDeclaration.isAbstract() && methodDeclaration.binding != null) this.scope.problemReporter().enumAbstractMethodMustBeImplemented(methodDeclaration); } } else if (enumConstantsWithoutBody != null) { for (int i = 0, count = this.methods.length; i < count; i++) { final AbstractMethodDeclaration methodDeclaration = this.methods[i]; if (methodDeclaration.isAbstract() && methodDeclaration.binding != null) { for (int f = 0, l = enumConstantsWithoutBody.length; f < l; f++) if (enumConstantsWithoutBody[f] != null) this.scope.problemReporter().enumConstantMustImplementAbstractMethod(methodDeclaration, enumConstantsWithoutBody[f]); } } } } break; } int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length; int methodsLength = this.methods == null ? 0 : this.methods.length; if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) { this.scope.problemReporter().tooManyMethods(this); } if (this.methods != null) { for (int i = 0, count = this.methods.length; i < count; i++) { this.methods[i].resolve(this.scope); } } // Resolve javadoc if (this.javadoc != null) { if (this.scope != null && (this.name != TypeConstants.PACKAGE_INFO_NAME)) { // if the type is package-info, the javadoc was resolved as part of the compilation unit javadoc this.javadoc.resolve(this.scope); } } else if (!sourceType.isLocalType()) { // Set javadoc visibility int visibility = sourceType.modifiers & ExtraCompilerModifiers.AccVisibilityMASK; ProblemReporter reporter = this.scope.problemReporter(); int severity = reporter.computeSeverity(IProblem.JavadocMissing); if (severity != ProblemSeverities.Ignore) { if (this.enclosingType != null) { visibility = Util.computeOuterMostVisibility(this.enclosingType, visibility); } int javadocModifiers = (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK) | visibility; reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers); } } } catch (AbortType e) { this.ignoreFurtherInvestigation = true; return; } } /** * Resolve a local type declaration */ public void resolve(BlockScope blockScope) { // need to build its scope first and proceed with binding's creation if ((this.bits & ASTNode.IsAnonymousType) == 0) { // check collision scenarii Binding existing = blockScope.getType(this.name); if (existing instanceof ReferenceBinding && existing != this.binding && existing.isValidBinding()) { ReferenceBinding existingType = (ReferenceBinding) existing; if (existingType instanceof TypeVariableBinding) { blockScope.problemReporter().typeHiding(this, (TypeVariableBinding) existingType); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=312989, check for collision with enclosing type. Scope outerScope = blockScope.parent; checkOuterScope:while (outerScope != null) { Binding existing2 = outerScope.getType(this.name); if (existing2 instanceof TypeVariableBinding && existing2.isValidBinding()) { TypeVariableBinding tvb = (TypeVariableBinding) existingType; Binding declaringElement = tvb.declaringElement; if (declaringElement instanceof ReferenceBinding && CharOperation.equals(((ReferenceBinding) declaringElement).sourceName(), this.name)) { blockScope.problemReporter().typeCollidesWithEnclosingType(this); break checkOuterScope; } } else if (existing2 instanceof ReferenceBinding && existing2.isValidBinding() && outerScope.isDefinedInType((ReferenceBinding) existing2)) { blockScope.problemReporter().typeCollidesWithEnclosingType(this); break checkOuterScope; } else if (existing2 == null) { break checkOuterScope; } outerScope = outerScope.parent; } } else if (existingType instanceof LocalTypeBinding && ((LocalTypeBinding) existingType).scope.methodScope() == blockScope.methodScope()) { // dup in same method blockScope.problemReporter().duplicateNestedType(this); } else if (blockScope.isDefinedInType(existingType)) { // collision with enclosing type blockScope.problemReporter().typeCollidesWithEnclosingType(this); } else if (blockScope.isDefinedInSameUnit(existingType)){ // only consider hiding inside same unit // hiding sibling blockScope.problemReporter().typeHiding(this, existingType); } } blockScope.addLocalType(this); } if (this.binding != null) { // remember local types binding for innerclass emulation propagation blockScope.referenceCompilationUnit().record((LocalTypeBinding)this.binding); // binding is not set if the receiver could not be created resolve(); updateMaxFieldCount(); } } /** * Resolve a member type declaration (can be a local member) */ public void resolve(ClassScope upperScope) { // member scopes are already created // request the construction of a binding if local member type if (this.binding != null && this.binding instanceof LocalTypeBinding) { // remember local types binding for innerclass emulation propagation upperScope.referenceCompilationUnit().record((LocalTypeBinding)this.binding); } resolve(); updateMaxFieldCount(); } /** * Resolve a top level type declaration */ public void resolve(CompilationUnitScope upperScope) { // top level : scope are already created resolve(); updateMaxFieldCount(); } public void tagAsHavingErrors() { this.ignoreFurtherInvestigation = true; } /** * Iteration for a package member type * */ public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) { try { if (visitor.visit(this, unitScope)) { if (this.javadoc != null) { this.javadoc.traverse(visitor, this.scope); } if (this.annotations != null) { int annotationsLength = this.annotations.length; for (int i = 0; i < annotationsLength; i++) this.annotations[i].traverse(visitor, this.staticInitializerScope); } if (this.superclass != null) this.superclass.traverse(visitor, this.scope); if (this.superInterfaces != null) { int length = this.superInterfaces.length; for (int i = 0; i < length; i++) this.superInterfaces[i].traverse(visitor, this.scope); } if (this.typeParameters != null) { int length = this.typeParameters.length; for (int i = 0; i < length; i++) { this.typeParameters[i].traverse(visitor, this.scope); } } if (this.memberTypes != null) { int length = this.memberTypes.length; for (int i = 0; i < length; i++) this.memberTypes[i].traverse(visitor, this.scope); } if (this.fields != null) { int length = this.fields.length; for (int i = 0; i < length; i++) { FieldDeclaration field; if ((field = this.fields[i]).isStatic()) { field.traverse(visitor, this.staticInitializerScope); } else { field.traverse(visitor, this.initializerScope); } } } if (this.methods != null) { int length = this.methods.length; for (int i = 0; i < length; i++) this.methods[i].traverse(visitor, this.scope); } } visitor.endVisit(this, unitScope); } catch (AbortType e) { // silent abort } } /** * Iteration for a local inner type */ public void traverse(ASTVisitor visitor, BlockScope blockScope) { try { if (visitor.visit(this, blockScope)) { if (this.javadoc != null) { this.javadoc.traverse(visitor, this.scope); } if (this.annotations != null) { int annotationsLength = this.annotations.length; for (int i = 0; i < annotationsLength; i++) this.annotations[i].traverse(visitor, this.staticInitializerScope); } if (this.superclass != null) this.superclass.traverse(visitor, this.scope); if (this.superInterfaces != null) { int length = this.superInterfaces.length; for (int i = 0; i < length; i++) this.superInterfaces[i].traverse(visitor, this.scope); } if (this.typeParameters != null) { int length = this.typeParameters.length; for (int i = 0; i < length; i++) { this.typeParameters[i].traverse(visitor, this.scope); } } if (this.memberTypes != null) { int length = this.memberTypes.length; for (int i = 0; i < length; i++) this.memberTypes[i].traverse(visitor, this.scope); } if (this.fields != null) { int length = this.fields.length; for (int i = 0; i < length; i++) { FieldDeclaration field = this.fields[i]; if (field.isStatic() && !field.isFinal()) { // local type cannot have static fields that are not final, https://bugs.eclipse.org/bugs/show_bug.cgi?id=244544 } else { field.traverse(visitor, this.initializerScope); } } } if (this.methods != null) { int length = this.methods.length; for (int i = 0; i < length; i++) this.methods[i].traverse(visitor, this.scope); } } visitor.endVisit(this, blockScope); } catch (AbortType e) { // silent abort } } /** * Iteration for a member innertype * */ public void traverse(ASTVisitor visitor, ClassScope classScope) { try { if (visitor.visit(this, classScope)) { if (this.javadoc != null) { this.javadoc.traverse(visitor, this.scope); } if (this.annotations != null) { int annotationsLength = this.annotations.length; for (int i = 0; i < annotationsLength; i++) this.annotations[i].traverse(visitor, this.staticInitializerScope); } if (this.superclass != null) this.superclass.traverse(visitor, this.scope); if (this.superInterfaces != null) { int length = this.superInterfaces.length; for (int i = 0; i < length; i++) this.superInterfaces[i].traverse(visitor, this.scope); } if (this.typeParameters != null) { int length = this.typeParameters.length; for (int i = 0; i < length; i++) { this.typeParameters[i].traverse(visitor, this.scope); } } if (this.memberTypes != null) { int length = this.memberTypes.length; for (int i = 0; i < length; i++) this.memberTypes[i].traverse(visitor, this.scope); } if (this.fields != null) { int length = this.fields.length; for (int i = 0; i < length; i++) { FieldDeclaration field; if ((field = this.fields[i]).isStatic()) { field.traverse(visitor, this.staticInitializerScope); } else { field.traverse(visitor, this.initializerScope); } } } if (this.methods != null) { int length = this.methods.length; for (int i = 0; i < length; i++) this.methods[i].traverse(visitor, this.scope); } } visitor.endVisit(this, classScope); } catch (AbortType e) { // silent abort } } /** * MaxFieldCount's computation is necessary so as to reserve space for * the flow info field portions. It corresponds to the maximum amount of * fields this class or one of its innertypes have. * * During name resolution, types are traversed, and the max field count is recorded * on the outermost type. It is then propagated down during the flow analysis. * * This method is doing either up/down propagation. */ void updateMaxFieldCount() { if (this.binding == null) return; // error scenario TypeDeclaration outerMostType = this.scope.outerMostClassScope().referenceType(); if (this.maxFieldCount > outerMostType.maxFieldCount) { outerMostType.maxFieldCount = this.maxFieldCount; // up } else { this.maxFieldCount = outerMostType.maxFieldCount; // down } } /** * Returns whether the type is a secondary one or not. */ public boolean isSecondary() { return (this.bits & ASTNode.IsSecondaryType) != 0; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java0000644000175000001440000000457212212041344031207 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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; } public ElementValuePair[] computeElementValuePairs() { int numberOfPairs = this.memberValuePairs == null ? 0 : this.memberValuePairs.length; if (numberOfPairs == 0) return Binding.NO_ELEMENT_VALUE_PAIRS; ElementValuePair[] pairs = new ElementValuePair[numberOfPairs]; for (int i = 0; i < numberOfPairs; i++) pairs[i] = this.memberValuePairs[i].compilerElementPair; return pairs; } /** * @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.type != null) { this.type.traverse(visitor, 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); } } ././@LongLink0000644000000000000000000000015212251602427011641 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression0000644000175000001440000002005112212041344032427 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; public class JavadocAllocationExpression extends AllocationExpression { public int tagSourceStart, tagSourceEnd; public int tagValue, memberStart; public char[][] qualification; public JavadocAllocationExpression(int start, int end) { this.sourceStart = start; this.sourceEnd = end; this.bits |= InsideJavadoc; } public JavadocAllocationExpression(long pos) { this((int) (pos >>> 32), (int) pos); } TypeBinding internalResolveType(Scope scope) { // Propagate the type checking to the arguments, and check if the constructor is defined. this.constant = Constant.NotAConstant; if (this.type == null) { this.resolvedType = scope.enclosingSourceType(); } else if (scope.kind == Scope.CLASS_SCOPE) { this.resolvedType = this.type.resolveType((ClassScope)scope); } else { this.resolvedType = this.type.resolveType((BlockScope)scope, true /* check bounds*/); } // buffering the arguments' types TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; boolean hasTypeVarArgs = false; if (this.arguments != null) { boolean argHasError = false; int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++) { Expression argument = this.arguments[i]; if (scope.kind == Scope.CLASS_SCOPE) { argumentTypes[i] = argument.resolveType((ClassScope)scope); } else { argumentTypes[i] = argument.resolveType((BlockScope)scope); } if (argumentTypes[i] == null) { argHasError = true; } else if (!hasTypeVarArgs) { hasTypeVarArgs = argumentTypes[i].isTypeVariable(); } } if (argHasError) { return null; } } // check resolved type if (this.resolvedType == null) { return null; } this.resolvedType = scope.environment().convertToRawType(this.type.resolvedType, true /*force the conversion of enclosing types*/); SourceTypeBinding enclosingType = scope.enclosingSourceType(); if (enclosingType == null ? false : enclosingType.isCompatibleWith(this.resolvedType)) { this.bits |= ASTNode.SuperAccess; } ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType; this.binding = scope.getConstructor(allocationType, argumentTypes, this); if (!this.binding.isValidBinding()) { ReferenceBinding enclosingTypeBinding = allocationType; MethodBinding contructorBinding = this.binding; while (!contructorBinding.isValidBinding() && (enclosingTypeBinding.isMemberType() || enclosingTypeBinding.isLocalType())) { enclosingTypeBinding = enclosingTypeBinding.enclosingType(); contructorBinding = scope.getConstructor(enclosingTypeBinding, argumentTypes, this); } if (contructorBinding.isValidBinding()) { this.binding = contructorBinding; } } if (!this.binding.isValidBinding()) { // First try to search a method instead MethodBinding methodBinding = scope.getMethod(this.resolvedType, this.resolvedType.sourceName(), argumentTypes, this); if (methodBinding.isValidBinding()) { this.binding = methodBinding; } else { if (this.binding.declaringClass == null) { this.binding.declaringClass = allocationType; } scope.problemReporter().javadocInvalidConstructor(this, this.binding, scope.getDeclarationModifiers()); } return this.resolvedType; } else if (this.binding.isVarargs()) { int length = argumentTypes.length; if (!(this.binding.parameters.length == length && argumentTypes[length-1].isArrayType())) { MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, argumentTypes, ProblemReasons.NotFound); scope.problemReporter().javadocInvalidConstructor(this, problem, scope.getDeclarationModifiers()); } } else if (hasTypeVarArgs) { MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, argumentTypes, ProblemReasons.NotFound); scope.problemReporter().javadocInvalidConstructor(this, problem, scope.getDeclarationModifiers()); } else if (this.binding instanceof ParameterizedMethodBinding) { ParameterizedMethodBinding paramMethodBinding = (ParameterizedMethodBinding) this.binding; if (paramMethodBinding.hasSubstitutedParameters()) { int length = argumentTypes.length; for (int i=0; i 1) { // accept qualified member class constructor reference => see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=103304 ReferenceBinding enclosingTypeBinding = allocationType; if (this.type instanceof JavadocQualifiedTypeReference && ((JavadocQualifiedTypeReference)this.type).tokens.length != length) { scope.problemReporter().javadocInvalidMemberTypeQualification(this.memberStart+1, this.sourceEnd, scope.getDeclarationModifiers()); } else { int idx = length; while (idx > 0 && CharOperation.equals(this.qualification[--idx], enclosingTypeBinding.sourceName) && (enclosingTypeBinding = enclosingTypeBinding.enclosingType()) != null) { // verify that each qualification token matches enclosing types } if (idx > 0 || enclosingTypeBinding != null) { scope.problemReporter().javadocInvalidMemberTypeQualification(this.memberStart+1, this.sourceEnd, scope.getDeclarationModifiers()); } } } } if (isMethodUseDeprecated(this.binding, scope, true)) { scope.problemReporter().javadocDeprecatedMethod(this.binding, this, scope.getDeclarationModifiers()); } return allocationType; } public boolean isSuperAccess() { return (this.bits & ASTNode.SuperAccess) != 0; } public TypeBinding resolveType(BlockScope scope) { return internalResolveType(scope); } public TypeBinding resolveType(ClassScope scope) { return internalResolveType(scope); } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, 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); } public void traverse(ASTVisitor visitor, ClassScope scope) { if (visitor.visit(this, 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); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java0000644000175000001440000000462312212041344030704 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.ASTVisitor; public class EmptyStatement extends Statement { public EmptyStatement(int startPosition, int endPosition) { this.sourceStart = startPosition; this.sourceEnd = endPosition; } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return flowInfo; } // Report an error if necessary public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int complaintLevel, boolean endOfBlock) { // before 1.4, empty statements are tolerated anywhere if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_4) { return complaintLevel; } return super.complainIfUnreachable(flowInfo, scope, complaintLevel, endOfBlock); } public void generateCode(BlockScope currentScope, CodeStream codeStream){ // no bytecode, no need to check for reachability or recording source positions } public StringBuffer printStatement(int tab, StringBuffer output) { return printIndent(tab, output).append(';'); } public void resolve(BlockScope scope) { if ((this.bits & IsUsefulEmptyStatement) == 0) { scope.problemReporter().superfluousSemicolon(this.sourceStart, this.sourceEnd); } else { scope.problemReporter().emptyControlFlowStatement(this.sourceStart, this.sourceEnd); } } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java0000644000175000001440000005724112212041344032420 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for * bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 361407 - Resource leak warning when resource is assigned to a field outside of constructor * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 383690 - [compiler] location of error re uninitialized final field should be aligned * bug 331649 - [compiler][null] consider null annotations for fields * bug 383368 - [compiler][null] syntactic null analysis for field references * bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import java.util.ArrayList; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.*; 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.*; import org.eclipse.jdt.internal.compiler.parser.*; import org.eclipse.jdt.internal.compiler.problem.*; import org.eclipse.jdt.internal.compiler.util.Util; public class ConstructorDeclaration extends AbstractMethodDeclaration { public ExplicitConstructorCall constructorCall; public TypeParameter[] typeParameters; public ConstructorDeclaration(CompilationResult compilationResult){ super(compilationResult); } /** * The flowInfo corresponds to non-static field initialization infos. It may be unreachable (155423), but still the explicit constructor call must be * analyzed as reachable, since it will be generated in the end. */ public void analyseCode(ClassScope classScope, InitializationFlowContext initializerFlowContext, FlowInfo flowInfo, int initialReachMode) { if (this.ignoreFurtherInvestigation) return; int nonStaticFieldInfoReachMode = flowInfo.reachMode(); flowInfo.setReachMode(initialReachMode); checkUnused: { MethodBinding constructorBinding; if ((constructorBinding = this.binding) == null) break checkUnused; if ((this.bits & ASTNode.IsDefaultConstructor) != 0) break checkUnused; if (constructorBinding.isUsed()) break checkUnused; if (constructorBinding.isPrivate()) { if ((this.binding.declaringClass.tagBits & TagBits.HasNonPrivateConstructor) == 0) break checkUnused; // tolerate as known pattern to block instantiation } else if (!constructorBinding.isOrEnclosedByPrivateType()) { break checkUnused; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=270446, When the AST built is an abridged version // we don't have all tree nodes we would otherwise expect. (see ASTParser.setFocalPosition) if (this.constructorCall == null) break checkUnused; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=264991, Don't complain about this // constructor being unused if the base class doesn't have a no-arg constructor. // See that a seemingly unused constructor that chains to another constructor with a // this(...) can be flagged as being unused without hesitation. // https://bugs.eclipse.org/bugs/show_bug.cgi?id=265142 if (this.constructorCall.accessMode != ExplicitConstructorCall.This) { ReferenceBinding superClass = constructorBinding.declaringClass.superclass(); if (superClass == null) break checkUnused; // see if there is a no-arg super constructor MethodBinding methodBinding = superClass.getExactConstructor(Binding.NO_PARAMETERS); if (methodBinding == null) break checkUnused; if (!methodBinding.canBeSeenBy(SuperReference.implicitSuperConstructorCall(), this.scope)) break checkUnused; // otherwise default super constructor exists, so go ahead and complain unused. } // complain unused this.scope.problemReporter().unusedPrivateConstructor(this); } // check constructor recursion, once all constructor got resolved if (isRecursive(null /*lazy initialized visited list*/)) { this.scope.problemReporter().recursiveConstructorInvocation(this.constructorCall); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=385780 if (this.typeParameters != null && !this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) { for (int i = 0, length = this.typeParameters.length; i < length; ++i) { TypeParameter typeParameter = this.typeParameters[i]; if ((typeParameter.binding.modifiers & ExtraCompilerModifiers.AccLocallyUsed) == 0) { this.scope.problemReporter().unusedTypeParameter(typeParameter); } } } try { ExceptionHandlingFlowContext constructorContext = new ExceptionHandlingFlowContext( initializerFlowContext.parent, this, this.binding.thrownExceptions, initializerFlowContext, this.scope, FlowInfo.DEAD_END); initializerFlowContext.checkInitializerExceptions( this.scope, constructorContext, flowInfo); // anonymous constructor can gain extra thrown exceptions from unhandled ones if (this.binding.declaringClass.isAnonymousType()) { ArrayList computedExceptions = constructorContext.extendedExceptions; if (computedExceptions != null){ int size; if ((size = computedExceptions.size()) > 0){ ReferenceBinding[] actuallyThrownExceptions; computedExceptions.toArray(actuallyThrownExceptions = new ReferenceBinding[size]); this.binding.thrownExceptions = actuallyThrownExceptions; } } } // nullity and mark as assigned analyseArguments(flowInfo); // propagate to constructor call if (this.constructorCall != null) { // if calling 'this(...)', then flag all non-static fields as definitely // set since they are supposed to be set inside other local constructor if (this.constructorCall.accessMode == ExplicitConstructorCall.This) { FieldBinding[] fields = this.binding.declaringClass.fields(); for (int i = 0, count = fields.length; i < count; i++) { FieldBinding field; if (!(field = fields[i]).isStatic()) { flowInfo.markAsDefinitelyAssigned(field); } } } flowInfo = this.constructorCall.analyseCode(this.scope, constructorContext, flowInfo); } // reuse the reachMode from non static field info flowInfo.setReachMode(nonStaticFieldInfoReachMode); // propagate to statements if (this.statements != null) { boolean enableSyntacticNullAnalysisForFields = this.scope.compilerOptions().enableSyntacticNullAnalysisForFields; int complaintLevel = (nonStaticFieldInfoReachMode & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE; for (int i = 0, count = this.statements.length; i < count; i++) { Statement stat = this.statements[i]; if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) { flowInfo = stat.analyseCode(this.scope, constructorContext, flowInfo); } if (enableSyntacticNullAnalysisForFields) { constructorContext.expireNullCheckedFieldInfo(); } } } // check for missing returning path if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) { this.bits |= ASTNode.NeedFreeReturn; } // reuse the initial reach mode for diagnosing missing blank finals // no, we should use the updated reach mode for diagnosing uninitialized blank finals. // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=235781 // flowInfo.setReachMode(initialReachMode); // check missing blank final field initializations (plus @NonNull) if ((this.constructorCall != null) && (this.constructorCall.accessMode != ExplicitConstructorCall.This)) { flowInfo = flowInfo.mergedWith(constructorContext.initsOnReturn); FieldBinding[] fields = this.binding.declaringClass.fields(); for (int i = 0, count = fields.length; i < count; i++) { FieldBinding field = fields[i]; if (!field.isStatic() && !flowInfo.isDefinitelyAssigned(field)) { if (field.isFinal()) { this.scope.problemReporter().uninitializedBlankFinalField( field, ((this.bits & ASTNode.IsDefaultConstructor) != 0) ? (ASTNode) this.scope.referenceType().declarationOf(field.original()) : this); } else if (field.isNonNull()) { FieldDeclaration fieldDecl = this.scope.referenceType().declarationOf(field.original()); if (!isValueProvidedUsingAnnotation(fieldDecl)) this.scope.problemReporter().uninitializedNonNullField( field, ((this.bits & ASTNode.IsDefaultConstructor) != 0) ? (ASTNode) fieldDecl : this); } } } } // check unreachable catch blocks constructorContext.complainIfUnusedExceptionHandlers(this); // check unused parameters this.scope.checkUnusedParameters(this.binding); this.scope.checkUnclosedCloseables(flowInfo, null, null/*don't report against a specific location*/, null); } catch (AbortMethod e) { this.ignoreFurtherInvestigation = true; } } boolean isValueProvidedUsingAnnotation(FieldDeclaration fieldDecl) { // a member field annotated with @Inject is considered to be initialized by the injector if (fieldDecl.annotations != null) { int length = fieldDecl.annotations.length; for (int i = 0; i < length; i++) { Annotation annotation = fieldDecl.annotations[i]; if (annotation.resolvedType.id == TypeIds.T_JavaxInjectInject) { return true; // no concept of "optional" } else if (annotation.resolvedType.id == TypeIds.T_ComGoogleInjectInject) { MemberValuePair[] memberValuePairs = annotation.memberValuePairs(); if (memberValuePairs == Annotation.NoValuePairs) return true; for (int j = 0; j < memberValuePairs.length; j++) { // if "optional=false" is specified, don't rely on initialization by the injector: if (CharOperation.equals(memberValuePairs[j].name, TypeConstants.OPTIONAL)) return memberValuePairs[j].value instanceof FalseLiteral; } } } } return false; } /** * Bytecode generation for a constructor * * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile */ public void generateCode(ClassScope classScope, ClassFile classFile) { int problemResetPC = 0; if (this.ignoreFurtherInvestigation) { if (this.binding == null) return; // Handle methods with invalid signature or duplicates int problemsLength; CategorizedProblem[] problems = this.scope.referenceCompilationUnit().compilationResult.getProblems(); CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); classFile.addProblemConstructor(this, this.binding, problemsCopy); return; } boolean restart = false; boolean abort = false; do { try { problemResetPC = classFile.contentsOffset; internalGenerateCode(classScope, classFile); restart = false; } catch (AbortMethod e) { if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { // a branch target required a goto_w, restart code gen in wide mode. classFile.contentsOffset = problemResetPC; classFile.methodCount--; classFile.codeStream.resetInWideMode(); // request wide mode restart = true; } else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) { classFile.contentsOffset = problemResetPC; classFile.methodCount--; classFile.codeStream.resetForCodeGenUnusedLocals(); restart = true; } else { restart = false; abort = true; } } } while (restart); if (abort) { int problemsLength; CategorizedProblem[] problems = this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC); } } public void generateSyntheticFieldInitializationsIfNecessary(MethodScope methodScope, CodeStream codeStream, ReferenceBinding declaringClass) { if (!declaringClass.isNestedType()) return; NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass; SyntheticArgumentBinding[] syntheticArgs = nestedType.syntheticEnclosingInstances(); if (syntheticArgs != null) { for (int i = 0, max = syntheticArgs.length; i < max; i++) { SyntheticArgumentBinding syntheticArg; if ((syntheticArg = syntheticArgs[i]).matchingField != null) { codeStream.aload_0(); codeStream.load(syntheticArg); codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */); } } } syntheticArgs = nestedType.syntheticOuterLocalVariables(); if (syntheticArgs != null) { for (int i = 0, max = syntheticArgs.length; i < max; i++) { SyntheticArgumentBinding syntheticArg; if ((syntheticArg = syntheticArgs[i]).matchingField != null) { codeStream.aload_0(); codeStream.load(syntheticArg); codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */); } } } } private void internalGenerateCode(ClassScope classScope, ClassFile classFile) { classFile.generateMethodInfoHeader(this.binding); int methodAttributeOffset = classFile.contentsOffset; int attributeNumber = classFile.generateMethodInfoAttributes(this.binding); if ((!this.binding.isNative()) && (!this.binding.isAbstract())) { TypeDeclaration declaringType = classScope.referenceContext; int codeAttributeOffset = classFile.contentsOffset; classFile.generateCodeAttributeHeader(); CodeStream codeStream = classFile.codeStream; codeStream.reset(this, classFile); // initialize local positions - including initializer scope. ReferenceBinding declaringClass = this.binding.declaringClass; int enumOffset = declaringClass.isEnum() ? 2 : 0; // String name, int ordinal int argSlotSize = 1 + enumOffset; // this==aload0 if (declaringClass.isNestedType()){ this.scope.extraSyntheticArguments = declaringClass.syntheticOuterLocalVariables(); this.scope.computeLocalVariablePositions(// consider synthetic arguments if any declaringClass.getEnclosingInstancesSlotSize() + 1 + enumOffset, codeStream); argSlotSize += declaringClass.getEnclosingInstancesSlotSize(); argSlotSize += declaringClass.getOuterLocalVariablesSlotSize(); } else { this.scope.computeLocalVariablePositions(1 + enumOffset, codeStream); } if (this.arguments != null) { for (int i = 0, max = this.arguments.length; i < max; i++) { // arguments initialization for local variable debug attributes LocalVariableBinding argBinding; codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding); argBinding.recordInitializationStartPC(0); switch(argBinding.type.id) { case TypeIds.T_long : case TypeIds.T_double : argSlotSize += 2; break; default : argSlotSize++; break; } } } MethodScope initializerScope = declaringType.initializerScope; initializerScope.computeLocalVariablePositions(argSlotSize, codeStream); // offset by the argument size (since not linked to method scope) boolean needFieldInitializations = this.constructorCall == null || this.constructorCall.accessMode != ExplicitConstructorCall.This; // post 1.4 target level, synthetic initializations occur prior to explicit constructor call boolean preInitSyntheticFields = this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_4; if (needFieldInitializations && preInitSyntheticFields){ generateSyntheticFieldInitializationsIfNecessary(this.scope, codeStream, declaringClass); codeStream.recordPositionsFrom(0, this.bodyStart); } // generate constructor call if (this.constructorCall != null) { this.constructorCall.generateCode(this.scope, codeStream); } // generate field initialization - only if not invoking another constructor call of the same class if (needFieldInitializations) { if (!preInitSyntheticFields){ generateSyntheticFieldInitializationsIfNecessary(this.scope, codeStream, declaringClass); } // generate user field initialization 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(initializerScope, codeStream); } } } } // generate statements if (this.statements != null) { for (int i = 0, max = this.statements.length; i < max; i++) { this.statements[i].generateCode(this.scope, codeStream); } } // if a problem got reported during code gen, then trigger problem method creation if (this.ignoreFurtherInvestigation) { throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null); } if ((this.bits & ASTNode.NeedFreeReturn) != 0) { codeStream.return_(); } // local variable attributes codeStream.exitUserScope(this.scope); codeStream.recordPositionsFrom(0, this.bodyEnd); try { classFile.completeCodeAttribute(codeAttributeOffset); } catch(NegativeArraySizeException e) { throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null); } attributeNumber++; if ((codeStream instanceof StackMapFrameCodeStream) && needFieldInitializations && declaringType.fields != null) { ((StackMapFrameCodeStream) codeStream).resetSecretLocals(); } } classFile.completeMethodInfo(this.binding, methodAttributeOffset, attributeNumber); } public boolean isConstructor() { return true; } public boolean isDefaultConstructor() { return (this.bits & ASTNode.IsDefaultConstructor) != 0; } public boolean isInitializationMethod() { 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. */ public boolean isRecursive(ArrayList visited) { if (this.binding == null || this.constructorCall == null || this.constructorCall.binding == null || this.constructorCall.isSuperAccess() || !this.constructorCall.binding.isValidBinding()) { return false; } ConstructorDeclaration targetConstructor = ((ConstructorDeclaration)this.scope.referenceType().declarationOf(this.constructorCall.binding.original())); if (targetConstructor == null) return false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=358762 if (this == targetConstructor) return true; // direct case if (visited == null) { // lazy allocation visited = new ArrayList(1); } else { int index = visited.indexOf(this); if (index >= 0) return index == 0; // only blame if directly part of the cycle } visited.add(this); return targetConstructor.isRecursive(visited); } public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { //fill up the constructor body with its statements if (((this.bits & ASTNode.IsDefaultConstructor) != 0) && this.constructorCall == null){ this.constructorCall = SuperReference.implicitSuperConstructorCall(); this.constructorCall.sourceStart = this.sourceStart; this.constructorCall.sourceEnd = this.sourceEnd; return; } parser.parse(this, unit, false); } public StringBuffer printBody(int indent, StringBuffer output) { output.append(" {"); //$NON-NLS-1$ if (this.constructorCall != null) { output.append('\n'); this.constructorCall.printStatement(indent, output); } if (this.statements != null) { for (int i = 0; i < this.statements.length; i++) { output.append('\n'); this.statements[i].printStatement(indent, output); } } output.append('\n'); printIndent(indent == 0 ? 0 : indent - 1, output).append('}'); return output; } public void resolveJavadoc() { if (this.binding == null || this.javadoc != null) { super.resolveJavadoc(); } else if ((this.bits & ASTNode.IsDefaultConstructor) == 0) { if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) { // Set javadoc visibility int javadocVisibility = this.binding.modifiers & ExtraCompilerModifiers.AccVisibilityMASK; ClassScope classScope = this.scope.classScope(); ProblemReporter reporter = this.scope.problemReporter(); int severity = reporter.computeSeverity(IProblem.JavadocMissing); if (severity != ProblemSeverities.Ignore) { if (classScope != null) { javadocVisibility = Util.computeOuterMostVisibility(classScope.referenceType(), javadocVisibility); } int javadocModifiers = (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK) | javadocVisibility; reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers); } } } } /* * Type checking for constructor, just another method, except for special check * for recursive constructor invocations. */ public void resolveStatements() { SourceTypeBinding sourceType = this.scope.enclosingSourceType(); if (!CharOperation.equals(sourceType.sourceName, this.selector)){ this.scope.problemReporter().missingReturnType(this); } if (this.typeParameters != null) { for (int i = 0, length = this.typeParameters.length; i < length; i++) { this.typeParameters[i].resolve(this.scope); } } if (this.binding != null && !this.binding.isPrivate()) { sourceType.tagBits |= TagBits.HasNonPrivateConstructor; } // if null ==> an error has occurs at parsing time .... if (this.constructorCall != null) { if (sourceType.id == TypeIds.T_JavaLangObject && this.constructorCall.accessMode != ExplicitConstructorCall.This) { // cannot use super() in java.lang.Object if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) { this.scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall); } this.constructorCall = null; } else { this.constructorCall.resolve(this.scope); } } if ((this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) { this.scope.problemReporter().methodNeedBody(this); } super.resolveStatements(); } public void traverse(ASTVisitor visitor, ClassScope classScope) { if (visitor.visit(this, classScope)) { if (this.javadoc != null) { this.javadoc.traverse(visitor, this.scope); } if (this.annotations != null) { int annotationsLength = this.annotations.length; for (int i = 0; i < annotationsLength; i++) this.annotations[i].traverse(visitor, this.scope); } if (this.typeParameters != null) { int typeParametersLength = this.typeParameters.length; for (int i = 0; i < typeParametersLength; i++) { this.typeParameters[i].traverse(visitor, this.scope); } } if (this.arguments != null) { int argumentLength = this.arguments.length; for (int i = 0; i < argumentLength; i++) this.arguments[i].traverse(visitor, this.scope); } if (this.thrownExceptions != null) { int thrownExceptionsLength = this.thrownExceptions.length; for (int i = 0; i < thrownExceptionsLength; i++) this.thrownExceptions[i].traverse(visitor, this.scope); } if (this.constructorCall != null) this.constructorCall.traverse(visitor, this.scope); if (this.statements != null) { int statementsLength = this.statements.length; for (int i = 0; i < statementsLength; i++) this.statements[i].traverse(visitor, this.scope); } } visitor.endVisit(this, classScope); } public TypeParameter[] typeParameters() { return this.typeParameters; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java0000644000175000001440000001421312212041344030455 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.BranchLabel; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.IntConstant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class CaseStatement extends Statement { public Expression constantExpression; public BranchLabel targetLabel; public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) { this.constantExpression = constantExpression; this.sourceEnd = sourceEnd; this.sourceStart = sourceStart; } public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { if (this.constantExpression != null) { if (this.constantExpression.constant == Constant.NotAConstant && !this.constantExpression.resolvedType.isEnum()) { currentScope.problemReporter().caseExpressionMustBeConstant(this.constantExpression); } this.constantExpression.analyseCode(currentScope, flowContext, flowInfo); } return flowInfo; } public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output); if (this.constantExpression == null) { output.append("default :"); //$NON-NLS-1$ } else { output.append("case "); //$NON-NLS-1$ this.constantExpression.printExpression(0, output).append(" :"); //$NON-NLS-1$ } return output; } /** * Case code generation * */ public void generateCode(BlockScope currentScope, CodeStream codeStream) { if ((this.bits & ASTNode.IsReachable) == 0) { return; } int pc = codeStream.position; this.targetLabel.place(); codeStream.recordPositionsFrom(pc, this.sourceStart); } /** * No-op : should use resolveCase(...) instead. */ public void resolve(BlockScope scope) { // 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 switchExpressionType, SwitchStatement switchStatement) { // switchExpressionType maybe null in error case scope.enclosingCase = this; // record entering in a switch case block if (this.constantExpression == null) { // remember the default case into the associated switch statement if (switchStatement.defaultCase != null) scope.problemReporter().duplicateDefaultCase(this); // on error the last default will be the selected one ... switchStatement.defaultCase = this; return Constant.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 != null && switchExpressionType.isEnum() && (this.constantExpression instanceof SingleNameReference)) { ((SingleNameReference) this.constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType); } TypeBinding caseType = this.constantExpression.resolveType(scope); if (caseType == null || switchExpressionType == null) return Constant.NotAConstant; if (this.constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType) || caseType.isCompatibleWith(switchExpressionType)) { if (caseType.isEnum()) { if (((this.constantExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) { scope.problemReporter().enumConstantsCannotBeSurroundedByParenthesis(this.constantExpression); } if (this.constantExpression instanceof NameReference && (this.constantExpression.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD) { NameReference reference = (NameReference) this.constantExpression; FieldBinding field = reference.fieldBinding(); if ((field.modifiers & ClassFileConstants.AccEnum) == 0) { scope.problemReporter().enumSwitchCannotTargetField(reference, field); } else if (reference instanceof QualifiedNameReference) { scope.problemReporter().cannotUseQualifiedEnumConstantInCaseLabel(reference, field); } return IntConstant.fromValue(field.original().id + 1); // (ordinal value + 1) zero should not be returned see bug 141810 } } else { return this.constantExpression.constant; } } else if (isBoxingCompatible(caseType, switchExpressionType, this.constantExpression, scope)) { // constantExpression.computeConversion(scope, caseType, switchExpressionType); - do not report boxing/unboxing conversion return this.constantExpression.constant; } scope.problemReporter().typeMismatchError(caseType, switchExpressionType, this.constantExpression, switchStatement.expression); return Constant.NotAConstant; } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { if (this.constantExpression != null) this.constantExpression.traverse(visitor, blockScope); } visitor.endVisit(this, blockScope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java0000644000175000001440000000717712212041344030641 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; public class BreakStatement extends BranchStatement { public BreakStatement(char[] label, int sourceStart, int e) { super(label, sourceStart, e); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // here requires to generate a sequence of finally blocks invocations depending corresponding // to each of the traversed try statements, so that execution will terminate properly. // lookup the label, this should answer the returnContext FlowContext targetContext = (this.label == null) ? flowContext.getTargetContextForDefaultBreak() : flowContext.getTargetContextForBreakLabel(this.label); if (targetContext == null) { if (this.label == null) { currentScope.problemReporter().invalidBreak(this); } else { currentScope.problemReporter().undefinedLabel(this); } return flowInfo; // pretend it did not break since no actual target } targetContext.recordAbruptExit(); this.initStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); this.targetLabel = targetContext.breakLabel(); FlowContext traversedContext = flowContext; int subCount = 0; this.subroutines = new SubRoutineStatement[5]; do { SubRoutineStatement sub; if ((sub = traversedContext.subroutine()) != null) { if (subCount == this.subroutines.length) { System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow } this.subroutines[subCount++] = sub; if (sub.isSubRoutineEscaping()) { break; } } traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); traversedContext.recordBreakTo(targetContext); if (traversedContext instanceof InsideSubRoutineFlowContext) { ASTNode node = traversedContext.associatedNode; if (node instanceof TryStatement) { TryStatement tryStatement = (TryStatement) node; flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits } } else if (traversedContext == targetContext) { // only record break info once accumulated through subroutines, and only against target context targetContext.recordBreakFrom(flowInfo); break; } } while ((traversedContext = traversedContext.getLocalParent()) != null); // resize subroutines if (subCount != this.subroutines.length) { System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount); } return FlowInfo.DEAD_END; } public StringBuffer printStatement(int tab, StringBuffer output) { printIndent(tab, output).append("break"); //$NON-NLS-1$ if (this.label != null) output.append(' ').append(this.label); return output.append(';'); } public void traverse(ASTVisitor visitor, BlockScope blockscope) { visitor.visit(this, blockscope); visitor.endVisit(this, blockscope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java0000644000175000001440000000467012212041344030157 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.impl.BooleanConstant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class TrueLiteral extends MagicLiteral { static final char[] source = {'t' , 'r' , 'u' , 'e'}; public TrueLiteral(int s , int e) { super(s,e); } public void computeConstant() { this.constant = BooleanConstant.fromValue(true); } /** * Code generation for the true 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(this.constant, this.implicitConversion); } codeStream.recordPositionsFrom(pc, this.sourceStart); } public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { // trueLabel being not nil means that we will not fall through into the TRUE case int pc = codeStream.position; // constant == true if (valueRequired) { if (falseLabel == null) { // implicit falling through the FALSE case if (trueLabel != null) { codeStream.goto_(trueLabel); } } } codeStream.recordPositionsFrom(pc, this.sourceStart); } public TypeBinding literalType(BlockScope scope) { return TypeBinding.BOOLEAN; } /** * */ public char[] source() { return source; } public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java0000644000175000001440000000710612212041344030502 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-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.Binding; 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); } } } private void internalResolve(Scope scope, boolean staticContext) { // detect variable/type name collisions if (this.binding != null) { Binding existingType = scope.parent.getBinding(this.name, Binding.TYPE, this, false/*do not resolve hidden field*/); if (existingType != null && this.binding != existingType && existingType.isValidBinding() && (existingType.kind() != Binding.TYPE_PARAMETER || !staticContext)) { scope.problemReporter().typeHiding(this, existingType); } } } public void resolve(BlockScope scope) { internalResolve(scope, scope.methodScope().isStatic); } public void resolve(ClassScope scope) { internalResolve(scope, scope.enclosingSourceType().isStatic()); } /* (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 (this.type != null) { this.type.traverse(visitor, scope); } if (this.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 (this.type != null) { this.type.traverse(visitor, scope); } if (this.bounds != null) { int boundsLength = this.bounds.length; for (int i = 0; i < boundsLength; i++) { this.bounds[i].traverse(visitor, scope); } } } visitor.endVisit(this, scope); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ClassFilePool.java0000644000175000001440000000313612212041344027627 0ustar dokousers/******************************************************************************* * Copyright (c) 2005, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; import java.util.Arrays; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; public class ClassFilePool { public static final int POOL_SIZE = 25; // need to have enough for 2 units ClassFile[] classFiles; private ClassFilePool() { // prevent instantiation this.classFiles = new ClassFile[POOL_SIZE]; } public static ClassFilePool newInstance() { return new ClassFilePool(); } public synchronized ClassFile acquire(SourceTypeBinding typeBinding) { for (int i = 0; i < POOL_SIZE; i++) { ClassFile classFile = this.classFiles[i]; if (classFile == null) { ClassFile newClassFile = new ClassFile(typeBinding); this.classFiles[i] = newClassFile; newClassFile.isShared = true; return newClassFile; } if (!classFile.isShared) { classFile.reset(typeBinding); classFile.isShared = true; return classFile; } } return new ClassFile(typeBinding); } public synchronized void release(ClassFile classFile) { classFile.isShared = false; } public void reset() { Arrays.fill(this.classFiles, null); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/Compiler.java0000644000175000001440000011425312212041344026705 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - contributions for * bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment * bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.env.*; import org.eclipse.jdt.internal.compiler.impl.*; import org.eclipse.jdt.internal.compiler.ast.*; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.parser.*; import org.eclipse.jdt.internal.compiler.problem.*; import org.eclipse.jdt.internal.compiler.util.*; import java.io.*; import java.util.*; public class Compiler implements ITypeRequestor, ProblemSeverities { public Parser parser; public ICompilerRequestor requestor; public CompilerOptions options; public ProblemReporter problemReporter; protected PrintWriter out; // output for messages that are not sent to problemReporter public CompilerStats stats; public CompilationProgress progress; public int remainingIterations = 1; // management of unit to be processed //public CompilationUnitResult currentCompilationUnitResult; public CompilationUnitDeclaration[] unitsToProcess; public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess // name lookup public LookupEnvironment lookupEnvironment; // ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD public static boolean DEBUG = false; public int parseThreshold = -1; public AbstractAnnotationProcessorManager annotationProcessorManager; public int annotationProcessorStartIndex = 0; public ReferenceBinding[] referenceBindings; public boolean useSingleThread = true; // by default the compiler will not use worker threads to read/process/write // number of initial units parsed at once (-1: none) /* * Static requestor reserved to listening compilation results in debug mode, * so as for example to monitor compiler activity independantly from a particular * builder implementation. It is reset at the end of compilation, and should not * persist any information after having been reset. */ public static IDebugRequestor DebugRequestor = null; /** * Answer a new compiler using the given name environment and compiler options. * The environment and options will be in effect for the lifetime of the compiler. * When the compiler is run, compilation results are sent to the given requestor. * * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment * Environment used by the compiler in order to resolve type and package * names. The name environment implements the actual connection of the compiler * to the outside world (e.g. in batch mode the name environment is performing * pure file accesses, reuse previous build state or connection to repositories). * Note: the name environment is responsible for implementing the actual classpath * rules. * * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy * Configurable part for problem handling, allowing the compiler client to * specify the rules for handling problems (stop on first error or accumulate * them all) and at the same time perform some actions such as opening a dialog * in UI when compiling interactively. * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies * * @param settings java.util.Map * The settings that control the compiler behavior. * * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor * Component which will receive and persist all compilation results and is intended * to consume them as they are produced. Typically, in a batch compiler, it is * responsible for writing out the actual .class files to the file system. * @see org.eclipse.jdt.internal.compiler.CompilationResult * * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory * Factory used inside the compiler to create problem descriptors. It allows the * compiler client to supply its own representation of compilation problems in * order to avoid object conversions. Note that the factory is not supposed * to accumulate the created problems, the compiler will gather them all and hand * them back as part of the compilation unit result. * * @deprecated this constructor is kept to preserve 3.1 and 3.2M4 compatibility */ public Compiler( INameEnvironment environment, IErrorHandlingPolicy policy, Map settings, final ICompilerRequestor requestor, IProblemFactory problemFactory) { this(environment, policy, new CompilerOptions(settings), requestor, problemFactory, null /* printwriter */, null /* progress */); } /** * Answer a new compiler using the given name environment and compiler options. * The environment and options will be in effect for the lifetime of the compiler. * When the compiler is run, compilation results are sent to the given requestor. * * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment * Environment used by the compiler in order to resolve type and package * names. The name environment implements the actual connection of the compiler * to the outside world (e.g. in batch mode the name environment is performing * pure file accesses, reuse previous build state or connection to repositories). * Note: the name environment is responsible for implementing the actual classpath * rules. * * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy * Configurable part for problem handling, allowing the compiler client to * specify the rules for handling problems (stop on first error or accumulate * them all) and at the same time perform some actions such as opening a dialog * in UI when compiling interactively. * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies * * @param settings java.util.Map * The settings that control the compiler behavior. * * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor * Component which will receive and persist all compilation results and is intended * to consume them as they are produced. Typically, in a batch compiler, it is * responsible for writing out the actual .class files to the file system. * @see org.eclipse.jdt.internal.compiler.CompilationResult * * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory * Factory used inside the compiler to create problem descriptors. It allows the * compiler client to supply its own representation of compilation problems in * order to avoid object conversions. Note that the factory is not supposed * to accumulate the created problems, the compiler will gather them all and hand * them back as part of the compilation unit result. * * @param parseLiteralExpressionsAsConstants boolean * This parameter is used to optimize the literals or leave them as they are in the source. * If you put true, "Hello" + " world" will be converted to "Hello world". * * @deprecated this constructor is kept to preserve 3.1 and 3.2M4 compatibility */ public Compiler( INameEnvironment environment, IErrorHandlingPolicy policy, Map settings, final ICompilerRequestor requestor, IProblemFactory problemFactory, boolean parseLiteralExpressionsAsConstants) { this(environment, policy, new CompilerOptions(settings, parseLiteralExpressionsAsConstants), requestor, problemFactory, null /* printwriter */, null /* progress */); } /** * Answer a new compiler using the given name environment and compiler options. * The environment and options will be in effect for the lifetime of the compiler. * When the compiler is run, compilation results are sent to the given requestor. * * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment * Environment used by the compiler in order to resolve type and package * names. The name environment implements the actual connection of the compiler * to the outside world (e.g. in batch mode the name environment is performing * pure file accesses, reuse previous build state or connection to repositories). * Note: the name environment is responsible for implementing the actual classpath * rules. * * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy * Configurable part for problem handling, allowing the compiler client to * specify the rules for handling problems (stop on first error or accumulate * them all) and at the same time perform some actions such as opening a dialog * in UI when compiling interactively. * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies * * @param options org.eclipse.jdt.internal.compiler.impl.CompilerOptions * The options that control the compiler behavior. * * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor * Component which will receive and persist all compilation results and is intended * to consume them as they are produced. Typically, in a batch compiler, it is * responsible for writing out the actual .class files to the file system. * @see org.eclipse.jdt.internal.compiler.CompilationResult * * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory * Factory used inside the compiler to create problem descriptors. It allows the * compiler client to supply its own representation of compilation problems in * order to avoid object conversions. Note that the factory is not supposed * to accumulate the created problems, the compiler will gather them all and hand * them back as part of the compilation unit result. */ public Compiler( INameEnvironment environment, IErrorHandlingPolicy policy, CompilerOptions options, final ICompilerRequestor requestor, IProblemFactory problemFactory) { this(environment, policy, options, requestor, problemFactory, null /* printwriter */, null /* progress */); } /** * Answer a new compiler using the given name environment and compiler options. * The environment and options will be in effect for the lifetime of the compiler. * When the compiler is run, compilation results are sent to the given requestor. * * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment * Environment used by the compiler in order to resolve type and package * names. The name environment implements the actual connection of the compiler * to the outside world (e.g. in batch mode the name environment is performing * pure file accesses, reuse previous build state or connection to repositories). * Note: the name environment is responsible for implementing the actual classpath * rules. * * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy * Configurable part for problem handling, allowing the compiler client to * specify the rules for handling problems (stop on first error or accumulate * them all) and at the same time perform some actions such as opening a dialog * in UI when compiling interactively. * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies * * @param options org.eclipse.jdt.internal.compiler.impl.CompilerOptions * The options that control the compiler behavior. * * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor * Component which will receive and persist all compilation results and is intended * to consume them as they are produced. Typically, in a batch compiler, it is * responsible for writing out the actual .class files to the file system. * @see org.eclipse.jdt.internal.compiler.CompilationResult * * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory * Factory used inside the compiler to create problem descriptors. It allows the * compiler client to supply its own representation of compilation problems in * order to avoid object conversions. Note that the factory is not supposed * to accumulate the created problems, the compiler will gather them all and hand * them back as part of the compilation unit result. * @deprecated */ public Compiler( INameEnvironment environment, IErrorHandlingPolicy policy, CompilerOptions options, final ICompilerRequestor requestor, IProblemFactory problemFactory, PrintWriter out) { this(environment, policy, options, requestor, problemFactory, out, null /* progress */); } public Compiler( INameEnvironment environment, IErrorHandlingPolicy policy, CompilerOptions options, final ICompilerRequestor requestor, IProblemFactory problemFactory, PrintWriter out, CompilationProgress progress) { this.options = options; this.progress = progress; // wrap requestor in DebugRequestor if one is specified if(DebugRequestor == null) { this.requestor = requestor; } else { this.requestor = new ICompilerRequestor(){ public void acceptResult(CompilationResult result){ if (DebugRequestor.isActive()){ DebugRequestor.acceptDebugResult(result); } requestor.acceptResult(result); } }; } this.problemReporter = new ProblemReporter(policy, this.options, problemFactory); this.lookupEnvironment = new LookupEnvironment(this, this.options, this.problemReporter, environment); this.out = out == null ? new PrintWriter(System.out, true) : out; this.stats = new CompilerStats(); initializeParser(); } /** * Add an additional binary type */ public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) { if (this.options.verbose) { this.out.println( Messages.bind(Messages.compilation_loadBinary, new String(binaryType.getName()))); // new Exception("TRACE BINARY").printStackTrace(System.out); // System.out.println(); } this.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, AccessRestriction accessRestriction) { // Switch the current policy and compilation result for this unit to the requested one. CompilationResult unitResult = new CompilationResult(sourceUnit, this.totalUnits, this.totalUnits, this.options.maxProblemsPerUnit); unitResult.checkSecondaryTypes = true; try { if (this.options.verbose) { String count = String.valueOf(this.totalUnits + 1); this.out.println( Messages.bind(Messages.compilation_request, new String[] { count, count, new String(sourceUnit.getFileName()) })); } // diet parsing for large collection of unit CompilationUnitDeclaration parsedUnit; if (this.totalUnits < this.parseThreshold) { parsedUnit = this.parser.parse(sourceUnit, unitResult); } else { parsedUnit = this.parser.dietParse(sourceUnit, unitResult); } parsedUnit.bits |= ASTNode.IsImplicitUnit; // initial type binding creation this.lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction); addCompilationUnit(sourceUnit, parsedUnit); // binding resolution this.lookupEnvironment.completeTypeBindings(parsedUnit); } catch (AbortCompilationUnit e) { // at this point, currentCompilationUnitResult may not be sourceUnit, but some other // one requested further along to resolve sourceUnit. if (unitResult.compilationUnit == sourceUnit) { // only report once this.requestor.acceptResult(unitResult.tagAsAccepted()); } else { throw e; // want to abort enclosing request to compile } } } /** * Add additional source types */ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) { this.problemReporter.abortDueToInternalError( Messages.bind(Messages.abort_againstSourceModel, new String[] { String.valueOf(sourceTypes[0].getName()), String.valueOf(sourceTypes[0].getFileName()) })); } protected synchronized void addCompilationUnit( ICompilationUnit sourceUnit, CompilationUnitDeclaration parsedUnit) { if (this.unitsToProcess == null) return; // not collecting units // append the unit to the list of ones to process later on int size = this.unitsToProcess.length; if (this.totalUnits == size) // when growing reposition units starting at position 0 System.arraycopy( this.unitsToProcess, 0, (this.unitsToProcess = new CompilationUnitDeclaration[size * 2]), 0, this.totalUnits); this.unitsToProcess[this.totalUnits++] = parsedUnit; } /** * Add the initial set of compilation units into the loop * -> build compilation unit declarations, their bindings and record their results. */ protected void beginToCompile(ICompilationUnit[] sourceUnits) { int maxUnits = sourceUnits.length; this.totalUnits = 0; this.unitsToProcess = new CompilationUnitDeclaration[maxUnits]; internalBeginToCompile(sourceUnits, maxUnits); } /** * Checks whether the compilation has been canceled and reports the given progress to the compiler progress. */ protected void reportProgress(String taskDecription) { if (this.progress != null) { if (this.progress.isCanceled()) { // Only AbortCompilation can stop the compiler cleanly. // We check cancellation again following the call to compile. throw new AbortCompilation(true, null); } this.progress.setTaskName(taskDecription); } } /** * Checks whether the compilation has been canceled and reports the given work increment to the compiler progress. */ protected void reportWorked(int workIncrement, int currentUnitIndex) { if (this.progress != null) { if (this.progress.isCanceled()) { // Only AbortCompilation can stop the compiler cleanly. // We check cancellation again following the call to compile. throw new AbortCompilation(true, null); } this.progress.worked(workIncrement, (this.totalUnits* this.remainingIterations) - currentUnitIndex - 1); } } /** * General API * -> compile each of supplied files * -> recompile any required types for which we have an incomplete principle structure */ public void compile(ICompilationUnit[] sourceUnits) { this.stats.startTime = System.currentTimeMillis(); CompilationUnitDeclaration unit = null; ProcessTaskManager processingTask = null; try { // build and record parsed units reportProgress(Messages.compilation_beginningToCompile); if (this.annotationProcessorManager == null) { beginToCompile(sourceUnits); } else { ICompilationUnit[] originalUnits = (ICompilationUnit[]) sourceUnits.clone(); // remember source units in case a source type collision occurs try { beginToCompile(sourceUnits); processAnnotations(); if (!this.options.generateClassFiles) { // -proc:only was set on the command line return; } } catch (SourceTypeCollisionException e) { reset(); // a generated type was referenced before it was created // the compiler either created a MissingType or found a BinaryType for it // so add the processor's generated files & start over, // but remember to only pass the generated files to the annotation processor int originalLength = originalUnits.length; int newProcessedLength = e.newAnnotationProcessorUnits.length; ICompilationUnit[] combinedUnits = new ICompilationUnit[originalLength + newProcessedLength]; System.arraycopy(originalUnits, 0, combinedUnits, 0, originalLength); System.arraycopy(e.newAnnotationProcessorUnits, 0, combinedUnits, originalLength, newProcessedLength); this.annotationProcessorStartIndex = originalLength; compile(combinedUnits); return; } } if (this.useSingleThread) { // process all units (some more could be injected in the loop by the lookup environment) for (int i = 0; i < this.totalUnits; i++) { unit = this.unitsToProcess[i]; reportProgress(Messages.bind(Messages.compilation_processing, new String(unit.getFileName()))); try { if (this.options.verbose) this.out.println( Messages.bind(Messages.compilation_process, new String[] { String.valueOf(i + 1), String.valueOf(this.totalUnits), new String(this.unitsToProcess[i].getFileName()) })); process(unit, i); } finally { // cleanup compilation unit result unit.cleanUp(); } this.unitsToProcess[i] = null; // release reference to processed unit declaration reportWorked(1, i); this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length; long acceptStart = System.currentTimeMillis(); this.requestor.acceptResult(unit.compilationResult.tagAsAccepted()); this.stats.generateTime += System.currentTimeMillis() - acceptStart; // record accept time as part of generation if (this.options.verbose) this.out.println( Messages.bind(Messages.compilation_done, new String[] { String.valueOf(i + 1), String.valueOf(this.totalUnits), new String(unit.getFileName()) })); } } else { processingTask = new ProcessTaskManager(this); int acceptedCount = 0; // process all units (some more could be injected in the loop by the lookup environment) // the processTask can continue to process units until its fixed sized cache is full then it must wait // for this this thread to accept the units as they appear (it only waits if no units are available) while (true) { try { unit = processingTask.removeNextUnit(); // waits if no units are in the processed queue } catch (Error e) { unit = processingTask.unitToProcess; throw e; } catch (RuntimeException e) { unit = processingTask.unitToProcess; throw e; } if (unit == null) break; reportWorked(1, acceptedCount++); this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length; this.requestor.acceptResult(unit.compilationResult.tagAsAccepted()); if (this.options.verbose) this.out.println( Messages.bind(Messages.compilation_done, new String[] { String.valueOf(acceptedCount), String.valueOf(this.totalUnits), new String(unit.getFileName()) })); } } } catch (AbortCompilation e) { this.handleInternalException(e, unit); } catch (Error e) { this.handleInternalException(e, unit, null); throw e; // rethrow } catch (RuntimeException e) { this.handleInternalException(e, unit, null); throw e; // rethrow } finally { if (processingTask != null) { processingTask.shutdown(); processingTask = null; } reset(); this.annotationProcessorStartIndex = 0; this.stats.endTime = System.currentTimeMillis(); } if (this.options.verbose) { if (this.totalUnits > 1) { this.out.println( Messages.bind(Messages.compilation_units, String.valueOf(this.totalUnits))); } else { this.out.println( Messages.bind(Messages.compilation_unit, String.valueOf(this.totalUnits))); } } } public synchronized CompilationUnitDeclaration getUnitToProcess(int next) { if (next < this.totalUnits) { CompilationUnitDeclaration unit = this.unitsToProcess[next]; this.unitsToProcess[next] = null; // release reference to processed unit declaration return unit; } return null; } public void setBinaryTypes(ReferenceBinding[] binaryTypes) { this.referenceBindings = binaryTypes; } /* * Compiler crash recovery in case of unexpected runtime exceptions */ protected void handleInternalException( Throwable internalException, CompilationUnitDeclaration unit, CompilationResult result) { if (result == null && unit != null) { result = unit.compilationResult; // current unit being processed ? } // Lookup environment may be in middle of connecting types if (result == null && this.lookupEnvironment.unitBeingCompleted != null) { result = this.lookupEnvironment.unitBeingCompleted.compilationResult; } if (result == null) { synchronized (this) { if (this.unitsToProcess != null && this.totalUnits > 0) result = this.unitsToProcess[this.totalUnits - 1].compilationResult; } } // last unit in beginToCompile ? boolean needToPrint = true; if (result != null) { /* create and record a compilation problem */ // only keep leading portion of the trace String[] pbArguments = new String[] { Messages.bind(Messages.compilation_internalError, Util.getExceptionSummary(internalException)), }; result .record( this.problemReporter .createProblem( result.getFileName(), IProblem.Unclassified, pbArguments, pbArguments, Error, // severity 0, // source start 0, // source end 0, // line number 0),// column number unit, true); /* hand back the compilation result */ if (!result.hasBeenAccepted) { this.requestor.acceptResult(result.tagAsAccepted()); needToPrint = false; } } if (needToPrint) { /* dump a stack trace to the console */ internalException.printStackTrace(); } } /* * Compiler recovery in case of internal AbortCompilation event */ protected void handleInternalException( AbortCompilation abortException, CompilationUnitDeclaration unit) { /* special treatment for SilentAbort: silently cancelling the compilation process */ if (abortException.isSilent) { if (abortException.silentException == null) { return; } throw abortException.silentException; } /* uncomment following line to see where the abort came from */ // abortException.printStackTrace(); // Exception may tell which compilation result it is related, and which problem caused it CompilationResult result = abortException.compilationResult; if (result == null && unit != null) { result = unit.compilationResult; // current unit being processed ? } // Lookup environment may be in middle of connecting types if (result == null && this.lookupEnvironment.unitBeingCompleted != null) { result = this.lookupEnvironment.unitBeingCompleted.compilationResult; } if (result == null) { synchronized (this) { if (this.unitsToProcess != null && this.totalUnits > 0) result = this.unitsToProcess[this.totalUnits - 1].compilationResult; } } // last unit in beginToCompile ? if (result != null && !result.hasBeenAccepted) { /* distant problem which could not be reported back there? */ if (abortException.problem != null) { recordDistantProblem: { CategorizedProblem distantProblem = abortException.problem; CategorizedProblem[] knownProblems = result.problems; for (int i = 0; i < result.problemCount; i++) { if (knownProblems[i] == distantProblem) { // already recorded break recordDistantProblem; } } if (distantProblem instanceof DefaultProblem) { // fixup filename TODO (philippe) should improve API to make this official ((DefaultProblem) distantProblem).setOriginatingFileName(result.getFileName()); } result.record(distantProblem, unit, true); } } else { /* distant internal exception which could not be reported back there */ if (abortException.exception != null) { this.handleInternalException(abortException.exception, null, result); return; } } /* hand back the compilation result */ if (!result.hasBeenAccepted) { this.requestor.acceptResult(result.tagAsAccepted()); } } else { abortException.printStackTrace(); } } public void initializeParser() { this.parser = new Parser(this.problemReporter, this.options.parseLiteralExpressionsAsConstants); } /** * Add the initial set of compilation units into the loop * -> build compilation unit declarations, their bindings and record their results. */ protected void internalBeginToCompile(ICompilationUnit[] sourceUnits, int maxUnits) { if (!this.useSingleThread && maxUnits >= ReadManager.THRESHOLD) this.parser.readManager = new ReadManager(sourceUnits, maxUnits); // Switch the current policy and compilation result for this unit to the requested one. for (int i = 0; i < maxUnits; i++) { CompilationResult unitResult = null; try { if (this.options.verbose) { this.out.println( Messages.bind(Messages.compilation_request, new String[] { String.valueOf(i + 1), String.valueOf(maxUnits), new String(sourceUnits[i].getFileName()) })); } // diet parsing for large collection of units CompilationUnitDeclaration parsedUnit; unitResult = new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit); long parseStart = System.currentTimeMillis(); if (this.totalUnits < this.parseThreshold) { parsedUnit = this.parser.parse(sourceUnits[i], unitResult); } else { parsedUnit = this.parser.dietParse(sourceUnits[i], unitResult); } long resolveStart = System.currentTimeMillis(); this.stats.parseTime += resolveStart - parseStart; // initial type binding creation this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); this.stats.resolveTime += System.currentTimeMillis() - resolveStart; addCompilationUnit(sourceUnits[i], parsedUnit); ImportReference currentPackage = parsedUnit.currentPackage; if (currentPackage != null) { unitResult.recordPackageName(currentPackage.tokens); } //} catch (AbortCompilationUnit e) { // requestor.acceptResult(unitResult.tagAsAccepted()); } catch (AbortCompilation a) { // best effort to find a way for reporting this problem: if (a.compilationResult == null) a.compilationResult = unitResult; throw a; } finally { sourceUnits[i] = null; // no longer hold onto the unit } } if (this.parser.readManager != null) { this.parser.readManager.shutdown(); this.parser.readManager = null; } // binding resolution this.lookupEnvironment.completeTypeBindings(); } /** * Process a compilation unit already parsed and build. */ public void process(CompilationUnitDeclaration unit, int i) { this.lookupEnvironment.unitBeingCompleted = unit; long parseStart = System.currentTimeMillis(); this.parser.getMethodBodies(unit); long resolveStart = System.currentTimeMillis(); this.stats.parseTime += resolveStart - parseStart; // fault in fields & methods if (unit.scope != null) unit.scope.faultInTypes(); // verify inherited methods if (unit.scope != null) unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier()); // type checking unit.resolve(); long analyzeStart = System.currentTimeMillis(); this.stats.resolveTime += analyzeStart - resolveStart; //No need of analysis or generation of code if statements are not required if (!this.options.ignoreMethodBodies) unit.analyseCode(); // flow analysis long generateStart = System.currentTimeMillis(); this.stats.analyzeTime += generateStart - analyzeStart; if (!this.options.ignoreMethodBodies) unit.generateCode(); // code generation // reference info if (this.options.produceReferenceInfo && unit.scope != null) unit.scope.storeDependencyInfo(); // finalize problems (suppressWarnings) unit.finalizeProblems(); this.stats.generateTime += System.currentTimeMillis() - generateStart; // refresh the total number of units known at this stage unit.compilationResult.totalUnitsKnown = this.totalUnits; this.lookupEnvironment.unitBeingCompleted = null; } protected void processAnnotations() { int newUnitSize = 0; int newClassFilesSize = 0; int bottom = this.annotationProcessorStartIndex; int top = this.totalUnits; ReferenceBinding[] binaryTypeBindingsTemp = this.referenceBindings; if (top == 0 && binaryTypeBindingsTemp == null) return; this.referenceBindings = null; do { // extract units to process int length = top - bottom; CompilationUnitDeclaration[] currentUnits = new CompilationUnitDeclaration[length]; int index = 0; for (int i = bottom; i < top; i++) { CompilationUnitDeclaration currentUnit = this.unitsToProcess[i]; if ((currentUnit.bits & ASTNode.IsImplicitUnit) == 0) { currentUnits[index++] = currentUnit; } } if (index != length) { System.arraycopy(currentUnits, 0, (currentUnits = new CompilationUnitDeclaration[index]), 0, index); } this.annotationProcessorManager.processAnnotations(currentUnits, binaryTypeBindingsTemp, false); ICompilationUnit[] newUnits = this.annotationProcessorManager.getNewUnits(); newUnitSize = newUnits.length; ReferenceBinding[] newClassFiles = this.annotationProcessorManager.getNewClassFiles(); binaryTypeBindingsTemp = newClassFiles; newClassFilesSize = newClassFiles.length; if (newUnitSize != 0) { ICompilationUnit[] newProcessedUnits = (ICompilationUnit[]) newUnits.clone(); // remember new units in case a source type collision occurs try { this.lookupEnvironment.isProcessingAnnotations = true; internalBeginToCompile(newUnits, newUnitSize); } catch (SourceTypeCollisionException e) { e.newAnnotationProcessorUnits = newProcessedUnits; throw e; } finally { this.lookupEnvironment.isProcessingAnnotations = false; this.annotationProcessorManager.reset(); } bottom = top; top = this.totalUnits; // last unit added } else { bottom = top; this.annotationProcessorManager.reset(); } } while (newUnitSize != 0 || newClassFilesSize != 0); this.annotationProcessorManager.processAnnotations(null, null, true); // process potential units added in the final round see 329156 ICompilationUnit[] newUnits = this.annotationProcessorManager.getNewUnits(); newUnitSize = newUnits.length; if (newUnitSize != 0) { ICompilationUnit[] newProcessedUnits = (ICompilationUnit[]) newUnits.clone(); // remember new units in case a source type collision occurs try { this.lookupEnvironment.isProcessingAnnotations = true; internalBeginToCompile(newUnits, newUnitSize); } catch (SourceTypeCollisionException e) { e.newAnnotationProcessorUnits = newProcessedUnits; throw e; } finally { this.lookupEnvironment.isProcessingAnnotations = false; this.annotationProcessorManager.reset(); } } else { this.annotationProcessorManager.reset(); } } public void reset() { this.lookupEnvironment.reset(); this.parser.scanner.source = null; this.unitsToProcess = null; if (DebugRequestor != null) DebugRequestor.reset(); this.problemReporter.reset(); } /** * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process */ public CompilationUnitDeclaration resolve( CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) { try { if (unit == null) { // build and record parsed units this.parseThreshold = 0; // will request a full parse beginToCompile(new ICompilationUnit[] { sourceUnit }); // find the right unit from what was injected via accept(ICompilationUnit,..): for (int i=0; i this.endPosition) || ((this.startPosition < 0) && (this.endPosition < 0)) || unitSource.length == 0) return Messages.problem_noSourceInformation; StringBuffer errorBuffer = new StringBuffer(); errorBuffer.append(' ').append(Messages.bind(Messages.problem_atLine, String.valueOf(this.line))); errorBuffer.append(Util.LINE_SEPARATOR); errorBuffer.append('\t'); char c; final char SPACE = '\u0020'; final char MARK = '^'; final char TAB = '\t'; //the next code tries to underline the token..... //it assumes (for a good display) that token source does not //contain any \r \n. This is false on statements ! //(the code still works but the display is not optimal !) // expand to line limits int length = unitSource.length, begin, end; for (begin = this.startPosition >= length ? length - 1 : this.startPosition; begin > 0; begin--) { if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break; } for (end = this.endPosition >= length ? length - 1 : this.endPosition ; end+1 < length; end++) { if ((c = unitSource[end + 1]) == '\r' || c == '\n') break; } // trim left and right spaces/tabs while ((c = unitSource[begin]) == ' ' || c == '\t') begin++; //while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated // copy source errorBuffer.append(unitSource, begin, end-begin+1); errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); //$NON-NLS-1$ // compute underline for (int i = begin; i = length ? length - 1 : this.endPosition); i++) { errorBuffer.append(MARK); } return errorBuffer.toString(); } /** * Answer back the original arguments recorded into the problem. * @return java.lang.String[] */ public String[] getArguments() { return this.arguments; } /** * @see org.eclipse.jdt.core.compiler.CategorizedProblem#getCategoryID() */ public int getCategoryID() { return ProblemReporter.getProblemCategory(this.severity, this.id); } /** * Answer the type of problem. * @see org.eclipse.jdt.core.compiler.IProblem#getID() * @return int */ public int getID() { return this.id; } /** * Answers a readable name for the category which this problem belongs to, * or null if none could be found. * FOR TESTING PURPOSE * @return java.lang.String */ public String getInternalCategoryMessage() { switch(getCategoryID()) { case CAT_UNSPECIFIED: return "unspecified"; //$NON-NLS-1$ case CAT_BUILDPATH: return "buildpath"; //$NON-NLS-1$ case CAT_SYNTAX: return "syntax"; //$NON-NLS-1$ case CAT_IMPORT: return "import"; //$NON-NLS-1$ case CAT_TYPE: return "type"; //$NON-NLS-1$ case CAT_MEMBER: return "member"; //$NON-NLS-1$ case CAT_INTERNAL: return "internal"; //$NON-NLS-1$ case CAT_JAVADOC: return "javadoc"; //$NON-NLS-1$ case CAT_CODE_STYLE: return "code style"; //$NON-NLS-1$ case CAT_POTENTIAL_PROGRAMMING_PROBLEM: return "potential programming problem"; //$NON-NLS-1$ case CAT_NAME_SHADOWING_CONFLICT: return "name shadowing conflict"; //$NON-NLS-1$ case CAT_DEPRECATION: return "deprecation"; //$NON-NLS-1$ case CAT_UNNECESSARY_CODE: return "unnecessary code"; //$NON-NLS-1$ case CAT_UNCHECKED_RAW: return "unchecked/raw"; //$NON-NLS-1$ case CAT_NLS: return "nls"; //$NON-NLS-1$ case CAT_RESTRICTION: return "restriction"; //$NON-NLS-1$ } return null; } /** * Returns the marker type associated to this problem. * @see org.eclipse.jdt.core.compiler.CategorizedProblem#getMarkerType() */ public String getMarkerType() { return this.id == IProblem.Task ? MARKER_TYPE_TASK : MARKER_TYPE_PROBLEM; } /** * Answer a localized, human-readable message string which describes the problem. * @return java.lang.String */ public String getMessage() { return this.message; } /** * Answer the file name in which the problem was found. * @return char[] */ public char[] getOriginatingFileName() { return this.fileName; } /** * Answer the end position of the problem (inclusive), or -1 if unknown. * @return int */ public int getSourceEnd() { return this.endPosition; } /** * Answer the line number in source where the problem begins. * @return int */ public int getSourceColumnNumber() { return this.column; } /** * Answer the line number in source where the problem begins. * @return int */ public int getSourceLineNumber() { return this.line; } /** * Answer the start position of the problem (inclusive), or -1 if unknown. * @return int */ public int getSourceStart() { return this.startPosition; } /* * Helper method: checks the severity to see if the Error bit is set. * @return boolean */ public boolean isError() { return (this.severity & ProblemSeverities.Error) != 0; } /* * Helper method: checks the severity to see if the Error bit is not set. * @return boolean */ public boolean isWarning() { return (this.severity & ProblemSeverities.Error) == 0; } public void setOriginatingFileName(char[] fileName) { this.fileName = fileName; } /** * Set the end position of the problem (inclusive), or -1 if unknown. * * Used for shifting problem positions. * @param sourceEnd the new value of the sourceEnd of the receiver */ public void setSourceEnd(int sourceEnd) { this.endPosition = sourceEnd; } /** * Set the line number in source where the problem begins. * @param lineNumber the new value of the line number of the receiver */ public void setSourceLineNumber(int lineNumber) { this.line = lineNumber; } /** * Set the start position of the problem (inclusive), or -1 if unknown. * * Used for shifting problem positions. * @param sourceStart the new value of the source start position of the receiver */ public void setSourceStart(int sourceStart) { this.startPosition = sourceStart; } public String toString() { String s = "Pb(" + (this.id & IProblem.IgnoreCategoriesMask) + ") "; //$NON-NLS-1$ //$NON-NLS-2$ if (this.message != null) { s += this.message; } else { if (this.arguments != null) for (int i = 0; i < this.arguments.length; i++) s += " " + this.arguments[i]; //$NON-NLS-1$ } return s; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java0000644000175000001440000000214312212041344030775 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; /* * Special unchecked exception type used * to abort from the compilation process * * should only be thrown from within problem handlers. */ public class AbortMethod extends AbortType { private static final long serialVersionUID = -1480267398969840003L; // backward compatible public AbortMethod(CompilationResult compilationResult, CategorizedProblem problem) { super(compilationResult, problem); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/messages.properties0000644000175000001440000014134212212041344031654 0ustar dokousers############################################################################### # Copyright (c) 2000, 2013 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # # Contributors: # IBM Corporation - initial API and implementation # Benjamin Muskalla - Contribution for bug 239066 # Stephan Herrmann - Contributions for # bug 185682 - Increment/decrement operators mark local variables as read # bug 349326 - [1.7] new warning for missing try-with-resources # bug 186342 - [compiler][null] Using annotations for null checking # bug 365662 - [compiler][null] warn on contradictory and redundant null annotations # bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults # bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations # bug 374605 - Unreasonable warning for enum-based switch statements # bug 388281 - [compiler][null] inheritance of null annotations as an option # bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated # bug 393719 - [compiler] inconsistent warnings on iteration variables # bug 331649 - [compiler][null] consider null annotations for fields # bug 382789 - [compiler][null] warn when syntactically-nonnull expression is compared against null # bug 400761 - [compiler][null] null may be return as boolean without a diagnostic ############################################################################### 0 = {0} 1 = super cannot be used in java.lang.Object 2 = {0} cannot be resolved to a type 3 = The type {0} is not visible 4 = The type {0} is ambiguous 5 = The type {0} is deprecated 6 = The nested type {0} cannot be referenced using its binary name 7 = The type {0} is never used locally 15 = Incompatible operand types {0} and {1} 16 = Incompatible conditional operand types {0} and {1} 17 = Type mismatch: cannot convert from {0} to {1} 18 = The static member type {0}.{1} should be accessed directly 20 = No enclosing instance of type {0} is accessible to invoke the super constructor. Must define a constructor and explicitly qualify its super constructor invocation with an instance of {0} (e.g. x.super() where x is an instance of {0}). 21 = No enclosing instance of type {0} is accessible. Must qualify the allocation with an enclosing instance of type {0} (e.g. x.new A() where x is an instance of {0}). 22 = No enclosing instance of the type {0} is accessible in scope 23 = Illegal enclosing instance specification for type {0} 24 = Cannot define static initializer in inner type {0} 25 = Cannot refer to a non-final variable {0} inside an inner class defined in a different method 26 = The member interface {0} can only be defined inside a top-level class or interface 27 = Cannot use an expression of the type {0} as a valid enclosing instance 28 = No enclosing instance of type {0} is available due to some intermediate constructor invocation 29 = An anonymous class cannot subclass the final class {0} 30 = The member annotation {0} can only be defined inside a top-level class or interface 31 = The member enum {0} can only be defined inside a top-level class or interface 32 = The member enum {0} must be defined inside a static member type 33 = The type {0} is hiding the type {1} 50 = {0} cannot be resolved 51 = The local variable {0} may not have been initialized 52 = void is an invalid type for the variable {0} ###[obsolete] 53 = An array of void is an invalid type for the variable {0} 54 = void[] is an invalid type 55 = Duplicate local variable {0} 56 = Duplicate parameter {0} 57 = The final local variable {0} may already have been assigned 58 = The final local variable {0} cannot be assigned. It must be blank and not using a compound assignment 59 = The parameter {0} should not be assigned 60 = The final local variable {0} cannot be assigned, since it is defined in an enclosing type 61 = The value of the local variable {0} is not used 62 = The value of the parameter {0} is not used 63 = The code of method {0}({1}) is exceeding the 65535 bytes limit 64 = The code for the static initializer is exceeding the 65535 bytes limit 65 = Too many parameters, parameter {0} is exceeding the limit of 255 words eligible for method parameters 66 = Too many local variables, local variable {0} is exceeding the limit of 65535 words eligible for method local variables 67 = Too many synthetic parameters, emulated parameter {0} is exceeding the limit of 255 words eligible for method parameters 68 = Too many array dimensions. Maximum is 255 69 = The code of constructor {0}({1}) is exceeding the 65535 bytes limit 70 = {0} cannot be resolved or is not a field 71 = The field {1}.{0} is not visible 72 = The field {0} is ambiguous 73 = The field {0}.{1} is deprecated 74 = Cannot make a static reference to the non-static field {0} 75 = Cannot reference a field before it is defined 76 = The static field {0}.{1} should be accessed in a static way 77 = The value of the field {0}.{1} is not used 78 = The static field {0}.{1} should be accessed directly 79 = Unqualified access to the field {0}.{1} 80 = The final field {0}.{1} cannot be assigned 81 = The blank final field {0} may not have been initialized 82 = The final field {0} may already have been assigned 83 = {0} cannot be resolved to a variable 90 = The local variable {0} is hiding another local variable defined in an enclosing type scope 91 = The local variable {0} is hiding a field from type {1} 92 = The field {0}.{1} is hiding another local variable defined in an enclosing type scope 93 = The field {0}.{1} is hiding a field from type {2} 94 = The parameter {0} is hiding another local variable defined in an enclosing type scope 95 = The parameter {0} is hiding a field from type {1} 96 = The serializable class {0} does not declare a static final serialVersionUID field of type long 100 = The method {1}({2}) is undefined for the type {0} 101 = The method {1}({2}) from the type {0} is not visible 102 = The method {1}({2}) is ambiguous for the type {0} 103 = The method {1}({2}) from the type {0} is deprecated 104 = Cannot directly invoke the abstract method {1}({2}) for the type {0} 105 = Void methods cannot return a value 106 = Cannot return a void result 107 = This method requires a body instead of a semicolon 108 = This method must return a result of type {0} 110 = This method has a constructor name 111 = Return type for the method is missing 112 = Native methods do not specify a body 113 = Abstract methods do not specify a body 114 = Cannot invoke {1}({2}) on the primitive type {0} 115 = The method {1}({2}) in the type {0} is not applicable for the arguments ({3}) 116 = Cannot invoke {1}({2}) on the array type {0} 117 = The static method {1}({2}) from the type {0} should be accessed in a static way 118 = The method {1}({2}) from the type {0} is never used locally 119 = The static method {1}({2}) from the type {0} should be accessed directly 120 = The method {1}({2}) from the type {0} refers to the missing type {3} 121 = The method {1}({2}) from the type {0} can be declared as static 122 = The method {1}({2}) from the type {0} can potentially be declared as static 129 = The constructor {0}({1}) refers to the missing type {2} 130 = The constructor {0}({1}) is undefined 131 = The constructor {0}({1}) is not visible 132 = The constructor {0}({1}) is ambiguous 133 = The constructor {0}({1}) is deprecated 134 = The constructor {0}({1}) is never used locally 135 = Cannot refer to an instance field {0} while explicitly invoking a constructor 136 = Cannot refer to an instance method while explicitly invoking a constructor 137 = Recursive constructor invocation {0}({1}) 138 = Cannot refer to 'this' nor 'super' while explicitly invoking a constructor 139 = Constructor call must be the first statement in a constructor 140 = Implicit super constructor {0}({1}) is undefined for default constructor. Must define an explicit constructor 141 = Implicit super constructor {0}({1}) is not visible for default constructor. Must define an explicit constructor 142 = Implicit super constructor {0}({1}) is ambiguous for default constructor. Must define an explicit constructor 143 = Implicit super constructor {0}({1}) is undefined. Must explicitly invoke another constructor 144 = Implicit super constructor {0}({1}) is not visible. Must explicitly invoke another constructor 145 = Implicit super constructor {0}({1}) is ambiguous. Must explicitly invoke another constructor 146 = Default constructor cannot handle exception type {0} thrown by implicit super constructor. Must define an explicit constructor 147 = Unhandled exception type {0} thrown by implicit super constructor 148 = The allocated object is never used 149 = Dead code 150 = The type of the expression must be an array type but it resolved to {0} 151 = Must explicitly convert the char[] to a String 152 = String constant is exceeding the limit of 65535 bytes of UTF8 encoding 153 = case expressions must be constant expressions 154 = The literal {1} of type {0} is out of range 156 = Cannot cast from {0} to {1} 157 = Cannot instantiate the type {0} 158 = Cannot define dimension expressions when an array initializer is provided 159 = Variable must provide either dimension expressions or an array initializer 160 = The operator {0} is undefined for the argument type(s) {1} 161 = Unreachable code 162 = Cannot return from within an initializer 163 = Initializer does not complete normally 164 = Expression must return a value 165 = Unreachable catch block for {0}. Only more specific exceptions are thrown and they are handled by previous catch block(s). 166 = The default case is already defined 167 = Unreachable catch block for {0}. This exception is never thrown from the try statement body 168 = Unhandled exception type {0} 169 = Cannot switch on a value of type {0}. Only convertible int values or enum variables are permitted 170 = Duplicate case 171 = Duplicate label {0} 172 = break cannot be used outside of a loop or a switch 173 = continue cannot be used outside of a loop 174 = The label {0} is missing 175 = {0} is not a valid type''s argument for the synchronized statement 176 = null is not a valid argument for the synchronized statement 177 = Cannot throw null as an exception 178 = The assignment to variable {0} has no effect 179 = Possible accidental assignment in place of a comparison. A condition expression should not be reduced to an assignment 180 = Unnecessary semicolon 181 = Unnecessary cast from {0} to {1} 182 = Unnecessary cast from {0} to {1}. It is already compatible with the argument type {2} 183 = The expression of type {0} is already an instance of type {1} 184 = finally block does not complete normally 185 = The declared exception {3} is not actually thrown by the method {1}({2}) from type {0} 186 = The declared exception {2} is not actually thrown by the constructor {0}({1}) 187 = Unreachable catch block for {0}. It is already handled by the catch block for {1} 188 = Empty control-flow statement 189 = Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally 190 = Read access to enclosing field {0}.{1} is emulated by a synthetic accessor method 191 = Write access to enclosing field {0}.{1} is emulated by a synthetic accessor method 192 = Access to enclosing method {1}({2}) from the type {0} is emulated by a synthetic accessor method 193 = Access to enclosing constructor {0}({1}) is emulated by a synthetic accessor method 194 = Switch case may be entered by falling through previous case. If intended, add a new comment //$FALL-THROUGH$ on the line above 195 = The method {1} is defined in an inherited type and an enclosing scope 196 = The field {0} is defined in an inherited type and an enclosing scope 197 = The type {0} is defined in an inherited type and an enclosing scope 198 = Cannot allocate the member type {0} using its compound name when qualified by an enclosing instance. The member type name is resolved relatively to the qualifying instance type 199 = The label {0} is never explicitly referenced 200 = Cannot use {0} in a static context 201 = Cannot make a static reference to the non-static method {1}({2}) from the type {0} 202 = Cannot specify an array dimension after an empty dimension #203 = Invalid cast expression 204 = Syntax error on token "{0}", {1} expected 205 = Syntax error on token "{0}", no accurate correction available 206 = Invalid argument to operation ++/-- 207 = Interfaces cannot have constructors 208 = Array constants can only be used in initializers 209 = Syntax error on keyword "{0}"; {1} expected 210 = Syntax error on keyword "{0}", no accurate correction available 211 = Comparing identical expressions 220 = Unmatched bracket 221 = The primitive type {0} of {1} does not have a field {2} 222 = Invalid expression as statement 223 = The left-hand side of an assignment must be a variable 224 = Missing semicolon 225 = Invalid parenthesized expression 230 = Syntax error on token "{0}", {1} expected before this token 231 = Syntax error on token "{0}", {1} expected after this token 232 = Syntax error on token "{0}", delete this token 233 = Syntax error on tokens, delete these tokens 234 = Syntax error on tokens, they can be merged to form {0} 235 = Syntax error on token "{0}", invalid {1} 236 = Syntax error on token(s), misplaced construct(s) 237 = Syntax error on tokens, {0} expected instead 238 = Syntax error on tokens, no accurate correction available 239 = Syntax error, unexpected {0} 240 = Syntax error, insert "{0}" to complete {1} 241 = Syntax error, insert "{0}" to complete scope 242 = Syntax error, insert "{0}" to complete phrase 250 = Unexpected end of file 251 = Invalid hex literal number 252 = Invalid octal literal number 253 = Invalid character constant 254 = Invalid escape sequence (valid ones are \\b \\t \\n \\f \\r \\" \\' \\\\ ) 255 = Invalid input 256 = Invalid unicode 257 = Invalid float literal number 258 = Null source string 259 = String literal is not properly closed by a double-quote 260 = Unexpected end of comment 261 = Non-externalized string literal; it should be followed by //$NON-NLS-$ 262 = Invalid digit (valid ones are 0..9) 263 = Invalid low surrogate: must be within 0xDC00 and 0xDFFF 264 = Invalid high surrogate: must be within 0xD800 and 0xDBFF 265 = Unnecessary $NON-NLS$ tag 266 = Invalid binary literal number (only '0' and '1' are expected) 267 = Binary literals can only be used with source level 1.7 or greater 268 = Underscores have to be located within digits 269 = Underscores can only be used with source level 1.7 or greater 280 = Discouraged access: {0} 300 = The interface {0} cannot define an initializer 301 = Duplicate modifier for the type {0} 302 = Illegal modifier for the class {0}; only public, abstract & final are permitted 303 = Illegal modifier for the interface {0}; only public & abstract are permitted 304 = Illegal modifier for the member class {0}; only public, protected, private, static, abstract & final are permitted 305 = Illegal modifier for the member interface {0}; only public, protected, private, static & abstract are permitted 306 = Illegal modifier for the local class {0}; only abstract or final is permitted 307 = Access restriction: {0} 308 = The class {0} can be either abstract or final, not both 309 = The interface member type {0} can only be public 310 = The member type {0} can only set one of public / protected / private 311 = The member type {0} cannot be declared static; static types can only be declared in static or top level types 312 = The type {0} cannot be the superclass of {1}; a superclass must be a class 313 = The type {1} cannot subclass the final class {0} 314 = Duplicate interface {0} for the type {1} 315 = The type {0} cannot be a superinterface of {1}; a superinterface must be an interface 316 = Cycle detected: the type {0} cannot extend/implement itself or one of its own member types 317 = Cycle detected: a cycle exists in the type hierarchy between {0} and {1} 318 = The nested type {0} cannot hide an enclosing type 319 = Duplicate nested type {0} 320 = No exception of type {0} can be thrown; an exception type must be a subclass of Throwable 321 = The package {0} collides with a type 322 = The type {1} collides with a package 323 = The type {1} is already defined 324 = The type {0} cannot be resolved. It is indirectly referenced from required .class files 325 = The public type {1} must be defined in its own file ###[obsolete] 326 = A package must be specified in {0} or a default package created 327 = The hierarchy of the type {0} is inconsistent 328 = The declared package "{1}" does not match the expected package "{0}" 329 = The type java.lang.Object cannot have a superclass or superinterfaces 330 = The type java.lang.Object must be a class 331 = Redundant superinterface {0} for the type {1}, already defined by {2} 332 = The type {0} should also implement hashCode() since it overrides Object.equals() 333 = The type {0} must be an abstract class to define abstract methods ###[obsolete] 330 = {0} cannot be resolved or is not a valid superclass ###[obsolete] 331 = Superclass {0} is not visible ###[obsolete] 332 = Superclass {0} is ambiguous ###[obsolete] 333 = Superclass {0} cannot be referenced using its binary name ###[obsolete] 334 = Superclass {0} is defined in an inherited type and an enclosing scope ###[obsolete] 335 = {0} cannot be resolved or is not a valid superinterface ###[obsolete] 336 = Superinterface {0} is not visible ###[obsolete] 337 = Superinterface {0} is ambiguous ###[obsolete] 338 = Superinterface {0} cannot be referenced using its binary name ###[obsolete] 339 = Superinterface {0} is defined in an inherited type and an enclosing scope 340 = Duplicate field {0}.{1} 341 = Duplicate modifier for the field {0} 342 = Illegal modifier for the field {0}; only public, protected, private, static, final, transient & volatile are permitted 343 = Illegal modifier for the interface field {0}.{1}; only public, static & final are permitted 344 = The field {0} can only set one of public / protected / private 345 = The field {0} can be either final or volatile, not both 346 = The field {0} cannot be declared static in a non-static inner type, unless initialized with a constant expression ###[obsolete] 350 = {2} cannot be resolved (or is not a valid type) for the field {1}.{0} ###[obsolete] 351 = The type {2} is not visible for the field {1}.{0} ###[obsolete] 352 = The type {2} is ambiguous for the field {1}.{0} ###[obsolete] 353 = The field type {2} cannot be referenced using its binary name ###[obsolete] 354 = The field type {2} is defined in an inherited type and an enclosing scope 355 = Duplicate method {0}({2}) in type {1} 356 = Illegal modifier for parameter {0}; only final is permitted 357 = Duplicate modifier for the method {1} in type {0} 358 = Illegal modifier for the method {0}; only public, protected, private, static, final, abstract, synchronized & native are permitted 359 = Illegal modifier for the interface method {0}; only public & abstract are permitted 360 = The method {1} in type {0} can only set one of public / protected / private 361 = The method {1} cannot be declared static; static methods can only be declared in a static or top level type 362 = The abstract method {1} in type {0} can only set a visibility modifier, one of public or protected 363 = The abstract method {1} in type {0} can only be defined by an abstract class 364 = void is an invalid type for the parameter {1} of the method {0} ###[obsolete] 365 = An array of void is an invalid type for the parameter {1} of the method {0} ###[obsolete] 366 = An array of void is an invalid return type for the method {0} 367 = The native method {1} cannot also be declared strictfp 368 = Duplicate modifier for parameter {0} 369 = Illegal modifier for the constructor in type {0}; only public, protected & private are permitted ###[obsolete] 370 = {2} cannot be resolved (or is not a valid type) for the parameter {1} of the method {0} ###[obsolete] 371 = The type {2} is not visible for the parameter {1} of the method {0} ###[obsolete] 372 = The type {2} is ambiguous for the parameter {1} of the method {0} ###[obsolete] 373 = The parameter type {2} cannot be referenced using its binary name ###[obsolete] 374 = The parameter type {2} is defined in an inherited type and an enclosing scope ###[obsolete] 375 = {1} cannot be resolved (or is not an exception type) for the method {0} ###[obsolete] 376 = The exception type {1} is not visible for the method {0} ###[obsolete] 377 = The exception type {1} is ambiguous for the method {0} ###[obsolete] 378 = The exception type {1} cannot be referenced using its binary name ###[obsolete] 379 = The exception type {1} is defined in an inherited type and an enclosing scope ###[obsolete] 380 = {1} cannot be resolved (or is not a valid return type) for the method {0} ###[obsolete] 381 = The return type {1} is not visible for the method {0} ###[obsolete] 382 = The return type {1} is ambiguous for the method {0} ###[obsolete] 383 = The return type {1} cannot be referenced using its binary name ###[obsolete] 384 = The return type {1} is defined in an inherited type and an enclosing scope 385 = The import {0} conflicts with a type defined in the same file 386 = The import {0} collides with another import statement 387 = Only a type can be imported. {0} resolves to a package 388 = The import {0} is never used 390 = The import {0} cannot be resolved ###[obsolete] 391 = The imported type {0} is not visible ###[obsolete] 392 = The imported type {0} is ambiguous ###[obsolete] 393 = The imported type {0} cannot be referenced using its binary name ###[obsolete] 394 = The imported type {0} is defined in an inherited type and an enclosing scope 391 = The static import {0} must be a field or member type 395 = Duplicate modifier for the variable {0} 396 = Illegal modifier for the variable {0}; only final is permitted ###[obsolete] 397 = Redundant null check: The variable {0} cannot be null at this location ###[obsolete] 398 = Null pointer access: The variable {0} can only be null at this location ###[obsolete] 399 = Potential null pointer access: The variable {0} may be null at this location 400 = The type {3} must implement the inherited abstract method {2}.{0}({1}) 401 = Cannot override the final method from {0} 402 = Exception {0} is not compatible with throws clause in {1} 403 = Exception {0} in throws clause of {1} is not compatible with {2} 404 = The return type is incompatible with {0} 405 = The inherited method {0} cannot hide the public abstract method in {1} 406 = This instance method cannot override the static method from {0} 407 = This static method cannot hide the instance method from {0} 408 = The static method {0} conflicts with the abstract method in {1} 409 = Cannot reduce the visibility of the inherited method from {0} 410 = The method {0} does not override the inherited method from {1} since it is private to a different package 411 = This class must implement the inherited abstract method {1}, but cannot override it since it is not visible from {0}. Either make the type abstract or make the inherited method visible 412 = The method {0} overrides a deprecated method from {1} 413 = The return type is incompatible with {0}, thus this interface cannot be implemented 414 = Exception {0} is not compatible with throws clause in {1}, thus this interface cannot be implemented 415 = The variable argument type {0} of the method {1} must be the last parameter 416 = The method {0} is overriding a method without making a super invocation 417 = The method {0}.{1}({2}) is overriding a synchronized method without being synchronized 418 = The type {3} must implement the inherited abstract method {2}.{0}({1}) to override {6}.{4}({5}) 419 = The return types are incompatible for the inherited methods {0} 420 = Code snippet support cannot find the class {0} 421 = Code snippet support cannot find the method {0}.{1}({2}) 422 = super cannot be used in the code snippet code 430 = Too many constants, the constant pool for {0} would exceed 65536 entries 431 = The type generates a string that requires more than 65535 bytes to encode in Utf8 format in the constant pool 432 = Too many fields for type {0}. Maximum is 65535 433 = Too many methods for type {0}. Maximum is 65535 434 = The synthetic method created to access {0}({1}) of type {2} has too many parameters 440 = 'assert' should not be used as an identifier, since it is a reserved keyword from source level 1.4 on 441 = 'enum' should not be used as an identifier, since it is a reserved keyword from source level 1.5 on 442 = Enum constants cannot be surrounded by parenthesis 450 = {0}{1} 451 = Null pointer access: The variable {0} can only be null at this location 452 = Potential null pointer access: The variable {0} may be null at this location 453 = Redundant null check: The variable {0} can only be null at this location 454 = Null comparison always yields false: The variable {0} can only be null at this location 455 = Redundant assignment: The variable {0} can only be null at this location 456 = instanceof always yields false: The variable {0} can only be null at this location 457 = Redundant null check: The variable {0} cannot be null at this location 458 = Null comparison always yields false: The variable {0} cannot be null at this location 459 = Potential null pointer access: This expression of type {0} may be null but requires auto-unboxing 461 = Null pointer access: This expression of type {0} is null but requires auto-unboxing 460 = Empty block should be documented ### DOC 462 = Invalid URL reference. Double quote the reference or use the href syntax 463 = Description expected after this reference 464 = Unexpected duplicated tag @{0} 465 = ''{0}'' visibility for malformed doc comments hides this ''{1}'' reference 466 = Invalid member type qualification 467 = Missing identifier 468 = Cannot make a static reference to the non-static type variable {0} 469 = Invalid param tag type parameter name 470 = Unexpected tag 471 = Missing tag for parameter {0} 472 = Missing parameter name 473 = Duplicate tag for parameter 474 = Parameter {0} is not declared 475 = Missing tag for return type 476 = Duplicate tag for return type 477 = Missing tag for declared exception {0} 478 = Missing class name 479 = Invalid class name 480 = Duplicate tag for thrown exception 481 = Exception {0} is not declared 482 = Missing reference 483 = Invalid reference 484 = Malformed link reference 485 = Invalid parameters declaration 486 = Missing comment for {0} declaration 487 = Invalid tag 488 = {0} cannot be resolved or is not a field 489 = The field {0} is not visible 490 = The field {0} is ambiguous 491 = The field {0}.{1} is deprecated 492 = The constructor {0}({1}) is undefined 493 = The constructor {0}({1}) is not visible 494 = The constructor {0}({1}) is ambiguous 495 = The constructor {0}({1}) is deprecated 496 = The method {1}({2}) is undefined for the type {0} 497 = The method {1}({2}) from the type {0} is not visible 498 = The method {1}({2}) is ambiguous for the type {0} 499 = The method {1}({2}) from the type {0} is deprecated 500 = Cannot invoke {1}({2}) on the primitive type {0} 501 = The method {1}({2}) in the type {0} is not applicable for the arguments ({3}) 502 = Cannot invoke {1}({2}) on the array type {0} 503 = {0} cannot be resolved to a type 504 = The type {0} is not visible 505 = The type {0} is ambiguous 506 = The type {0} is deprecated 507 = The nested type {0} cannot be referenced using its binary name 508 = The method {1} is defined in an inherited type and an enclosing scope 509 = The field {0} is defined in an inherited type and an enclosing scope 510 = The type {0} is defined in an inherited type and an enclosing scope 511 = {0} is an ambiguous method reference or is not a field 512 = Missing closing brace for inline tag 513 = Malformed reference (missing end space separator) 514 = Javadoc: 515 = Missing #: "{0}" 516 = Description expected after @{0} 517 = Only static field reference is allowed for @value tag 518 = Unexpected text 519 = Invalid param tag name ### GENERICS 520 = Duplicate type parameter {0} 521 = Cannot refer to the type parameter {0} as a supertype 522 = Cannot make a static reference to the non-static type {0} 523 = The type java.lang.Object cannot be declared as a generic 524 = The type {0} is not generic; it cannot be parameterized with arguments <{1}> 525 = Incorrect number of arguments for type {0}; it cannot be parameterized with arguments <{1}> 526 = Bound mismatch: The type {0} is not a valid substitute for the bounded parameter <{2} extends {3}> of the type {1} 527 = Method {0}({2}) has the same erasure {0}({3}) as another method in type {1} 528 = Illegal forward reference to type parameter {0} 529 = The type {0} is not an interface; it cannot be specified as a bounded parameter 530 = Type safety: The constructor {0}({1}) belongs to the raw type {0}. References to generic type {2} should be parameterized 531 = Type safety: The method {0}({1}) belongs to the raw type {2}. References to generic type {3} should be parameterized 532 = Type safety: The expression of type {0} needs unchecked conversion to conform to {1} 533 = Cannot use the type parameter {0} in a catch block 534 = Cannot use the parameterized type {0} either in catch block or throws clause 535 = Cannot create a generic array of {0} 536 = Type safety: The field {1} from the raw type {2} is assigned a value of type {0}. References to generic type {3} should be parameterized 537 = The type parameter {0} should not be bounded by the final type {1}. Final types cannot be further extended 538 = Inconsistent classfile encountered: The undefined type parameter {0} is referenced from within {1} 539 = The interface {2} cannot be implemented more than once with different arguments: {0} and {1} 540 = Bound mismatch: The constructor {0}({1}) of type {2} is not applicable for the arguments ({3}). The wildcard parameter {5} has no lower bound, and may actually be more restrictive than argument {4} 541 = Bound mismatch: The method {0}({1}) of type {2} is not applicable for the arguments ({3}). The wildcard parameter {5} has no lower bound, and may actually be more restrictive than argument {4} 542 = Bound mismatch: Cannot assign expression of type {0} to wildcard type {1}. The wildcard type has no lower bound, and may actually be more restrictive than expression type 543 = Bound mismatch: The generic method {0}({1}) of type {2} is not applicable for the arguments ({3}). The inferred type {4} is not a valid substitute for the bounded parameter <{5} extends {6}> 544 = Bound mismatch: The generic constructor {0}({1}) of type {2} is not applicable for the arguments ({3}). The inferred type {4} is not a valid substitute for the bounded parameter <{5} extends {6}> 545 = Type safety: Unchecked cast from {0} to {1} 546 = Cannot perform instanceof check against parameterized type {0}. Use the form {1} instead since further generic type information will be erased at runtime 547 = Cannot perform instanceof check against type parameter {0}. Use its erasure {1} instead since further generic type information will be erased at runtime 548 = The method {0}({1}) of type {2} is not generic; it cannot be parameterized with arguments <{3}> 549 = Incorrect number of type arguments for generic method <{3}>{0}({1}) of type {2}; it cannot be parameterized with arguments <{4}> 550 = The parameterized method <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4}) 551 = The constructor {0}({1}) of type {2} is not generic; it cannot be parameterized with arguments <{3}> 552 = Incorrect number of type arguments for generic constructor <{3}>{0}({1}) of type {2}; it cannot be parameterized with arguments <{4}> 553 = The parameterized constructor <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4}) 554 = The method {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}> 555 = The constructor {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}> 556 = The type {1} cannot extend or implement {0}. A supertype may not specify any wildcard 557 = The generic class {0} may not subclass java.lang.Throwable 558 = Illegal class literal for the type parameter {0} 559 = Type safety: The return type {0} for {1}({2}) from the type {3} needs unchecked conversion to conform to {4} from the type {5} 560 = Name clash: The method {0}({1}) of type {2} has the same erasure as {0}({3}) of type {4} but does not override it 561 = The member type {0}<{1}> must be qualified with a parameterized type, since it is not static 562 = The member type {0} must be parameterized, since it is qualified with a parameterized type 563 = The member type {0} cannot be qualified with a parameterized type, since it is static. Remove arguments from qualifying type {1} ###[obsolete] 564 = Bound conflict: {0} is inherited with conflicting arguments 565 = Duplicate methods named {0} with the parameters ({2}) and ({3}) are defined by the type {1} 566 = Cannot allocate the member type {0} using a parameterized compound name; use its simple name and an enclosing instance of type {1} 567 = Duplicate bound {0} 568 = The array type {0} cannot be used as a type parameter bound 569 = Type safety: Unchecked invocation {0}({3}) of the generic constructor {0}({1}) of type {2} 570 = Type safety: Unchecked invocation {0}({3}) of the generic method {0}({1}) of type {2} 571 = The type parameter {0} is hiding the type {1} 572 = {0} is a raw type. References to generic type {1} should be parameterized 573 = Cannot specify any additional bound {0} when first bound is a type parameter 574 = Type safety: A generic array of {0} is created for a varargs parameter 575 = Illegal qualified access from the type parameter {0} 576 = The nested type {0} is hiding the type parameter {1} of type {2} 577 = The nested type {0} is hiding the type parameter {1} of the generic method {2}({3}) of type {4} 578 = Wildcard is not allowed at this location 579 = Unused type arguments for the non generic method {0}({1}) of type {2}; it should not be parameterized with arguments <{3}> 583 = Duplicate methods named {0} with the parameters ({1}) and ({2}) are inherited from the types {3} and {4} 584 = Name clash: The method {0}({1}) of type {2} has the same erasure as {0}({3}) of type {4} but does not hide it ### FOREACH 580 = Type mismatch: cannot convert from element type {0} to {1} 581 = Can only iterate over an array or an instance of java.lang.Iterable 582 = Can only iterate over an array or an instance of java.util.Collection 585 = Type safety: Elements of type {0} need unchecked conversion to conform to {1} ### SOURCE LEVEL 590 = Syntax error, type parameters are only available if source level is 1.5 or greater 591 = Syntax error, static imports are only available if source level is 1.5 or greater 592 = Syntax error, 'for each' statements are only available if source level is 1.5 or greater 593 = Syntax error, parameterized types are only available if source level is 1.5 or greater 594 = Syntax error, enum declarations are only available if source level is 1.5 or greater 595 = Syntax error, varargs are only available if source level is 1.5 or greater 596 = Syntax error, annotations are only available if source level is 1.5 or greater 597 = Syntax error, annotation declarations are only available if source level is 1.5 or greater 598 = Syntax error, annotation declaration cannot have type parameters 599 = Syntax error, enum declaration cannot have type parameters ### ANNOTATIONS 600 = Illegal modifier for the annotation attribute {0}.{1}; only public & abstract are permitted 601 = Extended dimensions are illegal in an annotation attribute declaration 602 = Package annotations must be in file package-info.java 603 = Illegal modifier for the annotation type {0}; only public & abstract are permitted 604 = Illegal modifier for the member annotation type {0}; only public, protected, private, static & abstract are permitted 605 = Invalid type {0} for the annotation attribute {2}.{1}; only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof 606 = Cycle detected: the annotation type {0} cannot contain attributes of the annotation type itself 607 = Cycle detected: a cycle exists between annotation attributes of {0} and {1} 608 = Duplicate annotation @{0} 609 = The annotation @{0} must define the attribute {1} 610 = Duplicate attribute {0} in annotation @{1} 611 = The attribute {0} is undefined for the annotation type {1} 612 = The value for annotation attribute {0}.{1} must be a class literal 613 = The value for annotation attribute {0}.{1} must be a constant expression ###[obsolete] 614 = The annotation field {0}.{1} must be initialized with a constant expression 615 = Illegal modifier for the annotation field {0}.{1}; only public, static & final are permitted 616 = The annotation type {0} cannot override the method {1}.{2}({3}) 617 = Annotation attributes cannot have parameters 618 = Annotation attributes cannot be generic 619 = Annotation type declaration cannot have an explicit superclass 620 = Annotation type declaration cannot have explicit superinterfaces 621 = Duplicate element {0} specified in annotation @{1} 622 = The annotation @{0} is disallowed for this location 623 = The method {0}({1}) of type {2} must override a superclass method 624 = Annotation type declaration cannot have a constructor 625 = The value for annotation attribute {0}.{1} must be some @{2} annotation 626 = The annotation type {0} should not be used as a superinterface for {1} 627 = The method {0}({1}) of type {2} should be tagged with @Override since it actually overrides a superclass method 628 = The deprecated field {0}.{1} should be annotated with @Deprecated 629 = The deprecated method {0}({1}) of type {2} should be annotated with @Deprecated 630 = The deprecated type {0} should be annotated with @Deprecated 631 = Unsupported @SuppressWarnings("{0}") 632 = The value for annotation attribute {0}.{1} must be an array initializer 633 = The value for annotation attribute {0}.{1} must be an enum constant expression 634 = The method {0}({1}) of type {2} must override or implement a supertype method 635 = Unnecessary @SuppressWarnings("{0}") 636 = The method {0}({1}) of type {2} should be tagged with @Override since it actually overrides a superinterface method ### MORE GENERICS 660 = Unused type arguments for the non generic constructor {0}({1}) of type {2}; it should not be parameterized with arguments <{3}> 661 = Unused type parameter {0} ### MORE TYPE RELATED 662 = Illegal attempt to create arrays of union types ### NULL ANALYSIS FOR OTHER EXPRESSIONS 670 = Null comparison always yields false: this expression cannot be null 671 = Redundant null check: this expression cannot be null 672 = Null pointer access: This expression can only be null 673 = Potential null pointer access: This expression may be null ### CORRUPTED BINARIES 700 = The class file {0} contains a signature ''{1}'' ill-formed at position {2} ### CORRUPTED SOURCES 701 = Cannot read the source from {0}; either the file uses a different encoding than {1} or it is corrupted 702 = Cannot read the source from {0} due to internal exception {1} ### AUTOBOXING 720 = The expression of type {0} is boxed into {1} 721 = The expression of type {0} is unboxed into {1} ### ENUMS 750 = Illegal modifier for the enum {0}; only public is permitted 751 = Illegal modifier for the enum constant {0}; no modifier is allowed ###[obsolete] 752 = Illegal modifier for the local enum {0}; only abstract is permitted 753 = Illegal modifier for the member enum {0}; only public, protected, private & static are permitted 754 = The enum {1} already defines the method {0}({2}) implicitly 755 = The qualified case label {0}.{1} must be replaced with the unqualified enum constant {1} 756 = The type {1} may not subclass {0} explicitly 757 = Cannot invoke super constructor from enum constructor {0}({1}) 758 = The enum {2} can only define the abstract method {0}({1}) if it also defines enum constants with corresponding implementations 759 = The field {0}.{1} cannot be referenced from an enum case label; only enum constants can be used in enum switch 760 = Illegal modifier for the enum constructor; only private is permitted. 761 = The enum constant {1} needs a corresponding case label in this enum switch on {0} 762 = Cannot refer to the static enum field {0}.{1} within an initializer 763 = The enum constant {2} must implement the abstract method {0}({1}) 764 = The enum constant {0} cannot define abstract methods 765 = The method {1} cannot be abstract in the enum constant {0} 766 = The switch over the enum type {0} should have a default case 767 = The switch statement should have a default case 768 = The enum constant {1} should have a corresponding case label in this enum switch on {0}. To suppress this problem, add a comment //$CASES-OMITTED$ on the line above the ''default:'' 769 = The local variable {0} may not have been initialized. Note that a problem regarding missing ''default:'' on ''switch'' has been suppressed, which is perhaps related to this problem 770 = The blank final field {0} may not have been initialized. Note that a problem regarding missing ''default:'' on ''switch'' has been suppressed, which is perhaps related to this problem 771 = This method must return a result of type {0}. Note that a problem regarding missing ''default:'' on ''switch'' has been suppressed, which is perhaps related to this problem ### VARARGS 800 = Extended dimensions are illegal for a variable argument 801 = The argument of type {0} should explicitly be cast to {1} for the invocation of the varargs method {2}({3}) from type {4}. It could alternatively be cast to {5} for a varargs invocation 802 = The argument of type {0} should explicitly be cast to {1} for the invocation of the varargs constructor {2}({3}). It could alternatively be cast to {4} for a varargs invocation 803 = Varargs methods should only override or be overridden by other varargs methods unlike {2}.{0}({1}) and {4}.{0}({3}) 804 = @SafeVarargs annotation cannot be applied to fixed arity method {0} 805 = @SafeVarargs annotation cannot be applied to non-final instance method {0} 806 = Type safety: Potential heap pollution via varargs parameter {0} 807 = The method {0}({1}) of type {2} is not applicable as the formal varargs element type {3} is not accessible here 808 = The constructor {0}({1}) of type {2} is not applicable as the formal varargs element type {3} is not accessible here ### GENERIC JAVADOC 850 = Bound mismatch: The generic method {0}({1}) of type {2} is not applicable for the arguments ({3}). The inferred type {4} is not a valid substitute for the bounded parameter <{5} extends {6}> 851 = The method {0}({1}) of type {2} is not generic; it cannot be parameterized with arguments <{3}> 852 = Incorrect number of type arguments for generic method <{3}>{0}({1}) of type {2}; it cannot be parameterized with arguments <{4}> 853 = The parameterized method <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4}) 854 = The method {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}> 855 = Bound mismatch: The generic constructor {0}({1}) of type {2} is not applicable for the arguments ({3}). The inferred type {4} is not a valid substitute for the bounded parameter <{5} extends {6}> 856 = The constructor {0}({1}) of type {2} is not generic; it cannot be parameterized with arguments <{3}> 857 = Incorrect number of type arguments for generic constructor <{3}>{0}({1}) of type {2}; it cannot be parameterized with arguments <{4}> 858 = The parameterized constructor <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4}) 859 = The constructor {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}> ### Java 7 870 = The parameter {0} of a multi-catch block cannot be assigned 871 = The resource type {0} does not implement java.lang.AutoCloseable 872 = The resource {0} of a try-with-resources statement cannot be assigned 873 = The exception {0} is already caught by the alternative {1} 874 = Resource specification not allowed here for source level below 1.7 875 = Multi-catch parameters are not allowed for source level below 1.7 876 = Invocation of polymorphic methods not allowed for source level below 1.7 877 = Cannot switch on a value of type {0}. Only convertible int values, strings or enum variables are permitted 878 = Cannot infer type arguments for {0} 879 = Explicit type arguments cannot be used with '<>' in an allocation expression 880 = '<>' cannot be used with anonymous classes 881 = Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum variables are permitted 882 = Unhandled exception type {0} thrown by automatic close() invocation on {1} 883 = '<>' operator is not allowed for source level below 1.7 884 = Redundant specification of type arguments <{0}> 885 = Potential resource leak: ''{0}'' may not be closed 886 = Potential resource leak: ''{0}'' may not be closed at this location 887 = Resource leak: ''{0}'' is never closed 888 = Resource leak: ''{0}'' is not closed at this location 889 = Resource ''{0}'' should be managed by try-with-resource 890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted ### NULL ANNOTATIONS 910 = Null type mismatch: required ''@{0} {1}'' but the provided value is null 911 = Null type mismatch: required ''@{0} {1}'' but the provided value is inferred as @{2} 912 = Null type safety: The expression of type {0} needs unchecked conversion to conform to ''@{1} {2}'' 913 = A default nullness annotation has not been specified for the package {0} 914 = The return type is incompatible with the @{1} return from {0} 915 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2} 916 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter 917 = Missing non-null annotation: inherited method from {0} declares this parameter as @{1} 918 = Missing nullable annotation: inherited method from {1} declares this parameter as @{2} 919 = Potential null pointer access: The method {0} may return null 920 = Redundant null check: The method {0} cannot return null 921 = The method {0} from {1} cannot implement the corresponding method from {2} due to incompatible nullness constraints 922 = The nullness annotation is redundant with a default that applies to this location 923 = The nullness annotation @{0} is not applicable for the primitive type {1} 924 = Potential null pointer access: The field {0} is declared as @{1} 925 = Nullness default is redundant with the global default 926 = Nullness default is redundant with a default specified for the enclosing package {0} 927 = Nullness default is redundant with a default specified for the enclosing type {0} 928 = Nullness default is redundant with a default specified for the enclosing method {0} 929 = Contradictory null specification; only one of @{0} and @{1} can be specified at any location 930 = A default nullness annotation has not been specified for the type {0} 931 = Redundant null check: The variable {0} is specified as @{1} 932 = Null comparison always yields false: The variable {0} is specified as @{1} 933 = Null type mismatch: required ''@{0} {1}'' but the provided value is specified as @{2} 934 = The @{0} field {1} may not have been initialized 935 = The @{0} field {1} may not have been initialized. Note that a problem regarding missing ''default:'' on ''switch'' has been suppressed, which is perhaps related to this problem 936 = Null comparison always yields false: The method {0} cannot return null 937 = Redundant null check: The field {0} is declared as @{1} 938 = Null comparison always yields false: The field {0} is declared as @{1} 939 = The default ''@{0}'' conflicts with the inherited ''@{1}'' annotation in the overridden method from {2} 940 = Conflict between inherited null annotations ''@{0}'' declared in {1} versus ''@{2}'' declared in {3} ### ELABORATIONS ## Access restrictions 78592 = The type {1} is not accessible due to restriction on classpath entry {0} 78593 = The type {1} is not accessible due to restriction on required project {0} 78594 = The type {1} is not accessible due to restriction on required library {0} 78596 = The field {1} from the type {2} is not accessible due to restriction on classpath entry {0} 78597 = The field {1} from the type {2} is not accessible due to restriction on required project {0} 78598 = The field {1} from the type {2} is not accessible due to restriction on required library {0} 78600 = The constructor {1} is not accessible due to restriction on classpath entry {0} 78601 = The constructor {1} is not accessible due to restriction on required project {0} 78602 = The constructor {1} is not accessible due to restriction on required library {0} 78604 = The method {1} from the type {2} is not accessible due to restriction on classpath entry {0} 78606 = The method {1} from the type {2} is not accessible due to restriction on required library {0} 78605 = The method {1} from the type {2} is not accessible due to restriction on required project {0} ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java0000644000175000001440000000225712212041344032236 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; public interface ProblemSeverities { final int Ignore = 256; // during handling only final int Warning = 0; // during handling only final int Error = 1; // when bit is set: problem is error, if not it is a warning final int AbortCompilation = 2; final int AbortCompilationUnit = 4; final int AbortType = 8; final int AbortMethod = 16; final int Abort = 30; // 2r11110 final int Optional = 32; // when bit is set: problem was configurable final int SecondaryError = 64; final int Fatal = 128; // when bit is set: problem was either a mandatory error, or an optional+treatOptionalErrorAsFatal } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java0000644000175000001440000000165312212041344032364 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; /* * Special unchecked exception type used * to denote implementation that should never be reached. * * (internal only) */ public class ShouldNotImplement extends RuntimeException { private static final long serialVersionUID = 2669970476264283736L; // backward compatible public ShouldNotImplement(String message) { super(message); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java0000644000175000001440000000733212212041344032040 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.util.Util; /* * Special unchecked exception type used * to abort from the compilation process * * should only be thrown from within problem handlers. */ public class AbortCompilation extends RuntimeException { public CompilationResult compilationResult; public Throwable exception; public CategorizedProblem problem; /* special fields used to abort silently (e.g. when canceling build process) */ public boolean isSilent; public RuntimeException silentException; private static final long serialVersionUID = -2047226595083244852L; // backward compatible public AbortCompilation() { // empty } public AbortCompilation(CompilationResult compilationResult, CategorizedProblem problem) { this(); this.compilationResult = compilationResult; this.problem = problem; } public AbortCompilation(CompilationResult compilationResult, Throwable exception) { this(); this.compilationResult = compilationResult; this.exception = exception; } public AbortCompilation(boolean isSilent, RuntimeException silentException) { this(); this.isSilent = isSilent; this.silentException = silentException; } public String getMessage() { String message = super.getMessage(); StringBuffer buffer = new StringBuffer(message == null ? Util.EMPTY_STRING : message); if (this.problem != null) { buffer.append(this.problem); } else if (this.exception != null) { message = this.exception.getMessage(); buffer.append(message == null ? Util.EMPTY_STRING : message); } else if (this.silentException != null) { message = this.silentException.getMessage(); buffer.append(message == null ? Util.EMPTY_STRING : message); } return String.valueOf(buffer); } public void updateContext(InvocationSite invocationSite, CompilationResult unitResult) { if (this.problem == null) return; if (this.problem.getSourceStart() != 0 || this.problem.getSourceEnd() != 0) return; this.problem.setSourceStart(invocationSite.sourceStart()); this.problem.setSourceEnd(invocationSite.sourceEnd()); int[] lineEnds = unitResult.getLineSeparatorPositions(); this.problem.setSourceLineNumber(Util.getLineNumber(invocationSite.sourceStart(), lineEnds, 0, lineEnds.length-1)); this.compilationResult = unitResult; } public void updateContext(ASTNode astNode, CompilationResult unitResult) { if (this.problem == null) return; if (this.problem.getSourceStart() != 0 || this.problem.getSourceEnd() != 0) return; this.problem.setSourceStart(astNode.sourceStart()); this.problem.setSourceEnd(astNode.sourceEnd()); int[] lineEnds = unitResult.getLineSeparatorPositions(); this.problem.setSourceLineNumber(Util.getLineNumber(astNode.sourceStart(), lineEnds, 0, lineEnds.length-1)); this.compilationResult = unitResult; } public String getKey() { StringBuffer buffer = new StringBuffer(); if (this.problem != null) { buffer.append(this.problem); } return String.valueOf(buffer); } } ././@LongLink0000644000000000000000000000015012251602427011637 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.j0000644000175000001440000001746612212041344032350 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; import java.util.Enumeration; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.IProblemFactory; import org.eclipse.jdt.internal.compiler.util.HashtableOfInt; import org.eclipse.jdt.internal.compiler.util.Util; public class DefaultProblemFactory implements IProblemFactory { public HashtableOfInt messageTemplates; private Locale locale; private static HashtableOfInt DEFAULT_LOCALE_TEMPLATES; private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ private final static char[] FIRST_ARGUMENT = "{0}".toCharArray(); //$NON-NLS-1$ public DefaultProblemFactory() { this(Locale.getDefault()); } /** * @param loc the locale used to get the right message */ public DefaultProblemFactory(Locale loc) { setLocale(loc); } /** * Answer a new IProblem created according to the parameters value *
    *
  • originatingFileName the name of the file name from which the problem is originated *
  • problemId the problem id *
  • problemArguments the fully qualified arguments recorded inside the problem *
  • messageArguments the arguments needed to set the error message (shorter names than problemArguments ones) *
  • severity the severity of the problem *
  • startPosition the starting position of the problem *
  • endPosition the end position of the problem *
  • lineNumber the line on which the problem occured *
* @param originatingFileName char[] * @param problemId int * @param problemArguments String[] * @param messageArguments String[] * @param severity int * @param startPosition int * @param endPosition int * @param lineNumber int * @return CategorizedProblem */ public CategorizedProblem createProblem( char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber, int columnNumber) { return new DefaultProblem( originatingFileName, this.getLocalizedMessage(problemId, messageArguments), problemId, problemArguments, severity, startPosition, endPosition, lineNumber, columnNumber); } public CategorizedProblem createProblem( char[] originatingFileName, int problemId, String[] problemArguments, int elaborationId, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber, int columnNumber) { return new DefaultProblem( originatingFileName, this.getLocalizedMessage(problemId, elaborationId, messageArguments), problemId, problemArguments, severity, startPosition, endPosition, lineNumber, columnNumber); } private final static int keyFromID(int id) { return id + 1; // keys are offsetted by one in table, since it cannot handle 0 key } /** * Answer the locale used to retrieve the error messages * @return java.util.Locale */ public Locale getLocale() { return this.locale; } public void setLocale(Locale locale) { if (locale == this.locale) return; this.locale = locale; if (Locale.getDefault().equals(locale)){ if (DEFAULT_LOCALE_TEMPLATES == null){ DEFAULT_LOCALE_TEMPLATES = loadMessageTemplates(locale); } this.messageTemplates = DEFAULT_LOCALE_TEMPLATES; } else { this.messageTemplates = loadMessageTemplates(locale); } } public final String getLocalizedMessage(int id, String[] problemArguments) { return getLocalizedMessage(id, 0, problemArguments); } public final String getLocalizedMessage(int id, int elaborationId, String[] problemArguments) { String rawMessage = (String) this.messageTemplates.get(keyFromID(id & IProblem.IgnoreCategoriesMask)); if (rawMessage == null) { return "Unable to retrieve the error message for problem id: " //$NON-NLS-1$ + (id & IProblem.IgnoreCategoriesMask) + ". Check compiler resources."; //$NON-NLS-1$ } char[] message = rawMessage.toCharArray(); if (elaborationId != 0) { String elaboration = (String) this.messageTemplates.get(keyFromID(elaborationId)); if (elaboration == null) { return "Unable to retrieve the error message elaboration for elaboration id: " //$NON-NLS-1$ + elaborationId + ". Check compiler resources."; //$NON-NLS-1$ } message = CharOperation.replace(message, FIRST_ARGUMENT, elaboration.toCharArray()); } // for compatibility with MessageFormat which eliminates double quotes in original message message = CharOperation.replace(message, DOUBLE_QUOTES, SINGLE_QUOTE); if (problemArguments == null) { return new String(message); } int length = message.length; int start = 0; int end = length; StringBuffer output = null; if ((id & IProblem.Javadoc) != 0) { output = new StringBuffer(10+length+problemArguments.length*20); output.append((String) this.messageTemplates.get(keyFromID(IProblem.JavadocMessagePrefix & IProblem.IgnoreCategoriesMask))); } while (true) { if ((end = CharOperation.indexOf('{', message, start)) > -1) { if (output == null) output = new StringBuffer(length+problemArguments.length*20); output.append(message, start, end - start); if ((start = CharOperation.indexOf('}', message, end + 1)) > -1) { try { output.append(problemArguments[CharOperation.parseInt(message, end + 1, start - end - 1)]); } catch (NumberFormatException nfe) { output.append(message, end + 1, start - end); } catch (ArrayIndexOutOfBoundsException e) { return "Cannot bind message for problem (id: " //$NON-NLS-1$ + (id & IProblem.IgnoreCategoriesMask) + ") \"" //$NON-NLS-1$ + new String(message) + "\" with arguments: {" //$NON-NLS-1$ + Util.toString(problemArguments) +"}"; //$NON-NLS-1$ } start++; } else { output.append(message, end, length); break; } } else { if (output == null) { return new String(message); } output.append(message, start, length - start); break; } } // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=120410 return new String(output.toString()); } /** * @param problem CategorizedProblem * @return String */ public final String localizedMessage(CategorizedProblem problem) { return getLocalizedMessage(problem.getID(), problem.getArguments()); } /** * This method initializes the MessageTemplates class variable according * to the current Locale. * @param loc Locale * @return HashtableOfInt */ public static HashtableOfInt loadMessageTemplates(Locale loc) { ResourceBundle bundle = null; String bundleName = "org.eclipse.jdt.internal.compiler.problem.messages"; //$NON-NLS-1$ try { bundle = ResourceBundle.getBundle(bundleName, loc); } catch(MissingResourceException e) { System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + loc); //$NON-NLS-1$//$NON-NLS-2$ throw e; } HashtableOfInt templates = new HashtableOfInt(700); Enumeration keys = bundle.getKeys(); while (keys.hasMoreElements()) { String key = (String)keys.nextElement(); try { int messageID = Integer.parseInt(key); templates.put(keyFromID(messageID), bundle.getString(key)); } catch(NumberFormatException e) { // key ill-formed } catch (MissingResourceException e) { // available ID } } return templates; } } ././@LongLink0000644000000000000000000000014712251602427011645 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.ja0000644000175000001440000000264212212041344032350 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; import java.io.IOException; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; /* * Special unchecked exception type used * to abort from the compilation process * * should only be thrown from within problem handlers. */ public class AbortCompilationUnit extends AbortCompilation { private static final long serialVersionUID = -4253893529982226734L; // backward compatible public String encoding; public AbortCompilationUnit(CompilationResult compilationResult, CategorizedProblem problem) { super(compilationResult, problem); } /** * Used to surface encoding issues when reading sources */ public AbortCompilationUnit(CompilationResult compilationResult, IOException exception, String encoding) { super(compilationResult, exception); this.encoding = encoding; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java0000644000175000001440000122472712212041344031727 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Benjamin Muskalla - Contribution for bug 239066 * Stephan Herrmann - Contributions for * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used * bug 338303 - Warning about Redundant assignment conflicts with definite assignment * bug 349326 - [1.7] new warning for missing try-with-resources * bug 186342 - [compiler][null] Using annotations for null checking * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * bug 365662 - [compiler][null] warn on contradictory and redundant null annotations * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults * bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations * bug 374605 - Unreasonable warning for enum-based switch statements * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 376053 - [compiler][resource] Strange potential resource leak problems * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated * bug 393719 - [compiler] inconsistent warnings on iteration variables * bug 331649 - [compiler][null] consider null annotations for fields * bug 382789 - [compiler][null] warn when syntactically-nonnull expression is compared against null * bug 376590 - Private fields with @Inject are ignored by unused field validation * bug 400761 - [compiler][null] null may be return as boolean without a diagnostic * bug 395681 - [compiler] Improve simulation of javac6 behavior from bug 317719 after fixing bug 388795 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; import java.io.CharConversionException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Iterator; import java.util.List; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; import org.eclipse.jdt.internal.compiler.IProblemFactory; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ArrayReference; import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.BranchStatement; import org.eclipse.jdt.internal.compiler.ast.CaseStatement; import org.eclipse.jdt.internal.compiler.ast.CastExpression; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression; import org.eclipse.jdt.internal.compiler.ast.LabeledStatement; import org.eclipse.jdt.internal.compiler.ast.Literal; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.Reference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.SwitchStatement; import org.eclipse.jdt.internal.compiler.ast.ThisReference; 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.ast.UnaryExpression; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; 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.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants; import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; import org.eclipse.jdt.internal.compiler.parser.Scanner; import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; import org.eclipse.jdt.internal.compiler.util.Messages; public class ProblemReporter extends ProblemHandler { public ReferenceContext referenceContext; private Scanner positionScanner; private final static byte // TYPE_ACCESS = 0x0, FIELD_ACCESS = 0x4, CONSTRUCTOR_ACCESS = 0x8, METHOD_ACCESS = 0xC; public ProblemReporter(IErrorHandlingPolicy policy, CompilerOptions options, IProblemFactory problemFactory) { super(policy, options, problemFactory); } private static int getElaborationId (int leadProblemId, byte elaborationVariant) { return leadProblemId << 8 | elaborationVariant; // leadProblemId comes into the higher order bytes } public static int getIrritant(int problemID) { switch(problemID){ case IProblem.MaskedCatch : return CompilerOptions.MaskedCatchBlock; case IProblem.UnusedImport : return CompilerOptions.UnusedImport; case IProblem.MethodButWithConstructorName : return CompilerOptions.MethodWithConstructorName; case IProblem.OverridingNonVisibleMethod : return CompilerOptions.OverriddenPackageDefaultMethod; case IProblem.IncompatibleReturnTypeForNonInheritedInterfaceMethod : case IProblem.IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod : return CompilerOptions.IncompatibleNonInheritedInterfaceMethod; case IProblem.OverridingDeprecatedMethod : case IProblem.UsingDeprecatedType : case IProblem.UsingDeprecatedMethod : case IProblem.UsingDeprecatedConstructor : case IProblem.UsingDeprecatedField : return CompilerOptions.UsingDeprecatedAPI; case IProblem.LocalVariableIsNeverUsed : return CompilerOptions.UnusedLocalVariable; case IProblem.ArgumentIsNeverUsed : return CompilerOptions.UnusedArgument; case IProblem.NoImplicitStringConversionForCharArrayExpression : return CompilerOptions.NoImplicitStringConversion; case IProblem.NeedToEmulateFieldReadAccess : case IProblem.NeedToEmulateFieldWriteAccess : case IProblem.NeedToEmulateMethodAccess : case IProblem.NeedToEmulateConstructorAccess : return CompilerOptions.AccessEmulation; case IProblem.NonExternalizedStringLiteral : case IProblem.UnnecessaryNLSTag : return CompilerOptions.NonExternalizedString; case IProblem.UseAssertAsAnIdentifier : return CompilerOptions.AssertUsedAsAnIdentifier; case IProblem.UseEnumAsAnIdentifier : return CompilerOptions.EnumUsedAsAnIdentifier; case IProblem.NonStaticAccessToStaticMethod : case IProblem.NonStaticAccessToStaticField : return CompilerOptions.NonStaticAccessToStatic; case IProblem.IndirectAccessToStaticMethod : case IProblem.IndirectAccessToStaticField : case IProblem.IndirectAccessToStaticType : return CompilerOptions.IndirectStaticAccess; case IProblem.AssignmentHasNoEffect: return CompilerOptions.NoEffectAssignment; case IProblem.UnusedPrivateConstructor: case IProblem.UnusedPrivateMethod: case IProblem.UnusedPrivateField: case IProblem.UnusedPrivateType: return CompilerOptions.UnusedPrivateMember; case IProblem.LocalVariableHidingLocalVariable: case IProblem.LocalVariableHidingField: case IProblem.ArgumentHidingLocalVariable: case IProblem.ArgumentHidingField: return CompilerOptions.LocalVariableHiding; case IProblem.FieldHidingLocalVariable: case IProblem.FieldHidingField: return CompilerOptions.FieldHiding; case IProblem.TypeParameterHidingType: case IProblem.TypeHidingTypeParameterFromType: case IProblem.TypeHidingTypeParameterFromMethod: case IProblem.TypeHidingType: return CompilerOptions.TypeHiding; case IProblem.PossibleAccidentalBooleanAssignment: return CompilerOptions.AccidentalBooleanAssign; case IProblem.SuperfluousSemicolon: case IProblem.EmptyControlFlowStatement: return CompilerOptions.EmptyStatement; case IProblem.UndocumentedEmptyBlock: return CompilerOptions.UndocumentedEmptyBlock; case IProblem.UnnecessaryCast: case IProblem.UnnecessaryInstanceof: return CompilerOptions.UnnecessaryTypeCheck; case IProblem.FinallyMustCompleteNormally: return CompilerOptions.FinallyBlockNotCompleting; case IProblem.UnusedMethodDeclaredThrownException: case IProblem.UnusedConstructorDeclaredThrownException: return CompilerOptions.UnusedDeclaredThrownException; case IProblem.UnqualifiedFieldAccess: return CompilerOptions.UnqualifiedFieldAccess; case IProblem.UnnecessaryElse: return CompilerOptions.UnnecessaryElse; case IProblem.UnsafeRawConstructorInvocation: case IProblem.UnsafeRawMethodInvocation: case IProblem.UnsafeTypeConversion: case IProblem.UnsafeElementTypeConversion: case IProblem.UnsafeRawFieldAssignment: case IProblem.UnsafeGenericCast: case IProblem.UnsafeReturnTypeOverride: case IProblem.UnsafeRawGenericMethodInvocation: case IProblem.UnsafeRawGenericConstructorInvocation: case IProblem.UnsafeGenericArrayForVarargs: case IProblem.PotentialHeapPollutionFromVararg: return CompilerOptions.UncheckedTypeOperation; case IProblem.RawTypeReference: return CompilerOptions.RawTypeReference; case IProblem.MissingOverrideAnnotation: case IProblem.MissingOverrideAnnotationForInterfaceMethodImplementation: return CompilerOptions.MissingOverrideAnnotation; case IProblem.FieldMissingDeprecatedAnnotation: case IProblem.MethodMissingDeprecatedAnnotation: case IProblem.TypeMissingDeprecatedAnnotation: return CompilerOptions.MissingDeprecatedAnnotation; case IProblem.FinalBoundForTypeVariable: return CompilerOptions.FinalParameterBound; case IProblem.MissingSerialVersion: return CompilerOptions.MissingSerialVersion; case IProblem.ForbiddenReference: return CompilerOptions.ForbiddenReference; case IProblem.DiscouragedReference: return CompilerOptions.DiscouragedReference; case IProblem.MethodVarargsArgumentNeedCast : case IProblem.ConstructorVarargsArgumentNeedCast : return CompilerOptions.VarargsArgumentNeedCast; case IProblem.NullLocalVariableReference: case IProblem.NullableFieldReference: case IProblem.NullExpressionReference: case IProblem.NullUnboxing: return CompilerOptions.NullReference; case IProblem.PotentialNullLocalVariableReference: case IProblem.PotentialNullMessageSendReference: case IProblem.PotentialNullExpressionReference: case IProblem.PotentialNullUnboxing: return CompilerOptions.PotentialNullReference; case IProblem.RedundantLocalVariableNullAssignment: case IProblem.RedundantNullCheckOnNonNullLocalVariable: case IProblem.RedundantNullCheckOnNullLocalVariable: case IProblem.NonNullLocalVariableComparisonYieldsFalse: case IProblem.NullLocalVariableComparisonYieldsFalse: case IProblem.NullLocalVariableInstanceofYieldsFalse: case IProblem.RedundantNullCheckOnNonNullExpression: case IProblem.NonNullExpressionComparisonYieldsFalse: case IProblem.RedundantNullCheckOnNonNullMessageSend: case IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable: case IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse: case IProblem.NonNullMessageSendComparisonYieldsFalse: case IProblem.RedundantNullCheckOnNonNullSpecdField: case IProblem.NonNullSpecdFieldComparisonYieldsFalse: return CompilerOptions.RedundantNullCheck; case IProblem.RequiredNonNullButProvidedNull: case IProblem.RequiredNonNullButProvidedSpecdNullable: case IProblem.IllegalReturnNullityRedefinition: case IProblem.IllegalRedefinitionToNonNullParameter: case IProblem.IllegalDefinitionToNonNullParameter: case IProblem.ParameterLackingNullableAnnotation: case IProblem.CannotImplementIncompatibleNullness: case IProblem.UninitializedNonNullField: case IProblem.UninitializedNonNullFieldHintMissingDefault: case IProblem.ConflictingNullAnnotations: case IProblem.ConflictingInheritedNullAnnotations: return CompilerOptions.NullSpecViolation; case IProblem.ParameterLackingNonNullAnnotation: return CompilerOptions.NonnullParameterAnnotationDropped; case IProblem.RequiredNonNullButProvidedPotentialNull: return CompilerOptions.NullAnnotationInferenceConflict; case IProblem.RequiredNonNullButProvidedUnknown: return CompilerOptions.NullUncheckedConversion; case IProblem.RedundantNullAnnotation: case IProblem.RedundantNullDefaultAnnotation: case IProblem.RedundantNullDefaultAnnotationPackage: case IProblem.RedundantNullDefaultAnnotationType: case IProblem.RedundantNullDefaultAnnotationMethod: return CompilerOptions.RedundantNullAnnotation; case IProblem.BoxingConversion : case IProblem.UnboxingConversion : return CompilerOptions.AutoBoxing; case IProblem.MissingEnumConstantCase : case IProblem.MissingEnumConstantCaseDespiteDefault : // this one is further protected by CompilerOptions.reportMissingEnumCaseDespiteDefault return CompilerOptions.MissingEnumConstantCase; case IProblem.MissingDefaultCase : case IProblem.MissingEnumDefaultCase : return CompilerOptions.MissingDefaultCase; case IProblem.AnnotationTypeUsedAsSuperInterface : return CompilerOptions.AnnotationSuperInterface; case IProblem.UnhandledWarningToken : return CompilerOptions.UnhandledWarningToken; case IProblem.UnusedWarningToken : return CompilerOptions.UnusedWarningToken; case IProblem.UnusedLabel : return CompilerOptions.UnusedLabel; case IProblem.JavadocUnexpectedTag: case IProblem.JavadocDuplicateTag: case IProblem.JavadocDuplicateReturnTag: case IProblem.JavadocInvalidThrowsClass: case IProblem.JavadocInvalidSeeReference: case IProblem.JavadocInvalidParamTagName: case IProblem.JavadocInvalidParamTagTypeParameter: case IProblem.JavadocMalformedSeeReference: case IProblem.JavadocInvalidSeeHref: case IProblem.JavadocInvalidSeeArgs: case IProblem.JavadocInvalidTag: case IProblem.JavadocUnterminatedInlineTag: case IProblem.JavadocMissingHashCharacter: case IProblem.JavadocEmptyReturnTag: case IProblem.JavadocUnexpectedText: case IProblem.JavadocInvalidParamName: case IProblem.JavadocDuplicateParamName: case IProblem.JavadocMissingParamName: case IProblem.JavadocMissingIdentifier: case IProblem.JavadocInvalidMemberTypeQualification: case IProblem.JavadocInvalidThrowsClassName: case IProblem.JavadocDuplicateThrowsClassName: case IProblem.JavadocMissingThrowsClassName: case IProblem.JavadocMissingSeeReference: case IProblem.JavadocInvalidValueReference: case IProblem.JavadocUndefinedField: case IProblem.JavadocAmbiguousField: case IProblem.JavadocUndefinedConstructor: case IProblem.JavadocAmbiguousConstructor: case IProblem.JavadocUndefinedMethod: case IProblem.JavadocAmbiguousMethod: case IProblem.JavadocAmbiguousMethodReference: case IProblem.JavadocParameterMismatch: case IProblem.JavadocUndefinedType: case IProblem.JavadocAmbiguousType: case IProblem.JavadocInternalTypeNameProvided: case IProblem.JavadocNoMessageSendOnArrayType: case IProblem.JavadocNoMessageSendOnBaseType: case IProblem.JavadocInheritedMethodHidesEnclosingName: case IProblem.JavadocInheritedFieldHidesEnclosingName: case IProblem.JavadocInheritedNameHidesEnclosingTypeName: case IProblem.JavadocNonStaticTypeFromStaticInvocation: case IProblem.JavadocGenericMethodTypeArgumentMismatch: case IProblem.JavadocNonGenericMethod: case IProblem.JavadocIncorrectArityForParameterizedMethod: case IProblem.JavadocParameterizedMethodArgumentTypeMismatch: case IProblem.JavadocTypeArgumentsForRawGenericMethod: case IProblem.JavadocGenericConstructorTypeArgumentMismatch: case IProblem.JavadocNonGenericConstructor: case IProblem.JavadocIncorrectArityForParameterizedConstructor: case IProblem.JavadocParameterizedConstructorArgumentTypeMismatch: case IProblem.JavadocTypeArgumentsForRawGenericConstructor: case IProblem.JavadocNotVisibleField: case IProblem.JavadocNotVisibleConstructor: case IProblem.JavadocNotVisibleMethod: case IProblem.JavadocNotVisibleType: case IProblem.JavadocUsingDeprecatedField: case IProblem.JavadocUsingDeprecatedConstructor: case IProblem.JavadocUsingDeprecatedMethod: case IProblem.JavadocUsingDeprecatedType: case IProblem.JavadocHiddenReference: case IProblem.JavadocMissingTagDescription: case IProblem.JavadocInvalidSeeUrlReference: return CompilerOptions.InvalidJavadoc; case IProblem.JavadocMissingParamTag: case IProblem.JavadocMissingReturnTag: case IProblem.JavadocMissingThrowsTag: return CompilerOptions.MissingJavadocTags; case IProblem.JavadocMissing: return CompilerOptions.MissingJavadocComments; case IProblem.ParameterAssignment: return CompilerOptions.ParameterAssignment; case IProblem.FallthroughCase: return CompilerOptions.FallthroughCase; case IProblem.OverridingMethodWithoutSuperInvocation: return CompilerOptions.OverridingMethodWithoutSuperInvocation; case IProblem.UnusedTypeArgumentsForMethodInvocation: case IProblem.UnusedTypeArgumentsForConstructorInvocation: return CompilerOptions.UnusedTypeArguments; case IProblem.RedundantSuperinterface: return CompilerOptions.RedundantSuperinterface; case IProblem.ComparingIdentical: return CompilerOptions.ComparingIdentical; case IProblem.MissingSynchronizedModifierInInheritedMethod: return CompilerOptions.MissingSynchronizedModifierInInheritedMethod; case IProblem.ShouldImplementHashcode: return CompilerOptions.ShouldImplementHashcode; case IProblem.DeadCode: return CompilerOptions.DeadCode; case IProblem.Task : return CompilerOptions.Tasks; case IProblem.UnusedObjectAllocation: return CompilerOptions.UnusedObjectAllocation; case IProblem.MethodCanBeStatic: return CompilerOptions.MethodCanBeStatic; case IProblem.MethodCanBePotentiallyStatic: return CompilerOptions.MethodCanBePotentiallyStatic; case IProblem.UnclosedCloseable: case IProblem.UnclosedCloseableAtExit: return CompilerOptions.UnclosedCloseable; case IProblem.PotentiallyUnclosedCloseable: case IProblem.PotentiallyUnclosedCloseableAtExit: return CompilerOptions.PotentiallyUnclosedCloseable; case IProblem.ExplicitlyClosedAutoCloseable: return CompilerOptions.ExplicitlyClosedAutoCloseable; case IProblem.RedundantSpecificationOfTypeArguments: return CompilerOptions.RedundantSpecificationOfTypeArguments; case IProblem.MissingNonNullByDefaultAnnotationOnPackage: case IProblem.MissingNonNullByDefaultAnnotationOnType: return CompilerOptions.MissingNonNullByDefaultAnnotation; case IProblem.UnusedTypeParameter: return CompilerOptions.UnusedTypeParameter; } return 0; } /** * Compute problem category ID based on problem ID * @param problemID * @return a category ID * @see CategorizedProblem */ public static int getProblemCategory(int severity, int problemID) { categorizeOnIrritant: { // fatal problems even if optional are all falling into same category (not irritant based) if ((severity & ProblemSeverities.Fatal) != 0) break categorizeOnIrritant; int irritant = getIrritant(problemID); switch (irritant) { case CompilerOptions.MethodWithConstructorName : case CompilerOptions.AccessEmulation : case CompilerOptions.AssertUsedAsAnIdentifier : case CompilerOptions.NonStaticAccessToStatic : case CompilerOptions.UnqualifiedFieldAccess : case CompilerOptions.UndocumentedEmptyBlock : case CompilerOptions.IndirectStaticAccess : case CompilerOptions.FinalParameterBound : case CompilerOptions.EnumUsedAsAnIdentifier : case CompilerOptions.AnnotationSuperInterface : case CompilerOptions.AutoBoxing : case CompilerOptions.MissingOverrideAnnotation : case CompilerOptions.MissingDeprecatedAnnotation : case CompilerOptions.ParameterAssignment : case CompilerOptions.MethodCanBeStatic : case CompilerOptions.MethodCanBePotentiallyStatic : case CompilerOptions.ExplicitlyClosedAutoCloseable : return CategorizedProblem.CAT_CODE_STYLE; case CompilerOptions.MaskedCatchBlock : case CompilerOptions.NoImplicitStringConversion : case CompilerOptions.NoEffectAssignment : case CompilerOptions.AccidentalBooleanAssign : case CompilerOptions.EmptyStatement : case CompilerOptions.FinallyBlockNotCompleting : case CompilerOptions.MissingSerialVersion : case CompilerOptions.VarargsArgumentNeedCast : case CompilerOptions.NullReference : case CompilerOptions.PotentialNullReference : case CompilerOptions.RedundantNullCheck : case CompilerOptions.MissingEnumConstantCase : case CompilerOptions.MissingDefaultCase : case CompilerOptions.FallthroughCase : case CompilerOptions.OverridingMethodWithoutSuperInvocation : case CompilerOptions.ComparingIdentical : case CompilerOptions.MissingSynchronizedModifierInInheritedMethod : case CompilerOptions.ShouldImplementHashcode : case CompilerOptions.DeadCode : case CompilerOptions.UnusedObjectAllocation : case CompilerOptions.UnclosedCloseable : case CompilerOptions.PotentiallyUnclosedCloseable : return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM; case CompilerOptions.OverriddenPackageDefaultMethod : case CompilerOptions.IncompatibleNonInheritedInterfaceMethod : case CompilerOptions.LocalVariableHiding : case CompilerOptions.FieldHiding : case CompilerOptions.TypeHiding : return CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT; case CompilerOptions.UnusedLocalVariable : case CompilerOptions.UnusedArgument : case CompilerOptions.UnusedImport : case CompilerOptions.UnusedPrivateMember : case CompilerOptions.UnusedDeclaredThrownException : case CompilerOptions.UnnecessaryTypeCheck : case CompilerOptions.UnnecessaryElse : case CompilerOptions.UnhandledWarningToken : case CompilerOptions.UnusedWarningToken : case CompilerOptions.UnusedLabel : case CompilerOptions.RedundantSuperinterface : case CompilerOptions.RedundantSpecificationOfTypeArguments : case CompilerOptions.UnusedTypeParameter: return CategorizedProblem.CAT_UNNECESSARY_CODE; case CompilerOptions.UsingDeprecatedAPI : return CategorizedProblem.CAT_DEPRECATION; case CompilerOptions.NonExternalizedString : return CategorizedProblem.CAT_NLS; case CompilerOptions.Task : return CategorizedProblem.CAT_UNSPECIFIED; // TODO may want to improve case CompilerOptions.MissingJavadocComments : case CompilerOptions.MissingJavadocTags : case CompilerOptions.InvalidJavadoc : case CompilerOptions.InvalidJavadoc|CompilerOptions.UsingDeprecatedAPI : return CategorizedProblem.CAT_JAVADOC; case CompilerOptions.UncheckedTypeOperation : case CompilerOptions.RawTypeReference : return CategorizedProblem.CAT_UNCHECKED_RAW; case CompilerOptions.ForbiddenReference : case CompilerOptions.DiscouragedReference : return CategorizedProblem.CAT_RESTRICTION; case CompilerOptions.NullSpecViolation : case CompilerOptions.NullAnnotationInferenceConflict : case CompilerOptions.NullUncheckedConversion : case CompilerOptions.MissingNonNullByDefaultAnnotation: case CompilerOptions.NonnullParameterAnnotationDropped: return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM; case CompilerOptions.RedundantNullAnnotation : return CategorizedProblem.CAT_UNNECESSARY_CODE; default: break categorizeOnIrritant; } } // categorize fatal problems per ID switch (problemID) { case IProblem.IsClassPathCorrect : case IProblem.CorruptedSignature : return CategorizedProblem.CAT_BUILDPATH; default : if ((problemID & IProblem.Syntax) != 0) return CategorizedProblem.CAT_SYNTAX; if ((problemID & IProblem.ImportRelated) != 0) return CategorizedProblem.CAT_IMPORT; if ((problemID & IProblem.TypeRelated) != 0) return CategorizedProblem.CAT_TYPE; if ((problemID & (IProblem.FieldRelated|IProblem.MethodRelated|IProblem.ConstructorRelated)) != 0) return CategorizedProblem.CAT_MEMBER; } return CategorizedProblem.CAT_INTERNAL; } public void abortDueToInternalError(String errorMessage) { this.abortDueToInternalError(errorMessage, null); } public void abortDueToInternalError(String errorMessage, ASTNode location) { String[] arguments = new String[] {errorMessage}; this.handle( IProblem.Unclassified, arguments, arguments, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, location == null ? 0 : location.sourceStart, location == null ? 0 : location.sourceEnd); } public void abstractMethodCannotBeOverridden(SourceTypeBinding type, MethodBinding concreteMethod) { this.handle( // %1 must be abstract since it cannot override the inherited package-private abstract method %2 IProblem.AbstractMethodCannotBeOverridden, new String[] { new String(type.sourceName()), new String( CharOperation.concat( concreteMethod.declaringClass.readableName(), concreteMethod.readableName(), '.'))}, new String[] { new String(type.sourceName()), new String( CharOperation.concat( concreteMethod.declaringClass.shortReadableName(), concreteMethod.shortReadableName(), '.'))}, type.sourceStart(), type.sourceEnd()); } public void abstractMethodInAbstractClass(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) { if (type.isEnum() && type.isLocalType()) { FieldBinding field = type.scope.enclosingMethodScope().initializedField; FieldDeclaration decl = field.sourceField(); String[] arguments = new String[] {new String(decl.name), new String(methodDecl.selector)}; this.handle( IProblem.AbstractMethodInEnum, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd); } else { String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)}; this.handle( IProblem.AbstractMethodInAbstractClass, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd); } } public void abstractMethodInConcreteClass(SourceTypeBinding type) { if (type.isEnum() && type.isLocalType()) { FieldBinding field = type.scope.enclosingMethodScope().initializedField; FieldDeclaration decl = field.sourceField(); String[] arguments = new String[] {new String(decl.name)}; this.handle( IProblem.EnumConstantCannotDefineAbstractMethod, arguments, arguments, decl.sourceStart(), decl.sourceEnd()); } else { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.AbstractMethodsInConcreteClass, arguments, arguments, type.sourceStart(), type.sourceEnd()); } } public void abstractMethodMustBeImplemented(SourceTypeBinding type, MethodBinding abstractMethod) { if (type.isEnum() && type.isLocalType()) { FieldBinding field = type.scope.enclosingMethodScope().initializedField; FieldDeclaration decl = field.sourceField(); this.handle( // Must implement the inherited abstract method %1 // 8.4.3 - Every non-abstract subclass of an abstract type, A, must provide a concrete implementation of all of A's methods. IProblem.EnumConstantMustImplementAbstractMethod, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, false), new String(decl.name), }, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, true), new String(decl.name), }, decl.sourceStart(), decl.sourceEnd()); } else { this.handle( // Must implement the inherited abstract method %1 // 8.4.3 - Every non-abstract subclass of an abstract type, A, must provide a concrete implementation of all of A's methods. IProblem.AbstractMethodMustBeImplemented, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, false), new String(abstractMethod.declaringClass.readableName()), new String(type.readableName()), }, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, true), new String(abstractMethod.declaringClass.shortReadableName()), new String(type.shortReadableName()), }, type.sourceStart(), type.sourceEnd()); } } public void abstractMethodMustBeImplemented(SourceTypeBinding type, MethodBinding abstractMethod, MethodBinding concreteMethod) { this.handle( // Must implement the inherited abstract method %1 // 8.4.3 - Every non-abstract subclass of an abstract type, A, must provide a concrete implementation of all of A's methods. IProblem.AbstractMethodMustBeImplementedOverConcreteMethod, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, false), new String(abstractMethod.declaringClass.readableName()), new String(type.readableName()), new String(concreteMethod.selector), typesAsString(concreteMethod, false), new String(concreteMethod.declaringClass.readableName()), }, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, true), new String(abstractMethod.declaringClass.shortReadableName()), new String(type.shortReadableName()), new String(concreteMethod.selector), typesAsString(concreteMethod, true), new String(concreteMethod.declaringClass.shortReadableName()), }, type.sourceStart(), type.sourceEnd()); } public void abstractMethodNeedingNoBody(AbstractMethodDeclaration method) { this.handle( IProblem.BodyForAbstractMethod, NoArgument, NoArgument, method.sourceStart, method.sourceEnd, method, method.compilationResult()); } public void alreadyDefinedLabel(char[] labelName, ASTNode location) { String[] arguments = new String[] {new String(labelName)}; this.handle( IProblem.DuplicateLabel, arguments, arguments, location.sourceStart, location.sourceEnd); } public void annotationCannotOverrideMethod(MethodBinding overrideMethod, MethodBinding inheritedMethod) { ASTNode location = overrideMethod.sourceMethod(); this.handle( IProblem.AnnotationCannotOverrideMethod, new String[] { new String(overrideMethod.declaringClass.readableName()), new String(inheritedMethod.declaringClass.readableName()), new String(inheritedMethod.selector), typesAsString(inheritedMethod, false)}, new String[] { new String(overrideMethod.declaringClass.shortReadableName()), new String(inheritedMethod.declaringClass.shortReadableName()), new String(inheritedMethod.selector), typesAsString(inheritedMethod, true)}, location.sourceStart, location.sourceEnd); } public void annotationCircularity(TypeBinding sourceType, TypeBinding otherType, TypeReference reference) { if (sourceType == otherType) this.handle( IProblem.AnnotationCircularitySelfReference, new String[] {new String(sourceType.readableName())}, new String[] {new String(sourceType.shortReadableName())}, reference.sourceStart, reference.sourceEnd); else this.handle( IProblem.AnnotationCircularity, new String[] {new String(sourceType.readableName()), new String(otherType.readableName())}, new String[] {new String(sourceType.shortReadableName()), new String(otherType.shortReadableName())}, reference.sourceStart, reference.sourceEnd); } public void annotationMembersCannotHaveParameters(AnnotationMethodDeclaration annotationMethodDeclaration) { this.handle( IProblem.AnnotationMembersCannotHaveParameters, NoArgument, NoArgument, annotationMethodDeclaration.sourceStart, annotationMethodDeclaration.sourceEnd); } public void annotationMembersCannotHaveTypeParameters(AnnotationMethodDeclaration annotationMethodDeclaration) { this.handle( IProblem.AnnotationMembersCannotHaveTypeParameters, NoArgument, NoArgument, annotationMethodDeclaration.sourceStart, annotationMethodDeclaration.sourceEnd); } public void annotationTypeDeclarationCannotHaveConstructor(ConstructorDeclaration constructorDeclaration) { this.handle( IProblem.AnnotationTypeDeclarationCannotHaveConstructor, NoArgument, NoArgument, constructorDeclaration.sourceStart, constructorDeclaration.sourceEnd); } public void annotationTypeDeclarationCannotHaveSuperclass(TypeDeclaration typeDeclaration) { this.handle( IProblem.AnnotationTypeDeclarationCannotHaveSuperclass, NoArgument, NoArgument, typeDeclaration.sourceStart, typeDeclaration.sourceEnd); } public void annotationTypeDeclarationCannotHaveSuperinterfaces(TypeDeclaration typeDeclaration) { this.handle( IProblem.AnnotationTypeDeclarationCannotHaveSuperinterfaces, NoArgument, NoArgument, typeDeclaration.sourceStart, typeDeclaration.sourceEnd); } public void annotationTypeUsedAsSuperinterface(SourceTypeBinding type, TypeReference superInterfaceRef, ReferenceBinding superType) { this.handle( IProblem.AnnotationTypeUsedAsSuperInterface, new String[] {new String(superType.readableName()), new String(type.sourceName())}, new String[] {new String(superType.shortReadableName()), new String(type.sourceName())}, superInterfaceRef.sourceStart, superInterfaceRef.sourceEnd); } public void annotationValueMustBeAnnotation(TypeBinding annotationType, char[] name, Expression value, TypeBinding expectedType) { String str = new String(name); this.handle( IProblem.AnnotationValueMustBeAnnotation, new String[] { new String(annotationType.readableName()), str, new String(expectedType.readableName()), }, new String[] { new String(annotationType.shortReadableName()), str, new String(expectedType.readableName()), }, value.sourceStart, value.sourceEnd); } public void annotationValueMustBeArrayInitializer(TypeBinding annotationType, char[] name, Expression value) { String str = new String(name); this.handle( IProblem.AnnotationValueMustBeArrayInitializer, new String[] { new String(annotationType.readableName()), str }, new String[] { new String(annotationType.shortReadableName()), str}, value.sourceStart, value.sourceEnd); } public void annotationValueMustBeClassLiteral(TypeBinding annotationType, char[] name, Expression value) { String str = new String(name); this.handle( IProblem.AnnotationValueMustBeClassLiteral, new String[] { new String(annotationType.readableName()), str }, new String[] { new String(annotationType.shortReadableName()), str}, value.sourceStart, value.sourceEnd); } public void annotationValueMustBeConstant(TypeBinding annotationType, char[] name, Expression value, boolean isEnum) { String str = new String(name); if (isEnum) { this.handle( IProblem.AnnotationValueMustBeAnEnumConstant, new String[] { new String(annotationType.readableName()), str }, new String[] { new String(annotationType.shortReadableName()), str}, value.sourceStart, value.sourceEnd); } else { this.handle( IProblem.AnnotationValueMustBeConstant, new String[] { new String(annotationType.readableName()), str }, new String[] { new String(annotationType.shortReadableName()), str}, value.sourceStart, value.sourceEnd); } } public void anonymousClassCannotExtendFinalClass(TypeReference reference, TypeBinding type) { this.handle( IProblem.AnonymousClassCannotExtendFinalClass, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, reference.sourceStart, reference.sourceEnd); } public void argumentTypeCannotBeVoid(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, Argument arg) { String[] arguments = new String[] {new String(methodDecl.selector), new String(arg.name)}; this.handle( IProblem.ArgumentTypeCannotBeVoid, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd); } public void argumentTypeCannotBeVoidArray(Argument arg) { this.handle( IProblem.CannotAllocateVoidArray, NoArgument, NoArgument, arg.type.sourceStart, arg.type.sourceEnd); } public void arrayConstantsOnlyInArrayInitializers(int sourceStart, int sourceEnd) { this.handle( IProblem.ArrayConstantsOnlyInArrayInitializers, NoArgument, NoArgument, sourceStart, sourceEnd); } public void assignmentHasNoEffect(AbstractVariableDeclaration location, char[] name){ int severity = computeSeverity(IProblem.AssignmentHasNoEffect); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] { new String(name) }; int start = location.sourceStart; int end = location.sourceEnd; if (location.initialization != null) { end = location.initialization.sourceEnd; } this.handle( IProblem.AssignmentHasNoEffect, arguments, arguments, severity, start, end); } public void assignmentHasNoEffect(Assignment location, char[] name){ int severity = computeSeverity(IProblem.AssignmentHasNoEffect); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] { new String(name) }; this.handle( IProblem.AssignmentHasNoEffect, arguments, arguments, severity, location.sourceStart, location.sourceEnd); } public void attemptToReturnNonVoidExpression(ReturnStatement returnStatement, TypeBinding expectedType) { this.handle( IProblem.VoidMethodReturnsValue, new String[] {new String(expectedType.readableName())}, new String[] {new String(expectedType.shortReadableName())}, returnStatement.sourceStart, returnStatement.sourceEnd); } public void attemptToReturnVoidValue(ReturnStatement returnStatement) { this.handle( IProblem.MethodReturnsVoid, NoArgument, NoArgument, returnStatement.sourceStart, returnStatement.sourceEnd); } public void autoboxing(Expression expression, TypeBinding originalType, TypeBinding convertedType) { if (this.options.getSeverity(CompilerOptions.AutoBoxing) == ProblemSeverities.Ignore) return; this.handle( originalType.isBaseType() ? IProblem.BoxingConversion : IProblem.UnboxingConversion, new String[] { new String(originalType.readableName()), new String(convertedType.readableName()), }, new String[] { new String(originalType.shortReadableName()), new String(convertedType.shortReadableName()), }, expression.sourceStart, expression.sourceEnd); } public void boundCannotBeArray(ASTNode location, TypeBinding type) { this.handle( IProblem.BoundCannotBeArray, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void boundMustBeAnInterface(ASTNode location, TypeBinding type) { this.handle( IProblem.BoundMustBeAnInterface, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void bytecodeExceeds64KLimit(AbstractMethodDeclaration location) { MethodBinding method = location.binding; if (location.isConstructor()) { this.handle( IProblem.BytecodeExceeds64KLimitForConstructor, new String[] {new String(location.selector), typesAsString(method, false)}, new String[] {new String(location.selector), typesAsString(method, true)}, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.BytecodeExceeds64KLimit, new String[] {new String(location.selector), typesAsString(method, false)}, new String[] {new String(location.selector), typesAsString(method, true)}, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, location.sourceStart, location.sourceEnd); } } public void bytecodeExceeds64KLimit(TypeDeclaration location) { this.handle( IProblem.BytecodeExceeds64KLimitForClinit, NoArgument, NoArgument, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, location.sourceStart, location.sourceEnd); } public void cannotAllocateVoidArray(Expression expression) { this.handle( IProblem.CannotAllocateVoidArray, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void cannotAssignToFinalField(FieldBinding field, ASTNode location) { this.handle( IProblem.FinalFieldAssignment, new String[] { (field.declaringClass == null ? "array" : new String(field.declaringClass.readableName())), //$NON-NLS-1$ new String(field.readableName())}, new String[] { (field.declaringClass == null ? "array" : new String(field.declaringClass.shortReadableName())), //$NON-NLS-1$ new String(field.shortReadableName())}, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void cannotAssignToFinalLocal(LocalVariableBinding local, ASTNode location) { int problemId = 0; if ((local.tagBits & TagBits.MultiCatchParameter) != 0) { problemId = IProblem.AssignmentToMultiCatchParameter; } else if ((local.tagBits & TagBits.IsResource) != 0) { problemId = IProblem.AssignmentToResource; } else { problemId = IProblem.NonBlankFinalLocalAssignment; } String[] arguments = new String[] { new String(local.readableName())}; this.handle( problemId, arguments, arguments, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void cannotAssignToFinalOuterLocal(LocalVariableBinding local, ASTNode location) { String[] arguments = new String[] {new String(local.readableName())}; this.handle( IProblem.FinalOuterLocalAssignment, arguments, arguments, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void cannotDefineDimensionsAndInitializer(ArrayAllocationExpression expresssion) { this.handle( IProblem.CannotDefineDimensionExpressionsWithInit, NoArgument, NoArgument, expresssion.sourceStart, expresssion.sourceEnd); } public void cannotDireclyInvokeAbstractMethod(MessageSend messageSend, MethodBinding method) { this.handle( IProblem.DirectInvocationOfAbstractMethod, new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, messageSend.sourceStart, messageSend.sourceEnd); } public void cannotExtendEnum(SourceTypeBinding type, TypeReference superclass, TypeBinding superTypeBinding) { String name = new String(type.sourceName()); String superTypeFullName = new String(superTypeBinding.readableName()); String superTypeShortName = new String(superTypeBinding.shortReadableName()); if (superTypeShortName.equals(name)) superTypeShortName = superTypeFullName; this.handle( IProblem.CannotExtendEnum, new String[] {superTypeFullName, name}, new String[] {superTypeShortName, name}, superclass.sourceStart, superclass.sourceEnd); } public void cannotImportPackage(ImportReference importRef) { String[] arguments = new String[] {CharOperation.toString(importRef.tokens)}; this.handle( IProblem.CannotImportPackage, arguments, arguments, importRef.sourceStart, importRef.sourceEnd); } public void cannotInstantiate(TypeReference typeRef, TypeBinding type) { this.handle( IProblem.InvalidClassInstantiation, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, typeRef.sourceStart, typeRef.sourceEnd); } public void cannotInvokeSuperConstructorInEnum(ExplicitConstructorCall constructorCall, MethodBinding enumConstructor) { this.handle( IProblem.CannotInvokeSuperConstructorInEnum, new String[] { new String(enumConstructor.declaringClass.sourceName()), typesAsString(enumConstructor, false), }, new String[] { new String(enumConstructor.declaringClass.sourceName()), typesAsString(enumConstructor, true), }, constructorCall.sourceStart, constructorCall.sourceEnd); } public void cannotReadSource(CompilationUnitDeclaration unit, AbortCompilationUnit abortException, boolean verbose) { String fileName = new String(unit.compilationResult.fileName); if (abortException.exception instanceof CharConversionException) { // specific encoding issue String encoding = abortException.encoding; if (encoding == null) { encoding = System.getProperty("file.encoding"); //$NON-NLS-1$ } String[] arguments = new String[]{ fileName, encoding }; this.handle( IProblem.InvalidEncoding, arguments, arguments, 0, 0); return; } StringWriter stringWriter = new StringWriter(); PrintWriter writer = new PrintWriter(stringWriter); if (verbose) { abortException.exception.printStackTrace(writer); System.err.println(stringWriter.toString()); stringWriter = new StringWriter(); writer = new PrintWriter(stringWriter); } writer.print(abortException.exception.getClass().getName()); writer.print(':'); writer.print(abortException.exception.getMessage()); String exceptionTrace = stringWriter.toString(); String[] arguments = new String[]{ fileName, exceptionTrace }; this.handle( IProblem.CannotReadSource, arguments, arguments, 0, 0); } public void cannotReferToNonFinalOuterLocal(LocalVariableBinding local, ASTNode location) { String[] arguments =new String[]{ new String(local.readableName())}; this.handle( IProblem.OuterLocalMustBeFinal, arguments, arguments, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void cannotReturnInInitializer(ASTNode location) { this.handle( IProblem.CannotReturnInInitializer, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void cannotThrowNull(ASTNode expression) { this.handle( IProblem.CannotThrowNull, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void cannotThrowType(ASTNode exception, TypeBinding expectedType) { this.handle( IProblem.CannotThrowType, new String[] {new String(expectedType.readableName())}, new String[] {new String(expectedType.shortReadableName())}, exception.sourceStart, exception.sourceEnd); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391092 public void illegalArrayOfUnionType(char[] identifierName, TypeReference typeReference) { this.handle( IProblem.IllegalArrayOfUnionType, NoArgument, NoArgument, typeReference.sourceStart, typeReference.sourceEnd); } public void cannotUseQualifiedEnumConstantInCaseLabel(Reference location, FieldBinding field) { this.handle( IProblem.IllegalQualifiedEnumConstantLabel, new String[]{ String.valueOf(field.declaringClass.readableName()), String.valueOf(field.name) }, new String[]{ String.valueOf(field.declaringClass.shortReadableName()), String.valueOf(field.name) }, location.sourceStart(), location.sourceEnd()); } public void cannotUseSuperInCodeSnippet(int start, int end) { this.handle( IProblem.CannotUseSuperInCodeSnippet, NoArgument, NoArgument, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, start, end); } public void cannotUseSuperInJavaLangObject(ASTNode reference) { this.handle( IProblem.ObjectHasNoSuperclass, NoArgument, NoArgument, reference.sourceStart, reference.sourceEnd); } public void caseExpressionMustBeConstant(Expression expression) { this.handle( IProblem.NonConstantExpression, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void classExtendFinalClass(SourceTypeBinding type, TypeReference superclass, TypeBinding superTypeBinding) { String name = new String(type.sourceName()); String superTypeFullName = new String(superTypeBinding.readableName()); String superTypeShortName = new String(superTypeBinding.shortReadableName()); if (superTypeShortName.equals(name)) superTypeShortName = superTypeFullName; this.handle( IProblem.ClassExtendFinalClass, new String[] {superTypeFullName, name}, new String[] {superTypeShortName, name}, superclass.sourceStart, superclass.sourceEnd); } public void codeSnippetMissingClass(String missing, int start, int end) { String[] arguments = new String[]{missing}; this.handle( IProblem.CodeSnippetMissingClass, arguments, arguments, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, start, end); } public void codeSnippetMissingMethod(String className, String missingMethod, String argumentTypes, int start, int end) { String[] arguments = new String[]{ className, missingMethod, argumentTypes }; this.handle( IProblem.CodeSnippetMissingMethod, arguments, arguments, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, start, end); } public void comparingIdenticalExpressions(Expression comparison){ int severity = computeSeverity(IProblem.ComparingIdentical); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.ComparingIdentical, NoArgument, NoArgument, severity, comparison.sourceStart, comparison.sourceEnd); } /* * Given the current configuration, answers which category the problem * falls into: * ProblemSeverities.Error | ProblemSeverities.Warning | ProblemSeverities.Ignore * when different from Ignore, severity can be coupled with ProblemSeverities.Optional * to indicate that this problem is configurable through options */ public int computeSeverity(int problemID){ switch (problemID) { case IProblem.VarargsConflict : return ProblemSeverities.Warning; case IProblem.TypeCollidesWithPackage : return ProblemSeverities.Warning; /* * Javadoc tags resolved references errors */ case IProblem.JavadocInvalidParamName: case IProblem.JavadocDuplicateParamName: case IProblem.JavadocMissingParamName: case IProblem.JavadocInvalidMemberTypeQualification: case IProblem.JavadocInvalidThrowsClassName: case IProblem.JavadocDuplicateThrowsClassName: case IProblem.JavadocMissingThrowsClassName: case IProblem.JavadocMissingSeeReference: case IProblem.JavadocInvalidValueReference: case IProblem.JavadocUndefinedField: case IProblem.JavadocAmbiguousField: case IProblem.JavadocUndefinedConstructor: case IProblem.JavadocAmbiguousConstructor: case IProblem.JavadocUndefinedMethod: case IProblem.JavadocAmbiguousMethod: case IProblem.JavadocAmbiguousMethodReference: case IProblem.JavadocParameterMismatch: case IProblem.JavadocUndefinedType: case IProblem.JavadocAmbiguousType: case IProblem.JavadocInternalTypeNameProvided: case IProblem.JavadocNoMessageSendOnArrayType: case IProblem.JavadocNoMessageSendOnBaseType: case IProblem.JavadocInheritedMethodHidesEnclosingName: case IProblem.JavadocInheritedFieldHidesEnclosingName: case IProblem.JavadocInheritedNameHidesEnclosingTypeName: case IProblem.JavadocNonStaticTypeFromStaticInvocation: case IProblem.JavadocGenericMethodTypeArgumentMismatch: case IProblem.JavadocNonGenericMethod: case IProblem.JavadocIncorrectArityForParameterizedMethod: case IProblem.JavadocParameterizedMethodArgumentTypeMismatch: case IProblem.JavadocTypeArgumentsForRawGenericMethod: case IProblem.JavadocGenericConstructorTypeArgumentMismatch: case IProblem.JavadocNonGenericConstructor: case IProblem.JavadocIncorrectArityForParameterizedConstructor: case IProblem.JavadocParameterizedConstructorArgumentTypeMismatch: case IProblem.JavadocTypeArgumentsForRawGenericConstructor: if (!this.options.reportInvalidJavadocTags) { return ProblemSeverities.Ignore; } break; /* * Javadoc invalid tags due to deprecated references */ case IProblem.JavadocUsingDeprecatedField: case IProblem.JavadocUsingDeprecatedConstructor: case IProblem.JavadocUsingDeprecatedMethod: case IProblem.JavadocUsingDeprecatedType: if (!(this.options.reportInvalidJavadocTags && this.options.reportInvalidJavadocTagsDeprecatedRef)) { return ProblemSeverities.Ignore; } break; /* * Javadoc invalid tags due to non-visible references */ case IProblem.JavadocNotVisibleField: case IProblem.JavadocNotVisibleConstructor: case IProblem.JavadocNotVisibleMethod: case IProblem.JavadocNotVisibleType: case IProblem.JavadocHiddenReference: if (!(this.options.reportInvalidJavadocTags && this.options.reportInvalidJavadocTagsNotVisibleRef)) { return ProblemSeverities.Ignore; } break; /* * Javadoc missing tag descriptions */ case IProblem.JavadocEmptyReturnTag: if (CompilerOptions.NO_TAG.equals(this.options.reportMissingJavadocTagDescription)) { return ProblemSeverities.Ignore; } break; case IProblem.JavadocMissingTagDescription: if (! CompilerOptions.ALL_STANDARD_TAGS.equals(this.options.reportMissingJavadocTagDescription)) { return ProblemSeverities.Ignore; } break; } int irritant = getIrritant(problemID); if (irritant != 0) { if ((problemID & IProblem.Javadoc) != 0 && !this.options.docCommentSupport) return ProblemSeverities.Ignore; return this.options.getSeverity(irritant); } return ProblemSeverities.Error | ProblemSeverities.Fatal; } public void conditionalArgumentsIncompatibleTypes(ConditionalExpression expression, TypeBinding trueType, TypeBinding falseType) { this.handle( IProblem.IncompatibleTypesInConditionalOperator, new String[] {new String(trueType.readableName()), new String(falseType.readableName())}, new String[] {new String(trueType.sourceName()), new String(falseType.sourceName())}, expression.sourceStart, expression.sourceEnd); } public void conflictingImport(ImportReference importRef) { String[] arguments = new String[] {CharOperation.toString(importRef.tokens)}; this.handle( IProblem.ConflictingImport, arguments, arguments, importRef.sourceStart, importRef.sourceEnd); } public void constantOutOfRange(Literal literal, TypeBinding literalType) { String[] arguments = new String[] {new String(literalType.readableName()), new String(literal.source())}; this.handle( IProblem.NumericValueOutOfRange, arguments, arguments, literal.sourceStart, literal.sourceEnd); } public void corruptedSignature(TypeBinding enclosingType, char[] signature, int position) { this.handle( IProblem.CorruptedSignature, new String[] { new String(enclosingType.readableName()), new String(signature), String.valueOf(position) }, new String[] { new String(enclosingType.shortReadableName()), new String(signature), String.valueOf(position) }, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, 0, 0); } public void deprecatedField(FieldBinding field, ASTNode location) { int severity = computeSeverity(IProblem.UsingDeprecatedField); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.UsingDeprecatedField, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, severity, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void deprecatedMethod(MethodBinding method, ASTNode location) { boolean isConstructor = method.isConstructor(); int severity = computeSeverity(isConstructor ? IProblem.UsingDeprecatedConstructor : IProblem.UsingDeprecatedMethod); if (severity == ProblemSeverities.Ignore) return; if (isConstructor) { int start = -1; if(location instanceof AllocationExpression) { // omit the new keyword from the warning marker // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031 AllocationExpression allocationExpression = (AllocationExpression) location; if (allocationExpression.enumConstant != null) { start = allocationExpression.enumConstant.sourceStart; } start = allocationExpression.type.sourceStart; } this.handle( IProblem.UsingDeprecatedConstructor, new String[] {new String(method.declaringClass.readableName()), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), typesAsString(method, true)}, severity, (start == -1) ? location.sourceStart : start, location.sourceEnd); } else { int start = -1; if (location instanceof MessageSend) { // start the warning marker from the location where the name of the method starts // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031 start = (int) (((MessageSend)location).nameSourcePosition >>> 32); } this.handle( IProblem.UsingDeprecatedMethod, new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, severity, (start == -1) ? location.sourceStart : start, location.sourceEnd); } } public void deprecatedType(TypeBinding type, ASTNode location) { deprecatedType(type, location, Integer.MAX_VALUE); } // The argument 'index' makes sure that we demarcate partial types correctly while marking off // a deprecated type in a qualified reference (see bug 292510) public void deprecatedType(TypeBinding type, ASTNode location, int index) { if (location == null) return; // 1G828DN - no type ref for synthetic arguments int severity = computeSeverity(IProblem.UsingDeprecatedType); if (severity == ProblemSeverities.Ignore) return; type = type.leafComponentType(); int sourceStart = -1; if (location instanceof QualifiedTypeReference) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031 QualifiedTypeReference ref = (QualifiedTypeReference) location; if (index < Integer.MAX_VALUE) { sourceStart = (int) (ref.sourcePositions[index] >> 32); } } this.handle( IProblem.UsingDeprecatedType, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, severity, (sourceStart == -1) ? location.sourceStart : sourceStart, nodeSourceEnd(null, location, index)); } public void disallowedTargetForAnnotation(Annotation annotation) { this.handle( IProblem.DisallowedTargetForAnnotation, new String[] {new String(annotation.resolvedType.readableName())}, new String[] {new String(annotation.resolvedType.shortReadableName())}, annotation.sourceStart, annotation.sourceEnd); } public void polymorphicMethodNotBelow17(ASTNode node) { this.handle( IProblem.PolymorphicMethodNotBelow17, NoArgument, NoArgument, node.sourceStart, node.sourceEnd); } public void multiCatchNotBelow17(ASTNode node) { this.handle( IProblem.MultiCatchNotBelow17, NoArgument, NoArgument, node.sourceStart, node.sourceEnd); } public void duplicateAnnotation(Annotation annotation) { this.handle( IProblem.DuplicateAnnotation, new String[] {new String(annotation.resolvedType.readableName())}, new String[] {new String(annotation.resolvedType.shortReadableName())}, annotation.sourceStart, annotation.sourceEnd); } public void duplicateAnnotationValue(TypeBinding annotationType, MemberValuePair memberValuePair) { String name = new String(memberValuePair.name); this.handle( IProblem.DuplicateAnnotationMember, new String[] { name, new String(annotationType.readableName())}, new String[] { name, new String(annotationType.shortReadableName())}, memberValuePair.sourceStart, memberValuePair.sourceEnd); } public void duplicateBounds(ASTNode location, TypeBinding type) { this.handle( IProblem.DuplicateBounds, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void duplicateCase(CaseStatement caseStatement) { this.handle( IProblem.DuplicateCase, NoArgument, NoArgument, caseStatement.sourceStart, caseStatement.sourceEnd); } public void duplicateDefaultCase(ASTNode statement) { this.handle( IProblem.DuplicateDefaultCase, NoArgument, NoArgument, statement.sourceStart, statement.sourceEnd); } public void duplicateEnumSpecialMethod(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) { MethodBinding method = methodDecl.binding; this.handle( IProblem.CannotDeclareEnumSpecialMethod, new String[] { new String(methodDecl.selector), new String(method.declaringClass.readableName()), typesAsString(method, false)}, new String[] { new String(methodDecl.selector), new String(method.declaringClass.shortReadableName()), typesAsString(method, true)}, methodDecl.sourceStart, methodDecl.sourceEnd); } public void duplicateFieldInType(SourceTypeBinding type, FieldDeclaration fieldDecl) { this.handle( IProblem.DuplicateField, new String[] {new String(type.sourceName()), new String(fieldDecl.name)}, new String[] {new String(type.shortReadableName()), new String(fieldDecl.name)}, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void duplicateImport(ImportReference importRef) { String[] arguments = new String[] {CharOperation.toString(importRef.tokens)}; this.handle( IProblem.DuplicateImport, arguments, arguments, importRef.sourceStart, importRef.sourceEnd); } public void duplicateInheritedMethods(SourceTypeBinding type, MethodBinding inheritedMethod1, MethodBinding inheritedMethod2) { if (inheritedMethod1.declaringClass != inheritedMethod2.declaringClass) { this.handle( IProblem.DuplicateInheritedMethods, new String[] { new String(inheritedMethod1.selector), typesAsString(inheritedMethod1, inheritedMethod1.original().parameters, false), typesAsString(inheritedMethod2, inheritedMethod2.original().parameters, false), new String(inheritedMethod1.declaringClass.readableName()), new String(inheritedMethod2.declaringClass.readableName()), }, new String[] { new String(inheritedMethod1.selector), typesAsString(inheritedMethod1, inheritedMethod1.original().parameters, true), typesAsString(inheritedMethod2, inheritedMethod2.original().parameters, true), new String(inheritedMethod1.declaringClass.shortReadableName()), new String(inheritedMethod2.declaringClass.shortReadableName()), }, type.sourceStart(), type.sourceEnd()); return; } // Handle duplicates from same class. this.handle( IProblem.DuplicateParameterizedMethods, new String[] { new String(inheritedMethod1.selector), new String(inheritedMethod1.declaringClass.readableName()), typesAsString(inheritedMethod1, inheritedMethod1.original().parameters, false), typesAsString(inheritedMethod2, inheritedMethod2.original().parameters, false)}, new String[] { new String(inheritedMethod1.selector), new String(inheritedMethod1.declaringClass.shortReadableName()), typesAsString(inheritedMethod1, inheritedMethod1.original().parameters, true), typesAsString(inheritedMethod2, inheritedMethod2.original().parameters, true)}, type.sourceStart(), type.sourceEnd()); } public void duplicateInitializationOfBlankFinalField(FieldBinding field, Reference reference) { String[] arguments = new String[]{ new String(field.readableName())}; this.handle( IProblem.DuplicateBlankFinalFieldInitialization, arguments, arguments, nodeSourceStart(field, reference), nodeSourceEnd(field, reference)); } public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, ASTNode location) { String[] arguments = new String[] { new String(local.readableName())}; this.handle( IProblem.DuplicateFinalLocalInitialization, arguments, arguments, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void duplicateMethodInType(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, boolean equalParameters, int severity) { MethodBinding method = methodDecl.binding; if (equalParameters) { this.handle( IProblem.DuplicateMethod, new String[] { new String(methodDecl.selector), new String(method.declaringClass.readableName()), typesAsString(method, false)}, new String[] { new String(methodDecl.selector), new String(method.declaringClass.shortReadableName()), typesAsString(method, true)}, severity, methodDecl.sourceStart, methodDecl.sourceEnd); } else { int length = method.parameters.length; TypeBinding[] erasures = new TypeBinding[length]; for (int i = 0; i < length; i++) { erasures[i] = method.parameters[i].erasure(); } this.handle( IProblem.DuplicateMethodErasure, new String[] { new String(methodDecl.selector), new String(method.declaringClass.readableName()), typesAsString(method, false), typesAsString(method, erasures, false) } , new String[] { new String(methodDecl.selector), new String(method.declaringClass.shortReadableName()), typesAsString(method, true), typesAsString(method, erasures, true) }, severity, methodDecl.sourceStart, methodDecl.sourceEnd); } } public void duplicateModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) { /* to highlight modifiers use: this.handle( new Problem( DuplicateModifierForField, new String[] {new String(fieldDecl.name)}, fieldDecl.modifiers.sourceStart, fieldDecl.modifiers.sourceEnd)); */ String[] arguments = new String[] {new String(fieldDecl.name)}; this.handle( IProblem.DuplicateModifierForField, arguments, arguments, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void duplicateModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) { this.handle( IProblem.DuplicateModifierForMethod, new String[] {new String(type.sourceName()), new String(methodDecl.selector)}, new String[] {new String(type.shortReadableName()), new String(methodDecl.selector)}, methodDecl.sourceStart, methodDecl.sourceEnd); } public void duplicateModifierForType(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.DuplicateModifierForType, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void duplicateModifierForVariable(LocalDeclaration localDecl, boolean complainForArgument) { String[] arguments = new String[] {new String(localDecl.name)}; this.handle( complainForArgument ? IProblem.DuplicateModifierForArgument : IProblem.DuplicateModifierForVariable, arguments, arguments, localDecl.sourceStart, localDecl.sourceEnd); } public void duplicateNestedType(TypeDeclaration typeDecl) { String[] arguments = new String[] {new String(typeDecl.name)}; this.handle( IProblem.DuplicateNestedType, arguments, arguments, typeDecl.sourceStart, typeDecl.sourceEnd); } public void duplicateSuperinterface(SourceTypeBinding type, TypeReference reference, ReferenceBinding superType) { this.handle( IProblem.DuplicateSuperInterface, new String[] { new String(superType.readableName()), new String(type.sourceName())}, new String[] { new String(superType.shortReadableName()), new String(type.sourceName())}, reference.sourceStart, reference.sourceEnd); } public void duplicateTargetInTargetAnnotation(TypeBinding annotationType, NameReference reference) { FieldBinding field = reference.fieldBinding(); String name = new String(field.name); this.handle( IProblem.DuplicateTargetInTargetAnnotation, new String[] { name, new String(annotationType.readableName())}, new String[] { name, new String(annotationType.shortReadableName())}, nodeSourceStart(field, reference), nodeSourceEnd(field, reference)); } public void duplicateTypeParameterInType(TypeParameter typeParameter) { this.handle( IProblem.DuplicateTypeVariable, new String[] { new String(typeParameter.name)}, new String[] { new String(typeParameter.name)}, typeParameter.sourceStart, typeParameter.sourceEnd); } public void duplicateTypes(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) { String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)}; this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit int end = typeDecl.sourceEnd; if (end <= 0) { end = -1; } this.handle( IProblem.DuplicateTypes, arguments, arguments, typeDecl.sourceStart, end, compUnitDecl.compilationResult); } public void emptyControlFlowStatement(int sourceStart, int sourceEnd) { this.handle( IProblem.EmptyControlFlowStatement, NoArgument, NoArgument, sourceStart, sourceEnd); } public void enumAbstractMethodMustBeImplemented(AbstractMethodDeclaration method) { MethodBinding abstractMethod = method.binding; this.handle( // Must implement the inherited abstract method %1 // 8.4.3 - Every non-abstract subclass of an abstract type, A, must provide a concrete implementation of all of A's methods. IProblem.EnumAbstractMethodMustBeImplemented, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, false), new String(abstractMethod.declaringClass.readableName()), }, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, true), new String(abstractMethod.declaringClass.shortReadableName()), }, method.sourceStart(), method.sourceEnd()); } public void enumConstantMustImplementAbstractMethod(AbstractMethodDeclaration method, FieldDeclaration field) { MethodBinding abstractMethod = method.binding; this.handle( IProblem.EnumConstantMustImplementAbstractMethod, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, false), new String(field.name), }, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, true), new String(field.name), }, field.sourceStart(), field.sourceEnd()); } public void enumConstantsCannotBeSurroundedByParenthesis(Expression expression) { this.handle( IProblem.EnumConstantsCannotBeSurroundedByParenthesis, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void enumStaticFieldUsedDuringInitialization(FieldBinding field, ASTNode location) { this.handle( IProblem.EnumStaticFieldInInInitializerContext, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void enumSwitchCannotTargetField(Reference reference, FieldBinding field) { this.handle( IProblem.EnumSwitchCannotTargetField, new String[]{ String.valueOf(field.declaringClass.readableName()), String.valueOf(field.name) }, new String[]{ String.valueOf(field.declaringClass.shortReadableName()), String.valueOf(field.name) }, nodeSourceStart(field, reference), nodeSourceEnd(field, reference)); } public void errorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params) { StringBuffer buffer = new StringBuffer(); StringBuffer shortBuffer = new StringBuffer(); for (int i = 0, length = params.length; i < length; i++) { if (i != 0){ buffer.append(", "); //$NON-NLS-1$ shortBuffer.append(", "); //$NON-NLS-1$ } buffer.append(new String(params[i].readableName())); shortBuffer.append(new String(params[i].shortReadableName())); } int id = recType.isArrayType() ? IProblem.NoMessageSendOnArrayType : IProblem.NoMessageSendOnBaseType; this.handle( id, new String[] {new String(recType.readableName()), new String(messageSend.selector), buffer.toString()}, new String[] {new String(recType.shortReadableName()), new String(messageSend.selector), shortBuffer.toString()}, messageSend.sourceStart, messageSend.sourceEnd); } public void errorThisSuperInStatic(ASTNode reference) { String[] arguments = new String[] {reference.isSuper() ? "super" : "this"}; //$NON-NLS-2$ //$NON-NLS-1$ this.handle( IProblem.ThisInStaticContext, arguments, arguments, reference.sourceStart, reference.sourceEnd); } public void expressionShouldBeAVariable(Expression expression) { this.handle( IProblem.ExpressionShouldBeAVariable, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void fakeReachable(ASTNode location) { int sourceStart = location.sourceStart; int sourceEnd = location.sourceEnd; if (location instanceof LocalDeclaration) { LocalDeclaration declaration = (LocalDeclaration) location; sourceStart = declaration.declarationSourceStart; sourceEnd = declaration.declarationSourceEnd; } this.handle( IProblem.DeadCode, NoArgument, NoArgument, sourceStart, sourceEnd); } public void fieldHiding(FieldDeclaration fieldDecl, Binding hiddenVariable) { FieldBinding field = fieldDecl.binding; if (CharOperation.equals(TypeConstants.SERIALVERSIONUID, field.name) && field.isStatic() && field.isPrivate() && field.isFinal() && TypeBinding.LONG == field.type) { ReferenceBinding referenceBinding = field.declaringClass; if (referenceBinding != null) { if (referenceBinding.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) { return; // do not report field hiding for serialVersionUID field for class that implements Serializable } } } if (CharOperation.equals(TypeConstants.SERIALPERSISTENTFIELDS, field.name) && field.isStatic() && field.isPrivate() && field.isFinal() && field.type.dimensions() == 1 && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTSTREAMFIELD, field.type.leafComponentType().readableName())) { ReferenceBinding referenceBinding = field.declaringClass; if (referenceBinding != null) { if (referenceBinding.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) { return; // do not report field hiding for serialPersistenFields field for class that implements Serializable } } } boolean isLocal = hiddenVariable instanceof LocalVariableBinding; int severity = computeSeverity(isLocal ? IProblem.FieldHidingLocalVariable : IProblem.FieldHidingField); if (severity == ProblemSeverities.Ignore) return; if (isLocal) { this.handle( IProblem.FieldHidingLocalVariable, new String[] {new String(field.declaringClass.readableName()), new String(field.name) }, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name) }, severity, nodeSourceStart(hiddenVariable, fieldDecl), nodeSourceEnd(hiddenVariable, fieldDecl)); } else if (hiddenVariable instanceof FieldBinding) { FieldBinding hiddenField = (FieldBinding) hiddenVariable; this.handle( IProblem.FieldHidingField, new String[] {new String(field.declaringClass.readableName()), new String(field.name) , new String(hiddenField.declaringClass.readableName()) }, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name) , new String(hiddenField.declaringClass.shortReadableName()) }, severity, nodeSourceStart(hiddenField, fieldDecl), nodeSourceEnd(hiddenField, fieldDecl)); } } public void fieldsOrThisBeforeConstructorInvocation(ThisReference reference) { this.handle( IProblem.ThisSuperDuringConstructorInvocation, NoArgument, NoArgument, reference.sourceStart, reference.sourceEnd); } public void finallyMustCompleteNormally(Block finallyBlock) { this.handle( IProblem.FinallyMustCompleteNormally, NoArgument, NoArgument, finallyBlock.sourceStart, finallyBlock.sourceEnd); } public void finalMethodCannotBeOverridden(MethodBinding currentMethod, MethodBinding inheritedMethod) { this.handle( // Cannot override the final method from %1 // 8.4.3.3 - Final methods cannot be overridden or hidden. IProblem.FinalMethodCannotBeOverridden, new String[] {new String(inheritedMethod.declaringClass.readableName())}, new String[] {new String(inheritedMethod.declaringClass.shortReadableName())}, currentMethod.sourceStart(), currentMethod.sourceEnd()); } public void finalVariableBound(TypeVariableBinding typeVariable, TypeReference typeRef) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; int severity = computeSeverity(IProblem.FinalBoundForTypeVariable); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.FinalBoundForTypeVariable, new String[] { new String(typeVariable.sourceName), new String(typeRef.resolvedType.readableName())}, new String[] { new String(typeVariable.sourceName), new String(typeRef.resolvedType.shortReadableName())}, severity, typeRef.sourceStart, typeRef.sourceEnd); } /** @param classpathEntryType one of {@link AccessRestriction#COMMAND_LINE}, * {@link AccessRestriction#LIBRARY}, {@link AccessRestriction#PROJECT} */ public void forbiddenReference(FieldBinding field, ASTNode location, byte classpathEntryType, String classpathEntryName, int problemId) { int severity = computeSeverity(problemId); if (severity == ProblemSeverities.Ignore) return; this.handle( problemId, new String[] { new String(field.readableName()) }, // distinct from msg arg for quickfix purpose getElaborationId(IProblem.ForbiddenReference, (byte) (FIELD_ACCESS | classpathEntryType)), new String[] { classpathEntryName, new String(field.shortReadableName()), new String(field.declaringClass.shortReadableName())}, severity, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } /** @param classpathEntryType one of {@link AccessRestriction#COMMAND_LINE}, * {@link AccessRestriction#LIBRARY}, {@link AccessRestriction#PROJECT} */ public void forbiddenReference(MethodBinding method, ASTNode location, byte classpathEntryType, String classpathEntryName, int problemId) { int severity = computeSeverity(problemId); if (severity == ProblemSeverities.Ignore) return; if (method.isConstructor()) this.handle( problemId, new String[] { new String(method.readableName()) }, // distinct from msg arg for quickfix purpose getElaborationId(IProblem.ForbiddenReference, (byte) (CONSTRUCTOR_ACCESS | classpathEntryType)), new String[] { classpathEntryName, new String(method.shortReadableName())}, severity, location.sourceStart, location.sourceEnd); else this.handle( problemId, new String[] { new String(method.readableName()) }, // distinct from msg arg for quickfix purpose getElaborationId(IProblem.ForbiddenReference, (byte) (METHOD_ACCESS | classpathEntryType)), new String[] { classpathEntryName, new String(method.shortReadableName()), new String(method.declaringClass.shortReadableName())}, severity, location.sourceStart, location.sourceEnd); } /** @param classpathEntryType one of {@link AccessRestriction#COMMAND_LINE}, * {@link AccessRestriction#LIBRARY}, {@link AccessRestriction#PROJECT} */ public void forbiddenReference(TypeBinding type, ASTNode location, byte classpathEntryType, String classpathEntryName, int problemId) { if (location == null) return; int severity = computeSeverity(problemId); if (severity == ProblemSeverities.Ignore) return; this.handle( problemId, new String[] { new String(type.readableName()) }, // distinct from msg arg for quickfix purpose getElaborationId(IProblem.ForbiddenReference, /* TYPE_ACCESS | */ classpathEntryType), // TYPE_ACCESS values to 0 new String[] { classpathEntryName, new String(type.shortReadableName())}, severity, location.sourceStart, location.sourceEnd); } public void forwardReference(Reference reference, int indexInQualification, FieldBinding field) { this.handle( IProblem.ReferenceToForwardField, NoArgument, NoArgument, nodeSourceStart(field, reference, indexInQualification), nodeSourceEnd(field, reference, indexInQualification)); } public void forwardTypeVariableReference(ASTNode location, TypeVariableBinding type) { this.handle( IProblem.ReferenceToForwardTypeVariable, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void genericTypeCannotExtendThrowable(TypeDeclaration typeDecl) { ASTNode location = typeDecl.binding.isAnonymousType() ? typeDecl.allocation.type : typeDecl.superclass; this.handle( IProblem.GenericTypeCannotExtendThrowable, new String[]{ new String(typeDecl.binding.readableName()) }, new String[]{ new String(typeDecl.binding.shortReadableName()) }, location.sourceStart, location.sourceEnd); } // use this private API when the compilation unit result can be found through the // reference context. Otherwise, use the other API taking a problem and a compilation result // as arguments private void handle( int problemId, String[] problemArguments, int elaborationId, String[] messageArguments, int severity, int problemStartPosition, int problemEndPosition){ this.handle( problemId, problemArguments, elaborationId, messageArguments, severity, problemStartPosition, problemEndPosition, this.referenceContext, this.referenceContext == null ? null : this.referenceContext.compilationResult()); this.referenceContext = null; } // use this private API when the compilation unit result can be found through the // reference context. Otherwise, use the other API taking a problem and a compilation result // as arguments private void handle( int problemId, String[] problemArguments, String[] messageArguments, int problemStartPosition, int problemEndPosition){ this.handle( problemId, problemArguments, messageArguments, problemStartPosition, problemEndPosition, this.referenceContext, this.referenceContext == null ? null : this.referenceContext.compilationResult()); this.referenceContext = null; } // use this private API when the compilation unit result cannot be found through the // reference context. private void handle( int problemId, String[] problemArguments, String[] messageArguments, int problemStartPosition, int problemEndPosition, CompilationResult unitResult){ this.handle( problemId, problemArguments, messageArguments, problemStartPosition, problemEndPosition, this.referenceContext, unitResult); this.referenceContext = null; } // use this private API when the compilation unit result can be found through the // reference context. Otherwise, use the other API taking a problem and a compilation result // as arguments private void handle( int problemId, String[] problemArguments, String[] messageArguments, int severity, int problemStartPosition, int problemEndPosition){ this.handle( problemId, problemArguments, 0, // no elaboration messageArguments, severity, problemStartPosition, problemEndPosition); } public void hiddenCatchBlock(ReferenceBinding exceptionType, ASTNode location) { this.handle( IProblem.MaskedCatch, new String[] { new String(exceptionType.readableName()), }, new String[] { new String(exceptionType.shortReadableName()), }, location.sourceStart, location.sourceEnd); } public void hierarchyCircularity(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) { int start = 0; int end = 0; if (reference == null) { // can only happen when java.lang.Object is busted start = sourceType.sourceStart(); end = sourceType.sourceEnd(); } else { start = reference.sourceStart; end = reference.sourceEnd; } if (sourceType == superType) this.handle( IProblem.HierarchyCircularitySelfReference, new String[] {new String(sourceType.readableName()) }, new String[] {new String(sourceType.shortReadableName()) }, start, end); else this.handle( IProblem.HierarchyCircularity, new String[] {new String(sourceType.readableName()), new String(superType.readableName())}, new String[] {new String(sourceType.shortReadableName()), new String(superType.shortReadableName())}, start, end); } public void hierarchyCircularity(TypeVariableBinding type, ReferenceBinding superType, TypeReference reference) { int start = 0; int end = 0; start = reference.sourceStart; end = reference.sourceEnd; if (type == superType) this.handle( IProblem.HierarchyCircularitySelfReference, new String[] {new String(type.readableName()) }, new String[] {new String(type.shortReadableName()) }, start, end); else this.handle( IProblem.HierarchyCircularity, new String[] {new String(type.readableName()), new String(superType.readableName())}, new String[] {new String(type.shortReadableName()), new String(superType.shortReadableName())}, start, end); } public void hierarchyHasProblems(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.HierarchyHasProblems, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalAbstractModifierCombinationForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) { String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)}; this.handle( IProblem.IllegalAbstractModifierCombinationForMethod, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd); } public void illegalAccessFromTypeVariable(TypeVariableBinding variable, ASTNode location) { if ((location.bits & ASTNode.InsideJavadoc)!= 0) { javadocInvalidReference(location.sourceStart, location.sourceEnd); } else { String[] arguments = new String[] { new String(variable.sourceName) }; this.handle( IProblem.IllegalAccessFromTypeVariable, arguments, arguments, location.sourceStart, location.sourceEnd); } } public void illegalClassLiteralForTypeVariable(TypeVariableBinding variable, ASTNode location) { String[] arguments = new String[] { new String(variable.sourceName) }; this.handle( IProblem.IllegalClassLiteralForTypeVariable, arguments, arguments, location.sourceStart, location.sourceEnd); } public void illegalExtendedDimensions(AnnotationMethodDeclaration annotationTypeMemberDeclaration) { this.handle( IProblem.IllegalExtendedDimensions, NoArgument, NoArgument, annotationTypeMemberDeclaration.sourceStart, annotationTypeMemberDeclaration.sourceEnd); } public void illegalExtendedDimensions(Argument argument) { this.handle( IProblem.IllegalExtendedDimensionsForVarArgs, NoArgument, NoArgument, argument.sourceStart, argument.sourceEnd); } public void illegalGenericArray(TypeBinding leafComponentType, ASTNode location) { this.handle( IProblem.IllegalGenericArray, new String[]{ new String(leafComponentType.readableName())}, new String[]{ new String(leafComponentType.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void illegalInstanceOfGenericType(TypeBinding checkedType, ASTNode location) { TypeBinding erasedType = checkedType.leafComponentType().erasure(); StringBuffer recommendedFormBuffer = new StringBuffer(10); if (erasedType instanceof ReferenceBinding) { ReferenceBinding referenceBinding = (ReferenceBinding) erasedType; recommendedFormBuffer.append(referenceBinding.qualifiedSourceName()); } else { recommendedFormBuffer.append(erasedType.sourceName()); } int count = erasedType.typeVariables().length; if (count > 0) { recommendedFormBuffer.append('<'); for (int i = 0; i < count; i++) { if (i > 0) { recommendedFormBuffer.append(','); } recommendedFormBuffer.append('?'); } recommendedFormBuffer.append('>'); } for (int i = 0, dim = checkedType.dimensions(); i < dim; i++) { recommendedFormBuffer.append("[]"); //$NON-NLS-1$ } String recommendedForm = recommendedFormBuffer.toString(); if (checkedType.leafComponentType().isTypeVariable()) { this.handle( IProblem.IllegalInstanceofTypeParameter, new String[] { new String(checkedType.readableName()), recommendedForm, }, new String[] { new String(checkedType.shortReadableName()), recommendedForm, }, location.sourceStart, location.sourceEnd); return; } this.handle( IProblem.IllegalInstanceofParameterizedType, new String[] { new String(checkedType.readableName()), recommendedForm, }, new String[] { new String(checkedType.shortReadableName()), recommendedForm, }, location.sourceStart, location.sourceEnd); } public void illegalLocalTypeDeclaration(TypeDeclaration typeDeclaration) { if (isRecoveredName(typeDeclaration.name)) return; int problemID = 0; if ((typeDeclaration.modifiers & ClassFileConstants.AccEnum) != 0) { problemID = IProblem.CannotDefineEnumInLocalType; } else if ((typeDeclaration.modifiers & ClassFileConstants.AccAnnotation) != 0) { problemID = IProblem.CannotDefineAnnotationInLocalType; } else if ((typeDeclaration.modifiers & ClassFileConstants.AccInterface) != 0) { problemID = IProblem.CannotDefineInterfaceInLocalType; } if (problemID != 0) { String[] arguments = new String[] {new String(typeDeclaration.name)}; this.handle( problemID, arguments, arguments, typeDeclaration.sourceStart, typeDeclaration.sourceEnd); } } public void illegalModifierCombinationFinalAbstractForClass(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierCombinationFinalAbstractForClass, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierCombinationFinalVolatileForField(ReferenceBinding type, FieldDeclaration fieldDecl) { String[] arguments = new String[] {new String(fieldDecl.name)}; this.handle( IProblem.IllegalModifierCombinationFinalVolatileForField, arguments, arguments, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void illegalModifierForAnnotationField(FieldDeclaration fieldDecl) { String name = new String(fieldDecl.name); this.handle( IProblem.IllegalModifierForAnnotationField, new String[] { new String(fieldDecl.binding.declaringClass.readableName()), name, }, new String[] { new String(fieldDecl.binding.declaringClass.shortReadableName()), name, }, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void illegalModifierForAnnotationMember(AbstractMethodDeclaration methodDecl) { this.handle( IProblem.IllegalModifierForAnnotationMethod, new String[] { new String(methodDecl.binding.declaringClass.readableName()), new String(methodDecl.selector), }, new String[] { new String(methodDecl.binding.declaringClass.shortReadableName()), new String(methodDecl.selector), }, methodDecl.sourceStart, methodDecl.sourceEnd); } public void illegalModifierForAnnotationMemberType(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForAnnotationMemberType, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForAnnotationType(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForAnnotationType, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForClass(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForClass, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForEnum(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForEnum, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForEnumConstant(ReferenceBinding type, FieldDeclaration fieldDecl) { String[] arguments = new String[] {new String(fieldDecl.name)}; this.handle( IProblem.IllegalModifierForEnumConstant, arguments, arguments, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void illegalModifierForEnumConstructor(AbstractMethodDeclaration constructor) { this.handle( IProblem.IllegalModifierForEnumConstructor, NoArgument, NoArgument, constructor.sourceStart, constructor.sourceEnd); } public void illegalModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) { String[] arguments = new String[] {new String(fieldDecl.name)}; this.handle( IProblem.IllegalModifierForField, arguments, arguments, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void illegalModifierForInterface(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForInterface, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForInterfaceField(FieldDeclaration fieldDecl) { String name = new String(fieldDecl.name); this.handle( IProblem.IllegalModifierForInterfaceField, new String[] { new String(fieldDecl.binding.declaringClass.readableName()), name, }, new String[] { new String(fieldDecl.binding.declaringClass.shortReadableName()), name, }, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void illegalModifierForInterfaceMethod(AbstractMethodDeclaration methodDecl) { // cannot include parameter types since they are not resolved yet // and the error message would be too long this.handle( IProblem.IllegalModifierForInterfaceMethod, new String[] { new String(methodDecl.selector) }, new String[] { new String(methodDecl.selector) }, methodDecl.sourceStart, methodDecl.sourceEnd); } public void illegalModifierForLocalClass(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForLocalClass, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForMemberClass(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForMemberClass, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForMemberEnum(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForMemberEnum, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForMemberInterface(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalModifierForMemberInterface, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalModifierForMethod(AbstractMethodDeclaration methodDecl) { // cannot include parameter types since they are not resolved yet // and the error message would be too long this.handle( methodDecl.isConstructor() ? IProblem.IllegalModifierForConstructor : IProblem.IllegalModifierForMethod, new String[] { new String(methodDecl.selector) }, new String[] { new String(methodDecl.selector) }, methodDecl.sourceStart, methodDecl.sourceEnd); } public void illegalModifierForVariable(LocalDeclaration localDecl, boolean complainAsArgument) { String[] arguments = new String[] {new String(localDecl.name)}; this.handle( complainAsArgument ? IProblem.IllegalModifierForArgument : IProblem.IllegalModifierForVariable, arguments, arguments, localDecl.sourceStart, localDecl.sourceEnd); } public void illegalPrimitiveOrArrayTypeForEnclosingInstance(TypeBinding enclosingType, ASTNode location) { this.handle( IProblem.IllegalPrimitiveOrArrayTypeForEnclosingInstance, new String[] {new String(enclosingType.readableName())}, new String[] {new String(enclosingType.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void illegalQualifiedParameterizedTypeAllocation(TypeReference qualifiedTypeReference, TypeBinding allocatedType) { this.handle( IProblem.IllegalQualifiedParameterizedTypeAllocation, new String[] { new String(allocatedType.readableName()), new String(allocatedType.enclosingType().readableName()), }, new String[] { new String(allocatedType.shortReadableName()), new String(allocatedType.enclosingType().shortReadableName()), }, qualifiedTypeReference.sourceStart, qualifiedTypeReference.sourceEnd); } public void illegalStaticModifierForMemberType(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalStaticModifierForMemberType, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalUsageOfQualifiedTypeReference(QualifiedTypeReference qualifiedTypeReference) { StringBuffer buffer = new StringBuffer(); char[][] tokens = qualifiedTypeReference.tokens; for (int i = 0; i < tokens.length; i++) { if (i > 0) buffer.append('.'); buffer.append(tokens[i]); } String[] arguments = new String[] { String.valueOf(buffer)}; this.handle( IProblem.IllegalUsageOfQualifiedTypeReference, arguments, arguments, qualifiedTypeReference.sourceStart, qualifiedTypeReference.sourceEnd); } public void illegalUsageOfWildcard(TypeReference wildcard) { this.handle( IProblem.InvalidUsageOfWildcard, NoArgument, NoArgument, wildcard.sourceStart, wildcard.sourceEnd); } public void illegalVararg(Argument argType, AbstractMethodDeclaration methodDecl) { String[] arguments = new String[] {CharOperation.toString(argType.type.getTypeName()), new String(methodDecl.selector)}; this.handle( IProblem.IllegalVararg, arguments, arguments, argType.sourceStart, argType.sourceEnd); } public void illegalVisibilityModifierCombinationForField(ReferenceBinding type, FieldDeclaration fieldDecl) { String[] arguments = new String[] {new String(fieldDecl.name)}; this.handle( IProblem.IllegalVisibilityModifierCombinationForField, arguments, arguments, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void illegalVisibilityModifierCombinationForMemberType(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalVisibilityModifierCombinationForMemberType, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalVisibilityModifierCombinationForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) { String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)}; this.handle( IProblem.IllegalVisibilityModifierCombinationForMethod, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd); } public void illegalVisibilityModifierForInterfaceMemberType(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.IllegalVisibilityModifierForInterfaceMemberType, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void illegalVoidExpression(ASTNode location) { this.handle( IProblem.InvalidVoidExpression, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void importProblem(ImportReference importRef, Binding expectedImport) { if (expectedImport instanceof FieldBinding) { int id = IProblem.UndefinedField; FieldBinding field = (FieldBinding) expectedImport; String[] readableArguments = null; String[] shortArguments = null; switch (expectedImport.problemId()) { case ProblemReasons.NotVisible : id = IProblem.NotVisibleField; readableArguments = new String[] {CharOperation.toString(importRef.tokens), new String(field.declaringClass.readableName())}; shortArguments = new String[] {CharOperation.toString(importRef.tokens), new String(field.declaringClass.shortReadableName())}; break; case ProblemReasons.Ambiguous : id = IProblem.AmbiguousField; readableArguments = new String[] {new String(field.readableName())}; shortArguments = new String[] {new String(field.readableName())}; break; case ProblemReasons.ReceiverTypeNotVisible : id = IProblem.NotVisibleType; readableArguments = new String[] {new String(field.declaringClass.leafComponentType().readableName())}; shortArguments = new String[] {new String(field.declaringClass.leafComponentType().shortReadableName())}; break; } this.handle( id, readableArguments, shortArguments, nodeSourceStart(field, importRef), nodeSourceEnd(field, importRef)); return; } if (expectedImport.problemId() == ProblemReasons.NotFound) { char[][] tokens = expectedImport instanceof ProblemReferenceBinding ? ((ProblemReferenceBinding) expectedImport).compoundName : importRef.tokens; String[] arguments = new String[]{CharOperation.toString(tokens)}; this.handle( IProblem.ImportNotFound, arguments, arguments, importRef.sourceStart, (int) importRef.sourcePositions[tokens.length - 1]); return; } if (expectedImport.problemId() == ProblemReasons.InvalidTypeForStaticImport) { char[][] tokens = importRef.tokens; String[] arguments = new String[]{CharOperation.toString(tokens)}; this.handle( IProblem.InvalidTypeForStaticImport, arguments, arguments, importRef.sourceStart, (int) importRef.sourcePositions[tokens.length - 1]); return; } invalidType(importRef, (TypeBinding)expectedImport); } public void incompatibleExceptionInThrowsClause(SourceTypeBinding type, MethodBinding currentMethod, MethodBinding inheritedMethod, ReferenceBinding exceptionType) { if (type == currentMethod.declaringClass) { int id; if (currentMethod.declaringClass.isInterface() && !inheritedMethod.isPublic()){ // interface inheriting Object protected method id = IProblem.IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod; } else { id = IProblem.IncompatibleExceptionInThrowsClause; } this.handle( // Exception %1 is not compatible with throws clause in %2 // 9.4.4 - The type of exception in the throws clause is incompatible. id, new String[] { new String(exceptionType.sourceName()), new String( CharOperation.concat( inheritedMethod.declaringClass.readableName(), inheritedMethod.readableName(), '.'))}, new String[] { new String(exceptionType.sourceName()), new String( CharOperation.concat( inheritedMethod.declaringClass.shortReadableName(), inheritedMethod.shortReadableName(), '.'))}, currentMethod.sourceStart(), currentMethod.sourceEnd()); } else this.handle( // Exception %1 in throws clause of %2 is not compatible with %3 // 9.4.4 - The type of exception in the throws clause is incompatible. IProblem.IncompatibleExceptionInInheritedMethodThrowsClause, new String[] { new String(exceptionType.sourceName()), new String( CharOperation.concat( currentMethod.declaringClass.sourceName(), currentMethod.readableName(), '.')), new String( CharOperation.concat( inheritedMethod.declaringClass.readableName(), inheritedMethod.readableName(), '.'))}, new String[] { new String(exceptionType.sourceName()), new String( CharOperation.concat( currentMethod.declaringClass.sourceName(), currentMethod.shortReadableName(), '.')), new String( CharOperation.concat( inheritedMethod.declaringClass.shortReadableName(), inheritedMethod.shortReadableName(), '.'))}, type.sourceStart(), type.sourceEnd()); } public void incompatibleReturnType(MethodBinding currentMethod, MethodBinding inheritedMethod) { StringBuffer methodSignature = new StringBuffer(); methodSignature .append(inheritedMethod.declaringClass.readableName()) .append('.') .append(inheritedMethod.readableName()); StringBuffer shortSignature = new StringBuffer(); shortSignature .append(inheritedMethod.declaringClass.shortReadableName()) .append('.') .append(inheritedMethod.shortReadableName()); int id; final ReferenceBinding declaringClass = currentMethod.declaringClass; if (declaringClass.isInterface() && !inheritedMethod.isPublic()){ // interface inheriting Object protected method id = IProblem.IncompatibleReturnTypeForNonInheritedInterfaceMethod; } else { id = IProblem.IncompatibleReturnType; } AbstractMethodDeclaration method = currentMethod.sourceMethod(); int sourceStart = 0; int sourceEnd = 0; if (method == null) { if (declaringClass instanceof SourceTypeBinding) { SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) declaringClass; sourceStart = sourceTypeBinding.sourceStart(); sourceEnd = sourceTypeBinding.sourceEnd(); } } else if (method.isConstructor()){ sourceStart = method.sourceStart; sourceEnd = method.sourceEnd; } else { TypeReference returnType = ((MethodDeclaration) method).returnType; sourceStart = returnType.sourceStart; if (returnType instanceof ParameterizedSingleTypeReference) { ParameterizedSingleTypeReference typeReference = (ParameterizedSingleTypeReference) returnType; TypeReference[] typeArguments = typeReference.typeArguments; if (typeArguments[typeArguments.length - 1].sourceEnd > typeReference.sourceEnd) { sourceEnd = retrieveClosingAngleBracketPosition(typeReference.sourceEnd); } else { sourceEnd = returnType.sourceEnd; } } else if (returnType instanceof ParameterizedQualifiedTypeReference) { ParameterizedQualifiedTypeReference typeReference = (ParameterizedQualifiedTypeReference) returnType; sourceEnd = retrieveClosingAngleBracketPosition(typeReference.sourceEnd); } else { sourceEnd = returnType.sourceEnd; } } this.handle( id, new String[] {methodSignature.toString()}, new String[] {shortSignature.toString()}, sourceStart, sourceEnd); } public void incorrectArityForParameterizedType(ASTNode location, TypeBinding type, TypeBinding[] argumentTypes) { incorrectArityForParameterizedType(location, type, argumentTypes, Integer.MAX_VALUE); } public void incorrectArityForParameterizedType(ASTNode location, TypeBinding type, TypeBinding[] argumentTypes, int index) { if (location == null) { this.handle( IProblem.IncorrectArityForParameterizedType, new String[] {new String(type.readableName()), typesAsString(argumentTypes, false)}, new String[] {new String(type.shortReadableName()), typesAsString(argumentTypes, true)}, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); return; // not reached since aborted above } this.handle( IProblem.IncorrectArityForParameterizedType, new String[] {new String(type.readableName()), typesAsString(argumentTypes, false)}, new String[] {new String(type.shortReadableName()), typesAsString(argumentTypes, true)}, location.sourceStart, nodeSourceEnd(null, location, index)); } public void diamondNotBelow17(ASTNode location) { diamondNotBelow17(location, Integer.MAX_VALUE); } public void diamondNotBelow17(ASTNode location, int index) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=348493 if (location == null) { this.handle( IProblem.DiamondNotBelow17, NoArgument, NoArgument, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); return; // not reached since aborted above } this.handle( IProblem.DiamondNotBelow17, NoArgument, NoArgument, location.sourceStart, nodeSourceEnd(null, location, index)); } public void incorrectLocationForNonEmptyDimension(ArrayAllocationExpression expression, int index) { this.handle( IProblem.IllegalDimension, NoArgument, NoArgument, expression.dimensions[index].sourceStart, expression.dimensions[index].sourceEnd); } public void incorrectSwitchType(Expression expression, TypeBinding testType) { if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { if (testType.id == TypeIds.T_JavaLangString) { this.handle( IProblem.SwitchOnStringsNotBelow17, new String[] {new String(testType.readableName())}, new String[] {new String(testType.shortReadableName())}, expression.sourceStart, expression.sourceEnd); } else { if (this.options.sourceLevel < ClassFileConstants.JDK1_5 && testType.isEnum()) { this.handle( IProblem.SwitchOnEnumNotBelow15, new String[] {new String(testType.readableName())}, new String[] {new String(testType.shortReadableName())}, expression.sourceStart, expression.sourceEnd); } else { this.handle( IProblem.IncorrectSwitchType, new String[] {new String(testType.readableName())}, new String[] {new String(testType.shortReadableName())}, expression.sourceStart, expression.sourceEnd); } } } else { this.handle( IProblem.IncorrectSwitchType17, new String[] {new String(testType.readableName())}, new String[] {new String(testType.shortReadableName())}, expression.sourceStart, expression.sourceEnd); } } public void indirectAccessToStaticField(ASTNode location, FieldBinding field){ int severity = computeSeverity(IProblem.IndirectAccessToStaticField); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.IndirectAccessToStaticField, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, severity, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void indirectAccessToStaticMethod(ASTNode location, MethodBinding method) { int severity = computeSeverity(IProblem.IndirectAccessToStaticMethod); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.IndirectAccessToStaticMethod, new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, severity, location.sourceStart, location.sourceEnd); } private void inheritedMethodReducesVisibility(int sourceStart, int sourceEnd, MethodBinding concreteMethod, MethodBinding[] abstractMethods) { StringBuffer concreteSignature = new StringBuffer(); concreteSignature .append(concreteMethod.declaringClass.readableName()) .append('.') .append(concreteMethod.readableName()); StringBuffer shortSignature = new StringBuffer(); shortSignature .append(concreteMethod.declaringClass.shortReadableName()) .append('.') .append(concreteMethod.shortReadableName()); this.handle( // The inherited method %1 cannot hide the public abstract method in %2 IProblem.InheritedMethodReducesVisibility, new String[] { concreteSignature.toString(), new String(abstractMethods[0].declaringClass.readableName())}, new String[] { shortSignature.toString(), new String(abstractMethods[0].declaringClass.shortReadableName())}, sourceStart, sourceEnd); } public void inheritedMethodReducesVisibility(SourceTypeBinding type, MethodBinding concreteMethod, MethodBinding[] abstractMethods) { inheritedMethodReducesVisibility(type.sourceStart(), type.sourceEnd(), concreteMethod, abstractMethods); } public void inheritedMethodReducesVisibility(TypeParameter typeParameter, MethodBinding concreteMethod, MethodBinding[] abstractMethods) { inheritedMethodReducesVisibility(typeParameter.sourceStart(), typeParameter.sourceEnd(), concreteMethod, abstractMethods); } public void inheritedMethodsHaveIncompatibleReturnTypes(ASTNode location, MethodBinding[] inheritedMethods, int length) { StringBuffer methodSignatures = new StringBuffer(); StringBuffer shortSignatures = new StringBuffer(); for (int i = length; --i >= 0;) { methodSignatures .append(inheritedMethods[i].declaringClass.readableName()) .append('.') .append(inheritedMethods[i].readableName()); shortSignatures .append(inheritedMethods[i].declaringClass.shortReadableName()) .append('.') .append(inheritedMethods[i].shortReadableName()); if (i != 0){ methodSignatures.append(", "); //$NON-NLS-1$ shortSignatures.append(", "); //$NON-NLS-1$ } } this.handle( // Return type is incompatible with %1 // 9.4.2 - The return type from the method is incompatible with the declaration. IProblem.InheritedIncompatibleReturnType, new String[] {methodSignatures.toString()}, new String[] {shortSignatures.toString()}, location.sourceStart, location.sourceEnd); } public void inheritedMethodsHaveIncompatibleReturnTypes(SourceTypeBinding type, MethodBinding[] inheritedMethods, int length, boolean[] isOverridden) { StringBuffer methodSignatures = new StringBuffer(); StringBuffer shortSignatures = new StringBuffer(); for (int i = length; --i >= 0;) { if (isOverridden[i]) continue; methodSignatures .append(inheritedMethods[i].declaringClass.readableName()) .append('.') .append(inheritedMethods[i].readableName()); shortSignatures .append(inheritedMethods[i].declaringClass.shortReadableName()) .append('.') .append(inheritedMethods[i].shortReadableName()); if (i != 0){ methodSignatures.append(", "); //$NON-NLS-1$ shortSignatures.append(", "); //$NON-NLS-1$ } } this.handle( // Return type is incompatible with %1 // 9.4.2 - The return type from the method is incompatible with the declaration. IProblem.InheritedIncompatibleReturnType, new String[] {methodSignatures.toString()}, new String[] {shortSignatures.toString()}, type.sourceStart(), type.sourceEnd()); } public void inheritedMethodsHaveNameClash(SourceTypeBinding type, MethodBinding oneMethod, MethodBinding twoMethod) { this.handle( IProblem.MethodNameClash, new String[] { new String(oneMethod.selector), typesAsString(oneMethod.original(), false), new String(oneMethod.declaringClass.readableName()), typesAsString(twoMethod.original(), false), new String(twoMethod.declaringClass.readableName()), }, new String[] { new String(oneMethod.selector), typesAsString(oneMethod.original(), true), new String(oneMethod.declaringClass.shortReadableName()), typesAsString(twoMethod.original(), true), new String(twoMethod.declaringClass.shortReadableName()), }, type.sourceStart(), type.sourceEnd()); } public void initializerMustCompleteNormally(FieldDeclaration fieldDecl) { this.handle( IProblem.InitializerMustCompleteNormally, NoArgument, NoArgument, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void innerTypesCannotDeclareStaticInitializers(ReferenceBinding innerType, Initializer initializer) { this.handle( IProblem.CannotDefineStaticInitializerInLocalType, new String[] {new String(innerType.readableName())}, new String[] {new String(innerType.shortReadableName())}, initializer.sourceStart, initializer.sourceStart); } public void interfaceCannotHaveConstructors(ConstructorDeclaration constructor) { this.handle( IProblem.InterfaceCannotHaveConstructors, NoArgument, NoArgument, constructor.sourceStart, constructor.sourceEnd, constructor, constructor.compilationResult()); } public void interfaceCannotHaveInitializers(char [] sourceName, FieldDeclaration fieldDecl) { String[] arguments = new String[] {new String(sourceName)}; this.handle( IProblem.InterfaceCannotHaveInitializers, arguments, arguments, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void invalidAnnotationMemberType(MethodDeclaration methodDecl) { this.handle( IProblem.InvalidAnnotationMemberType, new String[] { new String(methodDecl.binding.returnType.readableName()), new String(methodDecl.selector), new String(methodDecl.binding.declaringClass.readableName()), }, new String[] { new String(methodDecl.binding.returnType.shortReadableName()), new String(methodDecl.selector), new String(methodDecl.binding.declaringClass.shortReadableName()), }, methodDecl.returnType.sourceStart, methodDecl.returnType.sourceEnd); } public void invalidBreak(ASTNode location) { this.handle( IProblem.InvalidBreak, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void invalidConstructor(Statement statement, MethodBinding targetConstructor) { boolean insideDefaultConstructor = (this.referenceContext instanceof ConstructorDeclaration) && ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor(); boolean insideImplicitConstructorCall = (statement instanceof ExplicitConstructorCall) && (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper); int sourceStart = statement.sourceStart; int sourceEnd = statement.sourceEnd; if (statement instanceof AllocationExpression) { AllocationExpression allocation = (AllocationExpression)statement; if (allocation.enumConstant != null) { sourceStart = allocation.enumConstant.sourceStart; sourceEnd = allocation.enumConstant.sourceEnd; } } int id = IProblem.UndefinedConstructor; //default... MethodBinding shownConstructor = targetConstructor; switch (targetConstructor.problemId()) { case ProblemReasons.NotFound : ProblemMethodBinding problemConstructor = (ProblemMethodBinding) targetConstructor; if (problemConstructor.closestMatch != null) { if ((problemConstructor.closestMatch.tagBits & TagBits.HasMissingType) != 0) { missingTypeInConstructor(statement, problemConstructor.closestMatch); return; } } if (insideDefaultConstructor){ id = IProblem.UndefinedConstructorInDefaultConstructor; } else if (insideImplicitConstructorCall){ id = IProblem.UndefinedConstructorInImplicitConstructorCall; } else { id = IProblem.UndefinedConstructor; } break; case ProblemReasons.NotVisible : if (insideDefaultConstructor){ id = IProblem.NotVisibleConstructorInDefaultConstructor; } else if (insideImplicitConstructorCall){ id = IProblem.NotVisibleConstructorInImplicitConstructorCall; } else { id = IProblem.NotVisibleConstructor; } problemConstructor = (ProblemMethodBinding) targetConstructor; if (problemConstructor.closestMatch != null) { shownConstructor = problemConstructor.closestMatch.original(); } break; case ProblemReasons.Ambiguous : if (insideDefaultConstructor){ id = IProblem.AmbiguousConstructorInDefaultConstructor; } else if (insideImplicitConstructorCall){ id = IProblem.AmbiguousConstructorInImplicitConstructorCall; } else { id = IProblem.AmbiguousConstructor; } break; case ProblemReasons.ParameterBoundMismatch : problemConstructor = (ProblemMethodBinding) targetConstructor; ParameterizedGenericMethodBinding substitutedConstructor = (ParameterizedGenericMethodBinding) problemConstructor.closestMatch; shownConstructor = substitutedConstructor.original(); int augmentedLength = problemConstructor.parameters.length; TypeBinding inferredTypeArgument = problemConstructor.parameters[augmentedLength-2]; TypeVariableBinding typeParameter = (TypeVariableBinding) problemConstructor.parameters[augmentedLength-1]; TypeBinding[] invocationArguments = new TypeBinding[augmentedLength-2]; // remove extra info from the end System.arraycopy(problemConstructor.parameters, 0, invocationArguments, 0, augmentedLength-2); this.handle( IProblem.GenericConstructorTypeArgumentMismatch, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(invocationArguments, false), new String(inferredTypeArgument.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(invocationArguments, true), new String(inferredTypeArgument.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) }, sourceStart, sourceEnd); return; case ProblemReasons.TypeParameterArityMismatch : problemConstructor = (ProblemMethodBinding) targetConstructor; shownConstructor = problemConstructor.closestMatch; if (shownConstructor.typeVariables == Binding.NO_TYPE_VARIABLES) { this.handle( IProblem.NonGenericConstructor, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(targetConstructor, true) }, sourceStart, sourceEnd); } else { this.handle( IProblem.IncorrectArityForParameterizedConstructor , new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(shownConstructor.typeVariables, false), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(shownConstructor.typeVariables, true), typesAsString(targetConstructor, true) }, sourceStart, sourceEnd); } return; case ProblemReasons.ParameterizedMethodTypeMismatch : problemConstructor = (ProblemMethodBinding) targetConstructor; shownConstructor = problemConstructor.closestMatch; this.handle( IProblem.ParameterizedConstructorArgumentTypeMismatch, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(((ParameterizedGenericMethodBinding)shownConstructor).typeArguments, false), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(((ParameterizedGenericMethodBinding)shownConstructor).typeArguments, true), typesAsString(targetConstructor, true) }, sourceStart, sourceEnd); return; case ProblemReasons.TypeArgumentsForRawGenericMethod : problemConstructor = (ProblemMethodBinding) targetConstructor; shownConstructor = problemConstructor.closestMatch; this.handle( IProblem.TypeArgumentsForRawGenericConstructor, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(targetConstructor, true) }, sourceStart, sourceEnd); return; case ProblemReasons.VarargsElementTypeNotVisible : problemConstructor = (ProblemMethodBinding) targetConstructor; shownConstructor = problemConstructor.closestMatch; TypeBinding varargsElementType = shownConstructor.parameters[shownConstructor.parameters.length - 1].leafComponentType(); this.handle( IProblem.VarargsElementTypeNotVisibleForConstructor, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), new String(varargsElementType.readableName()) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), new String(varargsElementType.shortReadableName()) }, sourceStart, sourceEnd); return; case ProblemReasons.NoError : // 0 default : needImplementation(statement); // want to fail to see why we were here... break; } this.handle( id, new String[] {new String(targetConstructor.declaringClass.readableName()), typesAsString(shownConstructor, false)}, new String[] {new String(targetConstructor.declaringClass.shortReadableName()), typesAsString(shownConstructor, true)}, sourceStart, sourceEnd); } public void invalidContinue(ASTNode location) { this.handle( IProblem.InvalidContinue, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void invalidEnclosingType(Expression expression, TypeBinding type, ReferenceBinding enclosingType) { if (enclosingType.isAnonymousType()) enclosingType = enclosingType.superclass(); if (enclosingType.sourceName != null && enclosingType.sourceName.length == 0) return; int flag = IProblem.UndefinedType; // default switch (type.problemId()) { case ProblemReasons.NotFound : // 1 flag = IProblem.UndefinedType; break; case ProblemReasons.NotVisible : // 2 flag = IProblem.NotVisibleType; break; case ProblemReasons.Ambiguous : // 3 flag = IProblem.AmbiguousType; break; case ProblemReasons.InternalNameProvided : flag = IProblem.InternalTypeNameProvided; break; case ProblemReasons.NoError : // 0 default : needImplementation(expression); // want to fail to see why we were here... break; } this.handle( flag, new String[] {new String(enclosingType.readableName()) + "." + new String(type.readableName())}, //$NON-NLS-1$ new String[] {new String(enclosingType.shortReadableName()) + "." + new String(type.shortReadableName())}, //$NON-NLS-1$ expression.sourceStart, expression.sourceEnd); } public void invalidExplicitConstructorCall(ASTNode location) { this.handle( IProblem.InvalidExplicitConstructorCall, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void invalidExpressionAsStatement(Expression expression){ this.handle( IProblem.InvalidExpressionAsStatement, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void invalidField(FieldReference fieldRef, TypeBinding searchedType) { if(isRecoveredName(fieldRef.token)) return; int id = IProblem.UndefinedField; FieldBinding field = fieldRef.binding; switch (field.problemId()) { case ProblemReasons.NotFound : if ((searchedType.tagBits & TagBits.HasMissingType) != 0) { this.handle( IProblem.UndefinedType, new String[] {new String(searchedType.leafComponentType().readableName())}, new String[] {new String(searchedType.leafComponentType().shortReadableName())}, fieldRef.receiver.sourceStart, fieldRef.receiver.sourceEnd); return; } id = IProblem.UndefinedField; /* also need to check that the searchedType is the receiver type if (searchedType.isHierarchyInconsistent()) severity = SecondaryError; */ break; case ProblemReasons.NotVisible : this.handle( IProblem.NotVisibleField, new String[] {new String(fieldRef.token), new String(field.declaringClass.readableName())}, new String[] {new String(fieldRef.token), new String(field.declaringClass.shortReadableName())}, nodeSourceStart(field, fieldRef), nodeSourceEnd(field, fieldRef)); return; case ProblemReasons.Ambiguous : id = IProblem.AmbiguousField; break; case ProblemReasons.NonStaticReferenceInStaticContext : id = IProblem.NonStaticFieldFromStaticInvocation; break; case ProblemReasons.NonStaticReferenceInConstructorInvocation : id = IProblem.InstanceFieldDuringConstructorInvocation; break; case ProblemReasons.InheritedNameHidesEnclosingName : id = IProblem.InheritedFieldHidesEnclosingName; break; case ProblemReasons.ReceiverTypeNotVisible : this.handle( IProblem.NotVisibleType, // cannot occur in javadoc comments new String[] {new String(searchedType.leafComponentType().readableName())}, new String[] {new String(searchedType.leafComponentType().shortReadableName())}, fieldRef.receiver.sourceStart, fieldRef.receiver.sourceEnd); return; case ProblemReasons.NoError : // 0 default : needImplementation(fieldRef); // want to fail to see why we were here... break; } String[] arguments = new String[] {new String(field.readableName())}; this.handle( id, arguments, arguments, nodeSourceStart(field, fieldRef), nodeSourceEnd(field, fieldRef)); } public void invalidField(NameReference nameRef, FieldBinding field) { if (nameRef instanceof QualifiedNameReference) { QualifiedNameReference ref = (QualifiedNameReference) nameRef; if (isRecoveredName(ref.tokens)) return; } else { SingleNameReference ref = (SingleNameReference) nameRef; if (isRecoveredName(ref.token)) return; } int id = IProblem.UndefinedField; switch (field.problemId()) { case ProblemReasons.NotFound : TypeBinding declaringClass = field.declaringClass; if (declaringClass != null && (declaringClass.tagBits & TagBits.HasMissingType) != 0) { this.handle( IProblem.UndefinedType, new String[] {new String(field.declaringClass.readableName())}, new String[] {new String(field.declaringClass.shortReadableName())}, nameRef.sourceStart, nameRef.sourceEnd); return; } String[] arguments = new String[] {new String(field.readableName())}; this.handle( id, arguments, arguments, nodeSourceStart(field, nameRef), nodeSourceEnd(field, nameRef)); return; case ProblemReasons.NotVisible : char[] name = field.readableName(); name = CharOperation.lastSegment(name, '.'); this.handle( IProblem.NotVisibleField, new String[] {new String(name), new String(field.declaringClass.readableName())}, new String[] {new String(name), new String(field.declaringClass.shortReadableName())}, nodeSourceStart(field, nameRef), nodeSourceEnd(field, nameRef)); return; case ProblemReasons.Ambiguous : id = IProblem.AmbiguousField; break; case ProblemReasons.NonStaticReferenceInStaticContext : id = IProblem.NonStaticFieldFromStaticInvocation; break; case ProblemReasons.NonStaticReferenceInConstructorInvocation : id = IProblem.InstanceFieldDuringConstructorInvocation; break; case ProblemReasons.InheritedNameHidesEnclosingName : id = IProblem.InheritedFieldHidesEnclosingName; break; case ProblemReasons.ReceiverTypeNotVisible : this.handle( IProblem.NotVisibleType, new String[] {new String(field.declaringClass.readableName())}, new String[] {new String(field.declaringClass.shortReadableName())}, nameRef.sourceStart, nameRef.sourceEnd); return; case ProblemReasons.NoError : // 0 default : needImplementation(nameRef); // want to fail to see why we were here... break; } String[] arguments = new String[] {new String(field.readableName())}; this.handle( id, arguments, arguments, nameRef.sourceStart, nameRef.sourceEnd); } public void invalidField(QualifiedNameReference nameRef, FieldBinding field, int index, TypeBinding searchedType) { //the resolution of the index-th field of qname failed //qname.otherBindings[index] is the binding that has produced the error //The different targetted errors should be : //UndefinedField //NotVisibleField //AmbiguousField if (isRecoveredName(nameRef.tokens)) return; if (searchedType.isBaseType()) { this.handle( IProblem.NoFieldOnBaseType, new String[] { new String(searchedType.readableName()), CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index)), new String(nameRef.tokens[index])}, new String[] { new String(searchedType.sourceName()), CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index)), new String(nameRef.tokens[index])}, nameRef.sourceStart, (int) nameRef.sourcePositions[index]); return; } int id = IProblem.UndefinedField; switch (field.problemId()) { case ProblemReasons.NotFound : if ((searchedType.tagBits & TagBits.HasMissingType) != 0) { this.handle( IProblem.UndefinedType, new String[] {new String(searchedType.leafComponentType().readableName())}, new String[] {new String(searchedType.leafComponentType().shortReadableName())}, nameRef.sourceStart, (int) nameRef.sourcePositions[index-1]); return; } String fieldName = new String(nameRef.tokens[index]); String[] arguments = new String[] {fieldName }; this.handle( id, arguments, arguments, nodeSourceStart(field, nameRef), nodeSourceEnd(field, nameRef)); return; case ProblemReasons.NotVisible : fieldName = new String(nameRef.tokens[index]); this.handle( IProblem.NotVisibleField, new String[] {fieldName, new String(field.declaringClass.readableName())}, new String[] {fieldName, new String(field.declaringClass.shortReadableName())}, nodeSourceStart(field, nameRef), nodeSourceEnd(field, nameRef)); return; case ProblemReasons.Ambiguous : id = IProblem.AmbiguousField; break; case ProblemReasons.NonStaticReferenceInStaticContext : id = IProblem.NonStaticFieldFromStaticInvocation; break; case ProblemReasons.NonStaticReferenceInConstructorInvocation : id = IProblem.InstanceFieldDuringConstructorInvocation; break; case ProblemReasons.InheritedNameHidesEnclosingName : id = IProblem.InheritedFieldHidesEnclosingName; break; case ProblemReasons.ReceiverTypeNotVisible : this.handle( IProblem.NotVisibleType, new String[] {new String(searchedType.leafComponentType().readableName())}, new String[] {new String(searchedType.leafComponentType().shortReadableName())}, nameRef.sourceStart, (int) nameRef.sourcePositions[index-1]); return; case ProblemReasons.NoError : // 0 default : needImplementation(nameRef); // want to fail to see why we were here... break; } String[] arguments = new String[] {CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index + 1))}; this.handle( id, arguments, arguments, nameRef.sourceStart, (int) nameRef.sourcePositions[index]); } public void invalidFileNameForPackageAnnotations(Annotation annotation) { this.handle( IProblem.InvalidFileNameForPackageAnnotations, NoArgument, NoArgument, annotation.sourceStart, annotation.sourceEnd); } public void invalidMethod(MessageSend messageSend, MethodBinding method) { if (isRecoveredName(messageSend.selector)) return; int id = IProblem.UndefinedMethod; //default... MethodBinding shownMethod = method; switch (method.problemId()) { case ProblemReasons.NotFound : if ((method.declaringClass.tagBits & TagBits.HasMissingType) != 0) { this.handle( IProblem.UndefinedType, new String[] {new String(method.declaringClass.readableName())}, new String[] {new String(method.declaringClass.shortReadableName())}, messageSend.receiver.sourceStart, messageSend.receiver.sourceEnd); return; } id = IProblem.UndefinedMethod; ProblemMethodBinding problemMethod = (ProblemMethodBinding) method; if (problemMethod.closestMatch != null) { shownMethod = problemMethod.closestMatch; if ((shownMethod.tagBits & TagBits.HasMissingType) != 0) { missingTypeInMethod(messageSend, shownMethod); return; } String closestParameterTypeNames = typesAsString(shownMethod, false); String parameterTypeNames = typesAsString(problemMethod.parameters, false); String closestParameterTypeShortNames = typesAsString(shownMethod, true); String parameterTypeShortNames = typesAsString(problemMethod.parameters, true); if (closestParameterTypeShortNames.equals(parameterTypeShortNames)) { closestParameterTypeShortNames = closestParameterTypeNames; parameterTypeShortNames = parameterTypeNames; } this.handle( IProblem.ParameterMismatch, new String[] { new String(shownMethod.declaringClass.readableName()), new String(shownMethod.selector), closestParameterTypeNames, parameterTypeNames }, new String[] { new String(shownMethod.declaringClass.shortReadableName()), new String(shownMethod.selector), closestParameterTypeShortNames, parameterTypeShortNames }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; } break; case ProblemReasons.NotVisible : id = IProblem.NotVisibleMethod; problemMethod = (ProblemMethodBinding) method; if (problemMethod.closestMatch != null) { shownMethod = problemMethod.closestMatch.original(); } break; case ProblemReasons.Ambiguous : id = IProblem.AmbiguousMethod; break; case ProblemReasons.InheritedNameHidesEnclosingName : id = IProblem.InheritedMethodHidesEnclosingName; break; case ProblemReasons.NonStaticReferenceInConstructorInvocation : id = IProblem.InstanceMethodDuringConstructorInvocation; break; case ProblemReasons.NonStaticReferenceInStaticContext : id = IProblem.StaticMethodRequested; break; case ProblemReasons.ReceiverTypeNotVisible : this.handle( IProblem.NotVisibleType, // cannot occur in javadoc comments new String[] {new String(method.declaringClass.readableName())}, new String[] {new String(method.declaringClass.shortReadableName())}, messageSend.receiver.sourceStart, messageSend.receiver.sourceEnd); return; case ProblemReasons.ParameterBoundMismatch : problemMethod = (ProblemMethodBinding) method; ParameterizedGenericMethodBinding substitutedMethod = (ParameterizedGenericMethodBinding) problemMethod.closestMatch; shownMethod = substitutedMethod.original(); int augmentedLength = problemMethod.parameters.length; TypeBinding inferredTypeArgument = problemMethod.parameters[augmentedLength-2]; TypeVariableBinding typeParameter = (TypeVariableBinding) problemMethod.parameters[augmentedLength-1]; TypeBinding[] invocationArguments = new TypeBinding[augmentedLength-2]; // remove extra info from the end System.arraycopy(problemMethod.parameters, 0, invocationArguments, 0, augmentedLength-2); this.handle( IProblem.GenericMethodTypeArgumentMismatch, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(invocationArguments, false), new String(inferredTypeArgument.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(invocationArguments, true), new String(inferredTypeArgument.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; case ProblemReasons.TypeParameterArityMismatch : problemMethod = (ProblemMethodBinding) method; shownMethod = problemMethod.closestMatch; if (shownMethod.typeVariables == Binding.NO_TYPE_VARIABLES) { this.handle( IProblem.NonGenericMethod , new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(method, true) }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); } else { this.handle( IProblem.IncorrectArityForParameterizedMethod , new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(shownMethod.typeVariables, false), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(shownMethod.typeVariables, true), typesAsString(method, true) }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); } return; case ProblemReasons.ParameterizedMethodTypeMismatch : problemMethod = (ProblemMethodBinding) method; shownMethod = problemMethod.closestMatch; this.handle( IProblem.ParameterizedMethodArgumentTypeMismatch, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(((ParameterizedGenericMethodBinding)shownMethod).typeArguments, false), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(((ParameterizedGenericMethodBinding)shownMethod).typeArguments, true), typesAsString(method, true) }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; case ProblemReasons.TypeArgumentsForRawGenericMethod : problemMethod = (ProblemMethodBinding) method; shownMethod = problemMethod.closestMatch; this.handle( IProblem.TypeArgumentsForRawGenericMethod , new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(method, true) }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; case ProblemReasons.VarargsElementTypeNotVisible: // https://bugs.eclipse.org/bugs/show_bug.cgi?id=346042 problemMethod = (ProblemMethodBinding) method; if (problemMethod.closestMatch != null) { shownMethod = problemMethod.closestMatch.original(); } TypeBinding varargsElementType = shownMethod.parameters[shownMethod.parameters.length - 1].leafComponentType(); this.handle( IProblem.VarargsElementTypeNotVisible, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), new String(varargsElementType.readableName()) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), new String(varargsElementType.shortReadableName()) }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; case ProblemReasons.NoError : // 0 default : needImplementation(messageSend); // want to fail to see why we were here... break; } this.handle( id, new String[] { new String(method.declaringClass.readableName()), new String(shownMethod.selector), typesAsString(shownMethod, false)}, new String[] { new String(method.declaringClass.shortReadableName()), new String(shownMethod.selector), typesAsString(shownMethod, true)}, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); } public void invalidNullToSynchronize(Expression expression) { this.handle( IProblem.InvalidNullToSynchronized, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void invalidOperator(BinaryExpression expression, TypeBinding leftType, TypeBinding rightType) { String leftName = new String(leftType.readableName()); String rightName = new String(rightType.readableName()); String leftShortName = new String(leftType.shortReadableName()); String rightShortName = new String(rightType.shortReadableName()); if (leftShortName.equals(rightShortName)){ leftShortName = leftName; rightShortName = rightName; } this.handle( IProblem.InvalidOperator, new String[] { expression.operatorToString(), leftName + ", " + rightName}, //$NON-NLS-1$ new String[] { expression.operatorToString(), leftShortName + ", " + rightShortName}, //$NON-NLS-1$ expression.sourceStart, expression.sourceEnd); } public void invalidOperator(CompoundAssignment assign, TypeBinding leftType, TypeBinding rightType) { String leftName = new String(leftType.readableName()); String rightName = new String(rightType.readableName()); String leftShortName = new String(leftType.shortReadableName()); String rightShortName = new String(rightType.shortReadableName()); if (leftShortName.equals(rightShortName)){ leftShortName = leftName; rightShortName = rightName; } this.handle( IProblem.InvalidOperator, new String[] { assign.operatorToString(), leftName + ", " + rightName}, //$NON-NLS-1$ new String[] { assign.operatorToString(), leftShortName + ", " + rightShortName}, //$NON-NLS-1$ assign.sourceStart, assign.sourceEnd); } public void invalidOperator(UnaryExpression expression, TypeBinding type) { this.handle( IProblem.InvalidOperator, new String[] {expression.operatorToString(), new String(type.readableName())}, new String[] {expression.operatorToString(), new String(type.shortReadableName())}, expression.sourceStart, expression.sourceEnd); } public void invalidParameterizedExceptionType(TypeBinding exceptionType, ASTNode location) { this.handle( IProblem.InvalidParameterizedExceptionType, new String[] {new String(exceptionType.readableName())}, new String[] {new String(exceptionType.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void invalidParenthesizedExpression(ASTNode reference) { this.handle( IProblem.InvalidParenthesizedExpression, NoArgument, NoArgument, reference.sourceStart, reference.sourceEnd); } public void invalidType(ASTNode location, TypeBinding type) { if (type instanceof ReferenceBinding) { if (isRecoveredName(((ReferenceBinding)type).compoundName)) return; } else if (type instanceof ArrayBinding) { TypeBinding leafType = ((ArrayBinding)type).leafComponentType; if (leafType instanceof ReferenceBinding) { if (isRecoveredName(((ReferenceBinding)leafType).compoundName)) return; } } if (type.isParameterizedType()) { List missingTypes = type.collectMissingTypes(null); if (missingTypes != null) { ReferenceContext savedContext = this.referenceContext; for (Iterator iterator = missingTypes.iterator(); iterator.hasNext(); ) { try { invalidType(location, (TypeBinding) iterator.next()); } finally { this.referenceContext = savedContext; } } return; } } int id = IProblem.UndefinedType; // default switch (type.problemId()) { case ProblemReasons.NotFound : id = IProblem.UndefinedType; break; case ProblemReasons.NotVisible : id = IProblem.NotVisibleType; break; case ProblemReasons.Ambiguous : id = IProblem.AmbiguousType; break; case ProblemReasons.InternalNameProvided : id = IProblem.InternalTypeNameProvided; break; case ProblemReasons.InheritedNameHidesEnclosingName : id = IProblem.InheritedTypeHidesEnclosingName; break; case ProblemReasons.NonStaticReferenceInStaticContext : id = IProblem.NonStaticTypeFromStaticInvocation; break; case ProblemReasons.IllegalSuperTypeVariable : id = IProblem.IllegalTypeVariableSuperReference; break; case ProblemReasons.NoError : // 0 default : needImplementation(location); // want to fail to see why we were here... break; } int end = location.sourceEnd; if (location instanceof QualifiedNameReference) { QualifiedNameReference ref = (QualifiedNameReference) location; if (isRecoveredName(ref.tokens)) return; if (ref.indexOfFirstFieldBinding >= 1) end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1]; } else if (location instanceof ParameterizedQualifiedTypeReference) { // must be before instanceof ArrayQualifiedTypeReference ParameterizedQualifiedTypeReference ref = (ParameterizedQualifiedTypeReference) location; if (isRecoveredName(ref.tokens)) return; if (type instanceof ReferenceBinding) { char[][] name = ((ReferenceBinding) type).compoundName; end = (int) ref.sourcePositions[name.length - 1]; } } else if (location instanceof ArrayQualifiedTypeReference) { ArrayQualifiedTypeReference arrayQualifiedTypeReference = (ArrayQualifiedTypeReference) location; if (isRecoveredName(arrayQualifiedTypeReference.tokens)) return; TypeBinding leafType = type.leafComponentType(); if (leafType instanceof ReferenceBinding) { char[][] name = ((ReferenceBinding) leafType).compoundName; // problem type will tell how much got resolved end = (int) arrayQualifiedTypeReference.sourcePositions[name.length-1]; } else { long[] positions = arrayQualifiedTypeReference.sourcePositions; end = (int) positions[positions.length - 1]; } } else if (location instanceof QualifiedTypeReference) { QualifiedTypeReference ref = (QualifiedTypeReference) location; if (isRecoveredName(ref.tokens)) return; if (type instanceof ReferenceBinding) { char[][] name = ((ReferenceBinding) type).compoundName; if (name.length <= ref.sourcePositions.length) end = (int) ref.sourcePositions[name.length - 1]; } } else if (location instanceof ImportReference) { ImportReference ref = (ImportReference) location; if (isRecoveredName(ref.tokens)) return; if (type instanceof ReferenceBinding) { char[][] name = ((ReferenceBinding) type).compoundName; end = (int) ref.sourcePositions[name.length - 1]; } } else if (location instanceof ArrayTypeReference) { ArrayTypeReference arrayTypeReference = (ArrayTypeReference) location; if (isRecoveredName(arrayTypeReference.token)) return; end = arrayTypeReference.originalSourceEnd; } this.handle( id, new String[] {new String(type.leafComponentType().readableName()) }, new String[] {new String(type.leafComponentType().shortReadableName())}, location.sourceStart, end); } public void invalidTypeForCollection(Expression expression) { this.handle( IProblem.InvalidTypeForCollection, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void invalidTypeForCollectionTarget14(Expression expression) { this.handle( IProblem.InvalidTypeForCollectionTarget14, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void invalidTypeToSynchronize(Expression expression, TypeBinding type) { this.handle( IProblem.InvalidTypeToSynchronized, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, expression.sourceStart, expression.sourceEnd); } public void invalidTypeVariableAsException(TypeBinding exceptionType, ASTNode location) { this.handle( IProblem.InvalidTypeVariableExceptionType, new String[] {new String(exceptionType.readableName())}, new String[] {new String(exceptionType.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void invalidUnaryExpression(Expression expression) { this.handle( IProblem.InvalidUnaryExpression, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void invalidUsageOfAnnotation(Annotation annotation) { this.handle( IProblem.InvalidUsageOfAnnotations, NoArgument, NoArgument, annotation.sourceStart, annotation.sourceEnd); } public void invalidUsageOfAnnotationDeclarations(TypeDeclaration annotationTypeDeclaration) { this.handle( IProblem.InvalidUsageOfAnnotationDeclarations, NoArgument, NoArgument, annotationTypeDeclaration.sourceStart, annotationTypeDeclaration.sourceEnd); } public void invalidUsageOfEnumDeclarations(TypeDeclaration enumDeclaration) { this.handle( IProblem.InvalidUsageOfEnumDeclarations, NoArgument, NoArgument, enumDeclaration.sourceStart, enumDeclaration.sourceEnd); } public void invalidUsageOfForeachStatements(LocalDeclaration elementVariable, Expression collection) { this.handle( IProblem.InvalidUsageOfForeachStatements, NoArgument, NoArgument, elementVariable.declarationSourceStart, collection.sourceEnd); } public void invalidUsageOfStaticImports(ImportReference staticImport) { this.handle( IProblem.InvalidUsageOfStaticImports, NoArgument, NoArgument, staticImport.declarationSourceStart, staticImport.declarationSourceEnd); } public void invalidUsageOfTypeArguments(TypeReference firstTypeReference, TypeReference lastTypeReference) { this.handle( IProblem.InvalidUsageOfTypeArguments, NoArgument, NoArgument, firstTypeReference.sourceStart, lastTypeReference.sourceEnd); } public void invalidUsageOfTypeParameters(TypeParameter firstTypeParameter, TypeParameter lastTypeParameter) { this.handle( IProblem.InvalidUsageOfTypeParameters, NoArgument, NoArgument, firstTypeParameter.declarationSourceStart, lastTypeParameter.declarationSourceEnd); } public void invalidUsageOfTypeParametersForAnnotationDeclaration(TypeDeclaration annotationTypeDeclaration) { TypeParameter[] parameters = annotationTypeDeclaration.typeParameters; int length = parameters.length; this.handle( IProblem.InvalidUsageOfTypeParametersForAnnotationDeclaration, NoArgument, NoArgument, parameters[0].declarationSourceStart, parameters[length - 1].declarationSourceEnd); } public void invalidUsageOfTypeParametersForEnumDeclaration(TypeDeclaration annotationTypeDeclaration) { TypeParameter[] parameters = annotationTypeDeclaration.typeParameters; int length = parameters.length; this.handle( IProblem.InvalidUsageOfTypeParametersForEnumDeclaration, NoArgument, NoArgument, parameters[0].declarationSourceStart, parameters[length - 1].declarationSourceEnd); } public void invalidUsageOfVarargs(Argument argument) { this.handle( IProblem.InvalidUsageOfVarargs, NoArgument, NoArgument, argument.type.sourceStart, argument.sourceEnd); } public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl, Object location) { this.referenceContext = compUnitDecl; String[] arguments = new String[] {CharOperation.toString(wellKnownTypeName)}; int start = 0, end = 0; if (location != null) { if (location instanceof InvocationSite) { InvocationSite site = (InvocationSite) location; start = site.sourceStart(); end = site.sourceEnd(); } else if (location instanceof ASTNode) { ASTNode node = (ASTNode) location; start = node.sourceStart(); end = node.sourceEnd(); } } this.handle( IProblem.IsClassPathCorrect, arguments, arguments, start, end); } private boolean isIdentifier(int token) { return token == TerminalTokens.TokenNameIdentifier; } private boolean isKeyword(int token) { switch(token) { case TerminalTokens.TokenNameabstract: case TerminalTokens.TokenNameassert: case TerminalTokens.TokenNamebyte: case TerminalTokens.TokenNamebreak: case TerminalTokens.TokenNameboolean: case TerminalTokens.TokenNamecase: case TerminalTokens.TokenNamechar: case TerminalTokens.TokenNamecatch: case TerminalTokens.TokenNameclass: case TerminalTokens.TokenNamecontinue: case TerminalTokens.TokenNamedo: case TerminalTokens.TokenNamedouble: case TerminalTokens.TokenNamedefault: case TerminalTokens.TokenNameelse: case TerminalTokens.TokenNameextends: case TerminalTokens.TokenNamefor: case TerminalTokens.TokenNamefinal: case TerminalTokens.TokenNamefloat: case TerminalTokens.TokenNamefalse: case TerminalTokens.TokenNamefinally: case TerminalTokens.TokenNameif: case TerminalTokens.TokenNameint: case TerminalTokens.TokenNameimport: case TerminalTokens.TokenNameinterface: case TerminalTokens.TokenNameimplements: case TerminalTokens.TokenNameinstanceof: case TerminalTokens.TokenNamelong: case TerminalTokens.TokenNamenew: case TerminalTokens.TokenNamenull: case TerminalTokens.TokenNamenative: case TerminalTokens.TokenNamepublic: case TerminalTokens.TokenNamepackage: case TerminalTokens.TokenNameprivate: case TerminalTokens.TokenNameprotected: case TerminalTokens.TokenNamereturn: case TerminalTokens.TokenNameshort: case TerminalTokens.TokenNamesuper: case TerminalTokens.TokenNamestatic: case TerminalTokens.TokenNameswitch: case TerminalTokens.TokenNamestrictfp: case TerminalTokens.TokenNamesynchronized: case TerminalTokens.TokenNametry: case TerminalTokens.TokenNamethis: case TerminalTokens.TokenNametrue: case TerminalTokens.TokenNamethrow: case TerminalTokens.TokenNamethrows: case TerminalTokens.TokenNametransient: case TerminalTokens.TokenNamevoid: case TerminalTokens.TokenNamevolatile: case TerminalTokens.TokenNamewhile: return true; default: return false; } } private boolean isLiteral(int token) { return Scanner.isLiteral(token); } private boolean isRecoveredName(char[] simpleName) { return simpleName == RecoveryScanner.FAKE_IDENTIFIER; } private boolean isRecoveredName(char[][] qualifiedName) { if(qualifiedName == null) return false; for (int i = 0; i < qualifiedName.length; i++) { if(qualifiedName[i] == RecoveryScanner.FAKE_IDENTIFIER) return true; } return false; } public void javadocAmbiguousMethodReference(int sourceStart, int sourceEnd, Binding fieldBinding, int modifiers) { int severity = computeSeverity(IProblem.JavadocAmbiguousMethodReference); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] {new String(fieldBinding.readableName())}; handle( IProblem.JavadocAmbiguousMethodReference, arguments, arguments, severity, sourceStart, sourceEnd); } } public void javadocDeprecatedField(FieldBinding field, ASTNode location, int modifiers) { int severity = computeSeverity(IProblem.JavadocUsingDeprecatedField); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { this.handle( IProblem.JavadocUsingDeprecatedField, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, severity, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } } public void javadocDeprecatedMethod(MethodBinding method, ASTNode location, int modifiers) { boolean isConstructor = method.isConstructor(); int severity = computeSeverity(isConstructor ? IProblem.JavadocUsingDeprecatedConstructor : IProblem.JavadocUsingDeprecatedMethod); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { if (isConstructor) { this.handle( IProblem.JavadocUsingDeprecatedConstructor, new String[] {new String(method.declaringClass.readableName()), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), typesAsString(method, true)}, severity, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.JavadocUsingDeprecatedMethod, new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, severity, location.sourceStart, location.sourceEnd); } } } public void javadocDeprecatedType(TypeBinding type, ASTNode location, int modifiers) { javadocDeprecatedType(type, location, modifiers, Integer.MAX_VALUE); } public void javadocDeprecatedType(TypeBinding type, ASTNode location, int modifiers, int index) { if (location == null) return; // 1G828DN - no type ref for synthetic arguments int severity = computeSeverity(IProblem.JavadocUsingDeprecatedType); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { if (type.isMemberType() && type instanceof ReferenceBinding && !javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, ((ReferenceBinding)type).modifiers)) { this.handle(IProblem.JavadocHiddenReference, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.JavadocUsingDeprecatedType, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, severity, location.sourceStart, nodeSourceEnd(null, location, index)); } } } public void javadocDuplicatedParamTag(char[] token, int sourceStart, int sourceEnd, int modifiers) { int severity = computeSeverity(IProblem.JavadocDuplicateParamName); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] {String.valueOf(token)}; this.handle( IProblem.JavadocDuplicateParamName, arguments, arguments, severity, sourceStart, sourceEnd); } } public void javadocDuplicatedReturnTag(int sourceStart, int sourceEnd){ this.handle(IProblem.JavadocDuplicateReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocDuplicatedTag(char[] tagName, int sourceStart, int sourceEnd){ String[] arguments = new String[] { new String(tagName) }; this.handle( IProblem.JavadocDuplicateTag, arguments, arguments, sourceStart, sourceEnd); } public void javadocDuplicatedThrowsClassName(TypeReference typeReference, int modifiers) { int severity = computeSeverity(IProblem.JavadocDuplicateThrowsClassName); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] {String.valueOf(typeReference.resolvedType.sourceName())}; this.handle( IProblem.JavadocDuplicateThrowsClassName, arguments, arguments, severity, typeReference.sourceStart, typeReference.sourceEnd); } } public void javadocEmptyReturnTag(int sourceStart, int sourceEnd, int modifiers) { int severity = computeSeverity(IProblem.JavadocEmptyReturnTag); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] { new String(JavadocTagConstants.TAG_RETURN) }; this.handle(IProblem.JavadocEmptyReturnTag, arguments, arguments, sourceStart, sourceEnd); } } public void javadocErrorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params, int modifiers) { int id = recType.isArrayType() ? IProblem.JavadocNoMessageSendOnArrayType : IProblem.JavadocNoMessageSendOnBaseType; int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; StringBuffer buffer = new StringBuffer(); StringBuffer shortBuffer = new StringBuffer(); for (int i = 0, length = params.length; i < length; i++) { if (i != 0){ buffer.append(", "); //$NON-NLS-1$ shortBuffer.append(", "); //$NON-NLS-1$ } buffer.append(new String(params[i].readableName())); shortBuffer.append(new String(params[i].shortReadableName())); } if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { this.handle( id, new String[] {new String(recType.readableName()), new String(messageSend.selector), buffer.toString()}, new String[] {new String(recType.shortReadableName()), new String(messageSend.selector), shortBuffer.toString()}, severity, messageSend.sourceStart, messageSend.sourceEnd); } } public void javadocHiddenReference(int sourceStart, int sourceEnd, Scope scope, int modifiers) { Scope currentScope = scope; while (currentScope.parent.kind != Scope.COMPILATION_UNIT_SCOPE ) { if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, currentScope.getDeclarationModifiers())) { return; } currentScope = currentScope.parent; } String[] arguments = new String[] { this.options.getVisibilityString(this.options.reportInvalidJavadocTagsVisibility), this.options.getVisibilityString(modifiers) }; this.handle(IProblem.JavadocHiddenReference, arguments, arguments, sourceStart, sourceEnd); } public void javadocInvalidConstructor(Statement statement, MethodBinding targetConstructor, int modifiers) { if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) return; int sourceStart = statement.sourceStart; int sourceEnd = statement.sourceEnd; if (statement instanceof AllocationExpression) { AllocationExpression allocation = (AllocationExpression)statement; if (allocation.enumConstant != null) { sourceStart = allocation.enumConstant.sourceStart; sourceEnd = allocation.enumConstant.sourceEnd; } } int id = IProblem.JavadocUndefinedConstructor; //default... ProblemMethodBinding problemConstructor = null; MethodBinding shownConstructor = null; switch (targetConstructor.problemId()) { case ProblemReasons.NotFound : id = IProblem.JavadocUndefinedConstructor; break; case ProblemReasons.NotVisible : id = IProblem.JavadocNotVisibleConstructor; break; case ProblemReasons.Ambiguous : id = IProblem.JavadocAmbiguousConstructor; break; case ProblemReasons.ParameterBoundMismatch : int severity = computeSeverity(IProblem.JavadocGenericConstructorTypeArgumentMismatch); if (severity == ProblemSeverities.Ignore) return; problemConstructor = (ProblemMethodBinding) targetConstructor; ParameterizedGenericMethodBinding substitutedConstructor = (ParameterizedGenericMethodBinding) problemConstructor.closestMatch; shownConstructor = substitutedConstructor.original(); int augmentedLength = problemConstructor.parameters.length; TypeBinding inferredTypeArgument = problemConstructor.parameters[augmentedLength-2]; TypeVariableBinding typeParameter = (TypeVariableBinding) problemConstructor.parameters[augmentedLength-1]; TypeBinding[] invocationArguments = new TypeBinding[augmentedLength-2]; // remove extra info from the end System.arraycopy(problemConstructor.parameters, 0, invocationArguments, 0, augmentedLength-2); this.handle( IProblem.JavadocGenericConstructorTypeArgumentMismatch, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(invocationArguments, false), new String(inferredTypeArgument.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(invocationArguments, true), new String(inferredTypeArgument.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) }, severity, sourceStart, sourceEnd); return; case ProblemReasons.TypeParameterArityMismatch : problemConstructor = (ProblemMethodBinding) targetConstructor; shownConstructor = problemConstructor.closestMatch; boolean noTypeVariables = shownConstructor.typeVariables == Binding.NO_TYPE_VARIABLES; severity = computeSeverity(noTypeVariables ? IProblem.JavadocNonGenericConstructor : IProblem.JavadocIncorrectArityForParameterizedConstructor); if (severity == ProblemSeverities.Ignore) return; if (noTypeVariables) { this.handle( IProblem.JavadocNonGenericConstructor, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(targetConstructor, true) }, severity, sourceStart, sourceEnd); } else { this.handle( IProblem.JavadocIncorrectArityForParameterizedConstructor, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(shownConstructor.typeVariables, false), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(shownConstructor.typeVariables, true), typesAsString(targetConstructor, true) }, severity, sourceStart, sourceEnd); } return; case ProblemReasons.ParameterizedMethodTypeMismatch : severity = computeSeverity(IProblem.JavadocParameterizedConstructorArgumentTypeMismatch); if (severity == ProblemSeverities.Ignore) return; problemConstructor = (ProblemMethodBinding) targetConstructor; shownConstructor = problemConstructor.closestMatch; this.handle( IProblem.JavadocParameterizedConstructorArgumentTypeMismatch, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(((ParameterizedGenericMethodBinding)shownConstructor).typeArguments, false), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(((ParameterizedGenericMethodBinding)shownConstructor).typeArguments, true), typesAsString(targetConstructor, true) }, severity, sourceStart, sourceEnd); return; case ProblemReasons.TypeArgumentsForRawGenericMethod : severity = computeSeverity(IProblem.JavadocTypeArgumentsForRawGenericConstructor); if (severity == ProblemSeverities.Ignore) return; problemConstructor = (ProblemMethodBinding) targetConstructor; shownConstructor = problemConstructor.closestMatch; this.handle( IProblem.JavadocTypeArgumentsForRawGenericConstructor, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, false), new String(shownConstructor.declaringClass.readableName()), typesAsString(targetConstructor, false) }, new String[] { new String(shownConstructor.declaringClass.sourceName()), typesAsString(shownConstructor, true), new String(shownConstructor.declaringClass.shortReadableName()), typesAsString(targetConstructor, true) }, severity, sourceStart, sourceEnd); return; case ProblemReasons.NoError : // 0 default : needImplementation(statement); // want to fail to see why we were here... break; } int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; this.handle( id, new String[] {new String(targetConstructor.declaringClass.readableName()), typesAsString(targetConstructor, false)}, new String[] {new String(targetConstructor.declaringClass.shortReadableName()), typesAsString(targetConstructor, true)}, severity, statement.sourceStart, statement.sourceEnd); } /* * Similar implementation than invalidField(FieldReference...) * Note that following problem id cannot occur for Javadoc: * - NonStaticReferenceInStaticContext : * - NonStaticReferenceInConstructorInvocation : * - ReceiverTypeNotVisible : */ public void javadocInvalidField(FieldReference fieldRef, Binding fieldBinding, TypeBinding searchedType, int modifiers) { int id = IProblem.JavadocUndefinedField; switch (fieldBinding.problemId()) { case ProblemReasons.NotFound : id = IProblem.JavadocUndefinedField; break; case ProblemReasons.NotVisible : id = IProblem.JavadocNotVisibleField; break; case ProblemReasons.Ambiguous : id = IProblem.JavadocAmbiguousField; break; case ProblemReasons.NoError : // 0 default : needImplementation(fieldRef); // want to fail to see why we were here... break; } int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; // report issue if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] {new String(fieldBinding.readableName())}; handle( id, arguments, arguments, severity, fieldRef.sourceStart, fieldRef.sourceEnd); } } public void javadocInvalidMemberTypeQualification(int sourceStart, int sourceEnd, int modifiers){ if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { this.handle(IProblem.JavadocInvalidMemberTypeQualification, NoArgument, NoArgument, sourceStart, sourceEnd); } } /* * Similar implementation than invalidMethod(MessageSend...) * Note that following problem id cannot occur for Javadoc: * - NonStaticReferenceInStaticContext : * - NonStaticReferenceInConstructorInvocation : * - ReceiverTypeNotVisible : */ public void javadocInvalidMethod(MessageSend messageSend, MethodBinding method, int modifiers) { if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) return; // set problem id ProblemMethodBinding problemMethod = null; MethodBinding shownMethod = null; int id = IProblem.JavadocUndefinedMethod; //default... switch (method.problemId()) { case ProblemReasons.NotFound : id = IProblem.JavadocUndefinedMethod; problemMethod = (ProblemMethodBinding) method; if (problemMethod.closestMatch != null) { int severity = computeSeverity(IProblem.JavadocParameterMismatch); if (severity == ProblemSeverities.Ignore) return; String closestParameterTypeNames = typesAsString(problemMethod.closestMatch, false); String parameterTypeNames = typesAsString(method, false); String closestParameterTypeShortNames = typesAsString(problemMethod.closestMatch, true); String parameterTypeShortNames = typesAsString(method, true); if (closestParameterTypeShortNames.equals(parameterTypeShortNames)){ closestParameterTypeShortNames = closestParameterTypeNames; parameterTypeShortNames = parameterTypeNames; } this.handle( IProblem.JavadocParameterMismatch, new String[] { new String(problemMethod.closestMatch.declaringClass.readableName()), new String(problemMethod.closestMatch.selector), closestParameterTypeNames, parameterTypeNames }, new String[] { new String(problemMethod.closestMatch.declaringClass.shortReadableName()), new String(problemMethod.closestMatch.selector), closestParameterTypeShortNames, parameterTypeShortNames }, severity, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; } break; case ProblemReasons.NotVisible : id = IProblem.JavadocNotVisibleMethod; break; case ProblemReasons.Ambiguous : id = IProblem.JavadocAmbiguousMethod; break; case ProblemReasons.ParameterBoundMismatch : int severity = computeSeverity(IProblem.JavadocGenericMethodTypeArgumentMismatch); if (severity == ProblemSeverities.Ignore) return; problemMethod = (ProblemMethodBinding) method; ParameterizedGenericMethodBinding substitutedMethod = (ParameterizedGenericMethodBinding) problemMethod.closestMatch; shownMethod = substitutedMethod.original(); int augmentedLength = problemMethod.parameters.length; TypeBinding inferredTypeArgument = problemMethod.parameters[augmentedLength-2]; TypeVariableBinding typeParameter = (TypeVariableBinding) problemMethod.parameters[augmentedLength-1]; TypeBinding[] invocationArguments = new TypeBinding[augmentedLength-2]; // remove extra info from the end System.arraycopy(problemMethod.parameters, 0, invocationArguments, 0, augmentedLength-2); this.handle( IProblem.JavadocGenericMethodTypeArgumentMismatch, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(invocationArguments, false), new String(inferredTypeArgument.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(invocationArguments, true), new String(inferredTypeArgument.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) }, severity, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; case ProblemReasons.TypeParameterArityMismatch : problemMethod = (ProblemMethodBinding) method; shownMethod = problemMethod.closestMatch; boolean noTypeVariables = shownMethod.typeVariables == Binding.NO_TYPE_VARIABLES; severity = computeSeverity(noTypeVariables ? IProblem.JavadocNonGenericMethod : IProblem.JavadocIncorrectArityForParameterizedMethod); if (severity == ProblemSeverities.Ignore) return; if (noTypeVariables) { this.handle( IProblem.JavadocNonGenericMethod, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(method, true) }, severity, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); } else { this.handle( IProblem.JavadocIncorrectArityForParameterizedMethod, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(shownMethod.typeVariables, false), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(shownMethod.typeVariables, true), typesAsString(method, true) }, severity, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); } return; case ProblemReasons.ParameterizedMethodTypeMismatch : severity = computeSeverity(IProblem.JavadocParameterizedMethodArgumentTypeMismatch); if (severity == ProblemSeverities.Ignore) return; problemMethod = (ProblemMethodBinding) method; shownMethod = problemMethod.closestMatch; this.handle( IProblem.JavadocParameterizedMethodArgumentTypeMismatch, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(((ParameterizedGenericMethodBinding)shownMethod).typeArguments, false), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(((ParameterizedGenericMethodBinding)shownMethod).typeArguments, true), typesAsString(method, true) }, severity, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; case ProblemReasons.TypeArgumentsForRawGenericMethod : severity = computeSeverity(IProblem.JavadocTypeArgumentsForRawGenericMethod); if (severity == ProblemSeverities.Ignore) return; problemMethod = (ProblemMethodBinding) method; shownMethod = problemMethod.closestMatch; this.handle( IProblem.JavadocTypeArgumentsForRawGenericMethod, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, false), new String(shownMethod.declaringClass.readableName()), typesAsString(method, false) }, new String[] { new String(shownMethod.selector), typesAsString(shownMethod, true), new String(shownMethod.declaringClass.shortReadableName()), typesAsString(method, true) }, severity, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); return; case ProblemReasons.NoError : // 0 default : needImplementation(messageSend); // want to fail to see why we were here... break; } int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; // report issue this.handle( id, new String[] { new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] { new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, severity, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); } public void javadocInvalidParamTagName(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidParamTagName, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocInvalidParamTypeParameter(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidParamTagTypeParameter, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocInvalidReference(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd); } /** * Report an invalid reference that does not conform to the href syntax. * Valid syntax example: @see IProblem.JavadocInvalidSeeHref */ public void javadocInvalidSeeHref(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidSeeHref, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocInvalidSeeReferenceArgs(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidSeeArgs, NoArgument, NoArgument, sourceStart, sourceEnd); } /** * Report a problem on an invalid URL reference. * Valid syntax example: @see IProblem.JavadocInvalidSeeUrlReference */ public void javadocInvalidSeeUrlReference(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidSeeUrlReference, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocInvalidTag(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidTag, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocInvalidThrowsClass(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocInvalidThrowsClass, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocInvalidThrowsClassName(TypeReference typeReference, int modifiers) { int severity = computeSeverity(IProblem.JavadocInvalidThrowsClassName); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] {String.valueOf(typeReference.resolvedType.sourceName())}; this.handle( IProblem.JavadocInvalidThrowsClassName, arguments, arguments, severity, typeReference.sourceStart, typeReference.sourceEnd); } } public void javadocInvalidType(ASTNode location, TypeBinding type, int modifiers) { if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { int id = IProblem.JavadocUndefinedType; // default switch (type.problemId()) { case ProblemReasons.NotFound : id = IProblem.JavadocUndefinedType; break; case ProblemReasons.NotVisible : id = IProblem.JavadocNotVisibleType; break; case ProblemReasons.Ambiguous : id = IProblem.JavadocAmbiguousType; break; case ProblemReasons.InternalNameProvided : id = IProblem.JavadocInternalTypeNameProvided; break; case ProblemReasons.InheritedNameHidesEnclosingName : id = IProblem.JavadocInheritedNameHidesEnclosingTypeName; break; case ProblemReasons.NonStaticReferenceInStaticContext : id = IProblem.JavadocNonStaticTypeFromStaticInvocation; break; case ProblemReasons.NoError : // 0 default : needImplementation(location); // want to fail to see why we were here... break; } int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; this.handle( id, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, severity, location.sourceStart, location.sourceEnd); } } public void javadocInvalidValueReference(int sourceStart, int sourceEnd, int modifiers) { if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) this.handle(IProblem.JavadocInvalidValueReference, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocMalformedSeeReference(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocMalformedSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocMissing(int sourceStart, int sourceEnd, int modifiers){ int severity = computeSeverity(IProblem.JavadocMissing); this.javadocMissing(sourceStart, sourceEnd, severity, modifiers); } public void javadocMissing(int sourceStart, int sourceEnd, int severity, int modifiers){ if (severity == ProblemSeverities.Ignore) return; boolean overriding = (modifiers & (ExtraCompilerModifiers.AccImplementing|ExtraCompilerModifiers.AccOverriding)) != 0; boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore) && (!overriding || this.options.reportMissingJavadocCommentsOverriding); if (report) { String arg = javadocVisibilityArgument(this.options.reportMissingJavadocCommentsVisibility, modifiers); if (arg != null) { String[] arguments = new String[] { arg }; this.handle( IProblem.JavadocMissing, arguments, arguments, severity, sourceStart, sourceEnd); } } } public void javadocMissingHashCharacter(int sourceStart, int sourceEnd, String ref){ int severity = computeSeverity(IProblem.JavadocMissingHashCharacter); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] { ref }; this.handle( IProblem.JavadocMissingHashCharacter, arguments, arguments, severity, sourceStart, sourceEnd); } public void javadocMissingIdentifier(int sourceStart, int sourceEnd, int modifiers){ if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) this.handle(IProblem.JavadocMissingIdentifier, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocMissingParamName(int sourceStart, int sourceEnd, int modifiers){ if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) this.handle(IProblem.JavadocMissingParamName, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocMissingParamTag(char[] name, int sourceStart, int sourceEnd, int modifiers) { int severity = computeSeverity(IProblem.JavadocMissingParamTag); if (severity == ProblemSeverities.Ignore) return; boolean overriding = (modifiers & (ExtraCompilerModifiers.AccImplementing|ExtraCompilerModifiers.AccOverriding)) != 0; boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore) && (!overriding || this.options.reportMissingJavadocTagsOverriding); if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] { String.valueOf(name) }; this.handle( IProblem.JavadocMissingParamTag, arguments, arguments, severity, sourceStart, sourceEnd); } } public void javadocMissingReference(int sourceStart, int sourceEnd, int modifiers){ if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) this.handle(IProblem.JavadocMissingSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocMissingReturnTag(int sourceStart, int sourceEnd, int modifiers){ boolean overriding = (modifiers & (ExtraCompilerModifiers.AccImplementing|ExtraCompilerModifiers.AccOverriding)) != 0; boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore) && (!overriding || this.options.reportMissingJavadocTagsOverriding); if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) { this.handle(IProblem.JavadocMissingReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd); } } public void javadocMissingTagDescription(char[] tokenName, int sourceStart, int sourceEnd, int modifiers) { int severity = computeSeverity(IProblem.JavadocMissingTagDescription); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] { new String(tokenName) }; // use IProblem.JavadocEmptyReturnTag for all identified tags this.handle(IProblem.JavadocEmptyReturnTag, arguments, arguments, sourceStart, sourceEnd); } } public void javadocMissingTagDescriptionAfterReference(int sourceStart, int sourceEnd, int modifiers){ int severity = computeSeverity(IProblem.JavadocMissingTagDescription); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { this.handle(IProblem.JavadocMissingTagDescription, NoArgument, NoArgument, severity, sourceStart, sourceEnd); } } public void javadocMissingThrowsClassName(int sourceStart, int sourceEnd, int modifiers){ if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { this.handle(IProblem.JavadocMissingThrowsClassName, NoArgument, NoArgument, sourceStart, sourceEnd); } } public void javadocMissingThrowsTag(TypeReference typeRef, int modifiers){ int severity = computeSeverity(IProblem.JavadocMissingThrowsTag); if (severity == ProblemSeverities.Ignore) return; boolean overriding = (modifiers & (ExtraCompilerModifiers.AccImplementing|ExtraCompilerModifiers.AccOverriding)) != 0; boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore) && (!overriding || this.options.reportMissingJavadocTagsOverriding); if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] { String.valueOf(typeRef.resolvedType.sourceName()) }; this.handle( IProblem.JavadocMissingThrowsTag, arguments, arguments, severity, typeRef.sourceStart, typeRef.sourceEnd); } } public void javadocUndeclaredParamTagName(char[] token, int sourceStart, int sourceEnd, int modifiers) { int severity = computeSeverity(IProblem.JavadocInvalidParamName); if (severity == ProblemSeverities.Ignore) return; if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) { String[] arguments = new String[] {String.valueOf(token)}; this.handle( IProblem.JavadocInvalidParamName, arguments, arguments, severity, sourceStart, sourceEnd); } } public void javadocUnexpectedTag(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocUnexpectedTag, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocUnexpectedText(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocUnexpectedText, NoArgument, NoArgument, sourceStart, sourceEnd); } public void javadocUnterminatedInlineTag(int sourceStart, int sourceEnd) { this.handle(IProblem.JavadocUnterminatedInlineTag, NoArgument, NoArgument, sourceStart, sourceEnd); } private boolean javadocVisibility(int visibility, int modifiers) { if (modifiers < 0) return true; switch (modifiers & ExtraCompilerModifiers.AccVisibilityMASK) { case ClassFileConstants.AccPublic : return true; case ClassFileConstants.AccProtected: return (visibility != ClassFileConstants.AccPublic); case ClassFileConstants.AccDefault: return (visibility == ClassFileConstants.AccDefault || visibility == ClassFileConstants.AccPrivate); case ClassFileConstants.AccPrivate: return (visibility == ClassFileConstants.AccPrivate); } return true; } private String javadocVisibilityArgument(int visibility, int modifiers) { String argument = null; switch (modifiers & ExtraCompilerModifiers.AccVisibilityMASK) { case ClassFileConstants.AccPublic : argument = CompilerOptions.PUBLIC; break; case ClassFileConstants.AccProtected: if (visibility != ClassFileConstants.AccPublic) { argument = CompilerOptions.PROTECTED; } break; case ClassFileConstants.AccDefault: if (visibility == ClassFileConstants.AccDefault || visibility == ClassFileConstants.AccPrivate) { argument = CompilerOptions.DEFAULT; } break; case ClassFileConstants.AccPrivate: if (visibility == ClassFileConstants.AccPrivate) { argument = CompilerOptions.PRIVATE; } break; } return argument; } public void localVariableHiding(LocalDeclaration local, Binding hiddenVariable, boolean isSpecialArgHidingField) { if (hiddenVariable instanceof LocalVariableBinding) { int id = (local instanceof Argument) ? IProblem.ArgumentHidingLocalVariable : IProblem.LocalVariableHidingLocalVariable; int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name) }; this.handle( id, arguments, arguments, severity, nodeSourceStart(hiddenVariable, local), nodeSourceEnd(hiddenVariable, local)); } else if (hiddenVariable instanceof FieldBinding) { if (isSpecialArgHidingField && !this.options.reportSpecialParameterHidingField){ return; } int id = (local instanceof Argument) ? IProblem.ArgumentHidingField : IProblem.LocalVariableHidingField; int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; FieldBinding field = (FieldBinding) hiddenVariable; this.handle( id, new String[] {new String(local.name) , new String(field.declaringClass.readableName()) }, new String[] {new String(local.name), new String(field.declaringClass.shortReadableName()) }, severity, local.sourceStart, local.sourceEnd); } } public void localVariableNonNullComparedToNull(LocalVariableBinding local, ASTNode location) { int severity = computeSeverity(IProblem.NonNullLocalVariableComparisonYieldsFalse); if (severity == ProblemSeverities.Ignore) return; String[] arguments; int problemId; if (local.isNonNull()) { char[][] annotationName = this.options.nonNullAnnotationName; // cannot be null if local is declared @NonNull arguments = new String[] {new String(local.name), new String(annotationName[annotationName.length-1]) }; problemId = IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse; } else { arguments = new String[] {new String(local.name) }; problemId = IProblem.NonNullLocalVariableComparisonYieldsFalse; } this.handle( problemId, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void localVariableNullComparedToNonNull(LocalVariableBinding local, ASTNode location) { int severity = computeSeverity(IProblem.NullLocalVariableComparisonYieldsFalse); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name) }; this.handle( IProblem.NullLocalVariableComparisonYieldsFalse, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } /** * @param expr expression being compared for null or nonnull * @param checkForNull true if checking for null, false if checking for nonnull */ public boolean expressionNonNullComparison(Expression expr, boolean checkForNull) { int problemId = 0; Binding binding = null; String[] arguments = null; int start = 0, end = 0; Expression location = expr; // unwrap uninteresting nodes: while (true) { if (expr instanceof Assignment) return false; // don't report against the assignment, but the variable else if (expr instanceof CastExpression) expr = ((CastExpression) expr).expression; else break; } // check all those kinds of expressions that can possible answer NON_NULL from nullStatus(): if (expr instanceof MessageSend) { problemId = checkForNull ? IProblem.NonNullMessageSendComparisonYieldsFalse : IProblem.RedundantNullCheckOnNonNullMessageSend; MethodBinding method = ((MessageSend)expr).binding; binding = method; arguments = new String[] { new String(method.shortReadableName()) }; start = location.sourceStart; end = location.sourceEnd; } else if (expr instanceof Reference && !(expr instanceof ThisReference) && !(expr instanceof ArrayReference)) { FieldBinding field = ((Reference)expr).lastFieldBinding(); if (field == null) { return false; } if (field.isNonNull()) { problemId = checkForNull ? IProblem.NonNullSpecdFieldComparisonYieldsFalse : IProblem.RedundantNullCheckOnNonNullSpecdField; char[][] nonNullName = this.options.nonNullAnnotationName; arguments = new String[] { new String(field.name), new String(nonNullName[nonNullName.length-1]) }; } binding = field; start = nodeSourceStart(binding, location); end = nodeSourceEnd(binding, location); } else if (expr instanceof AllocationExpression || expr instanceof ArrayAllocationExpression || expr instanceof ArrayInitializer || expr instanceof ClassLiteralAccess || expr instanceof ThisReference) { // fall through to bottom } else if (expr instanceof Literal || expr instanceof ConditionalExpression) { if (expr instanceof NullLiteral) { needImplementation(location); // reported as nonnull?? return false; } if (expr.resolvedType != null && expr.resolvedType.isBaseType()) { // false alarm, auto(un)boxing is involved return false; } // fall through to bottom } else if (expr instanceof BinaryExpression) { if ((expr.bits & ASTNode.ReturnTypeIDMASK) != TypeIds.T_JavaLangString) { // false alarm, primitive types involved, must be auto(un)boxing? return false; } // fall through to bottom } else { needImplementation(expr); // want to see if we get here return false; } if (problemId == 0) { // standard case, fill in details now problemId = checkForNull ? IProblem.NonNullExpressionComparisonYieldsFalse : IProblem.RedundantNullCheckOnNonNullExpression; start = location.sourceStart; end = location.sourceEnd; arguments = NoArgument; } this.handle(problemId, arguments, arguments, start, end); return true; } public void localVariableNullInstanceof(LocalVariableBinding local, ASTNode location) { int severity = computeSeverity(IProblem.NullLocalVariableInstanceofYieldsFalse); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name) }; this.handle( IProblem.NullLocalVariableInstanceofYieldsFalse, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void localVariableNullReference(LocalVariableBinding local, ASTNode location) { if (location instanceof Expression && (((Expression)location).implicitConversion & TypeIds.UNBOXING) != 0) { nullUnboxing(location, local.type); return; } int severity = computeSeverity(IProblem.NullLocalVariableReference); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name) }; this.handle( IProblem.NullLocalVariableReference, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void localVariablePotentialNullReference(LocalVariableBinding local, ASTNode location) { if (location instanceof Expression && (((Expression)location).implicitConversion & TypeIds.UNBOXING) != 0) { potentialNullUnboxing(location, local.type); return; } int severity = computeSeverity(IProblem.PotentialNullLocalVariableReference); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name)}; this.handle( IProblem.PotentialNullLocalVariableReference, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void potentialNullUnboxing(ASTNode expression, TypeBinding boxType) { String[] arguments = new String[] { String.valueOf(boxType.readableName()) }; String[] argumentsShort = new String[] { String.valueOf(boxType.shortReadableName()) }; this.handle(IProblem.PotentialNullUnboxing, arguments, argumentsShort, expression.sourceStart, expression.sourceEnd); } public void nullUnboxing(ASTNode expression, TypeBinding boxType) { String[] arguments = new String[] { String.valueOf(boxType.readableName()) }; String[] argumentsShort = new String[] { String.valueOf(boxType.shortReadableName()) }; this.handle(IProblem.NullUnboxing, arguments, argumentsShort, expression.sourceStart, expression.sourceEnd); } public void nullableFieldDereference(VariableBinding variable, long position) { String[] arguments = new String[] {new String(variable.name)}; char[][] nullableName = this.options.nullableAnnotationName; arguments = new String[] {new String(variable.name), new String(nullableName[nullableName.length-1])}; this.handle( IProblem.NullableFieldReference, arguments, arguments, (int)(position >>> 32), (int)(position)); } public void localVariableRedundantCheckOnNonNull(LocalVariableBinding local, ASTNode location) { int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullLocalVariable); if (severity == ProblemSeverities.Ignore) return; String[] arguments; int problemId; if (local.isNonNull()) { char[][] annotationName = this.options.nonNullAnnotationName; // cannot be null if local is declared @NonNull arguments = new String[] {new String(local.name), new String(annotationName[annotationName.length-1]) }; problemId = IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable; } else { arguments = new String[] {new String(local.name) }; problemId = IProblem.RedundantNullCheckOnNonNullLocalVariable; } this.handle( problemId, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void localVariableRedundantCheckOnNull(LocalVariableBinding local, ASTNode location) { int severity = computeSeverity(IProblem.RedundantNullCheckOnNullLocalVariable); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name) }; this.handle( IProblem.RedundantNullCheckOnNullLocalVariable, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void localVariableRedundantNullAssignment(LocalVariableBinding local, ASTNode location) { if ((location.bits & ASTNode.FirstAssignmentToLocal) != 0) // https://bugs.eclipse.org/338303 - Warning about Redundant assignment conflicts with definite assignment return; int severity = computeSeverity(IProblem.RedundantLocalVariableNullAssignment); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name) }; this.handle( IProblem.RedundantLocalVariableNullAssignment, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void methodMustOverride(AbstractMethodDeclaration method, long complianceLevel) { MethodBinding binding = method.binding; this.handle( complianceLevel == ClassFileConstants.JDK1_5 ? IProblem.MethodMustOverride : IProblem.MethodMustOverrideOrImplement, new String[] {new String(binding.selector), typesAsString(binding, false), new String(binding.declaringClass.readableName()), }, new String[] {new String(binding.selector), typesAsString(binding, true), new String(binding.declaringClass.shortReadableName()),}, method.sourceStart, method.sourceEnd); } public void methodNameClash(MethodBinding currentMethod, MethodBinding inheritedMethod, int severity) { this.handle( IProblem.MethodNameClash, new String[] { new String(currentMethod.selector), typesAsString(currentMethod, false), new String(currentMethod.declaringClass.readableName()), typesAsString(inheritedMethod, false), new String(inheritedMethod.declaringClass.readableName()), }, new String[] { new String(currentMethod.selector), typesAsString(currentMethod, true), new String(currentMethod.declaringClass.shortReadableName()), typesAsString(inheritedMethod, true), new String(inheritedMethod.declaringClass.shortReadableName()), }, severity, currentMethod.sourceStart(), currentMethod.sourceEnd()); } public void methodNameClashHidden(MethodBinding currentMethod, MethodBinding inheritedMethod) { this.handle( IProblem.MethodNameClashHidden, new String[] { new String(currentMethod.selector), typesAsString(currentMethod, currentMethod.parameters, false), new String(currentMethod.declaringClass.readableName()), typesAsString(inheritedMethod, inheritedMethod.parameters, false), new String(inheritedMethod.declaringClass.readableName()), }, new String[] { new String(currentMethod.selector), typesAsString(currentMethod, currentMethod.parameters, true), new String(currentMethod.declaringClass.shortReadableName()), typesAsString(inheritedMethod, inheritedMethod.parameters, true), new String(inheritedMethod.declaringClass.shortReadableName()), }, currentMethod.sourceStart(), currentMethod.sourceEnd()); } public void methodNeedBody(AbstractMethodDeclaration methodDecl) { this.handle( IProblem.MethodRequiresBody, NoArgument, NoArgument, methodDecl.sourceStart, methodDecl.sourceEnd); } public void methodNeedingNoBody(MethodDeclaration methodDecl) { this.handle( ((methodDecl.modifiers & ClassFileConstants.AccNative) != 0) ? IProblem.BodyForNativeMethod : IProblem.BodyForAbstractMethod, NoArgument, NoArgument, methodDecl.sourceStart, methodDecl.sourceEnd); } public void methodWithConstructorName(MethodDeclaration methodDecl) { this.handle( IProblem.MethodButWithConstructorName, NoArgument, NoArgument, methodDecl.sourceStart, methodDecl.sourceEnd); } public void methodCanBeDeclaredStatic(MethodDeclaration methodDecl) { int severity = computeSeverity(IProblem.MethodCanBeStatic); if (severity == ProblemSeverities.Ignore) return; MethodBinding method = methodDecl.binding; this.handle( IProblem.MethodCanBeStatic, new String[] { new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false) }, new String[] { new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true) }, severity, methodDecl.sourceStart, methodDecl.sourceEnd); } public void methodCanBePotentiallyDeclaredStatic(MethodDeclaration methodDecl) { int severity = computeSeverity(IProblem.MethodCanBePotentiallyStatic); if (severity == ProblemSeverities.Ignore) return; MethodBinding method = methodDecl.binding; this.handle( IProblem.MethodCanBePotentiallyStatic, new String[] { new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false) }, new String[] { new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true) }, severity, methodDecl.sourceStart, methodDecl.sourceEnd); } public void missingDeprecatedAnnotationForField(FieldDeclaration field) { int severity = computeSeverity(IProblem.FieldMissingDeprecatedAnnotation); if (severity == ProblemSeverities.Ignore) return; FieldBinding binding = field.binding; this.handle( IProblem.FieldMissingDeprecatedAnnotation, new String[] {new String(binding.declaringClass.readableName()), new String(binding.name), }, new String[] {new String(binding.declaringClass.shortReadableName()), new String(binding.name), }, severity, nodeSourceStart(binding, field), nodeSourceEnd(binding, field)); } public void missingDeprecatedAnnotationForMethod(AbstractMethodDeclaration method) { int severity = computeSeverity(IProblem.MethodMissingDeprecatedAnnotation); if (severity == ProblemSeverities.Ignore) return; MethodBinding binding = method.binding; this.handle( IProblem.MethodMissingDeprecatedAnnotation, new String[] {new String(binding.selector), typesAsString(binding, false), new String(binding.declaringClass.readableName()), }, new String[] {new String(binding.selector), typesAsString(binding, true), new String(binding.declaringClass.shortReadableName()),}, severity, method.sourceStart, method.sourceEnd); } public void missingDeprecatedAnnotationForType(TypeDeclaration type) { int severity = computeSeverity(IProblem.TypeMissingDeprecatedAnnotation); if (severity == ProblemSeverities.Ignore) return; TypeBinding binding = type.binding; this.handle( IProblem.TypeMissingDeprecatedAnnotation, new String[] {new String(binding.readableName()), }, new String[] {new String(binding.shortReadableName()),}, severity, type.sourceStart, type.sourceEnd); } public void missingEnumConstantCase(SwitchStatement switchStatement, FieldBinding enumConstant) { this.handle( switchStatement.defaultCase == null ? IProblem.MissingEnumConstantCase : IProblem.MissingEnumConstantCaseDespiteDefault, new String[] {new String(enumConstant.declaringClass.readableName()), new String(enumConstant.name) }, new String[] {new String(enumConstant.declaringClass.shortReadableName()), new String(enumConstant.name) }, switchStatement.expression.sourceStart, switchStatement.expression.sourceEnd); } public void missingDefaultCase(SwitchStatement switchStatement, boolean isEnumSwitch, TypeBinding expressionType) { if (isEnumSwitch) { this.handle( IProblem.MissingEnumDefaultCase, new String[] {new String(expressionType.readableName())}, new String[] {new String(expressionType.shortReadableName())}, switchStatement.expression.sourceStart, switchStatement.expression.sourceEnd); } else { this.handle( IProblem.MissingDefaultCase, NoArgument, NoArgument, switchStatement.expression.sourceStart, switchStatement.expression.sourceEnd); } } public void missingOverrideAnnotation(AbstractMethodDeclaration method) { int severity = computeSeverity(IProblem.MissingOverrideAnnotation); if (severity == ProblemSeverities.Ignore) return; MethodBinding binding = method.binding; this.handle( IProblem.MissingOverrideAnnotation, new String[] {new String(binding.selector), typesAsString(binding, false), new String(binding.declaringClass.readableName()), }, new String[] {new String(binding.selector), typesAsString(binding, true), new String(binding.declaringClass.shortReadableName()),}, severity, method.sourceStart, method.sourceEnd); } public void missingOverrideAnnotationForInterfaceMethodImplementation(AbstractMethodDeclaration method) { int severity = computeSeverity(IProblem.MissingOverrideAnnotationForInterfaceMethodImplementation); if (severity == ProblemSeverities.Ignore) return; MethodBinding binding = method.binding; this.handle( IProblem.MissingOverrideAnnotationForInterfaceMethodImplementation, new String[] {new String(binding.selector), typesAsString(binding, false), new String(binding.declaringClass.readableName()), }, new String[] {new String(binding.selector), typesAsString(binding, true), new String(binding.declaringClass.shortReadableName()),}, severity, method.sourceStart, method.sourceEnd); } public void missingReturnType(AbstractMethodDeclaration methodDecl) { this.handle( IProblem.MissingReturnType, NoArgument, NoArgument, methodDecl.sourceStart, methodDecl.sourceEnd); } public void missingSemiColon(Expression expression){ this.handle( IProblem.MissingSemiColon, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void missingSerialVersion(TypeDeclaration typeDecl) { String[] arguments = new String[] {new String(typeDecl.name)}; this.handle( IProblem.MissingSerialVersion, arguments, arguments, typeDecl.sourceStart, typeDecl.sourceEnd); } public void missingSynchronizedOnInheritedMethod(MethodBinding currentMethod, MethodBinding inheritedMethod) { this.handle( IProblem.MissingSynchronizedModifierInInheritedMethod, new String[] { new String(currentMethod.declaringClass.readableName()), new String(currentMethod.selector), typesAsString(currentMethod, false), }, new String[] { new String(currentMethod.declaringClass.shortReadableName()), new String(currentMethod.selector), typesAsString(currentMethod, true), }, currentMethod.sourceStart(), currentMethod.sourceEnd()); } public void missingTypeInConstructor(ASTNode location, MethodBinding constructor) { List missingTypes = constructor.collectMissingTypes(null); if (missingTypes == null) { System.err.println("The constructor " + constructor + " is wrongly tagged as containing missing types"); //$NON-NLS-1$ //$NON-NLS-2$ return; } TypeBinding missingType = (TypeBinding) missingTypes.get(0); int start = location.sourceStart; int end = location.sourceEnd; if (location instanceof QualifiedAllocationExpression) { QualifiedAllocationExpression qualifiedAllocation = (QualifiedAllocationExpression) location; if (qualifiedAllocation.anonymousType != null) { start = qualifiedAllocation.anonymousType.sourceStart; end = qualifiedAllocation.anonymousType.sourceEnd; } } this.handle( IProblem.MissingTypeInConstructor, new String[] { new String(constructor.declaringClass.readableName()), typesAsString(constructor, false), new String(missingType.readableName()), }, new String[] { new String(constructor.declaringClass.shortReadableName()), typesAsString(constructor, true), new String(missingType.shortReadableName()), }, start, end); } public void missingTypeInMethod(MessageSend messageSend, MethodBinding method) { List missingTypes = method.collectMissingTypes(null); if (missingTypes == null) { System.err.println("The method " + method + " is wrongly tagged as containing missing types"); //$NON-NLS-1$ //$NON-NLS-2$ return; } TypeBinding missingType = (TypeBinding) missingTypes.get(0); this.handle( IProblem.MissingTypeInMethod, new String[] { new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false), new String(missingType.readableName()), }, new String[] { new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true), new String(missingType.shortReadableName()), }, (int) (messageSend.nameSourcePosition >>> 32), (int) messageSend.nameSourcePosition); } public void missingValueForAnnotationMember(Annotation annotation, char[] memberName) { String memberString = new String(memberName); this.handle( IProblem.MissingValueForAnnotationMember, new String[] {new String(annotation.resolvedType.readableName()), memberString }, new String[] {new String(annotation.resolvedType.shortReadableName()), memberString}, annotation.sourceStart, annotation.sourceEnd); } public void mustDefineDimensionsOrInitializer(ArrayAllocationExpression expression) { this.handle( IProblem.MustDefineEitherDimensionExpressionsOrInitializer, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void mustUseAStaticMethod(MessageSend messageSend, MethodBinding method) { this.handle( IProblem.StaticMethodRequested, new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, messageSend.sourceStart, messageSend.sourceEnd); } public void nativeMethodsCannotBeStrictfp(ReferenceBinding type, AbstractMethodDeclaration methodDecl) { String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)}; this.handle( IProblem.NativeMethodsCannotBeStrictfp, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd); } public void needImplementation(ASTNode location) { this.abortDueToInternalError(Messages.abort_missingCode, location); } public void needToEmulateFieldAccess(FieldBinding field, ASTNode location, boolean isReadAccess) { int id = isReadAccess ? IProblem.NeedToEmulateFieldReadAccess : IProblem.NeedToEmulateFieldWriteAccess; int severity = computeSeverity(id); if (severity == ProblemSeverities.Ignore) return; this.handle( id, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, severity, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void needToEmulateMethodAccess( MethodBinding method, ASTNode location) { if (method.isConstructor()) { int severity = computeSeverity(IProblem.NeedToEmulateConstructorAccess); if (severity == ProblemSeverities.Ignore) return; if (method.declaringClass.isEnum()) return; // tolerate emulation for enum constructors, which can only be made private this.handle( IProblem.NeedToEmulateConstructorAccess, new String[] { new String(method.declaringClass.readableName()), typesAsString(method, false) }, new String[] { new String(method.declaringClass.shortReadableName()), typesAsString(method, true) }, severity, location.sourceStart, location.sourceEnd); return; } int severity = computeSeverity(IProblem.NeedToEmulateMethodAccess); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.NeedToEmulateMethodAccess, new String[] { new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false) }, new String[] { new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true) }, severity, location.sourceStart, location.sourceEnd); } public void noAdditionalBoundAfterTypeVariable(TypeReference boundReference) { this.handle( IProblem.NoAdditionalBoundAfterTypeVariable, new String[] { new String(boundReference.resolvedType.readableName()) }, new String[] { new String(boundReference.resolvedType.shortReadableName()) }, boundReference.sourceStart, boundReference.sourceEnd); } private int nodeSourceEnd(Binding field, ASTNode node) { return nodeSourceEnd(field, node, 0); } private int nodeSourceEnd(Binding field, ASTNode node, int index) { if (node instanceof ArrayTypeReference) { return ((ArrayTypeReference) node).originalSourceEnd; } else if (node instanceof QualifiedNameReference) { QualifiedNameReference ref = (QualifiedNameReference) node; if (ref.binding == field) { if (index == 0) { return (int) (ref.sourcePositions[ref.indexOfFirstFieldBinding-1]); } else { int length = ref.sourcePositions.length; if (index < length) { return (int) (ref.sourcePositions[index]); } return (int) (ref.sourcePositions[0]); } } FieldBinding[] otherFields = ref.otherBindings; if (otherFields != null) { int offset = ref.indexOfFirstFieldBinding; if (index != 0) { for (int i = 0, length = otherFields.length; i < length; i++) { if ((otherFields[i] == field) && (i + offset == index)) { return (int) (ref.sourcePositions[i + offset]); } } } else { for (int i = 0, length = otherFields.length; i < length; i++) { if (otherFields[i] == field) return (int) (ref.sourcePositions[i + offset]); } } } } else if (node instanceof ParameterizedQualifiedTypeReference) { ParameterizedQualifiedTypeReference reference = (ParameterizedQualifiedTypeReference) node; if (index < reference.sourcePositions.length) { return (int) reference.sourcePositions[index]; } } else if (node instanceof ArrayQualifiedTypeReference) { ArrayQualifiedTypeReference reference = (ArrayQualifiedTypeReference) node; int length = reference.sourcePositions.length; if (index < length) { return (int) reference.sourcePositions[index]; } return (int) reference.sourcePositions[length - 1]; } else if (node instanceof QualifiedTypeReference) { QualifiedTypeReference reference = (QualifiedTypeReference) node; int length = reference.sourcePositions.length; if (index < length) { return (int) reference.sourcePositions[index]; } } return node.sourceEnd; } private int nodeSourceStart(Binding field, ASTNode node) { return nodeSourceStart(field, node, 0); } private int nodeSourceStart(Binding field, ASTNode node, int index) { if (node instanceof FieldReference) { FieldReference fieldReference = (FieldReference) node; return (int) (fieldReference.nameSourcePosition >> 32); } else if (node instanceof QualifiedNameReference) { QualifiedNameReference ref = (QualifiedNameReference) node; if (ref.binding == field) { if (index == 0) { return (int) (ref.sourcePositions[ref.indexOfFirstFieldBinding-1] >> 32); } else { return (int) (ref.sourcePositions[index] >> 32); } } FieldBinding[] otherFields = ref.otherBindings; if (otherFields != null) { int offset = ref.indexOfFirstFieldBinding; if (index != 0) { for (int i = 0, length = otherFields.length; i < length; i++) { if ((otherFields[i] == field) && (i + offset == index)) { return (int) (ref.sourcePositions[i + offset] >> 32); } } } else { for (int i = 0, length = otherFields.length; i < length; i++) { if (otherFields[i] == field) { return (int) (ref.sourcePositions[i + offset] >> 32); } } } } } else if (node instanceof ParameterizedQualifiedTypeReference) { ParameterizedQualifiedTypeReference reference = (ParameterizedQualifiedTypeReference) node; return (int) (reference.sourcePositions[0]>>>32); } return node.sourceStart; } public void noMoreAvailableSpaceForArgument(LocalVariableBinding local, ASTNode location) { String[] arguments = new String[]{ new String(local.name) }; this.handle( local instanceof SyntheticArgumentBinding ? IProblem.TooManySyntheticArgumentSlots : IProblem.TooManyArgumentSlots, arguments, arguments, ProblemSeverities.Abort | ProblemSeverities.Error | ProblemSeverities.Fatal, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void noMoreAvailableSpaceForConstant(TypeDeclaration typeDeclaration) { this.handle( IProblem.TooManyBytesForStringConstant, new String[]{ new String(typeDeclaration.binding.readableName())}, new String[]{ new String(typeDeclaration.binding.shortReadableName())}, ProblemSeverities.Abort | ProblemSeverities.Error | ProblemSeverities.Fatal, typeDeclaration.sourceStart, typeDeclaration.sourceEnd); } public void noMoreAvailableSpaceForLocal(LocalVariableBinding local, ASTNode location) { String[] arguments = new String[]{ new String(local.name) }; this.handle( IProblem.TooManyLocalVariableSlots, arguments, arguments, ProblemSeverities.Abort | ProblemSeverities.Error | ProblemSeverities.Fatal, nodeSourceStart(local, location), nodeSourceEnd(local, location)); } public void noMoreAvailableSpaceInConstantPool(TypeDeclaration typeDeclaration) { this.handle( IProblem.TooManyConstantsInConstantPool, new String[]{ new String(typeDeclaration.binding.readableName())}, new String[]{ new String(typeDeclaration.binding.shortReadableName())}, ProblemSeverities.Abort | ProblemSeverities.Error | ProblemSeverities.Fatal, typeDeclaration.sourceStart, typeDeclaration.sourceEnd); } public void nonExternalizedStringLiteral(ASTNode location) { this.handle( IProblem.NonExternalizedStringLiteral, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void nonGenericTypeCannotBeParameterized(int index, ASTNode location, TypeBinding type, TypeBinding[] argumentTypes) { if (location == null) { // binary case this.handle( IProblem.NonGenericType, new String[] {new String(type.readableName()), typesAsString(argumentTypes, false)}, new String[] {new String(type.shortReadableName()), typesAsString(argumentTypes, true)}, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); return; } this.handle( IProblem.NonGenericType, new String[] {new String(type.readableName()), typesAsString(argumentTypes, false)}, new String[] {new String(type.shortReadableName()), typesAsString(argumentTypes, true)}, nodeSourceStart(null, location), nodeSourceEnd(null, location, index)); } public void nonStaticAccessToStaticField(ASTNode location, FieldBinding field) { nonStaticAccessToStaticField(location, field, -1); } public void nonStaticAccessToStaticField(ASTNode location, FieldBinding field, int index) { int severity = computeSeverity(IProblem.NonStaticAccessToStaticField); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.NonStaticAccessToStaticField, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, severity, nodeSourceStart(field, location, index), nodeSourceEnd(field, location, index)); } public void nonStaticAccessToStaticMethod(ASTNode location, MethodBinding method) { this.handle( IProblem.NonStaticAccessToStaticMethod, new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, location.sourceStart, location.sourceEnd); } public void nonStaticContextForEnumMemberType(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( IProblem.NonStaticContextForEnumMemberType, arguments, arguments, type.sourceStart(), type.sourceEnd()); } public void noSuchEnclosingInstance(TypeBinding targetType, ASTNode location, boolean isConstructorCall) { int id; if (isConstructorCall) { //28 = No enclosing instance of type {0} is available due to some intermediate constructor invocation id = IProblem.EnclosingInstanceInConstructorCall; } else if ((location instanceof ExplicitConstructorCall) && ((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper) { //20 = No enclosing instance of type {0} is accessible to invoke the super constructor. Must define a constructor and explicitly qualify its super constructor invocation with an instance of {0} (e.g. x.super() where x is an instance of {0}). id = IProblem.MissingEnclosingInstanceForConstructorCall; } else if (location instanceof AllocationExpression && (((AllocationExpression) location).binding.declaringClass.isMemberType() || (((AllocationExpression) location).binding.declaringClass.isAnonymousType() && ((AllocationExpression) location).binding.declaringClass.superclass().isMemberType()))) { //21 = No enclosing instance of type {0} is accessible. Must qualify the allocation with an enclosing instance of type {0} (e.g. x.new A() where x is an instance of {0}). id = IProblem.MissingEnclosingInstance; } else { // default //22 = No enclosing instance of the type {0} is accessible in scope id = IProblem.IncorrectEnclosingInstanceReference; } this.handle( id, new String[] { new String(targetType.readableName())}, new String[] { new String(targetType.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void notCompatibleTypesError(EqualExpression expression, TypeBinding leftType, TypeBinding rightType) { String leftName = new String(leftType.readableName()); String rightName = new String(rightType.readableName()); String leftShortName = new String(leftType.shortReadableName()); String rightShortName = new String(rightType.shortReadableName()); if (leftShortName.equals(rightShortName)){ leftShortName = leftName; rightShortName = rightName; } this.handle( IProblem.IncompatibleTypesInEqualityOperator, new String[] {leftName, rightName }, new String[] {leftShortName, rightShortName }, expression.sourceStart, expression.sourceEnd); } public void notCompatibleTypesError(InstanceOfExpression expression, TypeBinding leftType, TypeBinding rightType) { String leftName = new String(leftType.readableName()); String rightName = new String(rightType.readableName()); String leftShortName = new String(leftType.shortReadableName()); String rightShortName = new String(rightType.shortReadableName()); if (leftShortName.equals(rightShortName)){ leftShortName = leftName; rightShortName = rightName; } this.handle( IProblem.IncompatibleTypesInConditionalOperator, new String[] {leftName, rightName }, new String[] {leftShortName, rightShortName }, expression.sourceStart, expression.sourceEnd); } public void notCompatibleTypesErrorInForeach(Expression expression, TypeBinding leftType, TypeBinding rightType) { String leftName = new String(leftType.readableName()); String rightName = new String(rightType.readableName()); String leftShortName = new String(leftType.shortReadableName()); String rightShortName = new String(rightType.shortReadableName()); if (leftShortName.equals(rightShortName)){ leftShortName = leftName; rightShortName = rightName; } this.handle( IProblem.IncompatibleTypesInForeach, new String[] {leftName, rightName }, new String[] {leftShortName, rightShortName }, expression.sourceStart, expression.sourceEnd); } public void objectCannotBeGeneric(TypeDeclaration typeDecl) { this.handle( IProblem.ObjectCannotBeGeneric, NoArgument, NoArgument, typeDecl.typeParameters[0].sourceStart, typeDecl.typeParameters[typeDecl.typeParameters.length-1].sourceEnd); } public void objectCannotHaveSuperTypes(SourceTypeBinding type) { this.handle( IProblem.ObjectCannotHaveSuperTypes, NoArgument, NoArgument, type.sourceStart(), type.sourceEnd()); } public void objectMustBeClass(SourceTypeBinding type) { this.handle( IProblem.ObjectMustBeClass, NoArgument, NoArgument, type.sourceStart(), type.sourceEnd()); } public void operatorOnlyValidOnNumericType(CompoundAssignment assignment, TypeBinding leftType, TypeBinding rightType) { String leftName = new String(leftType.readableName()); String rightName = new String(rightType.readableName()); String leftShortName = new String(leftType.shortReadableName()); String rightShortName = new String(rightType.shortReadableName()); if (leftShortName.equals(rightShortName)){ leftShortName = leftName; rightShortName = rightName; } this.handle( IProblem.TypeMismatch, new String[] {leftName, rightName }, new String[] {leftShortName, rightShortName }, assignment.sourceStart, assignment.sourceEnd); } public void overridesDeprecatedMethod(MethodBinding localMethod, MethodBinding inheritedMethod) { this.handle( IProblem.OverridingDeprecatedMethod, new String[] { new String( CharOperation.concat( localMethod.declaringClass.readableName(), localMethod.readableName(), '.')), new String(inheritedMethod.declaringClass.readableName())}, new String[] { new String( CharOperation.concat( localMethod.declaringClass.shortReadableName(), localMethod.shortReadableName(), '.')), new String(inheritedMethod.declaringClass.shortReadableName())}, localMethod.sourceStart(), localMethod.sourceEnd()); } public void overridesMethodWithoutSuperInvocation(MethodBinding localMethod) { this.handle( IProblem.OverridingMethodWithoutSuperInvocation, new String[] { new String( CharOperation.concat( localMethod.declaringClass.readableName(), localMethod.readableName(), '.')) }, new String[] { new String( CharOperation.concat( localMethod.declaringClass.shortReadableName(), localMethod.shortReadableName(), '.')) }, localMethod.sourceStart(), localMethod.sourceEnd()); } public void overridesPackageDefaultMethod(MethodBinding localMethod, MethodBinding inheritedMethod) { this.handle( IProblem.OverridingNonVisibleMethod, new String[] { new String( CharOperation.concat( localMethod.declaringClass.readableName(), localMethod.readableName(), '.')), new String(inheritedMethod.declaringClass.readableName())}, new String[] { new String( CharOperation.concat( localMethod.declaringClass.shortReadableName(), localMethod.shortReadableName(), '.')), new String(inheritedMethod.declaringClass.shortReadableName())}, localMethod.sourceStart(), localMethod.sourceEnd()); } public void packageCollidesWithType(CompilationUnitDeclaration compUnitDecl) { String[] arguments = new String[] {CharOperation.toString(compUnitDecl.currentPackage.tokens)}; this.handle( IProblem.PackageCollidesWithType, arguments, arguments, compUnitDecl.currentPackage.sourceStart, compUnitDecl.currentPackage.sourceEnd); } public void packageIsNotExpectedPackage(CompilationUnitDeclaration compUnitDecl) { boolean hasPackageDeclaration = compUnitDecl.currentPackage == null; String[] arguments = new String[] { CharOperation.toString(compUnitDecl.compilationResult.compilationUnit.getPackageName()), hasPackageDeclaration ? "" : CharOperation.toString(compUnitDecl.currentPackage.tokens), //$NON-NLS-1$ }; int end; if (compUnitDecl.sourceEnd <= 0) { end = -1; } else { end = hasPackageDeclaration ? 0 : compUnitDecl.currentPackage.sourceEnd; } this.handle( IProblem.PackageIsNotExpectedPackage, arguments, arguments, hasPackageDeclaration ? 0 : compUnitDecl.currentPackage.sourceStart, end); } public void parameterAssignment(LocalVariableBinding local, ASTNode location) { int severity = computeSeverity(IProblem.ParameterAssignment); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] { new String(local.readableName())}; this.handle( IProblem.ParameterAssignment, arguments, arguments, severity, nodeSourceStart(local, location), nodeSourceEnd(local, location)); // should never be a qualified name reference } private String parameterBoundAsString(TypeVariableBinding typeVariable, boolean makeShort) { StringBuffer nameBuffer = new StringBuffer(10); if (typeVariable.firstBound == typeVariable.superclass) { nameBuffer.append(makeShort ? typeVariable.superclass.shortReadableName() : typeVariable.superclass.readableName()); } int length; if ((length = typeVariable.superInterfaces.length) > 0) { for (int i = 0; i < length; i++) { if (i > 0 || typeVariable.firstBound == typeVariable.superclass) nameBuffer.append(" & "); //$NON-NLS-1$ nameBuffer.append(makeShort ? typeVariable.superInterfaces[i].shortReadableName() : typeVariable.superInterfaces[i].readableName()); } } return nameBuffer.toString(); } public void parameterizedMemberTypeMissingArguments(ASTNode location, TypeBinding type, int index) { if (location == null) { // binary case this.handle( IProblem.MissingArgumentsForParameterizedMemberType, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); return; } this.handle( IProblem.MissingArgumentsForParameterizedMemberType, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, location.sourceStart, nodeSourceEnd(null, location, index)); } public void parseError( int startPosition, int endPosition, int currentToken, char[] currentTokenSource, String errorTokenName, String[] possibleTokens) { if (possibleTokens.length == 0) { //no suggestion available if (isKeyword(currentToken)) { String[] arguments = new String[] {new String(currentTokenSource)}; this.handle( IProblem.ParsingErrorOnKeywordNoSuggestion, arguments, arguments, // this is the current -invalid- token position startPosition, endPosition); return; } else { String[] arguments = new String[] {errorTokenName}; this.handle( IProblem.ParsingErrorNoSuggestion, arguments, arguments, // this is the current -invalid- token position startPosition, endPosition); return; } } //build a list of probable right tokens StringBuffer list = new StringBuffer(20); for (int i = 0, max = possibleTokens.length; i < max; i++) { if (i > 0) list.append(", "); //$NON-NLS-1$ list.append('"'); list.append(possibleTokens[i]); list.append('"'); } if (isKeyword(currentToken)) { String[] arguments = new String[] {new String(currentTokenSource), list.toString()}; this.handle( IProblem.ParsingErrorOnKeyword, arguments, arguments, // this is the current -invalid- token position startPosition, endPosition); return; } //extract the literal when it's a literal if (isLiteral(currentToken) || isIdentifier(currentToken)) { errorTokenName = new String(currentTokenSource); } String[] arguments = new String[] {errorTokenName, list.toString()}; this.handle( IProblem.ParsingError, arguments, arguments, // this is the current -invalid- token position startPosition, endPosition); } public void parseErrorDeleteToken( int start, int end, int currentKind, char[] errorTokenSource, String errorTokenName){ syntaxError( IProblem.ParsingErrorDeleteToken, start, end, currentKind, errorTokenSource, errorTokenName, null); } public void parseErrorDeleteTokens( int start, int end){ this.handle( IProblem.ParsingErrorDeleteTokens, NoArgument, NoArgument, start, end); } public void parseErrorInsertAfterToken( int start, int end, int currentKind, char[] errorTokenSource, String errorTokenName, String expectedToken){ syntaxError( IProblem.ParsingErrorInsertTokenAfter, start, end, currentKind, errorTokenSource, errorTokenName, expectedToken); } public void parseErrorInsertBeforeToken( int start, int end, int currentKind, char[] errorTokenSource, String errorTokenName, String expectedToken){ syntaxError( IProblem.ParsingErrorInsertTokenBefore, start, end, currentKind, errorTokenSource, errorTokenName, expectedToken); } public void parseErrorInsertToComplete( int start, int end, String inserted, String completed){ String[] arguments = new String[] {inserted, completed}; this.handle( IProblem.ParsingErrorInsertToComplete, arguments, arguments, start, end); } public void parseErrorInsertToCompletePhrase( int start, int end, String inserted){ String[] arguments = new String[] {inserted}; this.handle( IProblem.ParsingErrorInsertToCompletePhrase, arguments, arguments, start, end); } public void parseErrorInsertToCompleteScope( int start, int end, String inserted){ String[] arguments = new String[] {inserted}; this.handle( IProblem.ParsingErrorInsertToCompleteScope, arguments, arguments, start, end); } public void parseErrorInvalidToken( int start, int end, int currentKind, char[] errorTokenSource, String errorTokenName, String expectedToken){ syntaxError( IProblem.ParsingErrorInvalidToken, start, end, currentKind, errorTokenSource, errorTokenName, expectedToken); } public void parseErrorMergeTokens( int start, int end, String expectedToken){ String[] arguments = new String[] {expectedToken}; this.handle( IProblem.ParsingErrorMergeTokens, arguments, arguments, start, end); } public void parseErrorMisplacedConstruct( int start, int end){ this.handle( IProblem.ParsingErrorMisplacedConstruct, NoArgument, NoArgument, start, end); } public void parseErrorNoSuggestion( int start, int end, int currentKind, char[] errorTokenSource, String errorTokenName){ syntaxError( IProblem.ParsingErrorNoSuggestion, start, end, currentKind, errorTokenSource, errorTokenName, null); } public void parseErrorNoSuggestionForTokens( int start, int end){ this.handle( IProblem.ParsingErrorNoSuggestionForTokens, NoArgument, NoArgument, start, end); } public void parseErrorReplaceToken( int start, int end, int currentKind, char[] errorTokenSource, String errorTokenName, String expectedToken){ syntaxError( IProblem.ParsingError, start, end, currentKind, errorTokenSource, errorTokenName, expectedToken); } public void parseErrorReplaceTokens( int start, int end, String expectedToken){ String[] arguments = new String[] {expectedToken}; this.handle( IProblem.ParsingErrorReplaceTokens, arguments, arguments, start, end); } public void parseErrorUnexpectedEnd( int start, int end){ String[] arguments; if(this.referenceContext instanceof ConstructorDeclaration) { arguments = new String[] {Messages.parser_endOfConstructor}; } else if(this.referenceContext instanceof MethodDeclaration) { arguments = new String[] {Messages.parser_endOfMethod}; } else if(this.referenceContext instanceof TypeDeclaration) { arguments = new String[] {Messages.parser_endOfInitializer}; } else { arguments = new String[] {Messages.parser_endOfFile}; } this.handle( IProblem.ParsingErrorUnexpectedEOF, arguments, arguments, start, end); } public void possibleAccidentalBooleanAssignment(Assignment assignment) { this.handle( IProblem.PossibleAccidentalBooleanAssignment, NoArgument, NoArgument, assignment.sourceStart, assignment.sourceEnd); } public void possibleFallThroughCase(CaseStatement caseStatement) { // as long as we consider fake reachable as reachable, better keep 'possible' in the name this.handle( IProblem.FallthroughCase, NoArgument, NoArgument, caseStatement.sourceStart, caseStatement.sourceEnd); } public void publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) { this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)}; this.handle( IProblem.PublicClassMustMatchFileName, arguments, arguments, typeDecl.sourceStart, typeDecl.sourceEnd, compUnitDecl.compilationResult); } public void rawMemberTypeCannotBeParameterized(ASTNode location, ReferenceBinding type, TypeBinding[] argumentTypes) { if (location == null) { // binary case this.handle( IProblem.RawMemberTypeCannotBeParameterized, new String[] {new String(type.readableName()), typesAsString(argumentTypes, false), new String(type.enclosingType().readableName())}, new String[] {new String(type.shortReadableName()), typesAsString(argumentTypes, true), new String(type.enclosingType().shortReadableName())}, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); return; } this.handle( IProblem.RawMemberTypeCannotBeParameterized, new String[] {new String(type.readableName()), typesAsString(argumentTypes, false), new String(type.enclosingType().readableName())}, new String[] {new String(type.shortReadableName()), typesAsString(argumentTypes, true), new String(type.enclosingType().shortReadableName())}, location.sourceStart, location.sourceEnd); } public void rawTypeReference(ASTNode location, TypeBinding type) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 type = type.leafComponentType(); this.handle( IProblem.RawTypeReference, new String[] {new String(type.readableName()), new String(type.erasure().readableName()), }, new String[] {new String(type.shortReadableName()),new String(type.erasure().shortReadableName()),}, location.sourceStart, nodeSourceEnd(null, location, Integer.MAX_VALUE)); } public void recursiveConstructorInvocation(ExplicitConstructorCall constructorCall) { this.handle( IProblem.RecursiveConstructorInvocation, new String[] { new String(constructorCall.binding.declaringClass.readableName()), typesAsString(constructorCall.binding, false) }, new String[] { new String(constructorCall.binding.declaringClass.shortReadableName()), typesAsString(constructorCall.binding, true) }, constructorCall.sourceStart, constructorCall.sourceEnd); } public void redefineArgument(Argument arg) { String[] arguments = new String[] {new String(arg.name)}; this.handle( IProblem.RedefinedArgument, arguments, arguments, arg.sourceStart, arg.sourceEnd); } public void redefineLocal(LocalDeclaration localDecl) { String[] arguments = new String[] {new String(localDecl.name)}; this.handle( IProblem.RedefinedLocal, arguments, arguments, localDecl.sourceStart, localDecl.sourceEnd); } public void redundantSuperInterface(SourceTypeBinding type, TypeReference reference, ReferenceBinding superinterface, ReferenceBinding declaringType) { int severity = computeSeverity(IProblem.RedundantSuperinterface); if (severity != ProblemSeverities.Ignore) { this.handle( IProblem.RedundantSuperinterface, new String[] { new String(superinterface.readableName()), new String(type.readableName()), new String(declaringType.readableName())}, new String[] { new String(superinterface.shortReadableName()), new String(type.shortReadableName()), new String(declaringType.shortReadableName())}, severity, reference.sourceStart, reference.sourceEnd); } } public void referenceMustBeArrayTypeAt(TypeBinding arrayType, ArrayReference arrayRef) { this.handle( IProblem.ArrayReferenceRequired, new String[] {new String(arrayType.readableName())}, new String[] {new String(arrayType.shortReadableName())}, arrayRef.sourceStart, arrayRef.sourceEnd); } public void reset() { this.positionScanner = null; } public void resourceHasToImplementAutoCloseable(TypeBinding binding, TypeReference typeReference) { if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { return; // Not supported in 1.7 would have been reported. Hence another not required } this.handle( IProblem.ResourceHasToImplementAutoCloseable, new String[] {new String(binding.readableName())}, new String[] {new String(binding.shortReadableName())}, typeReference.sourceStart, typeReference.sourceEnd); } private int retrieveClosingAngleBracketPosition(int start) { if (this.referenceContext == null) return start; CompilationResult compilationResult = this.referenceContext.compilationResult(); if (compilationResult == null) return start; ICompilationUnit compilationUnit = compilationResult.getCompilationUnit(); if (compilationUnit == null) return start; char[] contents = compilationUnit.getContents(); if (contents.length == 0) return start; if (this.positionScanner == null) { this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false); this.positionScanner.returnOnlyGreater = true; } this.positionScanner.setSource(contents); this.positionScanner.resetTo(start, contents.length); int end = start; int count = 0; try { int token; loop: while ((token = this.positionScanner.getNextToken()) != TerminalTokens.TokenNameEOF) { switch(token) { case TerminalTokens.TokenNameLESS: count++; break; case TerminalTokens.TokenNameGREATER: count--; if (count == 0) { end = this.positionScanner.currentPosition - 1; break loop; } break; case TerminalTokens.TokenNameLBRACE : break loop; } } } catch(InvalidInputException e) { // ignore } return end; } private int retrieveEndingPositionAfterOpeningParenthesis(int sourceStart, int sourceEnd, int numberOfParen) { if (this.referenceContext == null) return sourceEnd; CompilationResult compilationResult = this.referenceContext.compilationResult(); if (compilationResult == null) return sourceEnd; ICompilationUnit compilationUnit = compilationResult.getCompilationUnit(); if (compilationUnit == null) return sourceEnd; char[] contents = compilationUnit.getContents(); if (contents.length == 0) return sourceEnd; if (this.positionScanner == null) { this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false); } this.positionScanner.setSource(contents); this.positionScanner.resetTo(sourceStart, sourceEnd); try { int token; int previousSourceEnd = sourceEnd; while ((token = this.positionScanner.getNextToken()) != TerminalTokens.TokenNameEOF) { switch(token) { case TerminalTokens.TokenNameRPAREN: return previousSourceEnd; default : previousSourceEnd = this.positionScanner.currentPosition - 1; } } } catch(InvalidInputException e) { // ignore } return sourceEnd; } private int retrieveStartingPositionAfterOpeningParenthesis(int sourceStart, int sourceEnd, int numberOfParen) { if (this.referenceContext == null) return sourceStart; CompilationResult compilationResult = this.referenceContext.compilationResult(); if (compilationResult == null) return sourceStart; ICompilationUnit compilationUnit = compilationResult.getCompilationUnit(); if (compilationUnit == null) return sourceStart; char[] contents = compilationUnit.getContents(); if (contents.length == 0) return sourceStart; if (this.positionScanner == null) { this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false); } this.positionScanner.setSource(contents); this.positionScanner.resetTo(sourceStart, sourceEnd); int count = 0; try { int token; while ((token = this.positionScanner.getNextToken()) != TerminalTokens.TokenNameEOF) { switch(token) { case TerminalTokens.TokenNameLPAREN: count++; if (count == numberOfParen) { this.positionScanner.getNextToken(); return this.positionScanner.startPosition; } } } } catch(InvalidInputException e) { // ignore } return sourceStart; } public void scannerError(Parser parser, String errorTokenName) { Scanner scanner = parser.scanner; int flag = IProblem.ParsingErrorNoSuggestion; int startPos = scanner.startPosition; int endPos = scanner.currentPosition - 1; //special treatment for recognized errors.... if (errorTokenName.equals(Scanner.END_OF_SOURCE)) flag = IProblem.EndOfSource; else if (errorTokenName.equals(Scanner.INVALID_HEXA)) flag = IProblem.InvalidHexa; else if (errorTokenName.equals(Scanner.ILLEGAL_HEXA_LITERAL)) flag = IProblem.IllegalHexaLiteral; else if (errorTokenName.equals(Scanner.INVALID_OCTAL)) flag = IProblem.InvalidOctal; else if (errorTokenName.equals(Scanner.INVALID_CHARACTER_CONSTANT)) flag = IProblem.InvalidCharacterConstant; else if (errorTokenName.equals(Scanner.INVALID_ESCAPE)) flag = IProblem.InvalidEscape; else if (errorTokenName.equals(Scanner.INVALID_UNICODE_ESCAPE)){ flag = IProblem.InvalidUnicodeEscape; // better locate the error message char[] source = scanner.source; int checkPos = scanner.currentPosition - 1; if (checkPos >= source.length) checkPos = source.length - 1; while (checkPos >= startPos){ if (source[checkPos] == '\\') break; checkPos --; } startPos = checkPos; } else if (errorTokenName.equals(Scanner.INVALID_LOW_SURROGATE)) { flag = IProblem.InvalidLowSurrogate; } else if (errorTokenName.equals(Scanner.INVALID_HIGH_SURROGATE)) { flag = IProblem.InvalidHighSurrogate; // better locate the error message char[] source = scanner.source; int checkPos = scanner.startPosition + 1; while (checkPos <= endPos){ if (source[checkPos] == '\\') break; checkPos ++; } endPos = checkPos - 1; } else if (errorTokenName.equals(Scanner.INVALID_FLOAT)) flag = IProblem.InvalidFloat; else if (errorTokenName.equals(Scanner.UNTERMINATED_STRING)) flag = IProblem.UnterminatedString; else if (errorTokenName.equals(Scanner.UNTERMINATED_COMMENT)) flag = IProblem.UnterminatedComment; else if (errorTokenName.equals(Scanner.INVALID_CHAR_IN_STRING)) flag = IProblem.UnterminatedString; else if (errorTokenName.equals(Scanner.INVALID_DIGIT)) flag = IProblem.InvalidDigit; else if (errorTokenName.equals(Scanner.INVALID_BINARY)) flag = IProblem.InvalidBinary; else if (errorTokenName.equals(Scanner.BINARY_LITERAL_NOT_BELOW_17)) flag = IProblem.BinaryLiteralNotBelow17; else if (errorTokenName.equals(Scanner.INVALID_UNDERSCORE)) flag = IProblem.IllegalUnderscorePosition; else if (errorTokenName.equals(Scanner.UNDERSCORES_IN_LITERALS_NOT_BELOW_17)) flag = IProblem.UnderscoresInLiteralsNotBelow17; String[] arguments = flag == IProblem.ParsingErrorNoSuggestion ? new String[] {errorTokenName} : NoArgument; this.handle( flag, arguments, arguments, // this is the current -invalid- token position startPos, endPos, parser.compilationUnit.compilationResult); } public void shouldImplementHashcode(SourceTypeBinding type) { this.handle( IProblem.ShouldImplementHashcode, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, type.sourceStart(), type.sourceEnd()); } public void shouldReturn(TypeBinding returnType, ASTNode location) { this.handle( methodHasMissingSwitchDefault() ? IProblem.ShouldReturnValueHintMissingDefault : IProblem.ShouldReturnValue, new String[] { new String (returnType.readableName())}, new String[] { new String (returnType.shortReadableName())}, location.sourceStart, location.sourceEnd); } public void signalNoImplicitStringConversionForCharArrayExpression(Expression expression) { this.handle( IProblem.NoImplicitStringConversionForCharArrayExpression, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void staticAndInstanceConflict(MethodBinding currentMethod, MethodBinding inheritedMethod) { if (currentMethod.isStatic()) this.handle( // This static method cannot hide the instance method from %1 // 8.4.6.4 - If a class inherits more than one method with the same signature a static (non-abstract) method cannot hide an instance method. IProblem.CannotHideAnInstanceMethodWithAStaticMethod, new String[] {new String(inheritedMethod.declaringClass.readableName())}, new String[] {new String(inheritedMethod.declaringClass.shortReadableName())}, currentMethod.sourceStart(), currentMethod.sourceEnd()); else this.handle( // This instance method cannot override the static method from %1 // 8.4.6.4 - If a class inherits more than one method with the same signature an instance (non-abstract) method cannot override a static method. IProblem.CannotOverrideAStaticMethodWithAnInstanceMethod, new String[] {new String(inheritedMethod.declaringClass.readableName())}, new String[] {new String(inheritedMethod.declaringClass.shortReadableName())}, currentMethod.sourceStart(), currentMethod.sourceEnd()); } public void staticFieldAccessToNonStaticVariable(ASTNode location, FieldBinding field) { String[] arguments = new String[] {new String(field.readableName())}; this.handle( IProblem.NonStaticFieldFromStaticInvocation, arguments, arguments, nodeSourceStart(field,location), nodeSourceEnd(field, location)); } public void staticInheritedMethodConflicts(SourceTypeBinding type, MethodBinding concreteMethod, MethodBinding[] abstractMethods) { this.handle( // The static method %1 conflicts with the abstract method in %2 // 8.4.6.4 - If a class inherits more than one method with the same signature it is an error for one to be static (non-abstract) and the other abstract. IProblem.StaticInheritedMethodConflicts, new String[] { new String(concreteMethod.readableName()), new String(abstractMethods[0].declaringClass.readableName())}, new String[] { new String(concreteMethod.readableName()), new String(abstractMethods[0].declaringClass.shortReadableName())}, type.sourceStart(), type.sourceEnd()); } public void staticMemberOfParameterizedType(ASTNode location, ReferenceBinding type, int index) { if (location == null) { // binary case this.handle( IProblem.StaticMemberOfParameterizedType, new String[] {new String(type.readableName()), new String(type.enclosingType().readableName()), }, new String[] {new String(type.shortReadableName()), new String(type.enclosingType().shortReadableName()), }, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); return; } /*if (location instanceof ArrayTypeReference) { ArrayTypeReference arrayTypeReference = (ArrayTypeReference) location; if (arrayTypeReference.token != null && arrayTypeReference.token.length == 0) return; end = arrayTypeReference.originalSourceEnd; }*/ this.handle( IProblem.StaticMemberOfParameterizedType, new String[] {new String(type.readableName()), new String(type.enclosingType().readableName()), }, new String[] {new String(type.shortReadableName()), new String(type.enclosingType().shortReadableName()), }, location.sourceStart, nodeSourceEnd(null, location, index)); } public void stringConstantIsExceedingUtf8Limit(ASTNode location) { this.handle( IProblem.StringConstantIsExceedingUtf8Limit, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void superclassMustBeAClass(SourceTypeBinding type, TypeReference superclassRef, ReferenceBinding superType) { this.handle( IProblem.SuperclassMustBeAClass, new String[] {new String(superType.readableName()), new String(type.sourceName())}, new String[] {new String(superType.shortReadableName()), new String(type.sourceName())}, superclassRef.sourceStart, superclassRef.sourceEnd); } public void superfluousSemicolon(int sourceStart, int sourceEnd) { this.handle( IProblem.SuperfluousSemicolon, NoArgument, NoArgument, sourceStart, sourceEnd); } public void superinterfaceMustBeAnInterface(SourceTypeBinding type, TypeReference superInterfaceRef, ReferenceBinding superType) { this.handle( IProblem.SuperInterfaceMustBeAnInterface, new String[] {new String(superType.readableName()), new String(type.sourceName())}, new String[] {new String(superType.shortReadableName()), new String(type.sourceName())}, superInterfaceRef.sourceStart, superInterfaceRef.sourceEnd); } public void superinterfacesCollide(TypeBinding type, ASTNode decl, TypeBinding superType, TypeBinding inheritedSuperType) { this.handle( IProblem.SuperInterfacesCollide, new String[] {new String(superType.readableName()), new String(inheritedSuperType.readableName()), new String(type.sourceName())}, new String[] {new String(superType.shortReadableName()), new String(inheritedSuperType.shortReadableName()), new String(type.sourceName())}, decl.sourceStart, decl.sourceEnd); } public void superTypeCannotUseWildcard(SourceTypeBinding type, TypeReference superclass, TypeBinding superTypeBinding) { String name = new String(type.sourceName()); String superTypeFullName = new String(superTypeBinding.readableName()); String superTypeShortName = new String(superTypeBinding.shortReadableName()); if (superTypeShortName.equals(name)) superTypeShortName = superTypeFullName; this.handle( IProblem.SuperTypeUsingWildcard, new String[] {superTypeFullName, name}, new String[] {superTypeShortName, name}, superclass.sourceStart, superclass.sourceEnd); } private void syntaxError( int id, int startPosition, int endPosition, int currentKind, char[] currentTokenSource, String errorTokenName, String expectedToken) { String eTokenName; if (isKeyword(currentKind) || isLiteral(currentKind) || isIdentifier(currentKind)) { eTokenName = new String(currentTokenSource); } else { eTokenName = errorTokenName; } String[] arguments; if(expectedToken != null) { arguments = new String[] {eTokenName, expectedToken}; } else { arguments = new String[] {eTokenName}; } this.handle( id, arguments, arguments, startPosition, endPosition); } public void task(String tag, String message, String priority, int start, int end){ this.handle( IProblem.Task, new String[] { tag, message, priority/*secret argument that is not surfaced in getMessage()*/}, new String[] { tag, message, priority/*secret argument that is not surfaced in getMessage()*/}, start, end); } public void tooManyDimensions(ASTNode expression) { this.handle( IProblem.TooManyArrayDimensions, NoArgument, NoArgument, expression.sourceStart, expression.sourceEnd); } public void tooManyFields(TypeDeclaration typeDeclaration) { this.handle( IProblem.TooManyFields, new String[]{ new String(typeDeclaration.binding.readableName())}, new String[]{ new String(typeDeclaration.binding.shortReadableName())}, ProblemSeverities.Abort | ProblemSeverities.Error | ProblemSeverities.Fatal, typeDeclaration.sourceStart, typeDeclaration.sourceEnd); } public void tooManyMethods(TypeDeclaration typeDeclaration) { this.handle( IProblem.TooManyMethods, new String[]{ new String(typeDeclaration.binding.readableName())}, new String[]{ new String(typeDeclaration.binding.shortReadableName())}, ProblemSeverities.Abort | ProblemSeverities.Error | ProblemSeverities.Fatal, typeDeclaration.sourceStart, typeDeclaration.sourceEnd); } public void tooManyParametersForSyntheticMethod(AbstractMethodDeclaration method) { MethodBinding binding = method.binding; String selector = null; if (binding.isConstructor()) { selector = new String(binding.declaringClass.sourceName()); } else { selector = new String(method.selector); } this.handle( IProblem.TooManyParametersForSyntheticMethod, new String[] {selector, typesAsString(binding, false), new String(binding.declaringClass.readableName()), }, new String[] {selector, typesAsString(binding, true), new String(binding.declaringClass.shortReadableName()),}, ProblemSeverities.AbortMethod | ProblemSeverities.Error | ProblemSeverities.Fatal, method.sourceStart, method.sourceEnd); } public void typeCastError(CastExpression expression, TypeBinding leftType, TypeBinding rightType) { String leftName = new String(leftType.readableName()); String rightName = new String(rightType.readableName()); String leftShortName = new String(leftType.shortReadableName()); String rightShortName = new String(rightType.shortReadableName()); if (leftShortName.equals(rightShortName)){ leftShortName = leftName; rightShortName = rightName; } this.handle( IProblem.IllegalCast, new String[] { rightName, leftName }, new String[] { rightShortName, leftShortName }, expression.sourceStart, expression.sourceEnd); } public void typeCollidesWithEnclosingType(TypeDeclaration typeDecl) { String[] arguments = new String[] {new String(typeDecl.name)}; this.handle( IProblem.HidingEnclosingType, arguments, arguments, typeDecl.sourceStart, typeDecl.sourceEnd); } public void typeCollidesWithPackage(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) { this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)}; this.handle( IProblem.TypeCollidesWithPackage, arguments, arguments, typeDecl.sourceStart, typeDecl.sourceEnd, compUnitDecl.compilationResult); } public void typeHiding(TypeDeclaration typeDecl, TypeBinding hiddenType) { int severity = computeSeverity(IProblem.TypeHidingType); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.TypeHidingType, new String[] { new String(typeDecl.name) , new String(hiddenType.shortReadableName()) }, new String[] { new String(typeDecl.name) , new String(hiddenType.readableName()) }, severity, typeDecl.sourceStart, typeDecl.sourceEnd); } public void typeHiding(TypeDeclaration typeDecl, TypeVariableBinding hiddenTypeParameter) { int severity = computeSeverity(IProblem.TypeHidingTypeParameterFromType); if (severity == ProblemSeverities.Ignore) return; if (hiddenTypeParameter.declaringElement instanceof TypeBinding) { TypeBinding declaringType = (TypeBinding) hiddenTypeParameter.declaringElement; this.handle( IProblem.TypeHidingTypeParameterFromType, new String[] { new String(typeDecl.name) , new String(hiddenTypeParameter.readableName()), new String(declaringType.readableName()) }, new String[] { new String(typeDecl.name) , new String(hiddenTypeParameter.shortReadableName()), new String(declaringType.shortReadableName()) }, severity, typeDecl.sourceStart, typeDecl.sourceEnd); } else { // type parameter of generic method MethodBinding declaringMethod = (MethodBinding) hiddenTypeParameter.declaringElement; this.handle( IProblem.TypeHidingTypeParameterFromMethod, new String[] { new String(typeDecl.name), new String(hiddenTypeParameter.readableName()), new String(declaringMethod.selector), typesAsString(declaringMethod, false), new String(declaringMethod.declaringClass.readableName()), }, new String[] { new String(typeDecl.name), new String(hiddenTypeParameter.shortReadableName()), new String(declaringMethod.selector), typesAsString(declaringMethod, true), new String(declaringMethod.declaringClass.shortReadableName()), }, severity, typeDecl.sourceStart, typeDecl.sourceEnd); } } public void typeHiding(TypeParameter typeParam, Binding hidden) { int severity = computeSeverity(IProblem.TypeParameterHidingType); if (severity == ProblemSeverities.Ignore) return; TypeBinding hiddenType = (TypeBinding) hidden; this.handle( IProblem.TypeParameterHidingType, new String[] { new String(typeParam.name) , new String(hiddenType.readableName()) }, new String[] { new String(typeParam.name) , new String(hiddenType.shortReadableName()) }, severity, typeParam.sourceStart, typeParam.sourceEnd); } public void typeMismatchError(TypeBinding actualType, TypeBinding expectedType, ASTNode location, ASTNode expectingLocation) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) { // don't expose type variable names, complain on erased types if (actualType instanceof TypeVariableBinding) actualType = actualType.erasure(); if (expectedType instanceof TypeVariableBinding) expectedType = expectedType.erasure(); } if (actualType != null && (actualType.tagBits & TagBits.HasMissingType) != 0) { // improve secondary error this.handle( IProblem.UndefinedType, new String[] {new String(actualType.leafComponentType().readableName())}, new String[] {new String(actualType.leafComponentType().shortReadableName())}, location.sourceStart, location.sourceEnd); return; } if (expectingLocation != null && (expectedType.tagBits & TagBits.HasMissingType) != 0) { // improve secondary error this.handle( IProblem.UndefinedType, new String[] {new String(expectedType.leafComponentType().readableName())}, new String[] {new String(expectedType.leafComponentType().shortReadableName())}, expectingLocation.sourceStart, expectingLocation.sourceEnd); return; } char[] actualShortReadableName = actualType.shortReadableName(); char[] expectedShortReadableName = expectedType.shortReadableName(); if (CharOperation.equals(actualShortReadableName, expectedShortReadableName)) { actualShortReadableName = actualType.readableName(); expectedShortReadableName = expectedType.readableName(); } this.handle( IProblem.TypeMismatch, new String[] {new String(actualType.readableName()), new String(expectedType.readableName())}, new String[] {new String(actualShortReadableName), new String(expectedShortReadableName)}, location.sourceStart, location.sourceEnd); } public void typeMismatchError(TypeBinding typeArgument, TypeVariableBinding typeParameter, ReferenceBinding genericType, ASTNode location) { if (location == null) { // binary case this.handle( IProblem.TypeArgumentMismatch, new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) }, new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) }, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); return; } this.handle( IProblem.TypeArgumentMismatch, new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) }, new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) }, location.sourceStart, location.sourceEnd); } private String typesAsString(MethodBinding methodBinding, boolean makeShort) { return typesAsString(methodBinding, methodBinding.parameters, makeShort); } private String typesAsString(MethodBinding methodBinding, TypeBinding[] parameters, boolean makeShort) { if (methodBinding.isPolymorphic()) { // get the original polymorphicMethod method TypeBinding[] types = methodBinding.original().parameters; StringBuffer buffer = new StringBuffer(10); for (int i = 0, length = types.length; i < length; i++) { if (i != 0) { buffer.append(", "); //$NON-NLS-1$ } TypeBinding type = types[i]; boolean isVarargType = i == length-1; if (isVarargType) { type = ((ArrayBinding)type).elementsType(); } buffer.append(new String(makeShort ? type.shortReadableName() : type.readableName())); if (isVarargType) { buffer.append("..."); //$NON-NLS-1$ } } return buffer.toString(); } StringBuffer buffer = new StringBuffer(10); for (int i = 0, length = parameters.length; i < length; i++) { if (i != 0) { buffer.append(", "); //$NON-NLS-1$ } TypeBinding type = parameters[i]; boolean isVarargType = methodBinding.isVarargs() && i == length-1; if (isVarargType) { type = ((ArrayBinding)type).elementsType(); } buffer.append(new String(makeShort ? type.shortReadableName() : type.readableName())); if (isVarargType) { buffer.append("..."); //$NON-NLS-1$ } } return buffer.toString(); } private String typesAsString(TypeBinding[] types, boolean makeShort) { StringBuffer buffer = new StringBuffer(10); for (int i = 0, length = types.length; i < length; i++) { if (i != 0) { buffer.append(", "); //$NON-NLS-1$ } TypeBinding type = types[i]; buffer.append(new String(makeShort ? type.shortReadableName() : type.readableName())); } return buffer.toString(); } public void undefinedAnnotationValue(TypeBinding annotationType, MemberValuePair memberValuePair) { if (isRecoveredName(memberValuePair.name)) return; String name = new String(memberValuePair.name); this.handle( IProblem.UndefinedAnnotationMember, new String[] { name, new String(annotationType.readableName())}, new String[] { name, new String(annotationType.shortReadableName())}, memberValuePair.sourceStart, memberValuePair.sourceEnd); } public void undefinedLabel(BranchStatement statement) { if (isRecoveredName(statement.label)) return; String[] arguments = new String[] {new String(statement.label)}; this.handle( IProblem.UndefinedLabel, arguments, arguments, statement.sourceStart, statement.sourceEnd); } // can only occur inside binaries public void undefinedTypeVariableSignature(char[] variableName, ReferenceBinding binaryType) { this.handle( IProblem.UndefinedTypeVariable, new String[] {new String(variableName), new String(binaryType.readableName()) }, new String[] {new String(variableName), new String(binaryType.shortReadableName())}, ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); } public void undocumentedEmptyBlock(int blockStart, int blockEnd) { this.handle( IProblem.UndocumentedEmptyBlock, NoArgument, NoArgument, blockStart, blockEnd); } public void unexpectedStaticModifierForField(SourceTypeBinding type, FieldDeclaration fieldDecl) { String[] arguments = new String[] {new String(fieldDecl.name)}; this.handle( IProblem.UnexpectedStaticModifierForField, arguments, arguments, fieldDecl.sourceStart, fieldDecl.sourceEnd); } public void unexpectedStaticModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) { String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)}; this.handle( IProblem.UnexpectedStaticModifierForMethod, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd); } public void unhandledException(TypeBinding exceptionType, ASTNode location) { boolean insideDefaultConstructor = (this.referenceContext instanceof ConstructorDeclaration) && ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor(); boolean insideImplicitConstructorCall = (location instanceof ExplicitConstructorCall) && (((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper); int sourceEnd = location.sourceEnd; if (location instanceof LocalDeclaration) { sourceEnd = ((LocalDeclaration) location).declarationEnd; } this.handle( insideDefaultConstructor ? IProblem.UnhandledExceptionInDefaultConstructor : (insideImplicitConstructorCall ? IProblem.UndefinedConstructorInImplicitConstructorCall : IProblem.UnhandledException), new String[] {new String(exceptionType.readableName())}, new String[] {new String(exceptionType.shortReadableName())}, location.sourceStart, sourceEnd); } public void unhandledExceptionFromAutoClose (TypeBinding exceptionType, ASTNode location) { LocalVariableBinding localBinding = ((LocalDeclaration)location).binding; if (localBinding != null) { this.handle( IProblem.UnhandledExceptionOnAutoClose, new String[] { new String(exceptionType.readableName()), new String(localBinding.readableName())}, new String[] { new String(exceptionType.shortReadableName()), new String(localBinding.shortReadableName())}, location.sourceStart, location.sourceEnd); } } public void unhandledWarningToken(Expression token) { String[] arguments = new String[] { token.constant.stringValue() }; this.handle( IProblem.UnhandledWarningToken, arguments, arguments, token.sourceStart, token.sourceEnd); } public void uninitializedBlankFinalField(FieldBinding field, ASTNode location) { String[] arguments = new String[] {new String(field.readableName())}; this.handle( methodHasMissingSwitchDefault() ? IProblem.UninitializedBlankFinalFieldHintMissingDefault : IProblem.UninitializedBlankFinalField, arguments, arguments, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void uninitializedNonNullField(FieldBinding field, ASTNode location) { char[][] nonNullAnnotationName = this.options.nonNullAnnotationName; String[] arguments = new String[] { new String(nonNullAnnotationName[nonNullAnnotationName.length-1]), new String(field.readableName()) }; this.handle( methodHasMissingSwitchDefault() ? IProblem.UninitializedNonNullFieldHintMissingDefault : IProblem.UninitializedNonNullField, arguments, arguments, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location) { binding.tagBits |= TagBits.NotInitialized; String[] arguments = new String[] {new String(binding.readableName())}; this.handle( methodHasMissingSwitchDefault() ? IProblem.UninitializedLocalVariableHintMissingDefault : IProblem.UninitializedLocalVariable, arguments, arguments, nodeSourceStart(binding, location), nodeSourceEnd(binding, location)); } private boolean methodHasMissingSwitchDefault() { MethodScope methodScope = null; if (this.referenceContext instanceof Block) { methodScope = ((Block)this.referenceContext).scope.methodScope(); } else if (this.referenceContext instanceof AbstractMethodDeclaration) { methodScope = ((AbstractMethodDeclaration)this.referenceContext).scope; } return methodScope != null && methodScope.hasMissingSwitchDefault; } public void unmatchedBracket(int position, ReferenceContext context, CompilationResult compilationResult) { this.handle( IProblem.UnmatchedBracket, NoArgument, NoArgument, position, position, context, compilationResult); } public void unnecessaryCast(CastExpression castExpression) { int severity = computeSeverity(IProblem.UnnecessaryCast); if (severity == ProblemSeverities.Ignore) return; TypeBinding castedExpressionType = castExpression.expression.resolvedType; this.handle( IProblem.UnnecessaryCast, new String[]{ new String(castedExpressionType.readableName()), new String(castExpression.type.resolvedType.readableName())}, new String[]{ new String(castedExpressionType.shortReadableName()), new String(castExpression.type.resolvedType.shortReadableName())}, severity, castExpression.sourceStart, castExpression.sourceEnd); } public void unnecessaryElse(ASTNode location) { this.handle( IProblem.UnnecessaryElse, NoArgument, NoArgument, location.sourceStart, location.sourceEnd); } public void unnecessaryEnclosingInstanceSpecification(Expression expression, ReferenceBinding targetType) { this.handle( IProblem.IllegalEnclosingInstanceSpecification, new String[]{ new String(targetType.readableName())}, new String[]{ new String(targetType.shortReadableName())}, expression.sourceStart, expression.sourceEnd); } public void unnecessaryInstanceof(InstanceOfExpression instanceofExpression, TypeBinding checkType) { int severity = computeSeverity(IProblem.UnnecessaryInstanceof); if (severity == ProblemSeverities.Ignore) return; TypeBinding expressionType = instanceofExpression.expression.resolvedType; this.handle( IProblem.UnnecessaryInstanceof, new String[]{ new String(expressionType.readableName()), new String(checkType.readableName())}, new String[]{ new String(expressionType.shortReadableName()), new String(checkType.shortReadableName())}, severity, instanceofExpression.sourceStart, instanceofExpression.sourceEnd); } public void unnecessaryNLSTags(int sourceStart, int sourceEnd) { this.handle( IProblem.UnnecessaryNLSTag, NoArgument, NoArgument, sourceStart, sourceEnd); } public void unnecessaryTypeArgumentsForMethodInvocation(MethodBinding method, TypeBinding[] genericTypeArguments, TypeReference[] typeArguments) { String methodName = method.isConstructor() ? new String(method.declaringClass.shortReadableName()) : new String(method.selector); this.handle( method.isConstructor() ? IProblem.UnusedTypeArgumentsForConstructorInvocation : IProblem.UnusedTypeArgumentsForMethodInvocation, new String[] { methodName, typesAsString(method, false), new String(method.declaringClass.readableName()), typesAsString(genericTypeArguments, false) }, new String[] { methodName, typesAsString(method, true), new String(method.declaringClass.shortReadableName()), typesAsString(genericTypeArguments, true) }, typeArguments[0].sourceStart, typeArguments[typeArguments.length-1].sourceEnd); } public void unqualifiedFieldAccess(NameReference reference, FieldBinding field) { int sourceStart = reference.sourceStart; int sourceEnd = reference.sourceEnd; if (reference instanceof SingleNameReference) { int numberOfParens = (reference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT; if (numberOfParens != 0) { sourceStart = retrieveStartingPositionAfterOpeningParenthesis(sourceStart, sourceEnd, numberOfParens); sourceEnd = retrieveEndingPositionAfterOpeningParenthesis(sourceStart, sourceEnd, numberOfParens); } else { sourceStart = nodeSourceStart(field, reference); sourceEnd = nodeSourceEnd(field, reference); } } else { sourceStart = nodeSourceStart(field, reference); sourceEnd = nodeSourceEnd(field, reference); } this.handle( IProblem.UnqualifiedFieldAccess, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, sourceStart, sourceEnd); } public void unreachableCatchBlock(ReferenceBinding exceptionType, ASTNode location) { this.handle( IProblem.UnreachableCatch, new String[] { new String(exceptionType.readableName()), }, new String[] { new String(exceptionType.shortReadableName()), }, location.sourceStart, location.sourceEnd); } public void unreachableCode(Statement statement) { int sourceStart = statement.sourceStart; int sourceEnd = statement.sourceEnd; if (statement instanceof LocalDeclaration) { LocalDeclaration declaration = (LocalDeclaration) statement; sourceStart = declaration.declarationSourceStart; sourceEnd = declaration.declarationSourceEnd; } else if (statement instanceof Expression) { int statemendEnd = ((Expression) statement).statementEnd; if (statemendEnd != -1) sourceEnd = statemendEnd; } this.handle( IProblem.CodeCannotBeReached, NoArgument, NoArgument, sourceStart, sourceEnd); } public void unresolvableReference(NameReference nameRef, Binding binding) { /* also need to check that the searchedType is the receiver type if (binding instanceof ProblemBinding) { ProblemBinding problem = (ProblemBinding) binding; if (problem.searchType != null && problem.searchType.isHierarchyInconsistent()) severity = SecondaryError; } */ String[] arguments = new String[] {new String(binding.readableName())}; int end = nameRef.sourceEnd; int sourceStart = nameRef.sourceStart; if (nameRef instanceof QualifiedNameReference) { QualifiedNameReference ref = (QualifiedNameReference) nameRef; if (isRecoveredName(ref.tokens)) return; if (ref.indexOfFirstFieldBinding >= 1) end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1]; } else { SingleNameReference ref = (SingleNameReference) nameRef; if (isRecoveredName(ref.token)) return; int numberOfParens = (ref.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT; if (numberOfParens != 0) { sourceStart = retrieveStartingPositionAfterOpeningParenthesis(sourceStart, end, numberOfParens); end = retrieveEndingPositionAfterOpeningParenthesis(sourceStart, end, numberOfParens); } } int problemId = (nameRef.bits & Binding.VARIABLE) != 0 && (nameRef.bits & Binding.TYPE) == 0 ? IProblem.UnresolvedVariable : IProblem.UndefinedName; this.handle( problemId, arguments, arguments, sourceStart, end); } public void unsafeCast(CastExpression castExpression, Scope scope) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 int severity = computeSeverity(IProblem.UnsafeGenericCast); if (severity == ProblemSeverities.Ignore) return; TypeBinding castedExpressionType = castExpression.expression.resolvedType; TypeBinding castExpressionResolvedType = castExpression.resolvedType; this.handle( IProblem.UnsafeGenericCast, new String[]{ new String(castedExpressionType.readableName()), new String(castExpressionResolvedType.readableName()) }, new String[]{ new String(castedExpressionType.shortReadableName()), new String(castExpressionResolvedType.shortReadableName()) }, severity, castExpression.sourceStart, castExpression.sourceEnd); } public void unsafeGenericArrayForVarargs(TypeBinding leafComponentType, ASTNode location) { int severity = computeSeverity(IProblem.UnsafeGenericArrayForVarargs); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.UnsafeGenericArrayForVarargs, new String[]{ new String(leafComponentType.readableName())}, new String[]{ new String(leafComponentType.shortReadableName())}, severity, location.sourceStart, location.sourceEnd); } public void unsafeRawFieldAssignment(FieldBinding field, TypeBinding expressionType, ASTNode location) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 int severity = computeSeverity(IProblem.UnsafeRawFieldAssignment); if (severity == ProblemSeverities.Ignore) return; this.handle( IProblem.UnsafeRawFieldAssignment, new String[] { new String(expressionType.readableName()), new String(field.name), new String(field.declaringClass.readableName()), new String(field.declaringClass.erasure().readableName()) }, new String[] { new String(expressionType.shortReadableName()), new String(field.name), new String(field.declaringClass.shortReadableName()), new String(field.declaringClass.erasure().shortReadableName()) }, severity, nodeSourceStart(field,location), nodeSourceEnd(field, location)); } public void unsafeRawGenericMethodInvocation(ASTNode location, MethodBinding rawMethod, TypeBinding[] argumentTypes) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 boolean isConstructor = rawMethod.isConstructor(); int severity = computeSeverity(isConstructor ? IProblem.UnsafeRawGenericConstructorInvocation : IProblem.UnsafeRawGenericMethodInvocation); if (severity == ProblemSeverities.Ignore) return; if (isConstructor) { this.handle( IProblem.UnsafeRawGenericConstructorInvocation, // The generic constructor {0}({1}) of type {2} is applied to non-parameterized type arguments ({3}) new String[] { new String(rawMethod.declaringClass.sourceName()), typesAsString(rawMethod.original(), false), new String(rawMethod.declaringClass.readableName()), typesAsString(argumentTypes, false), }, new String[] { new String(rawMethod.declaringClass.sourceName()), typesAsString(rawMethod.original(), true), new String(rawMethod.declaringClass.shortReadableName()), typesAsString(argumentTypes, true), }, severity, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.UnsafeRawGenericMethodInvocation, new String[] { new String(rawMethod.selector), typesAsString(rawMethod.original(), false), new String(rawMethod.declaringClass.readableName()), typesAsString(argumentTypes, false), }, new String[] { new String(rawMethod.selector), typesAsString(rawMethod.original(), true), new String(rawMethod.declaringClass.shortReadableName()), typesAsString(argumentTypes, true), }, severity, location.sourceStart, location.sourceEnd); } } public void unsafeRawInvocation(ASTNode location, MethodBinding rawMethod) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 boolean isConstructor = rawMethod.isConstructor(); int severity = computeSeverity(isConstructor ? IProblem.UnsafeRawConstructorInvocation : IProblem.UnsafeRawMethodInvocation); if (severity == ProblemSeverities.Ignore) return; if (isConstructor) { this.handle( IProblem.UnsafeRawConstructorInvocation, new String[] { new String(rawMethod.declaringClass.readableName()), typesAsString(rawMethod.original(), rawMethod.parameters, false), new String(rawMethod.declaringClass.erasure().readableName()), }, new String[] { new String(rawMethod.declaringClass.shortReadableName()), typesAsString(rawMethod.original(), rawMethod.parameters, true), new String(rawMethod.declaringClass.erasure().shortReadableName()), }, severity, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.UnsafeRawMethodInvocation, new String[] { new String(rawMethod.selector), typesAsString(rawMethod.original(), rawMethod.parameters, false), new String(rawMethod.declaringClass.readableName()), new String(rawMethod.declaringClass.erasure().readableName()), }, new String[] { new String(rawMethod.selector), typesAsString(rawMethod.original(), rawMethod.parameters, true), new String(rawMethod.declaringClass.shortReadableName()), new String(rawMethod.declaringClass.erasure().shortReadableName()), }, severity, location.sourceStart, location.sourceEnd); } } public void unsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod, SourceTypeBinding type) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) { return; } int severity = computeSeverity(IProblem.UnsafeReturnTypeOverride); if (severity == ProblemSeverities.Ignore) return; int start = type.sourceStart(); int end = type.sourceEnd(); if (currentMethod.declaringClass == type) { ASTNode location = ((MethodDeclaration) currentMethod.sourceMethod()).returnType; start = location.sourceStart(); end = location.sourceEnd(); } this.handle( IProblem.UnsafeReturnTypeOverride, new String[] { new String(currentMethod.returnType.readableName()), new String(currentMethod.selector), typesAsString(currentMethod.original(), false), new String(currentMethod.declaringClass.readableName()), new String(inheritedMethod.returnType.readableName()), new String(inheritedMethod.declaringClass.readableName()), //new String(inheritedMethod.returnType.erasure().readableName()), }, new String[] { new String(currentMethod.returnType.shortReadableName()), new String(currentMethod.selector), typesAsString(currentMethod.original(), true), new String(currentMethod.declaringClass.shortReadableName()), new String(inheritedMethod.returnType.shortReadableName()), new String(inheritedMethod.declaringClass.shortReadableName()), //new String(inheritedMethod.returnType.erasure().shortReadableName()), }, severity, start, end); } public void unsafeTypeConversion(Expression expression, TypeBinding expressionType, TypeBinding expectedType) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 int severity = computeSeverity(IProblem.UnsafeTypeConversion); if (severity == ProblemSeverities.Ignore) return; if (!this.options.reportUnavoidableGenericTypeProblems && expression.forcedToBeRaw(this.referenceContext)) { return; } this.handle( IProblem.UnsafeTypeConversion, new String[] { new String(expressionType.readableName()), new String(expectedType.readableName()), new String(expectedType.erasure().readableName()) }, new String[] { new String(expressionType.shortReadableName()), new String(expectedType.shortReadableName()), new String(expectedType.erasure().shortReadableName()) }, severity, expression.sourceStart, expression.sourceEnd); } public void unsafeElementTypeConversion(Expression expression, TypeBinding expressionType, TypeBinding expectedType) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259 int severity = computeSeverity(IProblem.UnsafeElementTypeConversion); if (severity == ProblemSeverities.Ignore) return; if (!this.options.reportUnavoidableGenericTypeProblems && expression.forcedToBeRaw(this.referenceContext)) { return; } this.handle( IProblem.UnsafeElementTypeConversion, new String[] { new String(expressionType.readableName()), new String(expectedType.readableName()), new String(expectedType.erasure().readableName()) }, new String[] { new String(expressionType.shortReadableName()), new String(expectedType.shortReadableName()), new String(expectedType.erasure().shortReadableName()) }, severity, expression.sourceStart, expression.sourceEnd); } public void unusedArgument(LocalDeclaration localDecl) { int severity = computeSeverity(IProblem.ArgumentIsNeverUsed); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(localDecl.name)}; this.handle( IProblem.ArgumentIsNeverUsed, arguments, arguments, severity, localDecl.sourceStart, localDecl.sourceEnd); } public void unusedDeclaredThrownException(ReferenceBinding exceptionType, AbstractMethodDeclaration method, ASTNode location) { boolean isConstructor = method.isConstructor(); int severity = computeSeverity(isConstructor ? IProblem.UnusedConstructorDeclaredThrownException : IProblem.UnusedMethodDeclaredThrownException); if (severity == ProblemSeverities.Ignore) return; if (isConstructor) { this.handle( IProblem.UnusedConstructorDeclaredThrownException, new String[] { new String(method.binding.declaringClass.readableName()), typesAsString(method.binding, false), new String(exceptionType.readableName()), }, new String[] { new String(method.binding.declaringClass.shortReadableName()), typesAsString(method.binding, true), new String(exceptionType.shortReadableName()), }, severity, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.UnusedMethodDeclaredThrownException, new String[] { new String(method.binding.declaringClass.readableName()), new String(method.selector), typesAsString(method.binding, false), new String(exceptionType.readableName()), }, new String[] { new String(method.binding.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method.binding, true), new String(exceptionType.shortReadableName()), }, severity, location.sourceStart, location.sourceEnd); } } public void unusedImport(ImportReference importRef) { int severity = computeSeverity(IProblem.UnusedImport); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] { CharOperation.toString(importRef.tokens) }; this.handle( IProblem.UnusedImport, arguments, arguments, severity, importRef.sourceStart, importRef.sourceEnd); } public void unusedLabel(LabeledStatement statement) { int severity = computeSeverity(IProblem.UnusedLabel); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(statement.label)}; this.handle( IProblem.UnusedLabel, arguments, arguments, severity, statement.sourceStart, statement.labelEnd); } public void unusedLocalVariable(LocalDeclaration localDecl) { int severity = computeSeverity(IProblem.LocalVariableIsNeverUsed); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(localDecl.name)}; this.handle( IProblem.LocalVariableIsNeverUsed, arguments, arguments, severity, localDecl.sourceStart, localDecl.sourceEnd); } public void unusedObjectAllocation(AllocationExpression allocationExpression) { this.handle( IProblem.UnusedObjectAllocation, NoArgument, NoArgument, allocationExpression.sourceStart, allocationExpression.sourceEnd); } public void unusedPrivateConstructor(ConstructorDeclaration constructorDecl) { int severity = computeSeverity(IProblem.UnusedPrivateConstructor); if (severity == ProblemSeverities.Ignore) return; if (excludeDueToAnnotation(constructorDecl.annotations, IProblem.UnusedPrivateConstructor)) return; MethodBinding constructor = constructorDecl.binding; this.handle( IProblem.UnusedPrivateConstructor, new String[] { new String(constructor.declaringClass.readableName()), typesAsString(constructor, false) }, new String[] { new String(constructor.declaringClass.shortReadableName()), typesAsString(constructor, true) }, severity, constructorDecl.sourceStart, constructorDecl.sourceEnd); } public void unusedPrivateField(FieldDeclaration fieldDecl) { int severity = computeSeverity(IProblem.UnusedPrivateField); if (severity == ProblemSeverities.Ignore) return; FieldBinding field = fieldDecl.binding; if (CharOperation.equals(TypeConstants.SERIALVERSIONUID, field.name) && field.isStatic() && field.isFinal() && TypeBinding.LONG == field.type) { ReferenceBinding referenceBinding = field.declaringClass; if (referenceBinding != null) { if (referenceBinding.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) { return; // do not report unused serialVersionUID field for class that implements Serializable } } } if (CharOperation.equals(TypeConstants.SERIALPERSISTENTFIELDS, field.name) && field.isStatic() && field.isFinal() && field.type.dimensions() == 1 && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTSTREAMFIELD, field.type.leafComponentType().readableName())) { ReferenceBinding referenceBinding = field.declaringClass; if (referenceBinding != null) { if (referenceBinding.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) { return; // do not report unused serialVersionUID field for class that implements Serializable } } } if (excludeDueToAnnotation(fieldDecl.annotations, IProblem.UnusedPrivateField)) return; this.handle( IProblem.UnusedPrivateField, new String[] { new String(field.declaringClass.readableName()), new String(field.name), }, new String[] { new String(field.declaringClass.shortReadableName()), new String(field.name), }, severity, nodeSourceStart(field, fieldDecl), nodeSourceEnd(field, fieldDecl)); } public void unusedPrivateMethod(AbstractMethodDeclaration methodDecl) { int severity = computeSeverity(IProblem.UnusedPrivateMethod); if (severity == ProblemSeverities.Ignore) return; MethodBinding method = methodDecl.binding; // no report for serialization support 'void readObject(ObjectInputStream)' if (!method.isStatic() && TypeBinding.VOID == method.returnType && method.parameters.length == 1 && method.parameters[0].dimensions() == 0 && CharOperation.equals(method.selector, TypeConstants.READOBJECT) && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTINPUTSTREAM, method.parameters[0].readableName())) { return; } // no report for serialization support 'void writeObject(ObjectOutputStream)' if (!method.isStatic() && TypeBinding.VOID == method.returnType && method.parameters.length == 1 && method.parameters[0].dimensions() == 0 && CharOperation.equals(method.selector, TypeConstants.WRITEOBJECT) && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTOUTPUTSTREAM, method.parameters[0].readableName())) { return; } // no report for serialization support 'Object readResolve()' if (!method.isStatic() && TypeIds.T_JavaLangObject == method.returnType.id && method.parameters.length == 0 && CharOperation.equals(method.selector, TypeConstants.READRESOLVE)) { return; } // no report for serialization support 'Object writeReplace()' if (!method.isStatic() && TypeIds.T_JavaLangObject == method.returnType.id && method.parameters.length == 0 && CharOperation.equals(method.selector, TypeConstants.WRITEREPLACE)) { return; } if (excludeDueToAnnotation(methodDecl.annotations, IProblem.UnusedPrivateMethod)) return; this.handle( IProblem.UnusedPrivateMethod, new String[] { new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false) }, new String[] { new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true) }, severity, methodDecl.sourceStart, methodDecl.sourceEnd); } /** * Returns true if a private member should not be warned as unused if * annotated with a non-standard annotation. * https://bugs.eclipse.org/365437 * https://bugs.eclipse.org/376590 */ private boolean excludeDueToAnnotation(Annotation[] annotations, int problemId) { int annotationsLen = 0; if (annotations != null) { annotationsLen = annotations.length; } else { return false; } if (annotationsLen == 0) return false; for (int i = 0; i < annotationsLen; i++) { TypeBinding resolvedType = annotations[i].resolvedType; if (resolvedType != null) { switch (resolvedType.id) { case TypeIds.T_JavaLangSuppressWarnings: case TypeIds.T_JavaLangDeprecated: case TypeIds.T_JavaLangSafeVarargs: case TypeIds.T_ConfiguredAnnotationNonNull: case TypeIds.T_ConfiguredAnnotationNullable: case TypeIds.T_ConfiguredAnnotationNonNullByDefault: break; case TypeIds.T_JavaxInjectInject: case TypeIds.T_ComGoogleInjectInject: if (problemId != IProblem.UnusedPrivateField) return true; // @Inject on method/ctor does constitute a relevant use, just on fields it doesn't break; default: // non-standard annotation found, don't warn return true; } } } return false; } public void unusedPrivateType(TypeDeclaration typeDecl) { int severity = computeSeverity(IProblem.UnusedPrivateType); if (severity == ProblemSeverities.Ignore) return; if (excludeDueToAnnotation(typeDecl.annotations, IProblem.UnusedPrivateType)) return; ReferenceBinding type = typeDecl.binding; this.handle( IProblem.UnusedPrivateType, new String[] { new String(type.readableName()), }, new String[] { new String(type.shortReadableName()), }, severity, typeDecl.sourceStart, typeDecl.sourceEnd); } public void unusedTypeParameter(TypeParameter typeParameter) { int severity = computeSeverity(IProblem.UnusedTypeParameter); if (severity == ProblemSeverities.Ignore) return; String [] arguments = new String[] {new String(typeParameter.name)}; this.handle( IProblem.UnusedTypeParameter, arguments, arguments, typeParameter.sourceStart, typeParameter.sourceEnd); } public void unusedWarningToken(Expression token) { String[] arguments = new String[] { token.constant.stringValue() }; this.handle( IProblem.UnusedWarningToken, arguments, arguments, token.sourceStart, token.sourceEnd); } public void useAssertAsAnIdentifier(int sourceStart, int sourceEnd) { this.handle( IProblem.UseAssertAsAnIdentifier, NoArgument, NoArgument, sourceStart, sourceEnd); } public void useEnumAsAnIdentifier(int sourceStart, int sourceEnd) { this.handle( IProblem.UseEnumAsAnIdentifier, NoArgument, NoArgument, sourceStart, sourceEnd); } public void varargsArgumentNeedCast(MethodBinding method, TypeBinding argumentType, InvocationSite location) { int severity = this.options.getSeverity(CompilerOptions.VarargsArgumentNeedCast); if (severity == ProblemSeverities.Ignore) return; ArrayBinding varargsType = (ArrayBinding)method.parameters[method.parameters.length-1]; if (method.isConstructor()) { this.handle( IProblem.ConstructorVarargsArgumentNeedCast, new String[] { new String(argumentType.readableName()), new String(varargsType.readableName()), new String(method.declaringClass.readableName()), typesAsString(method, false), new String(varargsType.elementsType().readableName()), }, new String[] { new String(argumentType.shortReadableName()), new String(varargsType.shortReadableName()), new String(method.declaringClass.shortReadableName()), typesAsString(method, true), new String(varargsType.elementsType().shortReadableName()), }, severity, location.sourceStart(), location.sourceEnd()); } else { this.handle( IProblem.MethodVarargsArgumentNeedCast, new String[] { new String(argumentType.readableName()), new String(varargsType.readableName()), new String(method.selector), typesAsString(method, false), new String(method.declaringClass.readableName()), new String(varargsType.elementsType().readableName()), }, new String[] { new String(argumentType.shortReadableName()), new String(varargsType.shortReadableName()), new String(method.selector), typesAsString(method, true), new String(method.declaringClass.shortReadableName()), new String(varargsType.elementsType().shortReadableName()), }, severity, location.sourceStart(), location.sourceEnd()); } } public void varargsConflict(MethodBinding method1, MethodBinding method2, SourceTypeBinding type) { this.handle( IProblem.VarargsConflict, new String[] { new String(method1.selector), typesAsString(method1, false), new String(method1.declaringClass.readableName()), typesAsString(method2, false), new String(method2.declaringClass.readableName()) }, new String[] { new String(method1.selector), typesAsString(method1, true), new String(method1.declaringClass.shortReadableName()), typesAsString(method2, true), new String(method2.declaringClass.shortReadableName()) }, method1.declaringClass == type ? method1.sourceStart() : type.sourceStart(), method1.declaringClass == type ? method1.sourceEnd() : type.sourceEnd()); } public void safeVarargsOnFixedArityMethod(MethodBinding method) { String [] arguments = new String[] { new String(method.isConstructor() ? method.declaringClass.shortReadableName() : method.selector)}; this.handle( IProblem.SafeVarargsOnFixedArityMethod, arguments, arguments, method.sourceStart(), method.sourceEnd()); } public void safeVarargsOnNonFinalInstanceMethod(MethodBinding method) { String [] arguments = new String[] { new String(method.isConstructor() ? method.declaringClass.shortReadableName() : method.selector)}; this.handle( IProblem.SafeVarargsOnNonFinalInstanceMethod, arguments, arguments, method.sourceStart(), method.sourceEnd()); } public void possibleHeapPollutionFromVararg(AbstractVariableDeclaration vararg) { String[] arguments = new String[] {new String(vararg.name)}; this.handle( IProblem.PotentialHeapPollutionFromVararg, arguments, arguments, vararg.sourceStart, vararg.sourceEnd); } public void variableTypeCannotBeVoid(AbstractVariableDeclaration varDecl) { String[] arguments = new String[] {new String(varDecl.name)}; this.handle( IProblem.VariableTypeCannotBeVoid, arguments, arguments, varDecl.sourceStart, varDecl.sourceEnd); } public void variableTypeCannotBeVoidArray(AbstractVariableDeclaration varDecl) { this.handle( IProblem.CannotAllocateVoidArray, NoArgument, NoArgument, varDecl.type.sourceStart, varDecl.type.sourceEnd); } public void visibilityConflict(MethodBinding currentMethod, MethodBinding inheritedMethod) { this.handle( // Cannot reduce the visibility of the inherited method from %1 // 8.4.6.3 - The access modifier of an hiding method must provide at least as much access as the hidden method. // 8.4.6.3 - The access modifier of an overiding method must provide at least as much access as the overriden method. IProblem.MethodReducesVisibility, new String[] {new String(inheritedMethod.declaringClass.readableName())}, new String[] {new String(inheritedMethod.declaringClass.shortReadableName())}, currentMethod.sourceStart(), currentMethod.sourceEnd()); } public void wildcardAssignment(TypeBinding variableType, TypeBinding expressionType, ASTNode location) { this.handle( IProblem.WildcardFieldAssignment, new String[] { new String(expressionType.readableName()), new String(variableType.readableName()) }, new String[] { new String(expressionType.shortReadableName()), new String(variableType.shortReadableName()) }, location.sourceStart, location.sourceEnd); } public void wildcardInvocation(ASTNode location, TypeBinding receiverType, MethodBinding method, TypeBinding[] arguments) { TypeBinding offendingArgument = null; TypeBinding offendingParameter = null; for (int i = 0, length = method.parameters.length; i < length; i++) { TypeBinding parameter = method.parameters[i]; if (parameter.isWildcard() && (((WildcardBinding) parameter).boundKind != Wildcard.SUPER)) { offendingParameter = parameter; offendingArgument = arguments[i]; break; } } if (method.isConstructor()) { this.handle( IProblem.WildcardConstructorInvocation, new String[] { new String(receiverType.sourceName()), typesAsString(method, false), new String(receiverType.readableName()), typesAsString(arguments, false), new String(offendingArgument.readableName()), new String(offendingParameter.readableName()), }, new String[] { new String(receiverType.sourceName()), typesAsString(method, true), new String(receiverType.shortReadableName()), typesAsString(arguments, true), new String(offendingArgument.shortReadableName()), new String(offendingParameter.shortReadableName()), }, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.WildcardMethodInvocation, new String[] { new String(method.selector), typesAsString(method, false), new String(receiverType.readableName()), typesAsString(arguments, false), new String(offendingArgument.readableName()), new String(offendingParameter.readableName()), }, new String[] { new String(method.selector), typesAsString(method, true), new String(receiverType.shortReadableName()), typesAsString(arguments, true), new String(offendingArgument.shortReadableName()), new String(offendingParameter.shortReadableName()), }, location.sourceStart, location.sourceEnd); } } public void wrongSequenceOfExceptionTypesError(TypeReference typeRef, TypeBinding exceptionType, TypeBinding hidingExceptionType) { //the two catch block under and upper are in an incorrect order. //under should be define BEFORE upper in the source this.handle( IProblem.InvalidCatchBlockSequence, new String[] { new String(exceptionType.readableName()), new String(hidingExceptionType.readableName()), }, new String[] { new String(exceptionType.shortReadableName()), new String(hidingExceptionType.shortReadableName()), }, typeRef.sourceStart, typeRef.sourceEnd); } public void wrongSequenceOfExceptionTypes(TypeReference typeRef, TypeBinding exceptionType, TypeBinding hidingExceptionType) { // type references inside a multi-catch block are not of union type this.handle( IProblem.InvalidUnionTypeReferenceSequence, new String[] { new String(exceptionType.readableName()), new String(hidingExceptionType.readableName()), }, new String[] { new String(exceptionType.shortReadableName()), new String(hidingExceptionType.shortReadableName()), }, typeRef.sourceStart, typeRef.sourceEnd); } public void autoManagedResourcesNotBelow17(LocalDeclaration[] resources) { this.handle( IProblem.AutoManagedResourceNotBelow17, NoArgument, NoArgument, resources[0].declarationSourceStart, resources[resources.length - 1].declarationSourceEnd); } public void cannotInferElidedTypes(AllocationExpression allocationExpression) { String arguments [] = new String [] { allocationExpression.type.toString() }; this.handle( IProblem.CannotInferElidedTypes, arguments, arguments, allocationExpression.sourceStart, allocationExpression.sourceEnd); } public void diamondNotWithExplicitTypeArguments(TypeReference[] typeArguments) { this.handle( IProblem.CannotUseDiamondWithExplicitTypeArguments, NoArgument, NoArgument, typeArguments[0].sourceStart, typeArguments[typeArguments.length - 1].sourceEnd); } public void diamondNotWithAnoymousClasses(TypeReference type) { this.handle( IProblem.CannotUseDiamondWithAnonymousClasses, NoArgument, NoArgument, type.sourceStart, type.sourceEnd); } public void redundantSpecificationOfTypeArguments(ASTNode location, TypeBinding[] argumentTypes) { int severity = computeSeverity(IProblem.RedundantSpecificationOfTypeArguments); if (severity != ProblemSeverities.Ignore) { int sourceStart = -1; if (location instanceof QualifiedTypeReference) { QualifiedTypeReference ref = (QualifiedTypeReference)location; sourceStart = (int) (ref.sourcePositions[ref.sourcePositions.length - 1] >> 32); } else { sourceStart = location.sourceStart; } this.handle( IProblem.RedundantSpecificationOfTypeArguments, new String[] {typesAsString(argumentTypes, false)}, new String[] {typesAsString(argumentTypes, true)}, severity, sourceStart, location.sourceEnd); } } public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) { String[] args = { trackVar.nameForReporting(location, this.referenceContext) }; if (location == null) { this.handle( IProblem.PotentiallyUnclosedCloseable, args, args, trackVar.sourceStart, trackVar.sourceEnd); } else { this.handle( IProblem.PotentiallyUnclosedCloseableAtExit, args, args, location.sourceStart, location.sourceEnd); } } public void unclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) { String[] args = { String.valueOf(trackVar.name) }; if (location == null) { this.handle( IProblem.UnclosedCloseable, args, args, trackVar.sourceStart, trackVar.sourceEnd); } else { this.handle( IProblem.UnclosedCloseableAtExit, args, args, location.sourceStart, location.sourceEnd); } } public void explicitlyClosedAutoCloseable(FakedTrackingVariable trackVar) { String[] args = { String.valueOf(trackVar.name) }; this.handle( IProblem.ExplicitlyClosedAutoCloseable, args, args, trackVar.sourceStart, trackVar.sourceEnd); } public void nullityMismatch(Expression expression, TypeBinding providedType, TypeBinding requiredType, int nullStatus, char[][] annotationName) { if ((nullStatus & FlowInfo.NULL) != 0) { nullityMismatchIsNull(expression, requiredType, annotationName); return; } if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) { VariableBinding var = expression.localVariableBinding(); if (var == null && expression instanceof Reference) { var = ((Reference)expression).lastFieldBinding(); } if (var != null && var.isNullable()) { nullityMismatchSpecdNullable(expression, requiredType, annotationName); return; } nullityMismatchPotentiallyNull(expression, requiredType, annotationName); return; } nullityMismatchIsUnknown(expression, providedType, requiredType, annotationName); } public void nullityMismatchIsNull(Expression expression, TypeBinding requiredType, char[][] annotationName) { int problemId = IProblem.RequiredNonNullButProvidedNull; String[] arguments = new String[] { String.valueOf(CharOperation.concatWith(annotationName, '.')), String.valueOf(requiredType.readableName()) }; String[] argumentsShort = new String[] { String.valueOf(annotationName[annotationName.length-1]), String.valueOf(requiredType.shortReadableName()) }; this.handle(problemId, arguments, argumentsShort, expression.sourceStart, expression.sourceEnd); } public void nullityMismatchSpecdNullable(Expression expression, TypeBinding requiredType, char[][] annotationName) { int problemId = IProblem.RequiredNonNullButProvidedSpecdNullable; char[][] nullableName = this.options.nullableAnnotationName; String[] arguments = new String[] { String.valueOf(CharOperation.concatWith(annotationName, '.')), String.valueOf(requiredType.readableName()), String.valueOf(CharOperation.concatWith(nullableName, '.')) }; String[] argumentsShort = new String[] { String.valueOf(annotationName[annotationName.length-1]), String.valueOf(requiredType.shortReadableName()), String.valueOf(nullableName[nullableName.length-1]) }; this.handle(problemId, arguments, argumentsShort, expression.sourceStart, expression.sourceEnd); } public void nullityMismatchPotentiallyNull(Expression expression, TypeBinding requiredType, char[][] annotationName) { int problemId = IProblem.RequiredNonNullButProvidedPotentialNull; char[][] nullableName = this.options.nullableAnnotationName; String[] arguments = new String[] { String.valueOf(CharOperation.concatWith(annotationName, '.')), String.valueOf(requiredType.readableName()), String.valueOf(CharOperation.concatWith(nullableName, '.')) }; String[] argumentsShort = new String[] { String.valueOf(annotationName[annotationName.length-1]), String.valueOf(requiredType.shortReadableName()), String.valueOf(nullableName[nullableName.length-1]) }; this.handle(problemId, arguments, argumentsShort, expression.sourceStart, expression.sourceEnd); } public void nullityMismatchIsUnknown(Expression expression, TypeBinding providedType, TypeBinding requiredType, char[][] annotationName) { int problemId = IProblem.RequiredNonNullButProvidedUnknown; String[] arguments = new String[] { String.valueOf(providedType.readableName()), String.valueOf(CharOperation.concatWith(annotationName, '.')), String.valueOf(requiredType.readableName()) }; String[] argumentsShort = new String[] { String.valueOf(providedType.shortReadableName()), String.valueOf(annotationName[annotationName.length-1]), String.valueOf(requiredType.shortReadableName()) }; this.handle(problemId, arguments, argumentsShort, expression.sourceStart, expression.sourceEnd); } public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) { int sourceStart = argument.type.sourceStart; if (argument.annotations != null) { for (int i=0; i inherited public void conflictingNullAnnotations(MethodBinding currentMethod, ASTNode location, MethodBinding inheritedMethod) { char[][] nonNullAnnotationName = this.options.nonNullAnnotationName; char[][] nullableAnnotationName = this.options.nullableAnnotationName; String[] arguments = { new String(CharOperation.concatWith(nonNullAnnotationName, '.')), new String(CharOperation.concatWith(nullableAnnotationName, '.')), new String(inheritedMethod.declaringClass.readableName()) }; String[] shortArguments = { new String(nonNullAnnotationName[nonNullAnnotationName.length-1]), new String(nullableAnnotationName[nullableAnnotationName.length-1]), new String(inheritedMethod.declaringClass.shortReadableName()) }; this.handle(IProblem.ConflictingNullAnnotations, arguments, shortArguments, location.sourceStart, location.sourceEnd); } // conflict between different inheriteds public void conflictingInheritedNullAnnotations(ASTNode location, boolean previousIsNonNull, MethodBinding previousInherited, boolean isNonNull, MethodBinding inheritedMethod) { char[][] previousAnnotationName = previousIsNonNull ? this.options.nonNullAnnotationName : this.options.nullableAnnotationName; char[][] annotationName = isNonNull ? this.options.nonNullAnnotationName : this.options.nullableAnnotationName; String[] arguments = { new String(CharOperation.concatWith(previousAnnotationName, '.')), new String(previousInherited.declaringClass.readableName()), new String(CharOperation.concatWith(annotationName, '.')), new String(inheritedMethod.declaringClass.readableName()) }; String[] shortArguments = { new String(previousAnnotationName[previousAnnotationName.length-1]), new String(previousInherited.declaringClass.shortReadableName()), new String(annotationName[annotationName.length-1]), new String(inheritedMethod.declaringClass.shortReadableName()) }; this.handle(IProblem.ConflictingInheritedNullAnnotations, arguments, shortArguments, location.sourceStart, location.sourceEnd); } public void illegalAnnotationForBaseType(TypeReference type, Annotation[] annotations, char[] annotationName, long nullAnnotationTagBit) { int typeId = (nullAnnotationTagBit == TagBits.AnnotationNullable) ? TypeIds.T_ConfiguredAnnotationNullable : TypeIds.T_ConfiguredAnnotationNonNull; String[] args = new String[] { new String(annotationName), new String(type.getLastToken()) }; Annotation annotation = findAnnotation(annotations, typeId); int start = annotation != null ? annotation.sourceStart : type.sourceStart; this.handle(IProblem.IllegalAnnotationForBaseType, args, args, start, type.sourceEnd); } private Annotation findAnnotation(Annotation[] annotations, int typeId) { if (annotations != null) { // should have a @NonNull/@Nullable annotation, search for it: int length = annotations.length; for (int j=0; j= 0 ? Util.getLineNumber(problemStartPosition, lineEnds = unitResult.getLineSeparatorPositions(), 0, lineEnds.length-1) : 0; int columnNumber = problemStartPosition >= 0 ? Util.searchColumnNumber(unitResult.getLineSeparatorPositions(), lineNumber, problemStartPosition) : 0; CategorizedProblem problem = this.createProblem( unitResult.getFileName(), problemId, problemArguments, elaborationId, messageArguments, severity, problemStartPosition, problemEndPosition, lineNumber, columnNumber); if (problem == null) return; // problem couldn't be created, ignore switch (severity & ProblemSeverities.Error) { case ProblemSeverities.Error : boolean mandatory = ((severity & ProblemSeverities.Optional) == 0); record(problem, unitResult, referenceContext, mandatory); if ((severity & ProblemSeverities.Fatal) != 0) { // don't abort or tag as error if the error is suppressed if (!referenceContext.hasErrors() && !mandatory && this.options.suppressOptionalErrors) { CompilationUnitDeclaration unitDecl = referenceContext.getCompilationUnitDeclaration(); if (unitDecl != null && unitDecl.isSuppressed(problem)) { return; } } referenceContext.tagAsHavingErrors(); // should abort ? int abortLevel; if ((abortLevel = this.policy.stopOnFirstError() ? ProblemSeverities.AbortCompilation : severity & ProblemSeverities.Abort) != 0) { referenceContext.abort(abortLevel, problem); } } break; case ProblemSeverities.Warning : record(problem, unitResult, referenceContext, false); break; } } /** * Standard problem handling API, the actual severity (warning/error/ignore) is deducted * from the problem ID and the current compiler options. */ public void handle( int problemId, String[] problemArguments, String[] messageArguments, int problemStartPosition, int problemEndPosition, ReferenceContext referenceContext, CompilationResult unitResult) { this.handle( problemId, problemArguments, 0, // no message elaboration messageArguments, computeSeverity(problemId), // severity inferred using the ID problemStartPosition, problemEndPosition, referenceContext, unitResult); } public void record(CategorizedProblem problem, CompilationResult unitResult, ReferenceContext referenceContext, boolean optionalError) { unitResult.record(problem, referenceContext, optionalError); } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/problem/AbortType.java0000644000175000001440000000215212212041344030476 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; /* * Special unchecked exception type used * to abort from the compilation process * * should only be thrown from within problem handlers. */ public class AbortType extends AbortCompilationUnit { private static final long serialVersionUID = -5882417089349134385L; // backward compatible public AbortType(CompilationResult compilationResult, CategorizedProblem problem) { super(compilationResult, problem); } } ././@LongLink0000644000000000000000000000015512251602427011644 Lustar rootrootecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/AbstractAnnotationProcessorManager.javaecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/AbstractAnnotationProcessorMana0000644000175000001440000000620612212041344032504 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * BEA - Patch for bug 172743 *******************************************************************************/ package org.eclipse.jdt.internal.compiler; import java.io.PrintWriter; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; public abstract class AbstractAnnotationProcessorManager { /** * Configure the receiver using the given batch compiler and the given options. * The parameter batchCompiler is expected to be an instance of the batch compiler. This method is * only used for the batch mode. For the IDE mode, please see {@link #configureFromPlatform(Compiler, Object, Object)}. * * @param batchCompiler the given batch compiler object * @param options the given options */ public abstract void configure(Object batchCompiler, String[] options); /** * Configure the receiver using the given compiler, the given compilationUnitLocator and * the given java project. * * @param compiler the given compiler * @param compilationUnitLocator the given compilation unit locator * @param javaProject the given java project */ public abstract void configureFromPlatform(Compiler compiler, Object compilationUnitLocator, Object javaProject); /** * Set the print writer for the standard output. * * @param out the given print writer for output */ public abstract void setOut(PrintWriter out); /** * Set the print writer for the standard error. * * @param err the given print writer for error */ public abstract void setErr(PrintWriter err); /** * Return the new units created in the last round. * * @return the new units created in the last round */ public abstract ICompilationUnit[] getNewUnits(); /** * Return the new binary bindings created in the last round. * * @return the new binary bindings created in the last round */ public abstract ReferenceBinding[] getNewClassFiles(); /** * Returns the deleted units. * @return the deleted units */ public abstract ICompilationUnit[] getDeletedUnits(); /** * Reinitialize the receiver */ public abstract void reset(); /** * Run a new annotation processing round on the given values. * * @param units the given source type * @param referenceBindings the given binary types * @param isLastRound flag to notify the last round */ public abstract void processAnnotations(CompilationUnitDeclaration[] units, ReferenceBinding[] referenceBindings, boolean isLastRound); /** * Set the processors for annotation processing. * * @param processors the given processors */ public abstract void setProcessors(Object[] processors); } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/ClassFile.java0000644000175000001440000066703012212041344027006 0ustar dokousers/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; 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.AttributeNamesConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrame; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.ExceptionMarker; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackDepthMarker; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackMarker; import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.StringConstant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; 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.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement; import org.eclipse.jdt.internal.compiler.util.Messages; import org.eclipse.jdt.internal.compiler.util.Util; /** * Represents a class file wrapper on bytes, it is aware of its actual * type name. * * Public APIs are listed below: * * byte[] getBytes(); * Answer the actual bytes of the class file * * char[][] getCompoundName(); * Answer the compound name of the class file. * For example, {{java}, {util}, {Hashtable}}. * * byte[] getReducedBytes(); * Answer a smaller byte format, which is only contains some structural * information. Those bytes are decodable with a regular class file reader, * such as DietClassFileReader */ public class ClassFile implements TypeConstants, TypeIds { private byte[] bytes; 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 Set innerClassesBindings; public int methodCount; public int methodCountOffset; // pool managment boolean isShared = false; // used to generate private access methods // debug and stack map attributes public int produceAttributes; public SourceTypeBinding referenceBinding; public boolean isNestedType; public long targetJDK; public List missingTypes = null; public Set visitedTypes; 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 * 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 = ClassFile.getNewInstance(typeBinding); classFile.initialize(typeBinding, null, true); if (typeBinding.hasMemberTypes()) { // see bug 180109 ReferenceBinding[] members = typeBinding.memberTypes; for (int i = 0, l = members.length; i < l; i++) classFile.recordInnerClasses(members[i]); } // TODO (olivier) handle cases where a field cannot be generated (name too long) // TODO (olivier) handle too many methods // inner attributes if (typeBinding.isNestedType()) { classFile.recordInnerClasses(typeBinding); } TypeVariableBinding[] typeVariables = typeBinding.typeVariables(); for (int i = 0, max = typeVariables.length; i < max; i++) { TypeVariableBinding typeVariableBinding = typeVariables[i]; if ((typeVariableBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { Util.recordNestedType(classFile, typeVariableBinding); } } // add its fields FieldBinding[] fields = typeBinding.fields(); if ((fields != null) && (fields != Binding.NO_FIELDS)) { 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 int problemsLength; CategorizedProblem[] problems = unitResult.getErrors(); if (problems == null) { problems = new CategorizedProblem[0]; } CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); AbstractMethodDeclaration[] methodDecls = typeDeclaration.methods; if (methodDecls != 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, length = methodDecls.length; i < length; i++) { AbstractMethodDeclaration methodDecl = methodDecls[i]; MethodBinding method = methodDecl.binding; if (method == null || method.isConstructor()) continue; method.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; classFile.addAbstractMethod(methodDecl, method); } } else { for (int i = 0, length = methodDecls.length; i < length; i++) { AbstractMethodDeclaration methodDecl = methodDecls[i]; MethodBinding method = methodDecl.binding; if (method == null) continue; if (method.isConstructor()) { classFile.addProblemConstructor(methodDecl, method, problemsCopy); } else if (method.isAbstract()) { classFile.addAbstractMethod(methodDecl, method); } else { classFile.addProblemMethod(methodDecl, method, problemsCopy); } } } // 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.createProblemType(memberType, unitResult); } } } classFile.addAttributes(); unitResult.record(typeBinding.constantPoolName(), classFile); } public static ClassFile getNewInstance(SourceTypeBinding typeBinding) { LookupEnvironment env = typeBinding.scope.environment(); return env.classFilePool.acquire(typeBinding); } /** * INTERNAL USE-ONLY * This methods creates a new instance of the receiver. */ protected ClassFile() { // default constructor for subclasses } public ClassFile(SourceTypeBinding typeBinding) { // default constructor for subclasses this.constantPool = new ConstantPool(this); final CompilerOptions options = typeBinding.scope.compilerOptions(); this.targetJDK = options.targetJDK; this.produceAttributes = options.produceDebugAttributes; this.referenceBinding = typeBinding; this.isNestedType = typeBinding.isNestedType(); if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; this.codeStream = new StackMapFrameCodeStream(this); } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) { this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3 this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP; this.codeStream = new StackMapFrameCodeStream(this); } else { this.codeStream = new CodeStream(this); } initByteArrays(); } /** * INTERNAL USE-ONLY * Generate the byte for a problem method info that correspond to a bogus method. * * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding */ public void addAbstractMethod( AbstractMethodDeclaration method, MethodBinding methodBinding) { this.generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; int attributeNumber = this.generateMethodInfoAttributes(methodBinding); completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); } /** * INTERNAL USE-ONLY * This methods generate all the attributes for the receiver. * For a class they could be: * - source file attribute * - inner classes attribute * - deprecated attribute */ public void addAttributes() { // update the method count this.contents[this.methodCountOffset++] = (byte) (this.methodCount >> 8); this.contents[this.methodCountOffset] = (byte) this.methodCount; int attributesNumber = 0; // leave two bytes for the number of attributes and store the current offset int attributeOffset = this.contentsOffset; this.contentsOffset += 2; // source attribute if ((this.produceAttributes & ClassFileConstants.ATTR_SOURCE) != 0) { String fullFileName = new String(this.referenceBinding.scope.referenceCompilationUnit().getFileName()); fullFileName = fullFileName.replace('\\', '/'); int lastIndex = fullFileName.lastIndexOf('/'); if (lastIndex != -1) { fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length()); } attributesNumber += generateSourceAttribute(fullFileName); } // Deprecated attribute if (this.referenceBinding.isDeprecated()) { // check that there is enough space to write all the bytes for the field info corresponding // to the @fieldBinding attributesNumber += generateDeprecatedAttribute(); } // add signature attribute char[] genericSignature = this.referenceBinding.genericSignature(); if (genericSignature != null) { attributesNumber += generateSignatureAttribute(genericSignature); } if (this.targetJDK >= ClassFileConstants.JDK1_5 && this.referenceBinding.isNestedType() && !this.referenceBinding.isMemberType()) { // add enclosing method attribute (1.5 mode only) attributesNumber += generateEnclosingMethodAttribute(); } if (this.targetJDK >= ClassFileConstants.JDK1_4) { TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; if (typeDeclaration != null) { final Annotation[] annotations = typeDeclaration.annotations; if (annotations != null) { attributesNumber += generateRuntimeAnnotations(annotations); } } } if (this.referenceBinding.isHierarchyInconsistent()) { ReferenceBinding superclass = this.referenceBinding.superclass; if (superclass != null) { this.missingTypes = superclass.collectMissingTypes(this.missingTypes); } ReferenceBinding[] superInterfaces = this.referenceBinding.superInterfaces(); for (int i = 0, max = superInterfaces.length; i < max; i++) { this.missingTypes = superInterfaces[i].collectMissingTypes(this.missingTypes); } attributesNumber += generateHierarchyInconsistentAttribute(); } // Inner class attribute int numberOfInnerClasses = this.innerClassesBindings == null ? 0 : this.innerClassesBindings.size(); if (numberOfInnerClasses != 0) { ReferenceBinding[] innerClasses = new ReferenceBinding[numberOfInnerClasses]; this.innerClassesBindings.toArray(innerClasses); Arrays.sort(innerClasses, new Comparator() { public int compare(Object o1, Object o2) { TypeBinding binding1 = (TypeBinding) o1; TypeBinding binding2 = (TypeBinding) o2; return CharOperation.compareTo(binding1.constantPoolName(), binding2.constantPoolName()); } }); attributesNumber += generateInnerClassAttribute(numberOfInnerClasses, innerClasses); } if (this.missingTypes != null) { generateMissingTypesAttribute(); attributesNumber++; } // update the number of attributes if (attributeOffset + 2 >= this.contents.length) { resizeContents(2); } this.contents[attributeOffset++] = (byte) (attributesNumber >> 8); this.contents[attributeOffset] = (byte) attributesNumber; // resynchronize all offsets of the classfile this.header = this.constantPool.poolContent; this.headerOffset = this.constantPool.currentOffset; int constantPoolCount = this.constantPool.currentIndex; this.header[this.constantPoolOffset++] = (byte) (constantPoolCount >> 8); this.header[this.constantPoolOffset] = (byte) constantPoolCount; } /** * INTERNAL USE-ONLY * This methods generate all the default abstract method infos that correpond to * the abstract methods inherited from superinterfaces. */ public void addDefaultAbstractMethods() { // default abstract methods MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods(); for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) { MethodBinding methodBinding = defaultAbstractMethods[i]; generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; int attributeNumber = generateMethodInfoAttributes(methodBinding); completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); } } private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) { int attributesNumber = 0; // 4.7.2 only static constant fields get a ConstantAttribute // Generate the constantValueAttribute Constant fieldConstant = fieldBinding.constant(); if (fieldConstant != Constant.NotAConstant){ attributesNumber += generateConstantValueAttribute(fieldConstant, fieldBinding, fieldAttributeOffset); } if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) { attributesNumber += generateSyntheticAttribute(); } if (fieldBinding.isDeprecated()) { attributesNumber += generateDeprecatedAttribute(); } // add signature attribute char[] genericSignature = fieldBinding.genericSignature(); if (genericSignature != null) { attributesNumber += generateSignatureAttribute(genericSignature); } if (this.targetJDK >= ClassFileConstants.JDK1_4) { FieldDeclaration fieldDeclaration = fieldBinding.sourceField(); if (fieldDeclaration != null) { Annotation[] annotations = fieldDeclaration.annotations; if (annotations != null) { attributesNumber += generateRuntimeAnnotations(annotations); } } } if ((fieldBinding.tagBits & TagBits.HasMissingType) != 0) { this.missingTypes = fieldBinding.type.collectMissingTypes(this.missingTypes); } 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 (this.contentsOffset + 8 >= this.contents.length) { resizeContents(8); } // Now we can generate all entries into the byte array // First the accessFlags int accessFlags = fieldBinding.getAccessFlags(); if (this.targetJDK < ClassFileConstants.JDK1_5) { // pre 1.5, synthetic was an attribute, not a modifier accessFlags &= ~ClassFileConstants.AccSynthetic; } this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); this.contents[this.contentsOffset++] = (byte) accessFlags; // Then the nameIndex int nameIndex = this.constantPool.literalIndex(fieldBinding.name); this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8); this.contents[this.contentsOffset++] = (byte) nameIndex; // Then the descriptorIndex int descriptorIndex = this.constantPool.literalIndex(fieldBinding.type); this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8); this.contents[this.contentsOffset++] = (byte) descriptorIndex; int fieldAttributeOffset = this.contentsOffset; int attributeNumber = 0; // leave some space for the number of attributes this.contentsOffset += 2; attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset); if (this.contentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[fieldAttributeOffset] = (byte) attributeNumber; } /** * 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) */ /** * 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 = this.referenceBinding; FieldBinding[] syntheticFields = currentBinding.syntheticFields(); int fieldCount = currentBinding.fieldCount() + (syntheticFields == null ? 0 : syntheticFields.length); // write the number of fields if (fieldCount > 0xFFFF) { this.referenceBinding.scope.problemReporter().tooManyFields(this.referenceBinding.scope.referenceType()); } this.contents[this.contentsOffset++] = (byte) (fieldCount >> 8); this.contents[this.contentsOffset++] = (byte) fieldCount; FieldDeclaration[] fieldDecls = currentBinding.scope.referenceContext.fields; for (int i = 0, max = fieldDecls == null ? 0 : fieldDecls.length; i < max; i++) { FieldDeclaration fieldDecl = fieldDecls[i]; if (fieldDecl.binding != null) { addFieldInfo(fieldDecl.binding); } } if (syntheticFields != null) { for (int i = 0, max = syntheticFields.length; i < max; i++) { addFieldInfo(syntheticFields[i]); } } } private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, CategorizedProblem problem, CompilationResult compilationResult) { // always clear the strictfp/native/abstract bit for a problem method generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract)); int methodAttributeOffset = this.contentsOffset; int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute attributeNumber++; int codeAttributeOffset = this.contentsOffset; generateCodeAttributeHeader(); StringBuffer buffer = new StringBuffer(25); buffer.append("\t" + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ buffer.insert(0, Messages.compilation_unresolvedProblem); String problemString = buffer.toString(); this.codeStream.init(this); this.codeStream.preserveUnusedLocals = true; this.codeStream.initializeMaxLocals(methodBinding); // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") this.codeStream.generateCodeAttributeForProblemMethod(problemString); completeCodeAttributeForMissingAbstractProblemMethod( methodBinding, codeAttributeOffset, compilationResult.getLineSeparatorPositions(), problem.getSourceLineNumber()); completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); } /** * INTERNAL USE-ONLY * Generate the byte for a problem clinit method info that correspond to a boggus method. * * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[] */ public void addProblemClinit(CategorizedProblem[] problems) { generateMethodInfoHeaderForClinit(); // leave two spaces for the number of attributes this.contentsOffset -= 2; int attributeOffset = this.contentsOffset; this.contentsOffset += 2; int attributeNumber = 0; int codeAttributeOffset = this.contentsOffset; generateCodeAttributeHeader(); this.codeStream.resetForProblemClinit(this); String problemString = "" ; //$NON-NLS-1$ int problemLine = 0; if (problems != null) { int max = problems.length; StringBuffer buffer = new StringBuffer(25); int count = 0; for (int i = 0; i < max; i++) { CategorizedProblem problem = problems[i]; if ((problem != null) && (problem.isError())) { buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ count++; if (problemLine == 0) { problemLine = problem.getSourceLineNumber(); } problems[i] = null; } } // insert the top line afterwards, once knowing how many problems we have to consider if (count > 1) { buffer.insert(0, Messages.compilation_unresolvedProblems); } else { buffer.insert(0, Messages.compilation_unresolvedProblem); } problemString = buffer.toString(); } // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") this.codeStream.generateCodeAttributeForProblemMethod(problemString); attributeNumber++; // code attribute completeCodeAttributeForClinit( codeAttributeOffset, problemLine); if (this.contentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contents[attributeOffset++] = (byte) (attributeNumber >> 8); this.contents[attributeOffset] = (byte) attributeNumber; } /** * INTERNAL USE-ONLY * Generate the byte for a problem method info that correspond to a boggus constructor. * * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[] */ public void addProblemConstructor( AbstractMethodDeclaration method, MethodBinding methodBinding, CategorizedProblem[] problems) { // always clear the strictfp/native/abstract bit for a problem method generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract)); int methodAttributeOffset = this.contentsOffset; int attributesNumber = generateMethodInfoAttributes(methodBinding); // Code attribute attributesNumber++; int codeAttributeOffset = this.contentsOffset; generateCodeAttributeHeader(); this.codeStream.reset(method, this); String problemString = "" ; //$NON-NLS-1$ int problemLine = 0; if (problems != null) { int max = problems.length; StringBuffer buffer = new StringBuffer(25); int count = 0; for (int i = 0; i < max; i++) { CategorizedProblem problem = problems[i]; if ((problem != null) && (problem.isError())) { buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ count++; if (problemLine == 0) { problemLine = problem.getSourceLineNumber(); } } } // insert the top line afterwards, once knowing how many problems we have to consider if (count > 1) { buffer.insert(0, Messages.compilation_unresolvedProblems); } else { buffer.insert(0, Messages.compilation_unresolvedProblem); } problemString = buffer.toString(); } // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") this.codeStream.generateCodeAttributeForProblemMethod(problemString); completeCodeAttributeForProblemMethod( method, methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions(), problemLine); completeMethodInfo(methodBinding, methodAttributeOffset, attributesNumber); } /** * INTERNAL USE-ONLY * Generate the byte for a problem method info that correspond to a boggus constructor. * Reset the position inside the contents byte array to the savedOffset. * * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[] * @param savedOffset int */ public void addProblemConstructor( AbstractMethodDeclaration method, MethodBinding methodBinding, CategorizedProblem[] problems, int savedOffset) { // we need to move back the contentsOffset to the value at the beginning of the method this.contentsOffset = savedOffset; this.methodCount--; // we need to remove the method that causes the problem addProblemConstructor(method, methodBinding, problems); } /** * INTERNAL USE-ONLY * Generate the byte for a problem method info that correspond to a boggus method. * * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[] */ public void addProblemMethod( AbstractMethodDeclaration method, MethodBinding methodBinding, CategorizedProblem[] problems) { if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) { method.abort(ProblemSeverities.AbortType, null); } // always clear the strictfp/native/abstract bit for a problem method generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract)); int methodAttributeOffset = this.contentsOffset; int attributesNumber = generateMethodInfoAttributes(methodBinding); // Code attribute attributesNumber++; int codeAttributeOffset = this.contentsOffset; generateCodeAttributeHeader(); this.codeStream.reset(method, this); String problemString = "" ; //$NON-NLS-1$ int problemLine = 0; if (problems != null) { int max = problems.length; StringBuffer buffer = new StringBuffer(25); int count = 0; for (int i = 0; i < max; i++) { CategorizedProblem problem = problems[i]; if ((problem != null) && (problem.isError()) && (problem.getSourceStart() >= method.declarationSourceStart) && (problem.getSourceEnd() <= method.declarationSourceEnd)) { buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ count++; if (problemLine == 0) { problemLine = problem.getSourceLineNumber(); } problems[i] = null; } } // insert the top line afterwards, once knowing how many problems we have to consider if (count > 1) { buffer.insert(0, Messages.compilation_unresolvedProblems); } else { buffer.insert(0, Messages.compilation_unresolvedProblem); } problemString = buffer.toString(); } // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") this.codeStream.generateCodeAttributeForProblemMethod(problemString); completeCodeAttributeForProblemMethod( method, methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions(), problemLine); completeMethodInfo(methodBinding, methodAttributeOffset, attributesNumber); } /** * INTERNAL USE-ONLY * Generate the byte for a problem method info that correspond to a boggus method. * Reset the position inside the contents byte array to the savedOffset. * * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[] * @param savedOffset int */ public void addProblemMethod( AbstractMethodDeclaration method, MethodBinding methodBinding, CategorizedProblem[] problems, int savedOffset) { // we need to move back the contentsOffset to the value at the beginning of the method this.contentsOffset = savedOffset; this.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 generateMissingAbstractMethods(this.referenceBinding.scope.referenceType().missingAbstractMethods, this.referenceBinding.scope.referenceCompilationUnit().compilationResult); MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods(); for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) { MethodBinding methodBinding = defaultAbstractMethods[i]; generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; int attributeNumber = generateMethodInfoAttributes(methodBinding); completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); } // 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.purpose) { case SyntheticMethodBinding.FieldReadAccess : case SyntheticMethodBinding.SuperFieldReadAccess : // generate a method info to emulate an reading access to // a non-accessible field addSyntheticFieldReadAccessMethod(syntheticMethod); break; case SyntheticMethodBinding.FieldWriteAccess : case SyntheticMethodBinding.SuperFieldWriteAccess : // 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; case SyntheticMethodBinding.SwitchTable : // generate a method info to define the switch table synthetic method addSyntheticSwitchTable(syntheticMethod); break; case SyntheticMethodBinding.TooManyEnumsConstants : addSyntheticEnumInitializationMethod(syntheticMethod); } } } } /** * INTERNAL USE-ONLY * 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(SyntheticMethodBinding methodBinding) { generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForConstructorAccess(methodBinding); completeCodeAttributeForSyntheticMethod( methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } /** * 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); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForEnumValueOf(methodBinding); completeCodeAttributeForSyntheticMethod( methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } /** * 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); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForEnumValues(methodBinding); completeCodeAttributeForSyntheticMethod( methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } public void addSyntheticEnumInitializationMethod(SyntheticMethodBinding methodBinding) { generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForEnumInitializationMethod(methodBinding); completeCodeAttributeForSyntheticMethod( methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } /** * 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(SyntheticMethodBinding methodBinding) { generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding); completeCodeAttributeForSyntheticMethod( methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } /** * INTERNAL USE-ONLY * Generate the byte for a problem method info that correspond to a synthetic method that * generate an write access to a private field. * * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding */ public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) { generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding); completeCodeAttributeForSyntheticMethod( methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } /** * INTERNAL USE-ONLY * 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(SyntheticMethodBinding methodBinding) { generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForMethodAccess(methodBinding); completeCodeAttributeForSyntheticMethod( methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } public void addSyntheticSwitchTable(SyntheticMethodBinding methodBinding) { generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... int attributeNumber = generateMethodInfoAttributes(methodBinding); // Code attribute int codeAttributeOffset = this.contentsOffset; attributeNumber++; // add code attribute generateCodeAttributeHeader(); this.codeStream.init(this); this.codeStream.generateSyntheticBodyForSwitchTable(methodBinding); completeCodeAttributeForSyntheticMethod( true, methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass) .scope .referenceCompilationUnit() .compilationResult .getLineSeparatorPositions()); // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributeNumber; } /** * INTERNAL USE-ONLY * That method completes the creation of the code attribute by setting * - the attribute_length * - max_stack * - max_locals * - code_length * - exception table * - and debug attributes if necessary. * * @param codeAttributeOffset int */ public void completeCodeAttribute(int codeAttributeOffset) { // reinitialize the localContents with the byte modified by the code stream this.contents = this.codeStream.bCodeStream; int localContentsOffset = this.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 code_length = this.codeStream.position; if (code_length > 65535) { this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit( this.codeStream.methodDeclaration); } if (localContentsOffset + 20 >= this.contents.length) { resizeContents(20); } int max_stack = this.codeStream.stackMax; this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); this.contents[codeAttributeOffset + 7] = (byte) max_stack; int max_locals = this.codeStream.maxLocals; this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); this.contents[codeAttributeOffset + 9] = (byte) max_locals; 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; boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0; // write the exception table ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous) for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) { exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2; } int exSize = exceptionHandlersCount * 8 + 2; if (exSize + localContentsOffset >= this.contents.length) { resizeContents(exSize); } // there is no exception table, so we need to offset by 2 the current offset and move // on the attribute generation this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8); this.contents[localContentsOffset++] = (byte) exceptionHandlersCount; for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { ExceptionLabel exceptionLabel = exceptionLabels[i]; if (exceptionLabel != null) { int iRange = 0, maxRange = exceptionLabel.getCount(); if ((maxRange & 1) != 0) { this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError( Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.methodDeclaration.selector)), this.codeStream.methodDeclaration); } while (iRange < maxRange) { int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions this.contents[localContentsOffset++] = (byte) (start >> 8); this.contents[localContentsOffset++] = (byte) start; int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions this.contents[localContentsOffset++] = (byte) (end >> 8); this.contents[localContentsOffset++] = (byte) end; int handlerPC = exceptionLabel.position; if (addStackMaps) { StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; stackMapFrameCodeStream.addFramePosition(handlerPC); // stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType); } this.contents[localContentsOffset++] = (byte) (handlerPC >> 8); this.contents[localContentsOffset++] = (byte) handlerPC; if (exceptionLabel.exceptionType == null) { // any exception handler this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; } else { int nameIndex; if (exceptionLabel.exceptionType == TypeBinding.NULL) { /* represents ClassNotFoundException, see class literal access*/ nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); } else { nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType); } this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; } } } } // debug attributes int codeAttributeAttributeOffset = localContentsOffset; int attributesNumber = 0; // leave two bytes for the attribute_length localContentsOffset += 2; if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contentsOffset = localContentsOffset; // first we handle the linenumber attribute if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { attributesNumber += generateLineNumberAttribute(); } // then we do the local variable attribute if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { final boolean methodDeclarationIsStatic = this.codeStream.methodDeclaration.isStatic(); attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, false); } if (addStackMaps) { attributesNumber += generateStackMapTableAttribute( this.codeStream.methodDeclaration.binding, code_length, codeAttributeOffset, max_locals, false); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { attributesNumber += generateStackMapAttribute( this.codeStream.methodDeclaration.binding, code_length, codeAttributeOffset, max_locals, false); } this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; // update the attribute length int codeAttributeLength = this.contentsOffset - (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; } /** * INTERNAL USE-ONLY * That method completes the creation of the code attribute by setting * - the attribute_length * - max_stack * - max_locals * - code_length * - exception table * - and debug attributes if necessary. * * @param codeAttributeOffset int */ public void completeCodeAttributeForClinit(int codeAttributeOffset) { // reinitialize the contents with the byte modified by the code stream this.contents = this.codeStream.bCodeStream; int localContentsOffset = this.codeStream.classFileOffset; // codeAttributeOffset is the position inside contents 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 code_length = this.codeStream.position; if (code_length > 65535) { this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit( this.codeStream.methodDeclaration.scope.referenceType()); } if (localContentsOffset + 20 >= this.contents.length) { resizeContents(20); } int max_stack = this.codeStream.stackMax; this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); this.contents[codeAttributeOffset + 7] = (byte) max_stack; int max_locals = this.codeStream.maxLocals; this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); this.contents[codeAttributeOffset + 9] = (byte) max_locals; 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; boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0; // write the exception table ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous) for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) { exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2; } int exSize = exceptionHandlersCount * 8 + 2; if (exSize + localContentsOffset >= this.contents.length) { resizeContents(exSize); } // there is no exception table, so we need to offset by 2 the current offset and move // on the attribute generation this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8); this.contents[localContentsOffset++] = (byte) exceptionHandlersCount; for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { ExceptionLabel exceptionLabel = exceptionLabels[i]; if (exceptionLabel != null) { int iRange = 0, maxRange = exceptionLabel.getCount(); if ((maxRange & 1) != 0) { this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError( Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.methodDeclaration.selector)), this.codeStream.methodDeclaration); } while (iRange < maxRange) { int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions this.contents[localContentsOffset++] = (byte) (start >> 8); this.contents[localContentsOffset++] = (byte) start; int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions this.contents[localContentsOffset++] = (byte) (end >> 8); this.contents[localContentsOffset++] = (byte) end; int handlerPC = exceptionLabel.position; this.contents[localContentsOffset++] = (byte) (handlerPC >> 8); this.contents[localContentsOffset++] = (byte) handlerPC; if (addStackMaps) { StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; stackMapFrameCodeStream.addFramePosition(handlerPC); // stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType); } if (exceptionLabel.exceptionType == null) { // any exception handler this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; } else { int nameIndex; if (exceptionLabel.exceptionType == TypeBinding.NULL) { /* represents denote ClassNotFoundException, see class literal access*/ nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); } else { nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType); } this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; } } } } // debug attributes int codeAttributeAttributeOffset = localContentsOffset; int attributesNumber = 0; // leave two bytes for the attribute_length localContentsOffset += 2; if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contentsOffset = localContentsOffset; // first we handle the linenumber attribute if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { attributesNumber += generateLineNumberAttribute(); } // then we do the local variable attribute if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { attributesNumber += generateLocalVariableTableAttribute(code_length, true, false); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { attributesNumber += generateStackMapTableAttribute( null, code_length, codeAttributeOffset, max_locals, true); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { attributesNumber += generateStackMapAttribute( null, code_length, codeAttributeOffset, max_locals, true); } // update the number of attributes // ensure first that there is enough space available inside the contents array if (codeAttributeAttributeOffset + 2 >= this.contents.length) { resizeContents(2); } this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; // update the attribute length int codeAttributeLength = this.contentsOffset - (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; } /** * INTERNAL USE-ONLY * That method completes the creation of the code attribute by setting * - the attribute_length * - max_stack * - max_locals * - code_length * - exception table * - and debug attributes if necessary. */ public void completeCodeAttributeForClinit( int codeAttributeOffset, int problemLine) { // reinitialize the contents with the byte modified by the code stream this.contents = this.codeStream.bCodeStream; int localContentsOffset = this.codeStream.classFileOffset; // codeAttributeOffset is the position inside contents 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 code_length = this.codeStream.position; if (code_length > 65535) { this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit( this.codeStream.methodDeclaration.scope.referenceType()); } if (localContentsOffset + 20 >= this.contents.length) { resizeContents(20); } int max_stack = this.codeStream.stackMax; this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); this.contents[codeAttributeOffset + 7] = (byte) max_stack; int max_locals = this.codeStream.maxLocals; this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); this.contents[codeAttributeOffset + 9] = (byte) max_locals; 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 this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; // debug attributes int codeAttributeAttributeOffset = localContentsOffset; int attributesNumber = 0; // leave two bytes for the attribute_length localContentsOffset += 2; // first we handle the linenumber attribute if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contentsOffset = localContentsOffset; // first we handle the linenumber attribute if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { attributesNumber += generateLineNumberAttribute(problemLine); } localContentsOffset = this.contentsOffset; // then we do the local variable attribute if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { int localVariableNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName); if (localContentsOffset + 8 >= this.contents.length) { resizeContents(8); } this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8); this.contents[localContentsOffset++] = (byte) localVariableNameIndex; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 2; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; attributesNumber++; } this.contentsOffset = localContentsOffset; if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { attributesNumber += generateStackMapTableAttribute( null, code_length, codeAttributeOffset, max_locals, true); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { attributesNumber += generateStackMapAttribute( null, code_length, codeAttributeOffset, max_locals, true); } // update the number of attributes // ensure first that there is enough space available inside the contents array if (codeAttributeAttributeOffset + 2 >= this.contents.length) { resizeContents(2); } this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; // update the attribute length int codeAttributeLength = this.contentsOffset - (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; } /** * */ public void completeCodeAttributeForMissingAbstractProblemMethod( MethodBinding binding, int codeAttributeOffset, int[] startLineIndexes, int problemLine) { // reinitialize the localContents with the byte modified by the code stream this.contents = this.codeStream.bCodeStream; int localContentsOffset = this.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 = this.codeStream.stackMax; this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); this.contents[codeAttributeOffset + 7] = (byte) max_stack; int max_locals = this.codeStream.maxLocals; this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); this.contents[codeAttributeOffset + 9] = (byte) max_locals; int code_length = this.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 attributesNumber = 0; // leave two bytes for the attribute_length localContentsOffset += 2; // first we handle the linenumber attribute if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contentsOffset = localContentsOffset; if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { if (problemLine == 0) { problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1); } attributesNumber += generateLineNumberAttribute(problemLine); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { attributesNumber += generateStackMapTableAttribute( binding, code_length, codeAttributeOffset, max_locals, false); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { attributesNumber += generateStackMapAttribute( binding, code_length, codeAttributeOffset, max_locals, false); } // 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) (attributesNumber >> 8); this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; // update the attribute length int codeAttributeLength = this.contentsOffset - (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; } /** * INTERNAL USE-ONLY * That method completes the creation of the code attribute by setting * - the attribute_length * - max_stack * - max_locals * - code_length * - exception table * - and debug attributes if necessary. * * @param codeAttributeOffset int */ public void completeCodeAttributeForProblemMethod( AbstractMethodDeclaration method, MethodBinding binding, int codeAttributeOffset, int[] startLineIndexes, int problemLine) { // reinitialize the localContents with the byte modified by the code stream this.contents = this.codeStream.bCodeStream; int localContentsOffset = this.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 = this.codeStream.stackMax; this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); this.contents[codeAttributeOffset + 7] = (byte) max_stack; int max_locals = this.codeStream.maxLocals; this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); this.contents[codeAttributeOffset + 9] = (byte) max_locals; int code_length = this.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); } // write the exception table this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; // debug attributes int codeAttributeAttributeOffset = localContentsOffset; int attributesNumber = 0; // leave two bytes for the attribute_length localContentsOffset += 2; // first we handle the linenumber attribute if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contentsOffset = localContentsOffset; if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { if (problemLine == 0) { problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1); } attributesNumber += generateLineNumberAttribute(problemLine); } // then we do the local variable attribute if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { final boolean methodDeclarationIsStatic = this.codeStream.methodDeclaration.isStatic(); attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, false); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { attributesNumber += generateStackMapTableAttribute( binding, code_length, codeAttributeOffset, max_locals, false); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { attributesNumber += generateStackMapAttribute( binding, code_length, codeAttributeOffset, max_locals, false); } // 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) (attributesNumber >> 8); this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; // update the attribute length int codeAttributeLength = this.contentsOffset - (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; } /** * INTERNAL USE-ONLY * That method completes the creation of the code attribute by setting * - the attribute_length * - max_stack * - max_locals * - code_length * - exception table * - and debug attributes if necessary. * * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding * @param codeAttributeOffset int */ public void completeCodeAttributeForSyntheticMethod( boolean hasExceptionHandlers, SyntheticMethodBinding binding, int codeAttributeOffset, int[] startLineIndexes) { // reinitialize the contents with the byte modified by the code stream this.contents = this.codeStream.bCodeStream; int localContentsOffset = this.codeStream.classFileOffset; // codeAttributeOffset is the position inside contents 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 = this.codeStream.stackMax; this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); this.contents[codeAttributeOffset + 7] = (byte) max_stack; int max_locals = this.codeStream.maxLocals; this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); this.contents[codeAttributeOffset + 9] = (byte) max_locals; int code_length = this.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; if ((localContentsOffset + 40) >= this.contents.length) { resizeContents(40); } boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0; if (hasExceptionHandlers) { // write the exception table ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous) for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) { exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2; } int exSize = exceptionHandlersCount * 8 + 2; if (exSize + localContentsOffset >= this.contents.length) { resizeContents(exSize); } // there is no exception table, so we need to offset by 2 the current offset and move // on the attribute generation this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8); this.contents[localContentsOffset++] = (byte) exceptionHandlersCount; for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { ExceptionLabel exceptionLabel = exceptionLabels[i]; if (exceptionLabel != null) { int iRange = 0, maxRange = exceptionLabel.getCount(); if ((maxRange & 1) != 0) { this.referenceBinding.scope.problemReporter().abortDueToInternalError( Messages.bind(Messages.abort_invalidExceptionAttribute, new String(binding.selector), this.referenceBinding.scope.problemReporter().referenceContext)); } while (iRange < maxRange) { int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions this.contents[localContentsOffset++] = (byte) (start >> 8); this.contents[localContentsOffset++] = (byte) start; int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions this.contents[localContentsOffset++] = (byte) (end >> 8); this.contents[localContentsOffset++] = (byte) end; int handlerPC = exceptionLabel.position; if (addStackMaps) { StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; stackMapFrameCodeStream.addFramePosition(handlerPC); } this.contents[localContentsOffset++] = (byte) (handlerPC >> 8); this.contents[localContentsOffset++] = (byte) handlerPC; if (exceptionLabel.exceptionType == null) { // any exception handler this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; } else { int nameIndex; switch(exceptionLabel.exceptionType.id) { case T_null : /* represents ClassNotFoundException, see class literal access*/ nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); break; case T_long : /* represents NoSuchFieldError, see switch table generation*/ nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName); break; default: nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType); } this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; } } } } } else { // there is no exception table, so we need to offset by 2 the current offset and move // on the attribute generation this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; } // debug attributes int codeAttributeAttributeOffset = localContentsOffset; int attributesNumber = 0; // leave two bytes for the attribute_length localContentsOffset += 2; if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } this.contentsOffset = localContentsOffset; // first we handle the linenumber attribute if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { int lineNumber = Util.getLineNumber(binding.sourceStart, startLineIndexes, 0, startLineIndexes.length-1); attributesNumber += generateLineNumberAttribute(lineNumber); } // then we do the local variable attribute if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { final boolean methodDeclarationIsStatic = binding.isStatic(); attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, true); } if (addStackMaps) { attributesNumber += generateStackMapTableAttribute(binding, code_length, codeAttributeOffset, max_locals, false); } if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { attributesNumber += generateStackMapAttribute( binding, code_length, codeAttributeOffset, max_locals, false); } // update the number of attributes // ensure first that there is enough space available inside the contents array if (codeAttributeAttributeOffset + 2 >= this.contents.length) { resizeContents(2); } this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; // update the attribute length int codeAttributeLength = this.contentsOffset - (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; } /** * INTERNAL USE-ONLY * That method completes the creation of the code attribute by setting * - the attribute_length * - max_stack * - max_locals * - code_length * - exception table * - and debug attributes if necessary. * * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding * @param codeAttributeOffset int */ public void completeCodeAttributeForSyntheticMethod( SyntheticMethodBinding binding, int codeAttributeOffset, int[] startLineIndexes) { this.completeCodeAttributeForSyntheticMethod( false, binding, codeAttributeOffset, startLineIndexes); } /** * INTERNAL USE-ONLY * Complete the creation of a method info by setting up the number of attributes at the right offset. * * @param methodAttributeOffset int * @param attributesNumber int */ public void completeMethodInfo( MethodBinding binding, int methodAttributeOffset, int attributesNumber) { // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributesNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributesNumber; } /** * INTERNAL USE-ONLY * This methods returns a char[] representing the file name of the receiver * * @return char[] */ public char[] fileName() { return this.constantPool.UTF8Cache.returnKeyFor(2); } private void generateAnnotation(Annotation annotation, int currentOffset) { int startingContentsOffset = currentOffset; if (this.contentsOffset + 4 >= this.contents.length) { resizeContents(4); } TypeBinding annotationTypeBinding = annotation.resolvedType; if (annotationTypeBinding == null) { this.contentsOffset = startingContentsOffset; return; } if (annotationTypeBinding.isMemberType()) { this.recordInnerClasses(annotationTypeBinding); } final int typeIndex = this.constantPool.literalIndex(annotationTypeBinding.signature()); this.contents[this.contentsOffset++] = (byte) (typeIndex >> 8); this.contents[this.contentsOffset++] = (byte) typeIndex; if (annotation instanceof NormalAnnotation) { NormalAnnotation normalAnnotation = (NormalAnnotation) annotation; MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs; if (memberValuePairs != null) { final int memberValuePairsLength = memberValuePairs.length; this.contents[this.contentsOffset++] = (byte) (memberValuePairsLength >> 8); this.contents[this.contentsOffset++] = (byte) memberValuePairsLength; for (int i = 0; i < memberValuePairsLength; i++) { MemberValuePair memberValuePair = memberValuePairs[i]; if (this.contentsOffset + 2 >= this.contents.length) { resizeContents(2); } final int elementNameIndex = this.constantPool.literalIndex(memberValuePair.name); this.contents[this.contentsOffset++] = (byte) (elementNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) elementNameIndex; MethodBinding methodBinding = memberValuePair.binding; if (methodBinding == null) { this.contentsOffset = startingContentsOffset; } else { try { generateElementValue(memberValuePair.value, methodBinding.returnType, startingContentsOffset); } catch(ClassCastException e) { this.contentsOffset = startingContentsOffset; } catch(ShouldNotImplement e) { this.contentsOffset = startingContentsOffset; } } } } else { this.contents[this.contentsOffset++] = 0; this.contents[this.contentsOffset++] = 0; } } else if (annotation instanceof SingleMemberAnnotation) { SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation; // this is a single member annotation (one member value) this.contents[this.contentsOffset++] = 0; this.contents[this.contentsOffset++] = 1; if (this.contentsOffset + 2 >= this.contents.length) { resizeContents(2); } final int elementNameIndex = this.constantPool.literalIndex(VALUE); this.contents[this.contentsOffset++] = (byte) (elementNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) elementNameIndex; MethodBinding methodBinding = singleMemberAnnotation.memberValuePairs()[0].binding; if (methodBinding == null) { this.contentsOffset = startingContentsOffset; } else { try { generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, startingContentsOffset); } catch(ClassCastException e) { this.contentsOffset = startingContentsOffset; } catch(ShouldNotImplement e) { this.contentsOffset = startingContentsOffset; } } } else { // this is a marker annotation (no member value pairs) this.contents[this.contentsOffset++] = 0; this.contents[this.contentsOffset++] = 0; } } private int generateAnnotationDefaultAttribute(AnnotationMethodDeclaration declaration, int attributeOffset) { int attributesNumber = 0; // add an annotation default attribute int annotationDefaultNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName); if (this.contentsOffset + 6 >= this.contents.length) { resizeContents(6); } this.contents[this.contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) annotationDefaultNameIndex; int attributeLengthOffset = this.contentsOffset; this.contentsOffset += 4; generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset); if (this.contentsOffset != attributeOffset) { int attributeLength = this.contentsOffset - attributeLengthOffset - 4; this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[attributeLengthOffset++] = (byte) attributeLength; attributesNumber++; } return attributesNumber; } /** * INTERNAL USE-ONLY * That method generates the header of a code attribute. * - the index inside the constant pool for the attribute name ("Code") * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4). */ public void generateCodeAttributeHeader() { if (this.contentsOffset + 20 >= this.contents.length) { resizeContents(20); } int constantValueNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.CodeName); this.contents[this.contentsOffset++] = (byte) (constantValueNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) constantValueNameIndex; // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4) this.contentsOffset += 12; } private int generateConstantValueAttribute(Constant fieldConstant, FieldBinding fieldBinding, int fieldAttributeOffset) { int localContentsOffset = this.contentsOffset; int attributesNumber = 1; if (localContentsOffset + 8 >= this.contents.length) { resizeContents(8); } // Now we generate the constant attribute corresponding to the fieldBinding int constantValueNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.ConstantValueName); this.contents[localContentsOffset++] = (byte) (constantValueNameIndex >> 8); this.contents[localContentsOffset++] = (byte) constantValueNameIndex; // The attribute length = 2 in case of a constantValue attribute this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 2; // Need to add the constant_value_index switch (fieldConstant.typeID()) { case T_boolean : int booleanValueIndex = this.constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0); this.contents[localContentsOffset++] = (byte) (booleanValueIndex >> 8); this.contents[localContentsOffset++] = (byte) booleanValueIndex; break; case T_byte : case T_char : case T_int : case T_short : int integerValueIndex = this.constantPool.literalIndex(fieldConstant.intValue()); this.contents[localContentsOffset++] = (byte) (integerValueIndex >> 8); this.contents[localContentsOffset++] = (byte) integerValueIndex; break; case T_float : int floatValueIndex = this.constantPool.literalIndex(fieldConstant.floatValue()); this.contents[localContentsOffset++] = (byte) (floatValueIndex >> 8); this.contents[localContentsOffset++] = (byte) floatValueIndex; break; case T_double : int doubleValueIndex = this.constantPool.literalIndex(fieldConstant.doubleValue()); this.contents[localContentsOffset++] = (byte) (doubleValueIndex >> 8); this.contents[localContentsOffset++] = (byte) doubleValueIndex; break; case T_long : int longValueIndex = this.constantPool.literalIndex(fieldConstant.longValue()); this.contents[localContentsOffset++] = (byte) (longValueIndex >> 8); this.contents[localContentsOffset++] = (byte) longValueIndex; break; case T_JavaLangString : int stringValueIndex = this.constantPool.literalIndex( ((StringConstant) fieldConstant).stringValue()); if (stringValueIndex == -1) { if (!this.creatingProblemType) { // report an error and abort: will lead to a problem type classfile creation TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; FieldDeclaration[] fieldDecls = typeDeclaration.fields; int max = fieldDecls == null ? 0 : fieldDecls.length; for (int i = 0; i < max; i++) { if (fieldDecls[i].binding == fieldBinding) { // problem should abort typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit( fieldDecls[i]); } } } else { // already inside a problem type creation : no constant for this field this.contentsOffset = fieldAttributeOffset; attributesNumber = 0; } } else { this.contents[localContentsOffset++] = (byte) (stringValueIndex >> 8); this.contents[localContentsOffset++] = (byte) stringValueIndex; } } this.contentsOffset = localContentsOffset; return attributesNumber; } private int generateDeprecatedAttribute() { int localContentsOffset = this.contentsOffset; if (localContentsOffset + 6 >= this.contents.length) { resizeContents(6); } int deprecatedAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.DeprecatedName); this.contents[localContentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) deprecatedAttributeNameIndex; // the length of a deprecated attribute is equals to 0 this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contentsOffset = localContentsOffset; return 1; } private void generateElementValue( Expression defaultValue, TypeBinding memberValuePairReturnType, int attributeOffset) { Constant constant = defaultValue.constant; TypeBinding defaultValueBinding = defaultValue.resolvedType; if (defaultValueBinding == null) { this.contentsOffset = attributeOffset; } else { if (defaultValueBinding.isMemberType()) { this.recordInnerClasses(defaultValueBinding); } if (memberValuePairReturnType.isMemberType()) { this.recordInnerClasses(memberValuePairReturnType); } if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) { // automatic wrapping if (this.contentsOffset + 3 >= this.contents.length) { resizeContents(3); } this.contents[this.contentsOffset++] = (byte) '['; this.contents[this.contentsOffset++] = (byte) 0; this.contents[this.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 (this.contentsOffset + 3 >= this.contents.length) { resizeContents(3); } switch (binding.id) { case T_boolean : this.contents[this.contentsOffset++] = (byte) 'Z'; int booleanValueIndex = this.constantPool.literalIndex(constant.booleanValue() ? 1 : 0); this.contents[this.contentsOffset++] = (byte) (booleanValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) booleanValueIndex; break; case T_byte : this.contents[this.contentsOffset++] = (byte) 'B'; int integerValueIndex = this.constantPool.literalIndex(constant.intValue()); this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) integerValueIndex; break; case T_char : this.contents[this.contentsOffset++] = (byte) 'C'; integerValueIndex = this.constantPool.literalIndex(constant.intValue()); this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) integerValueIndex; break; case T_int : this.contents[this.contentsOffset++] = (byte) 'I'; integerValueIndex = this.constantPool.literalIndex(constant.intValue()); this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) integerValueIndex; break; case T_short : this.contents[this.contentsOffset++] = (byte) 'S'; integerValueIndex = this.constantPool.literalIndex(constant.intValue()); this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) integerValueIndex; break; case T_float : this.contents[this.contentsOffset++] = (byte) 'F'; int floatValueIndex = this.constantPool.literalIndex(constant.floatValue()); this.contents[this.contentsOffset++] = (byte) (floatValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) floatValueIndex; break; case T_double : this.contents[this.contentsOffset++] = (byte) 'D'; int doubleValueIndex = this.constantPool.literalIndex(constant.doubleValue()); this.contents[this.contentsOffset++] = (byte) (doubleValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) doubleValueIndex; break; case T_long : this.contents[this.contentsOffset++] = (byte) 'J'; int longValueIndex = this.constantPool.literalIndex(constant.longValue()); this.contents[this.contentsOffset++] = (byte) (longValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) longValueIndex; break; case T_JavaLangString : this.contents[this.contentsOffset++] = (byte) 's'; int stringValueIndex = this.constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray()); if (stringValueIndex == -1) { if (!this.creatingProblemType) { // report an error and abort: will lead to a problem type classfile creation TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue); } else { // already inside a problem type creation : no attribute this.contentsOffset = attributeOffset; } } else { this.contents[this.contentsOffset++] = (byte) (stringValueIndex >> 8); this.contents[this.contentsOffset++] = (byte) stringValueIndex; } } } private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) { if (defaultValueBinding != null) { if (defaultValueBinding.isEnum()) { if (this.contentsOffset + 5 >= this.contents.length) { resizeContents(5); } this.contents[this.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 { this.contentsOffset = attributeOffset; } if (fieldBinding != null) { final int enumConstantTypeNameIndex = this.constantPool.literalIndex(fieldBinding.type.signature()); final int enumConstantNameIndex = this.constantPool.literalIndex(fieldBinding.name); this.contents[this.contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) enumConstantTypeNameIndex; this.contents[this.contentsOffset++] = (byte) (enumConstantNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) enumConstantNameIndex; } } else if (defaultValueBinding.isAnnotationType()) { if (this.contentsOffset + 1 >= this.contents.length) { resizeContents(1); } this.contents[this.contentsOffset++] = (byte) '@'; generateAnnotation((Annotation) defaultValue, attributeOffset); } else if (defaultValueBinding.isArrayType()) { // array type if (this.contentsOffset + 3 >= this.contents.length) { resizeContents(3); } this.contents[this.contentsOffset++] = (byte) '['; if (defaultValue instanceof ArrayInitializer) { ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue; int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0; this.contents[this.contentsOffset++] = (byte) (arrayLength >> 8); this.contents[this.contentsOffset++] = (byte) arrayLength; for (int i = 0; i < arrayLength; i++) { generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset); } } else { this.contentsOffset = attributeOffset; } } else { // class type if (this.contentsOffset + 3 >= this.contents.length) { resizeContents(3); } this.contents[this.contentsOffset++] = (byte) 'c'; if (defaultValue instanceof ClassLiteralAccess) { ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue; final int classInfoIndex = this.constantPool.literalIndex(classLiteralAccess.targetType.signature()); this.contents[this.contentsOffset++] = (byte) (classInfoIndex >> 8); this.contents[this.contentsOffset++] = (byte) classInfoIndex; } else { this.contentsOffset = attributeOffset; } } } else { this.contentsOffset = attributeOffset; } } private int generateEnclosingMethodAttribute() { int localContentsOffset = this.contentsOffset; // add enclosing method attribute (1.5 mode only) if (localContentsOffset + 10 >= this.contents.length) { resizeContents(10); } int enclosingMethodAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName); this.contents[localContentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) enclosingMethodAttributeNameIndex; // the length of a signature attribute is equals to 2 this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 4; int enclosingTypeIndex = this.constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName()); this.contents[localContentsOffset++] = (byte) (enclosingTypeIndex >> 8); this.contents[localContentsOffset++] = (byte) enclosingTypeIndex; byte methodIndexByte1 = 0; byte methodIndexByte2 = 0; if (this.referenceBinding instanceof LocalTypeBinding) { MethodBinding methodBinding = ((LocalTypeBinding) this.referenceBinding).enclosingMethod; if (methodBinding != null) { int enclosingMethodIndex = this.constantPool.literalIndexForNameAndType(methodBinding.selector, methodBinding.signature(this)); methodIndexByte1 = (byte) (enclosingMethodIndex >> 8); methodIndexByte2 = (byte) enclosingMethodIndex; } } this.contents[localContentsOffset++] = methodIndexByte1; this.contents[localContentsOffset++] = methodIndexByte2; this.contentsOffset = localContentsOffset; return 1; } private int generateExceptionsAttribute(ReferenceBinding[] thrownsExceptions) { int localContentsOffset = this.contentsOffset; int length = thrownsExceptions.length; int exSize = 8 + length * 2; if (exSize + this.contentsOffset >= this.contents.length) { resizeContents(exSize); } int exceptionNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.ExceptionsName); this.contents[localContentsOffset++] = (byte) (exceptionNameIndex >> 8); this.contents[localContentsOffset++] = (byte) exceptionNameIndex; // The attribute length = length * 2 + 2 in case of a exception attribute int attributeLength = length * 2 + 2; this.contents[localContentsOffset++] = (byte) (attributeLength >> 24); this.contents[localContentsOffset++] = (byte) (attributeLength >> 16); this.contents[localContentsOffset++] = (byte) (attributeLength >> 8); this.contents[localContentsOffset++] = (byte) attributeLength; this.contents[localContentsOffset++] = (byte) (length >> 8); this.contents[localContentsOffset++] = (byte) length; for (int i = 0; i < length; i++) { int exceptionIndex = this.constantPool.literalIndexForType(thrownsExceptions[i]); this.contents[localContentsOffset++] = (byte) (exceptionIndex >> 8); this.contents[localContentsOffset++] = (byte) exceptionIndex; } this.contentsOffset = localContentsOffset; return 1; } private int generateHierarchyInconsistentAttribute() { int localContentsOffset = this.contentsOffset; // add an attribute for inconsistent hierarchy if (localContentsOffset + 6 >= this.contents.length) { resizeContents(6); } int inconsistentHierarchyNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.InconsistentHierarchy); this.contents[localContentsOffset++] = (byte) (inconsistentHierarchyNameIndex >> 8); this.contents[localContentsOffset++] = (byte) inconsistentHierarchyNameIndex; // the length of an inconsistent hierarchy attribute is equals to 0 this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contentsOffset = localContentsOffset; return 1; } private int generateInnerClassAttribute(int numberOfInnerClasses, ReferenceBinding[] innerClasses) { int localContentsOffset = this.contentsOffset; // Generate the inner class attribute int exSize = 8 * numberOfInnerClasses + 8; if (exSize + localContentsOffset >= this.contents.length) { resizeContents(exSize); } // Now we now the size of the attribute and the number of entries // attribute name int attributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.InnerClassName); this.contents[localContentsOffset++] = (byte) (attributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) attributeNameIndex; int value = (numberOfInnerClasses << 3) + 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) (numberOfInnerClasses >> 8); this.contents[localContentsOffset++] = (byte) numberOfInnerClasses; for (int i = 0; i < numberOfInnerClasses; i++) { ReferenceBinding innerClass = innerClasses[i]; int accessFlags = innerClass.getAccessFlags(); int innerClassIndex = this.constantPool.literalIndexForType(innerClass.constantPoolName()); // inner class index this.contents[localContentsOffset++] = (byte) (innerClassIndex >> 8); this.contents[localContentsOffset++] = (byte) innerClassIndex; // outer class index: anonymous and local have no outer class index if (innerClass.isMemberType()) { // member or member of local int outerClassIndex = this.constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName()); this.contents[localContentsOffset++] = (byte) (outerClassIndex >> 8); this.contents[localContentsOffset++] = (byte) outerClassIndex; } else { // equals to 0 if the innerClass is not a member type this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; } // name index if (!innerClass.isAnonymousType()) { int nameIndex = this.constantPool.literalIndex(innerClass.sourceName()); this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; } else { // equals to 0 if the innerClass is an anonymous type this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; } // access flag if (innerClass.isAnonymousType()) { accessFlags &= ~ClassFileConstants.AccFinal; } else if (innerClass.isMemberType() && innerClass.isInterface()) { accessFlags |= ClassFileConstants.AccStatic; // implicitely static } this.contents[localContentsOffset++] = (byte) (accessFlags >> 8); this.contents[localContentsOffset++] = (byte) accessFlags; } this.contentsOffset = localContentsOffset; return 1; } private int generateLineNumberAttribute() { int localContentsOffset = this.contentsOffset; int attributesNumber = 0; /* 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[] pcToSourceMapTable; if (((pcToSourceMapTable = this.codeStream.pcToSourceMap) != null) && (this.codeStream.pcToSourceMapSize != 0)) { int lineNumberNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName); if (localContentsOffset + 8 >= this.contents.length) { resizeContents(8); } this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8); this.contents[localContentsOffset++] = (byte) lineNumberNameIndex; int lineNumberTableOffset = localContentsOffset; localContentsOffset += 6; // leave space for attribute_length and line_number_table_length int numberOfEntries = 0; int length = this.codeStream.pcToSourceMapSize; for (int i = 0; i < length;) { // write the entry if (localContentsOffset + 4 >= this.contents.length) { resizeContents(4); } int pc = pcToSourceMapTable[i++]; this.contents[localContentsOffset++] = (byte) (pc >> 8); this.contents[localContentsOffset++] = (byte) pc; int lineNumber = pcToSourceMapTable[i++]; this.contents[localContentsOffset++] = (byte) (lineNumber >> 8); this.contents[localContentsOffset++] = (byte) lineNumber; numberOfEntries++; } // now we change the size of the line number attribute int lineNumberAttr_length = numberOfEntries * 4 + 2; this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24); this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16); this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8); this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length; this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8); this.contents[lineNumberTableOffset++] = (byte) numberOfEntries; attributesNumber = 1; } this.contentsOffset = localContentsOffset; return attributesNumber; } // this is used for problem and synthetic methods private int generateLineNumberAttribute(int problemLine) { int localContentsOffset = this.contentsOffset; if (localContentsOffset + 12 >= this.contents.length) { resizeContents(12); } /* 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 = this.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; // 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 this.contentsOffset = localContentsOffset; return 1; } private int generateLocalVariableTableAttribute(int code_length, boolean methodDeclarationIsStatic, boolean isSynthetic) { int attributesNumber = 0; int localContentsOffset = this.contentsOffset; int numberOfEntries = 0; int localVariableNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName); int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1); for (int i = 0; i < this.codeStream.allLocalsCounter; i++) { LocalVariableBinding localVariableBinding = this.codeStream.locals[i]; maxOfEntries += 10 * localVariableBinding.initializationCount; } // reserve enough space if (localContentsOffset + maxOfEntries >= this.contents.length) { resizeContents(maxOfEntries); } this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8); this.contents[localContentsOffset++] = (byte) localVariableNameIndex; int localVariableTableOffset = localContentsOffset; // leave space for attribute_length and local_variable_table_length localContentsOffset += 6; int nameIndex; int descriptorIndex; SourceTypeBinding declaringClassBinding = null; if (!methodDeclarationIsStatic && !isSynthetic) { 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 = this.constantPool.literalIndex(ConstantPool.This); this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; declaringClassBinding = (SourceTypeBinding) this.codeStream.methodDeclaration.binding.declaringClass; descriptorIndex = this.constantPool.literalIndex( 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; } // used to remember the local variable with a generic type int genericLocalVariablesCounter = 0; LocalVariableBinding[] genericLocalVariables = null; int numberOfGenericEntries = 0; for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { LocalVariableBinding localVariable = this.codeStream.locals[i]; int initializationCount = localVariable.initializationCount; if (initializationCount == 0) continue; if (localVariable.declaration == null) continue; final TypeBinding localVariableTypeBinding = localVariable.type; boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable(); if (isParameterizedType) { if (genericLocalVariables == null) { // we cannot have more than max locals genericLocalVariables = new LocalVariableBinding[max]; } genericLocalVariables[genericLocalVariablesCounter++] = localVariable; } for (int j = 0; j < initializationCount; j++) { int startPC = localVariable.initializationPCs[j << 1]; int endPC = localVariable.initializationPCs[(j << 1) + 1]; if (startPC != endPC) { // only entries for non zero length if (endPC == -1) { localVariable.declaringScope.problemReporter().abortDueToInternalError( Messages.bind(Messages.abort_invalidAttribute, new String(localVariable.name)), (ASTNode) localVariable.declaringScope.methodScope().referenceContext); } if (isParameterizedType) { numberOfGenericEntries++; } // now we can safely add the local entry numberOfEntries++; 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 = this.constantPool.literalIndex(localVariable.name); this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; descriptorIndex = this.constantPool.literalIndex(localVariableTypeBinding.signature()); 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; } } } int value = numberOfEntries * 10 + 2; this.contents[localVariableTableOffset++] = (byte) (value >> 24); this.contents[localVariableTableOffset++] = (byte) (value >> 16); this.contents[localVariableTableOffset++] = (byte) (value >> 8); this.contents[localVariableTableOffset++] = (byte) value; this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8); this.contents[localVariableTableOffset] = (byte) numberOfEntries; attributesNumber++; final boolean currentInstanceIsGeneric = !methodDeclarationIsStatic && declaringClassBinding != null && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES; 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 = this.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 = this.constantPool.literalIndex(ConstantPool.This); this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; descriptorIndex = this.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 = this.constantPool.literalIndex(localVariable.name); this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; descriptorIndex = this.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; } } } attributesNumber++; } this.contentsOffset = localContentsOffset; return attributesNumber; } /** * INTERNAL USE-ONLY * That method generates the attributes of a code attribute. * They could be: * - an exception attribute for each try/catch found inside the method * - a deprecated attribute * - a synthetic attribute for synthetic access methods * * It returns the number of attributes created for the code attribute. * * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding * @return int */ public int generateMethodInfoAttributes(MethodBinding methodBinding) { // leave two bytes for the attribute_number this.contentsOffset += 2; if (this.contentsOffset + 2 >= this.contents.length) { resizeContents(2); } // now we can handle all the attribute for that method info: // it could be: // - a CodeAttribute // - a ExceptionAttribute // - a DeprecatedAttribute // - a SyntheticAttribute // Exception attribute ReferenceBinding[] thrownsExceptions; int attributesNumber = 0; if ((thrownsExceptions = methodBinding.thrownExceptions) != Binding.NO_EXCEPTIONS) { // The method has a throw clause. So we need to add an exception attribute // check that there is enough space to write all the bytes for the exception attribute attributesNumber += generateExceptionsAttribute(thrownsExceptions); } if (methodBinding.isDeprecated()) { // Deprecated attribute attributesNumber += generateDeprecatedAttribute(); } if (this.targetJDK < ClassFileConstants.JDK1_5) { if (methodBinding.isSynthetic()) { attributesNumber += generateSyntheticAttribute(); } if (methodBinding.isVarargs()) { attributesNumber += generateVarargsAttribute(); } } // add signature attribute char[] genericSignature = methodBinding.genericSignature(); if (genericSignature != null) { attributesNumber += generateSignatureAttribute(genericSignature); } if (this.targetJDK >= ClassFileConstants.JDK1_4) { AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod(); if (methodDeclaration != null) { Annotation[] annotations = methodDeclaration.annotations; if (annotations != null) { attributesNumber += generateRuntimeAnnotations(annotations); } if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) { Argument[] arguments = methodDeclaration.arguments; if (arguments != null) { attributesNumber += generateRuntimeAnnotationsForParameters(arguments); } } } } if ((methodBinding.tagBits & TagBits.HasMissingType) != 0) { this.missingTypes = methodBinding.collectMissingTypes(this.missingTypes); } return attributesNumber; } public int generateMethodInfoAttributes(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) { int attributesNumber = generateMethodInfoAttributes(methodBinding); int attributeOffset = this.contentsOffset; if ((declaration.modifiers & ClassFileConstants.AccAnnotationDefault) != 0) { // add an annotation default attribute attributesNumber += generateAnnotationDefaultAttribute(declaration, attributeOffset); } return attributesNumber; } /** * INTERNAL USE-ONLY * That method generates the header of a method info: * The header consists in: * - the access flags * - the name index of the method name inside the constant pool * - the descriptor index of the signature of the method inside the constant pool. * * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding */ public void generateMethodInfoHeader(MethodBinding methodBinding) { generateMethodInfoHeader(methodBinding, methodBinding.modifiers); } /** * INTERNAL USE-ONLY * That method generates the header of a method info: * The header consists in: * - the access flags * - the name index of the method name inside the constant pool * - the descriptor index of the signature of the method inside the constant pool. * * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding * @param accessFlags the access flags */ public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) { // check that there is enough space to write all the bytes for the method info corresponding // to the @methodBinding this.methodCount++; // add one more method if (this.contentsOffset + 10 >= this.contents.length) { resizeContents(10); } if (this.targetJDK < ClassFileConstants.JDK1_5) { // pre 1.5, synthetic is an attribute, not a modifier // pre 1.5, varargs is an attribute, not a modifier (-target jsr14 mode) accessFlags &= ~(ClassFileConstants.AccSynthetic | ClassFileConstants.AccVarargs); } if ((methodBinding.tagBits & TagBits.ClearPrivateModifier) != 0) { accessFlags &= ~ClassFileConstants.AccPrivate; } this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); this.contents[this.contentsOffset++] = (byte) accessFlags; int nameIndex = this.constantPool.literalIndex(methodBinding.selector); this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8); this.contents[this.contentsOffset++] = (byte) nameIndex; int descriptorIndex = this.constantPool.literalIndex(methodBinding.signature(this)); this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8); this.contents[this.contentsOffset++] = (byte) descriptorIndex; } /** * INTERNAL USE-ONLY * That method generates the method info header of a clinit: * The header consists in: * - the access flags (always default access + static) * - the name index of the method name (always ) inside the constant pool * - the descriptor index of the signature (always ()V) of the method inside the constant pool. */ public void generateMethodInfoHeaderForClinit() { // check that there is enough space to write all the bytes for the method info corresponding // to the @methodBinding this.methodCount++; // add one more method if (this.contentsOffset + 10 >= this.contents.length) { resizeContents(10); } this.contents[this.contentsOffset++] = (byte) ((ClassFileConstants.AccDefault | ClassFileConstants.AccStatic) >> 8); this.contents[this.contentsOffset++] = (byte) (ClassFileConstants.AccDefault | ClassFileConstants.AccStatic); int nameIndex = this.constantPool.literalIndex(ConstantPool.Clinit); this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8); this.contents[this.contentsOffset++] = (byte) nameIndex; int descriptorIndex = this.constantPool.literalIndex(ConstantPool.ClinitSignature); this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8); this.contents[this.contentsOffset++] = (byte) descriptorIndex; // We know that we won't get more than 1 attribute: the code attribute this.contents[this.contentsOffset++] = 0; this.contents[this.contentsOffset++] = 1; } /** * 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) { TypeDeclaration currentDeclaration = this.referenceBinding.scope.referenceContext; int typeDeclarationSourceStart = currentDeclaration.sourceStart(); int typeDeclarationSourceEnd = currentDeclaration.sourceEnd(); for (int i = 0, max = methodDeclarations.length; i < max; i++) { MethodDeclaration methodDeclaration = methodDeclarations[i]; MethodBinding methodBinding = methodDeclaration.binding; String readableName = new String(methodBinding.readableName()); CategorizedProblem[] problems = compilationResult.problems; int problemsCount = compilationResult.problemCount; for (int j = 0; j < problemsCount; j++) { CategorizedProblem problem = problems[j]; if (problem != null && problem.getID() == IProblem.AbstractMethodMustBeImplemented && problem.getMessage().indexOf(readableName) != -1 && problem.getSourceStart() >= typeDeclarationSourceStart && problem.getSourceEnd() <= typeDeclarationSourceEnd) { // we found a match addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult); } } } } } private void generateMissingTypesAttribute() { int initialSize = this.missingTypes.size(); int[] missingTypesIndexes = new int[initialSize]; int numberOfMissingTypes = 0; if (initialSize > 1) { Collections.sort(this.missingTypes, new Comparator() { public int compare(Object o1, Object o2) { TypeBinding typeBinding1 = (TypeBinding) o1; TypeBinding typeBinding2 = (TypeBinding) o2; return CharOperation.compareTo(typeBinding1.constantPoolName(), typeBinding2.constantPoolName()); } }); } int previousIndex = 0; next: for (int i = 0; i < initialSize; i++) { int missingTypeIndex = this.constantPool.literalIndexForType((TypeBinding) this.missingTypes.get(i)); if (previousIndex == missingTypeIndex) { continue next; } previousIndex = missingTypeIndex; missingTypesIndexes[numberOfMissingTypes++] = missingTypeIndex; } // we don't need to resize as we interate from 0 to numberOfMissingTypes when recording the indexes in the .class file int attributeLength = numberOfMissingTypes * 2 + 2; if (this.contentsOffset + attributeLength + 6 >= this.contents.length) { resizeContents(attributeLength + 6); } int missingTypesNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.MissingTypesName); this.contents[this.contentsOffset++] = (byte) (missingTypesNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) missingTypesNameIndex; // generate attribute length this.contents[this.contentsOffset++] = (byte) (attributeLength >> 24); this.contents[this.contentsOffset++] = (byte) (attributeLength >> 16); this.contents[this.contentsOffset++] = (byte) (attributeLength >> 8); this.contents[this.contentsOffset++] = (byte) attributeLength; // generate number of missing types this.contents[this.contentsOffset++] = (byte) (numberOfMissingTypes >> 8); this.contents[this.contentsOffset++] = (byte) numberOfMissingTypes; // generate entry for each missing type for (int i = 0; i < numberOfMissingTypes; i++) { int missingTypeIndex = missingTypesIndexes[i]; this.contents[this.contentsOffset++] = (byte) (missingTypeIndex >> 8); this.contents[this.contentsOffset++] = (byte) missingTypeIndex; } } /** * @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 (annotation.isRuntimeInvisible()) { invisibleAnnotationsCounter++; } else if (annotation.isRuntimeVisible()) { visibleAnnotationsCounter++; } } int annotationAttributeOffset = this.contentsOffset; int constantPOffset = this.constantPool.currentOffset; int constantPoolIndex = this.constantPool.currentIndex; if (invisibleAnnotationsCounter != 0) { if (this.contentsOffset + 10 >= this.contents.length) { resizeContents(10); } int runtimeInvisibleAnnotationsAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName); this.contents[this.contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex; int attributeLengthOffset = this.contentsOffset; this.contentsOffset += 4; // leave space for the attribute length int annotationsLengthOffset = this.contentsOffset; this.contentsOffset += 2; // leave space for the annotations length int counter = 0; loop: for (int i = 0; i < length; i++) { if (invisibleAnnotationsCounter == 0) break loop; Annotation annotation = annotations[i]; if (annotation.isRuntimeInvisible()) { int currentAnnotationOffset = this.contentsOffset; generateAnnotation(annotation, currentAnnotationOffset); invisibleAnnotationsCounter--; if (this.contentsOffset != currentAnnotationOffset) { counter++; } } } if (counter != 0) { this.contents[annotationsLengthOffset++] = (byte) (counter >> 8); this.contents[annotationsLengthOffset++] = (byte) counter; int attributeLength = this.contentsOffset - attributeLengthOffset - 4; this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[attributeLengthOffset++] = (byte) attributeLength; attributesNumber++; } else { this.contentsOffset = annotationAttributeOffset; // reset the constant pool to its state before the clinit this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeInvisibleAnnotationsName, constantPoolIndex, constantPOffset); } } annotationAttributeOffset = this.contentsOffset; constantPOffset = this.constantPool.currentOffset; constantPoolIndex = this.constantPool.currentIndex; if (visibleAnnotationsCounter != 0) { if (this.contentsOffset + 10 >= this.contents.length) { resizeContents(10); } int runtimeVisibleAnnotationsAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName); this.contents[this.contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex; int attributeLengthOffset = this.contentsOffset; this.contentsOffset += 4; // leave space for the attribute length int annotationsLengthOffset = this.contentsOffset; this.contentsOffset += 2; // leave space for the annotations length int counter = 0; loop: for (int i = 0; i < length; i++) { if (visibleAnnotationsCounter == 0) break loop; Annotation annotation = annotations[i]; if (annotation.isRuntimeVisible()) { visibleAnnotationsCounter--; int currentAnnotationOffset = this.contentsOffset; generateAnnotation(annotation, currentAnnotationOffset); if (this.contentsOffset != currentAnnotationOffset) { counter++; } } } if (counter != 0) { this.contents[annotationsLengthOffset++] = (byte) (counter >> 8); this.contents[annotationsLengthOffset++] = (byte) counter; int attributeLength = this.contentsOffset - attributeLengthOffset - 4; this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[attributeLengthOffset++] = (byte) attributeLength; attributesNumber++; } else { this.contentsOffset = annotationAttributeOffset; this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeVisibleAnnotationsName, constantPoolIndex, constantPOffset); } } 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 (annotation.isRuntimeInvisible()) { annotationsCounters[i][INVISIBLE_INDEX]++; invisibleParametersAnnotationsCounter++; } else if (annotation.isRuntimeVisible()) { annotationsCounters[i][VISIBLE_INDEX]++; visibleParametersAnnotationsCounter++; } } } } int attributesNumber = 0; int annotationAttributeOffset = this.contentsOffset; if (invisibleParametersAnnotationsCounter != 0) { int globalCounter = 0; if (this.contentsOffset + 7 >= this.contents.length) { resizeContents(7); } int attributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName); this.contents[this.contentsOffset++] = (byte) (attributeNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) attributeNameIndex; int attributeLengthOffset = this.contentsOffset; this.contentsOffset += 4; // leave space for the attribute length this.contents[this.contentsOffset++] = (byte) argumentsLength; for (int i = 0; i < argumentsLength; i++) { if (this.contentsOffset + 2 >= this.contents.length) { resizeContents(2); } if (invisibleParametersAnnotationsCounter == 0) { this.contents[this.contentsOffset++] = (byte) 0; this.contents[this.contentsOffset++] = (byte) 0; } else { final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX]; int invisibleAnnotationsOffset = this.contentsOffset; // leave space for number of annotations this.contentsOffset += 2; int counter = 0; 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 (annotation.isRuntimeInvisible()) { int currentAnnotationOffset = this.contentsOffset; generateAnnotation(annotation, currentAnnotationOffset); if (this.contentsOffset != currentAnnotationOffset) { counter++; globalCounter++; } invisibleParametersAnnotationsCounter--; } } } this.contents[invisibleAnnotationsOffset++] = (byte) (counter >> 8); this.contents[invisibleAnnotationsOffset] = (byte) counter; } } if (globalCounter != 0) { int attributeLength = this.contentsOffset - attributeLengthOffset - 4; this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[attributeLengthOffset++] = (byte) attributeLength; attributesNumber++; } else { // if globalCounter is 0, this means that the code generation for all visible annotations failed this.contentsOffset = annotationAttributeOffset; } } if (visibleParametersAnnotationsCounter != 0) { int globalCounter = 0; if (this.contentsOffset + 7 >= this.contents.length) { resizeContents(7); } int attributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName); this.contents[this.contentsOffset++] = (byte) (attributeNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) attributeNameIndex; int attributeLengthOffset = this.contentsOffset; this.contentsOffset += 4; // leave space for the attribute length this.contents[this.contentsOffset++] = (byte) argumentsLength; for (int i = 0; i < argumentsLength; i++) { if (this.contentsOffset + 2 >= this.contents.length) { resizeContents(2); } if (visibleParametersAnnotationsCounter == 0) { this.contents[this.contentsOffset++] = (byte) 0; this.contents[this.contentsOffset++] = (byte) 0; } else { final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX]; int visibleAnnotationsOffset = this.contentsOffset; // leave space for number of annotations this.contentsOffset += 2; int counter = 0; 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 (annotation.isRuntimeVisible()) { int currentAnnotationOffset = this.contentsOffset; generateAnnotation(annotation, currentAnnotationOffset); if (this.contentsOffset != currentAnnotationOffset) { counter++; globalCounter++; } visibleParametersAnnotationsCounter--; } } } this.contents[visibleAnnotationsOffset++] = (byte) (counter >> 8); this.contents[visibleAnnotationsOffset] = (byte) counter; } } if (globalCounter != 0) { int attributeLength = this.contentsOffset - attributeLengthOffset - 4; this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[attributeLengthOffset++] = (byte) attributeLength; attributesNumber++; } else { // if globalCounter is 0, this means that the code generation for all visible annotations failed this.contentsOffset = annotationAttributeOffset; } } return attributesNumber; } private int generateSignatureAttribute(char[] genericSignature) { int localContentsOffset = this.contentsOffset; if (localContentsOffset + 8 >= this.contents.length) { resizeContents(8); } int signatureAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.SignatureName); this.contents[localContentsOffset++] = (byte) (signatureAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) signatureAttributeNameIndex; // the length of a signature attribute is equals to 2 this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 2; int signatureIndex = this.constantPool.literalIndex(genericSignature); this.contents[localContentsOffset++] = (byte) (signatureIndex >> 8); this.contents[localContentsOffset++] = (byte) signatureIndex; this.contentsOffset = localContentsOffset; return 1; } private int generateSourceAttribute(String fullFileName) { int localContentsOffset = this.contentsOffset; // check that there is enough space to write all the bytes for the field info corresponding // to the @fieldBinding if (localContentsOffset + 8 >= this.contents.length) { resizeContents(8); } int sourceAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.SourceName); this.contents[localContentsOffset++] = (byte) (sourceAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) sourceAttributeNameIndex; // The length of a source file attribute is 2. This is a fixed-length // attribute this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 2; // write the source file name int fileNameIndex = this.constantPool.literalIndex(fullFileName.toCharArray()); this.contents[localContentsOffset++] = (byte) (fileNameIndex >> 8); this.contents[localContentsOffset++] = (byte) fileNameIndex; this.contentsOffset = localContentsOffset; return 1; } private int generateStackMapAttribute( MethodBinding methodBinding, int code_length, int codeAttributeOffset, int max_locals, boolean isClinit) { int attributesNumber = 0; int localContentsOffset = this.contentsOffset; StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; stackMapFrameCodeStream.removeFramePosition(code_length); if (stackMapFrameCodeStream.hasFramePositions()) { Map frames = new HashMap(); List realFrames = traverse(isClinit ? null : methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit); int numberOfFrames = realFrames.size(); if (numberOfFrames > 1) { int stackMapTableAttributeOffset = localContentsOffset; // add the stack map table attribute if (localContentsOffset + 8 >= this.contents.length) { resizeContents(8); } int stackMapAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.StackMapName); this.contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex; int stackMapAttributeLengthOffset = localContentsOffset; // generate the attribute localContentsOffset += 4; if (localContentsOffset + 4 >= this.contents.length) { resizeContents(4); } int numberOfFramesOffset = localContentsOffset; localContentsOffset += 2; if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0); for (int j = 1; j < numberOfFrames; j++) { // select next frame currentFrame = (StackMapFrame) realFrames.get(j); // generate current frame // need to find differences between the current frame and the previous frame int frameOffset = currentFrame.pc; // FULL_FRAME if (localContentsOffset + 5 >= this.contents.length) { resizeContents(5); } this.contents[localContentsOffset++] = (byte) (frameOffset >> 8); this.contents[localContentsOffset++] = (byte) frameOffset; int numberOfLocalOffset = localContentsOffset; localContentsOffset += 2; // leave two spots for number of locals int numberOfLocalEntries = 0; int numberOfLocals = currentFrame.getNumberOfLocals(); int numberOfEntries = 0; int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length; for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) { if (localContentsOffset + 3 >= this.contents.length) { resizeContents(3); } VerificationTypeInfo info = currentFrame.locals[i]; if (info == null) { this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; } else { switch(info.id()) { case T_boolean : case T_byte : case T_char : case T_int : case T_short : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; break; case T_float : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; break; case T_long : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; i++; break; case T_double : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; i++; break; case T_null : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; break; default: this.contents[localContentsOffset++] = (byte) info.tag; switch (info.tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED : int offset = info.offset; this.contents[localContentsOffset++] = (byte) (offset >> 8); this.contents[localContentsOffset++] = (byte) offset; break; case VerificationTypeInfo.ITEM_OBJECT : int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); this.contents[localContentsOffset++] = (byte) (indexForType >> 8); this.contents[localContentsOffset++] = (byte) indexForType; } } numberOfLocalEntries++; } numberOfEntries++; } if (localContentsOffset + 4 >= this.contents.length) { resizeContents(4); } this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8); this.contents[numberOfLocalOffset] = (byte) numberOfEntries; int numberOfStackItems = currentFrame.numberOfStackItems; this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8); this.contents[localContentsOffset++] = (byte) numberOfStackItems; for (int i = 0; i < numberOfStackItems; i++) { if (localContentsOffset + 3 >= this.contents.length) { resizeContents(3); } VerificationTypeInfo info = currentFrame.stackItems[i]; if (info == null) { this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; } else { switch(info.id()) { case T_boolean : case T_byte : case T_char : case T_int : case T_short : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; break; case T_float : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; break; case T_long : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; break; case T_double : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; break; case T_null : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; break; default: this.contents[localContentsOffset++] = (byte) info.tag; switch (info.tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED : int offset = info.offset; this.contents[localContentsOffset++] = (byte) (offset >> 8); this.contents[localContentsOffset++] = (byte) offset; break; case VerificationTypeInfo.ITEM_OBJECT : int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); this.contents[localContentsOffset++] = (byte) (indexForType >> 8); this.contents[localContentsOffset++] = (byte) indexForType; } } } } } numberOfFrames--; if (numberOfFrames != 0) { this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8); this.contents[numberOfFramesOffset] = (byte) numberOfFrames; int attributeLength = localContentsOffset - stackMapAttributeLengthOffset - 4; this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24); this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[stackMapAttributeLengthOffset] = (byte) attributeLength; attributesNumber++; } else { localContentsOffset = stackMapTableAttributeOffset; } } } this.contentsOffset = localContentsOffset; return attributesNumber; } private int generateStackMapTableAttribute( MethodBinding methodBinding, int code_length, int codeAttributeOffset, int max_locals, boolean isClinit) { int attributesNumber = 0; int localContentsOffset = this.contentsOffset; StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; stackMapFrameCodeStream.removeFramePosition(code_length); if (stackMapFrameCodeStream.hasFramePositions()) { Map frames = new HashMap(); List realFrames = traverse(isClinit ? null: methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit); int numberOfFrames = realFrames.size(); if (numberOfFrames > 1) { int stackMapTableAttributeOffset = localContentsOffset; // add the stack map table attribute if (localContentsOffset + 8 >= this.contents.length) { resizeContents(8); } int stackMapTableAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.StackMapTableName); this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex; int stackMapTableAttributeLengthOffset = localContentsOffset; // generate the attribute localContentsOffset += 4; if (localContentsOffset + 4 >= this.contents.length) { resizeContents(4); } int numberOfFramesOffset = localContentsOffset; localContentsOffset += 2; if (localContentsOffset + 2 >= this.contents.length) { resizeContents(2); } StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0); StackMapFrame prevFrame = null; for (int j = 1; j < numberOfFrames; j++) { // select next frame prevFrame = currentFrame; currentFrame = (StackMapFrame) realFrames.get(j); // generate current frame // need to find differences between the current frame and the previous frame int offsetDelta = currentFrame.getOffsetDelta(prevFrame); switch (currentFrame.getFrameType(prevFrame)) { case StackMapFrame.APPEND_FRAME : if (localContentsOffset + 3 >= this.contents.length) { resizeContents(3); } int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame); this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals); this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); this.contents[localContentsOffset++] = (byte) offsetDelta; int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals); int numberOfLocals = currentFrame.getNumberOfLocals(); for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) { if (localContentsOffset + 6 >= this.contents.length) { resizeContents(6); } VerificationTypeInfo info = currentFrame.locals[i]; if (info == null) { this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; } else { switch(info.id()) { case T_boolean : case T_byte : case T_char : case T_int : case T_short : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; break; case T_float : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; break; case T_long : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; i++; break; case T_double : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; i++; break; case T_null : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; break; default: this.contents[localContentsOffset++] = (byte) info.tag; switch (info.tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED : int offset = info.offset; this.contents[localContentsOffset++] = (byte) (offset >> 8); this.contents[localContentsOffset++] = (byte) offset; break; case VerificationTypeInfo.ITEM_OBJECT : int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); this.contents[localContentsOffset++] = (byte) (indexForType >> 8); this.contents[localContentsOffset++] = (byte) indexForType; } } numberOfDifferentLocals--; } } break; case StackMapFrame.SAME_FRAME : if (localContentsOffset + 1 >= this.contents.length) { resizeContents(1); } this.contents[localContentsOffset++] = (byte) offsetDelta; break; case StackMapFrame.SAME_FRAME_EXTENDED : if (localContentsOffset + 3 >= this.contents.length) { resizeContents(3); } this.contents[localContentsOffset++] = (byte) 251; this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); this.contents[localContentsOffset++] = (byte) offsetDelta; break; case StackMapFrame.CHOP_FRAME : if (localContentsOffset + 3 >= this.contents.length) { resizeContents(3); } numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame); this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals); this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); this.contents[localContentsOffset++] = (byte) offsetDelta; break; case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS : if (localContentsOffset + 4 >= this.contents.length) { resizeContents(4); } this.contents[localContentsOffset++] = (byte) (offsetDelta + 64); if (currentFrame.stackItems[0] == null) { this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; } else { switch(currentFrame.stackItems[0].id()) { case T_boolean : case T_byte : case T_char : case T_int : case T_short : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; break; case T_float : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; break; case T_long : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; break; case T_double : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; break; case T_null : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; break; default: VerificationTypeInfo info = currentFrame.stackItems[0]; byte tag = (byte) info.tag; this.contents[localContentsOffset++] = tag; switch (tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED : int offset = info.offset; this.contents[localContentsOffset++] = (byte) (offset >> 8); this.contents[localContentsOffset++] = (byte) offset; break; case VerificationTypeInfo.ITEM_OBJECT : int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); this.contents[localContentsOffset++] = (byte) (indexForType >> 8); this.contents[localContentsOffset++] = (byte) indexForType; } } } break; case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED : if (localContentsOffset + 6 >= this.contents.length) { resizeContents(6); } this.contents[localContentsOffset++] = (byte) 247; this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); this.contents[localContentsOffset++] = (byte) offsetDelta; if (currentFrame.stackItems[0] == null) { this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; } else { switch(currentFrame.stackItems[0].id()) { case T_boolean : case T_byte : case T_char : case T_int : case T_short : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; break; case T_float : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; break; case T_long : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; break; case T_double : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; break; case T_null : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; break; default: VerificationTypeInfo info = currentFrame.stackItems[0]; byte tag = (byte) info.tag; this.contents[localContentsOffset++] = tag; switch (tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED : int offset = info.offset; this.contents[localContentsOffset++] = (byte) (offset >> 8); this.contents[localContentsOffset++] = (byte) offset; break; case VerificationTypeInfo.ITEM_OBJECT : int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); this.contents[localContentsOffset++] = (byte) (indexForType >> 8); this.contents[localContentsOffset++] = (byte) indexForType; } } } break; default : // FULL_FRAME if (localContentsOffset + 5 >= this.contents.length) { resizeContents(5); } this.contents[localContentsOffset++] = (byte) 255; this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); this.contents[localContentsOffset++] = (byte) offsetDelta; int numberOfLocalOffset = localContentsOffset; localContentsOffset += 2; // leave two spots for number of locals int numberOfLocalEntries = 0; numberOfLocals = currentFrame.getNumberOfLocals(); int numberOfEntries = 0; int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length; for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) { if (localContentsOffset + 3 >= this.contents.length) { resizeContents(3); } VerificationTypeInfo info = currentFrame.locals[i]; if (info == null) { this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; } else { switch(info.id()) { case T_boolean : case T_byte : case T_char : case T_int : case T_short : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; break; case T_float : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; break; case T_long : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; i++; break; case T_double : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; i++; break; case T_null : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; break; default: this.contents[localContentsOffset++] = (byte) info.tag; switch (info.tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED : int offset = info.offset; this.contents[localContentsOffset++] = (byte) (offset >> 8); this.contents[localContentsOffset++] = (byte) offset; break; case VerificationTypeInfo.ITEM_OBJECT : int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); this.contents[localContentsOffset++] = (byte) (indexForType >> 8); this.contents[localContentsOffset++] = (byte) indexForType; } } numberOfLocalEntries++; } numberOfEntries++; } if (localContentsOffset + 4 >= this.contents.length) { resizeContents(4); } this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8); this.contents[numberOfLocalOffset] = (byte) numberOfEntries; int numberOfStackItems = currentFrame.numberOfStackItems; this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8); this.contents[localContentsOffset++] = (byte) numberOfStackItems; for (int i = 0; i < numberOfStackItems; i++) { if (localContentsOffset + 3 >= this.contents.length) { resizeContents(3); } VerificationTypeInfo info = currentFrame.stackItems[i]; if (info == null) { this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; } else { switch(info.id()) { case T_boolean : case T_byte : case T_char : case T_int : case T_short : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; break; case T_float : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; break; case T_long : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; break; case T_double : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; break; case T_null : this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; break; default: this.contents[localContentsOffset++] = (byte) info.tag; switch (info.tag) { case VerificationTypeInfo.ITEM_UNINITIALIZED : int offset = info.offset; this.contents[localContentsOffset++] = (byte) (offset >> 8); this.contents[localContentsOffset++] = (byte) offset; break; case VerificationTypeInfo.ITEM_OBJECT : int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); this.contents[localContentsOffset++] = (byte) (indexForType >> 8); this.contents[localContentsOffset++] = (byte) indexForType; } } } } } } numberOfFrames--; if (numberOfFrames != 0) { this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8); this.contents[numberOfFramesOffset] = (byte) numberOfFrames; int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4; this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24); this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength; attributesNumber++; } else { localContentsOffset = stackMapTableAttributeOffset; } } } this.contentsOffset = localContentsOffset; return attributesNumber; } private int generateSyntheticAttribute() { int localContentsOffset = this.contentsOffset; if (localContentsOffset + 6 >= this.contents.length) { resizeContents(6); } int syntheticAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.SyntheticName); this.contents[localContentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) syntheticAttributeNameIndex; // the length of a synthetic attribute is equals to 0 this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contentsOffset = localContentsOffset; return 1; } private int generateVarargsAttribute() { int localContentsOffset = this.contentsOffset; /* * handle of the target jsr14 for varargs in the source * Varargs attribute * Check that there is enough space to write the attribute */ if (localContentsOffset + 6 >= this.contents.length) { resizeContents(6); } int varargsAttributeNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.VarargsName); this.contents[localContentsOffset++] = (byte) (varargsAttributeNameIndex >> 8); this.contents[localContentsOffset++] = (byte) varargsAttributeNameIndex; // the length of a varargs attribute is equals to 0 this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contents[localContentsOffset++] = 0; this.contentsOffset = localContentsOffset; return 1; } /** * EXTERNAL API * Answer the actual bytes of the class file * * This method encodes the receiver structure into a byte array which is the content of the classfile. * Returns the byte array that represents the encoded structure of the receiver. * * @return byte[] */ public byte[] getBytes() { if (this.bytes == null) { this.bytes = new byte[this.headerOffset + this.contentsOffset]; System.arraycopy(this.header, 0, this.bytes, 0, this.headerOffset); System.arraycopy(this.contents, 0, this.bytes, this.headerOffset, this.contentsOffset); } return this.bytes; } /** * EXTERNAL API * Answer the compound name of the class file. * @return char[][] * e.g. {{java}, {util}, {Hashtable}}. */ public char[][] getCompoundName() { return CharOperation.splitOn('/', fileName()); } private int getParametersCount(char[] methodSignature) { int i = CharOperation.indexOf('(', methodSignature); i++; char currentCharacter = methodSignature[i]; if (currentCharacter == ')') { return 0; } int result = 0; while (true) { currentCharacter = methodSignature[i]; if (currentCharacter == ')') { return result; } switch (currentCharacter) { case '[': // array type int scanType = scanType(methodSignature, i + 1); result++; i = scanType + 1; break; case 'L': scanType = CharOperation.indexOf(';', methodSignature, i + 1); result++; i = scanType + 1; break; case 'Z': case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': result++; i++; break; default: throw new IllegalArgumentException("Invalid starting type character : " + currentCharacter); //$NON-NLS-1$ } } } private char[] getReturnType(char[] methodSignature) { // skip type parameters int paren = CharOperation.lastIndexOf(')', methodSignature); // there could be thrown exceptions behind, thus scan one type exactly return CharOperation.subarray(methodSignature, paren + 1, methodSignature.length); } private final int i4At(byte[] reference, int relativeOffset, int structOffset) { int position = relativeOffset + structOffset; return ((reference[position++] & 0xFF) << 24) + ((reference[position++] & 0xFF) << 16) + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF); } protected void initByteArrays() { int members = this.referenceBinding.methods().length + this.referenceBinding.fields().length; this.header = new byte[INITIAL_HEADER_SIZE]; this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE]; } public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boolean createProblemType) { // generate the magic numbers inside the header this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 24); this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 16); this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 8); this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 0); long targetVersion = this.targetJDK; this.header[this.headerOffset++] = (byte) (targetVersion >> 8); // minor high this.header[this.headerOffset++] = (byte) (targetVersion>> 0); // minor low this.header[this.headerOffset++] = (byte) (targetVersion >> 24); // major high this.header[this.headerOffset++] = (byte) (targetVersion >> 16); // major low this.constantPoolOffset = this.headerOffset; this.headerOffset += 2; this.constantPool.initialize(this); // Modifier manipulations for classfile int accessFlags = aType.getAccessFlags(); if (aType.isPrivate()) { // rewrite private to non-public accessFlags &= ~ClassFileConstants.AccPublic; } if (aType.isProtected()) { // rewrite protected into public accessFlags |= ClassFileConstants.AccPublic; } // clear all bits that are illegal for a class or an interface accessFlags &= ~( ClassFileConstants.AccStrictfp | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative); // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value) if (!aType.isInterface()) { // class or enum accessFlags |= ClassFileConstants.AccSuper; } if (aType.isAnonymousType()) { accessFlags &= ~ClassFileConstants.AccFinal; } int finalAbstract = ClassFileConstants.AccFinal | ClassFileConstants.AccAbstract; if ((accessFlags & finalAbstract) == finalAbstract) { accessFlags &= ~finalAbstract; } this.enclosingClassFile = parentClassFile; // innerclasses get their names computed at code gen time // now we continue to generate the bytes inside the contents array this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); this.contents[this.contentsOffset++] = (byte) accessFlags; int classNameIndex = this.constantPool.literalIndexForType(aType); this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) classNameIndex; int superclassNameIndex; if (aType.isInterface()) { superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); } else { if (aType.superclass != null) { if ((aType.superclass.tagBits & TagBits.HasMissingType) != 0) { superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); } else { superclassNameIndex = this.constantPool.literalIndexForType(aType.superclass); } } else { superclassNameIndex = 0; } } this.contents[this.contentsOffset++] = (byte) (superclassNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) superclassNameIndex; ReferenceBinding[] superInterfacesBinding = aType.superInterfaces(); int interfacesCount = superInterfacesBinding.length; int interfacesCountPosition = this.contentsOffset; this.contentsOffset += 2; int interfaceCounter = 0; for (int i = 0; i < interfacesCount; i++) { ReferenceBinding binding = superInterfacesBinding[i]; if ((binding.tagBits & TagBits.HasMissingType) != 0) { continue; } interfaceCounter++; int interfaceIndex = this.constantPool.literalIndexForType(binding); this.contents[this.contentsOffset++] = (byte) (interfaceIndex >> 8); this.contents[this.contentsOffset++] = (byte) interfaceIndex; } this.contents[interfacesCountPosition++] = (byte) (interfaceCounter >> 8); this.contents[interfacesCountPosition] = (byte) interfaceCounter; this.creatingProblemType = createProblemType; // retrieve the enclosing one guaranteed to be the one matching the propagated flow info // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check) this.codeStream.maxFieldCount = aType.scope.outerMostClassScope().referenceType().maxFieldCount; } private void initializeDefaultLocals(StackMapFrame frame, MethodBinding methodBinding, int maxLocals, int codeLength) { if (maxLocals != 0) { int resolvedPosition = 0; // take into account enum constructor synthetic name+ordinal final boolean isConstructor = methodBinding.isConstructor(); if (isConstructor || !methodBinding.isStatic()) { LocalVariableBinding localVariableBinding = new LocalVariableBinding(ConstantPool.This, methodBinding.declaringClass, 0, false); localVariableBinding.resolvedPosition = 0; this.codeStream.record(localVariableBinding); localVariableBinding.recordInitializationStartPC(0); localVariableBinding.recordInitializationEndPC(codeLength); frame.putLocal(resolvedPosition, new VerificationTypeInfo( isConstructor ? VerificationTypeInfo.ITEM_UNINITIALIZED_THIS : VerificationTypeInfo.ITEM_OBJECT, methodBinding.declaringClass)); resolvedPosition++; } if (isConstructor) { if (methodBinding.declaringClass.isEnum()) { LocalVariableBinding localVariableBinding = new LocalVariableBinding(" name".toCharArray(), this.referenceBinding.scope.getJavaLangString(), 0, false); //$NON-NLS-1$ localVariableBinding.resolvedPosition = resolvedPosition; this.codeStream.record(localVariableBinding); localVariableBinding.recordInitializationStartPC(0); localVariableBinding.recordInitializationEndPC(codeLength); frame.putLocal(resolvedPosition, new VerificationTypeInfo( TypeIds.T_JavaLangString, ConstantPool.JavaLangStringConstantPoolName)); resolvedPosition++; localVariableBinding = new LocalVariableBinding(" ordinal".toCharArray(), TypeBinding.INT, 0, false); //$NON-NLS-1$ localVariableBinding.resolvedPosition = resolvedPosition; this.codeStream.record(localVariableBinding); localVariableBinding.recordInitializationStartPC(0); localVariableBinding.recordInitializationEndPC(codeLength); frame.putLocal(resolvedPosition, new VerificationTypeInfo( TypeBinding.INT)); resolvedPosition++; } // take into account the synthetic parameters if (methodBinding.declaringClass.isNestedType()) { ReferenceBinding enclosingInstanceTypes[]; if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) { for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) { // an enclosingInstanceType can only be a reference // binding. It cannot be // LongBinding or DoubleBinding LocalVariableBinding localVariableBinding = new LocalVariableBinding((" enclosingType" + i).toCharArray(), enclosingInstanceTypes[i], 0, false); //$NON-NLS-1$ localVariableBinding.resolvedPosition = resolvedPosition; this.codeStream.record(localVariableBinding); localVariableBinding.recordInitializationStartPC(0); localVariableBinding.recordInitializationEndPC(codeLength); frame.putLocal(resolvedPosition, new VerificationTypeInfo(enclosingInstanceTypes[i])); resolvedPosition++; } } TypeBinding[] arguments; if ((arguments = methodBinding.parameters) != null) { for (int i = 0, max = arguments.length; i < max; i++) { final TypeBinding typeBinding = arguments[i]; frame.putLocal(resolvedPosition, new VerificationTypeInfo(typeBinding)); switch (typeBinding.id) { case TypeIds.T_double: case TypeIds.T_long: resolvedPosition += 2; break; default: resolvedPosition++; } } } SyntheticArgumentBinding syntheticArguments[]; if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) { for (int i = 0, max = syntheticArguments.length; i < max; i++) { final TypeBinding typeBinding = syntheticArguments[i].type; LocalVariableBinding localVariableBinding = new LocalVariableBinding((" synthetic" + i).toCharArray(), typeBinding, 0, false); //$NON-NLS-1$ localVariableBinding.resolvedPosition = resolvedPosition; this.codeStream.record(localVariableBinding); localVariableBinding.recordInitializationStartPC(0); localVariableBinding.recordInitializationEndPC(codeLength); frame.putLocal(resolvedPosition, new VerificationTypeInfo(typeBinding)); switch (typeBinding.id) { case TypeIds.T_double: case TypeIds.T_long: resolvedPosition += 2; break; default: resolvedPosition++; } } } } else { TypeBinding[] arguments; if ((arguments = methodBinding.parameters) != null) { for (int i = 0, max = arguments.length; i < max; i++) { final TypeBinding typeBinding = arguments[i]; frame.putLocal(resolvedPosition, new VerificationTypeInfo(typeBinding)); switch (typeBinding.id) { case TypeIds.T_double: case TypeIds.T_long: resolvedPosition += 2; break; default: resolvedPosition++; } } } } } else { TypeBinding[] arguments; if ((arguments = methodBinding.parameters) != null) { for (int i = 0, max = arguments.length; i < max; i++) { final TypeBinding typeBinding = arguments[i]; frame.putLocal(resolvedPosition, new VerificationTypeInfo(typeBinding)); switch (typeBinding.id) { case TypeIds.T_double: case TypeIds.T_long: resolvedPosition += 2; break; default: resolvedPosition++; } } } } } } private void initializeLocals(boolean isStatic, int currentPC, StackMapFrame currentFrame) { VerificationTypeInfo[] locals = currentFrame.locals; int localsLength = locals.length; int i = 0; if (!isStatic) { // we don't want to reset the first local if the method is not static i = 1; } for (; i < localsLength; i++) { locals[i] = null; } i = 0; locals: for (int max = this.codeStream.allLocalsCounter; i < max; i++) { LocalVariableBinding localVariable = this.codeStream.locals[i]; if (localVariable == null) continue; int resolvedPosition = localVariable.resolvedPosition; final TypeBinding localVariableTypeBinding = localVariable.type; inits: for (int j = 0; j < localVariable.initializationCount; j++) { int startPC = localVariable.initializationPCs[j << 1]; int endPC = localVariable.initializationPCs[(j << 1) + 1]; if (currentPC < startPC) { continue inits; } else if (currentPC < endPC) { // the current local is an active local if (currentFrame.locals[resolvedPosition] == null) { currentFrame.locals[resolvedPosition] = new VerificationTypeInfo( localVariableTypeBinding); } continue locals; } } } } /** * INTERNAL USE-ONLY * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name * for all inner types of the receiver. * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile */ public ClassFile outerMostEnclosingClassFile() { ClassFile current = this; while (current.enclosingClassFile != null) current = current.enclosingClassFile; return current; } public void recordInnerClasses(TypeBinding binding) { if (this.innerClassesBindings == null) { this.innerClassesBindings = new HashSet(INNER_CLASSES_SIZE); } ReferenceBinding innerClass = (ReferenceBinding) binding; this.innerClassesBindings.add(innerClass.erasure()); ReferenceBinding enclosingType = innerClass.enclosingType(); while (enclosingType != null && enclosingType.isNestedType()) { this.innerClassesBindings.add(enclosingType.erasure()); enclosingType = enclosingType.enclosingType(); } } public void reset(SourceTypeBinding typeBinding) { // the code stream is reinitialized for each method final CompilerOptions options = typeBinding.scope.compilerOptions(); this.referenceBinding = typeBinding; this.isNestedType = typeBinding.isNestedType(); this.targetJDK = options.targetJDK; this.produceAttributes = options.produceDebugAttributes; if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) { this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3 this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP; } this.bytes = null; this.constantPool.reset(); this.codeStream.reset(this); this.constantPoolOffset = 0; this.contentsOffset = 0; this.creatingProblemType = false; this.enclosingClassFile = null; this.headerOffset = 0; this.methodCount = 0; this.methodCountOffset = 0; if (this.innerClassesBindings != null) { this.innerClassesBindings.clear(); } this.missingTypes = null; this.visitedTypes = null; } /** * Resize the pool contents */ private final void resizeContents(int minimalSize) { int length = this.contents.length; int toAdd = length; if (toAdd < minimalSize) toAdd = minimalSize; System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length); } private VerificationTypeInfo retrieveLocal(int currentPC, int resolvedPosition) { for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { LocalVariableBinding localVariable = this.codeStream.locals[i]; if (localVariable == null) continue; if (resolvedPosition == localVariable.resolvedPosition) { inits: for (int j = 0; j < localVariable.initializationCount; j++) { int startPC = localVariable.initializationPCs[j << 1]; int endPC = localVariable.initializationPCs[(j << 1) + 1]; if (currentPC < startPC) { continue inits; } else if (currentPC < endPC) { // the current local is an active local return new VerificationTypeInfo(localVariable.type); } } } } return null; } private int scanType(char[] methodSignature, int index) { switch (methodSignature[index]) { case '[': // array type return scanType(methodSignature, index + 1); case 'L': return CharOperation.indexOf(';', methodSignature, index + 1); case 'Z': case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': return index; default: throw new IllegalArgumentException(); } } /** * INTERNAL USE-ONLY * This methods leaves the space for method counts recording. */ public void setForMethodInfos() { // leave some space for the methodCount this.methodCountOffset = this.contentsOffset; this.contentsOffset += 2; } private List filterFakeFrames(Set realJumpTargets, Map frames, int codeLength) { // no more frame to generate // filter out "fake" frames realJumpTargets.remove(new Integer(codeLength)); List result = new ArrayList(); for (Iterator iterator = realJumpTargets.iterator(); iterator.hasNext(); ) { Integer jumpTarget = (Integer) iterator.next(); StackMapFrame frame = (StackMapFrame) frames.get(jumpTarget); if (frame != null) { result.add(frame); } } Collections.sort(result, new Comparator() { public int compare(Object o1, Object o2) { StackMapFrame frame = (StackMapFrame) o1; StackMapFrame frame2 = (StackMapFrame) o2; return frame.pc - frame2.pc; } }); return result; } public List traverse(MethodBinding methodBinding, int maxLocals, byte[] bytecodes, int codeOffset, int codeLength, Map frames, boolean isClinit) { Set realJumpTarget = new HashSet(); StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; int[] framePositions = stackMapFrameCodeStream.getFramePositions(); int pc = codeOffset; int index; int[] constantPoolOffsets = this.constantPool.offsets; byte[] poolContents = this.constantPool.poolContent; // set initial values for frame positions int indexInFramePositions = 0; int framePositionsLength = framePositions.length; int currentFramePosition = framePositions[0]; // set initial values for stack depth markers int indexInStackDepthMarkers = 0; StackDepthMarker[] stackDepthMarkers = stackMapFrameCodeStream.getStackDepthMarkers(); int stackDepthMarkersLength = stackDepthMarkers == null ? 0 : stackDepthMarkers.length; boolean hasStackDepthMarkers = stackDepthMarkersLength != 0; StackDepthMarker stackDepthMarker = null; if (hasStackDepthMarkers) { stackDepthMarker = stackDepthMarkers[0]; } // set initial values for stack markers (used only in cldc mode) int indexInStackMarkers = 0; StackMarker[] stackMarkers = stackMapFrameCodeStream.getStackMarkers(); int stackMarkersLength = stackMarkers == null ? 0 : stackMarkers.length; boolean hasStackMarkers = stackMarkersLength != 0; StackMarker stackMarker = null; if (hasStackMarkers) { stackMarker = stackMarkers[0]; } // set initial values for exception markers int indexInExceptionMarkers = 0; ExceptionMarker[] exceptionMarkers= stackMapFrameCodeStream.getExceptionMarkers(); int exceptionsMarkersLength = exceptionMarkers == null ? 0 : exceptionMarkers.length; boolean hasExceptionMarkers = exceptionsMarkersLength != 0; ExceptionMarker exceptionMarker = null; if (hasExceptionMarkers) { exceptionMarker = exceptionMarkers[0]; } StackMapFrame frame = new StackMapFrame(maxLocals); if (!isClinit) { initializeDefaultLocals(frame, methodBinding, maxLocals, codeLength); } frame.pc = -1; add(frames, frame.duplicate()); addRealJumpTarget(realJumpTarget, -1); for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { ExceptionLabel exceptionLabel = this.codeStream.exceptionLabels[i]; if (exceptionLabel != null) { addRealJumpTarget(realJumpTarget, exceptionLabel.position); } } while (true) { int currentPC = pc - codeOffset; if (hasStackMarkers && stackMarker.pc == currentPC) { VerificationTypeInfo[] infos = frame.stackItems; VerificationTypeInfo[] tempInfos = new VerificationTypeInfo[frame.numberOfStackItems]; System.arraycopy(infos, 0, tempInfos, 0, frame.numberOfStackItems); stackMarker.setInfos(tempInfos); } else if (hasStackMarkers && stackMarker.destinationPC == currentPC) { VerificationTypeInfo[] infos = stackMarker.infos; frame.stackItems = infos; frame.numberOfStackItems = infos.length; indexInStackMarkers++; if (indexInStackMarkers < stackMarkersLength) { stackMarker = stackMarkers[indexInStackMarkers]; } else { hasStackMarkers = false; } } if (hasStackDepthMarkers && stackDepthMarker.pc == currentPC) { TypeBinding typeBinding = stackDepthMarker.typeBinding; if (typeBinding != null) { if (stackDepthMarker.delta > 0) { frame.addStackItem(new VerificationTypeInfo(typeBinding)); } else { frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(typeBinding); } } else { frame.numberOfStackItems--; } indexInStackDepthMarkers++; if (indexInStackDepthMarkers < stackDepthMarkersLength) { stackDepthMarker = stackDepthMarkers[indexInStackDepthMarkers]; } else { hasStackDepthMarkers = false; } } if (hasExceptionMarkers && exceptionMarker.pc == currentPC) { frame.numberOfStackItems = 0; frame.addStackItem(new VerificationTypeInfo(0, VerificationTypeInfo.ITEM_OBJECT, exceptionMarker.constantPoolName)); indexInExceptionMarkers++; if (indexInExceptionMarkers < exceptionsMarkersLength) { exceptionMarker = exceptionMarkers[indexInExceptionMarkers]; } else { hasExceptionMarkers = false; } } if (currentFramePosition < currentPC) { do { indexInFramePositions++; if (indexInFramePositions < framePositionsLength) { currentFramePosition = framePositions[indexInFramePositions]; } else { currentFramePosition = Integer.MAX_VALUE; } } while (currentFramePosition < currentPC); } if (currentFramePosition == currentPC) { // need to build a new frame and create a stack map attribute entry StackMapFrame currentFrame = frame.duplicate(); currentFrame.pc = currentPC; // initialize locals initializeLocals(isClinit ? true : methodBinding.isStatic(), currentPC, currentFrame); // insert a new frame add(frames, currentFrame); indexInFramePositions++; if (indexInFramePositions < framePositionsLength) { currentFramePosition = framePositions[indexInFramePositions]; } else { currentFramePosition = Integer.MAX_VALUE; } } byte opcode = (byte) u1At(bytecodes, 0, pc); switch (opcode) { case Opcodes.OPC_nop: pc++; break; case Opcodes.OPC_aconst_null: frame.addStackItem(TypeBinding.NULL); pc++; break; case Opcodes.OPC_iconst_m1: case Opcodes.OPC_iconst_0: case Opcodes.OPC_iconst_1: case Opcodes.OPC_iconst_2: case Opcodes.OPC_iconst_3: case Opcodes.OPC_iconst_4: case Opcodes.OPC_iconst_5: frame.addStackItem(TypeBinding.INT); pc++; break; case Opcodes.OPC_lconst_0: case Opcodes.OPC_lconst_1: frame.addStackItem(TypeBinding.LONG); pc++; break; case Opcodes.OPC_fconst_0: case Opcodes.OPC_fconst_1: case Opcodes.OPC_fconst_2: frame.addStackItem(TypeBinding.FLOAT); pc++; break; case Opcodes.OPC_dconst_0: case Opcodes.OPC_dconst_1: frame.addStackItem(TypeBinding.DOUBLE); pc++; break; case Opcodes.OPC_bipush: frame.addStackItem(TypeBinding.BYTE); pc += 2; break; case Opcodes.OPC_sipush: frame.addStackItem(TypeBinding.SHORT); pc += 3; break; case Opcodes.OPC_ldc: index = u1At(bytecodes, 1, pc); switch (u1At(poolContents, 0, constantPoolOffsets[index])) { case ClassFileConstants.StringTag: frame .addStackItem(new VerificationTypeInfo( TypeIds.T_JavaLangString, ConstantPool.JavaLangStringConstantPoolName)); break; case ClassFileConstants.IntegerTag: frame.addStackItem(TypeBinding.INT); break; case ClassFileConstants.FloatTag: frame.addStackItem(TypeBinding.FLOAT); break; case ClassFileConstants.ClassTag: frame.addStackItem(new VerificationTypeInfo( TypeIds.T_JavaLangClass, ConstantPool.JavaLangClassConstantPoolName)); } pc += 2; break; case Opcodes.OPC_ldc_w: index = u2At(bytecodes, 1, pc); switch (u1At(poolContents, 0, constantPoolOffsets[index])) { case ClassFileConstants.StringTag: frame .addStackItem(new VerificationTypeInfo( TypeIds.T_JavaLangString, ConstantPool.JavaLangStringConstantPoolName)); break; case ClassFileConstants.IntegerTag: frame.addStackItem(TypeBinding.INT); break; case ClassFileConstants.FloatTag: frame.addStackItem(TypeBinding.FLOAT); break; case ClassFileConstants.ClassTag: frame.addStackItem(new VerificationTypeInfo( TypeIds.T_JavaLangClass, ConstantPool.JavaLangClassConstantPoolName)); } pc += 3; break; case Opcodes.OPC_ldc2_w: index = u2At(bytecodes, 1, pc); switch (u1At(poolContents, 0, constantPoolOffsets[index])) { case ClassFileConstants.DoubleTag: frame.addStackItem(TypeBinding.DOUBLE); break; case ClassFileConstants.LongTag: frame.addStackItem(TypeBinding.LONG); break; } pc += 3; break; case Opcodes.OPC_iload: frame.addStackItem(TypeBinding.INT); pc += 2; break; case Opcodes.OPC_lload: frame.addStackItem(TypeBinding.LONG); pc += 2; break; case Opcodes.OPC_fload: frame.addStackItem(TypeBinding.FLOAT); pc += 2; break; case Opcodes.OPC_dload: frame.addStackItem(TypeBinding.DOUBLE); pc += 2; break; case Opcodes.OPC_aload: index = u1At(bytecodes, 1, pc); VerificationTypeInfo localsN = retrieveLocal(currentPC, index); frame.addStackItem(localsN); pc += 2; break; case Opcodes.OPC_iload_0: case Opcodes.OPC_iload_1: case Opcodes.OPC_iload_2: case Opcodes.OPC_iload_3: frame.addStackItem(TypeBinding.INT); pc++; break; case Opcodes.OPC_lload_0: case Opcodes.OPC_lload_1: case Opcodes.OPC_lload_2: case Opcodes.OPC_lload_3: frame.addStackItem(TypeBinding.LONG); pc++; break; case Opcodes.OPC_fload_0: case Opcodes.OPC_fload_1: case Opcodes.OPC_fload_2: case Opcodes.OPC_fload_3: frame.addStackItem(TypeBinding.FLOAT); pc++; break; case Opcodes.OPC_dload_0: case Opcodes.OPC_dload_1: case Opcodes.OPC_dload_2: case Opcodes.OPC_dload_3: frame.addStackItem(TypeBinding.DOUBLE); pc++; break; case Opcodes.OPC_aload_0: VerificationTypeInfo locals0 = frame.locals[0]; if (locals0 == null || locals0.tag != VerificationTypeInfo.ITEM_UNINITIALIZED_THIS) { // special case to handle uninitialized object locals0 = retrieveLocal(currentPC, 0); } frame.addStackItem(locals0); pc++; break; case Opcodes.OPC_aload_1: VerificationTypeInfo locals1 = retrieveLocal(currentPC, 1); frame.addStackItem(locals1); pc++; break; case Opcodes.OPC_aload_2: VerificationTypeInfo locals2 = retrieveLocal(currentPC, 2); frame.addStackItem(locals2); pc++; break; case Opcodes.OPC_aload_3: VerificationTypeInfo locals3 = retrieveLocal(currentPC, 3); frame.addStackItem(locals3); pc++; break; case Opcodes.OPC_iaload: frame.numberOfStackItems -=2; frame.addStackItem(TypeBinding.INT); pc++; break; case Opcodes.OPC_laload: frame.numberOfStackItems -=2; frame.addStackItem(TypeBinding.LONG); pc++; break; case Opcodes.OPC_faload: frame.numberOfStackItems -=2; frame.addStackItem(TypeBinding.FLOAT); pc++; break; case Opcodes.OPC_daload: frame.numberOfStackItems -=2; frame.addStackItem(TypeBinding.DOUBLE); pc++; break; case Opcodes.OPC_aaload: frame.numberOfStackItems--; frame.replaceWithElementType(); pc++; break; case Opcodes.OPC_baload: frame.numberOfStackItems -=2; frame.addStackItem(TypeBinding.BYTE); pc++; break; case Opcodes.OPC_caload: frame.numberOfStackItems -=2; frame.addStackItem(TypeBinding.CHAR); pc++; break; case Opcodes.OPC_saload: frame.numberOfStackItems -=2; frame.addStackItem(TypeBinding.SHORT); pc++; break; case Opcodes.OPC_istore: case Opcodes.OPC_lstore: case Opcodes.OPC_fstore: case Opcodes.OPC_dstore: frame.numberOfStackItems--; pc += 2; break; case Opcodes.OPC_astore: index = u1At(bytecodes, 1, pc); frame.numberOfStackItems--; pc += 2; break; case Opcodes.OPC_astore_0: frame.locals[0] = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; pc++; break; case Opcodes.OPC_astore_1: case Opcodes.OPC_astore_2: case Opcodes.OPC_astore_3: case Opcodes.OPC_istore_0: case Opcodes.OPC_istore_1: case Opcodes.OPC_istore_2: case Opcodes.OPC_istore_3: case Opcodes.OPC_lstore_0: case Opcodes.OPC_lstore_1: case Opcodes.OPC_lstore_2: case Opcodes.OPC_lstore_3: case Opcodes.OPC_fstore_0: case Opcodes.OPC_fstore_1: case Opcodes.OPC_fstore_2: case Opcodes.OPC_fstore_3: case Opcodes.OPC_dstore_0: case Opcodes.OPC_dstore_1: case Opcodes.OPC_dstore_2: case Opcodes.OPC_dstore_3: frame.numberOfStackItems--; pc++; break; case Opcodes.OPC_iastore: case Opcodes.OPC_lastore: case Opcodes.OPC_fastore: case Opcodes.OPC_dastore: case Opcodes.OPC_aastore: case Opcodes.OPC_bastore: case Opcodes.OPC_castore: case Opcodes.OPC_sastore: frame.numberOfStackItems-=3; pc++; break; case Opcodes.OPC_pop: frame.numberOfStackItems--; pc++; break; case Opcodes.OPC_pop2: int numberOfStackItems = frame.numberOfStackItems; switch(frame.stackItems[numberOfStackItems - 1].id()) { case TypeIds.T_long : case TypeIds.T_double : frame.numberOfStackItems--; break; default: frame.numberOfStackItems -= 2; } pc++; break; case Opcodes.OPC_dup: frame.addStackItem(frame.stackItems[frame.numberOfStackItems - 1]); pc++; break; case Opcodes.OPC_dup_x1: VerificationTypeInfo info = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; VerificationTypeInfo info2 = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; frame.addStackItem(info); frame.addStackItem(info2); frame.addStackItem(info); pc++; break; case Opcodes.OPC_dup_x2: info = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; info2 = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; switch(info2.id()) { case TypeIds.T_long : case TypeIds.T_double : frame.addStackItem(info); frame.addStackItem(info2); frame.addStackItem(info); break; default: numberOfStackItems = frame.numberOfStackItems; VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1]; frame.numberOfStackItems--; frame.addStackItem(info); frame.addStackItem(info3); frame.addStackItem(info2); frame.addStackItem(info); } pc++; break; case Opcodes.OPC_dup2: info = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; switch(info.id()) { case TypeIds.T_double : case TypeIds.T_long : frame.addStackItem(info); frame.addStackItem(info); break; default: info2 = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; frame.addStackItem(info2); frame.addStackItem(info); frame.addStackItem(info2); frame.addStackItem(info); } pc++; break; case Opcodes.OPC_dup2_x1: info = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; info2 = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; switch(info.id()) { case TypeIds.T_double : case TypeIds.T_long : frame.addStackItem(info); frame.addStackItem(info2); frame.addStackItem(info); break; default: VerificationTypeInfo info3 = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; frame.addStackItem(info2); frame.addStackItem(info); frame.addStackItem(info3); frame.addStackItem(info2); frame.addStackItem(info); } pc++; break; case Opcodes.OPC_dup2_x2: numberOfStackItems = frame.numberOfStackItems; info = frame.stackItems[numberOfStackItems - 1]; frame.numberOfStackItems--; info2 = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; switch(info.id()) { case TypeIds.T_long : case TypeIds.T_double : switch(info2.id()) { case TypeIds.T_long : case TypeIds.T_double : // form 4 frame.addStackItem(info); frame.addStackItem(info2); frame.addStackItem(info); break; default: // form 2 numberOfStackItems = frame.numberOfStackItems; VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1]; frame.numberOfStackItems--; frame.addStackItem(info); frame.addStackItem(info3); frame.addStackItem(info2); frame.addStackItem(info); } break; default: numberOfStackItems = frame.numberOfStackItems; VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1]; frame.numberOfStackItems--; switch(info3.id()) { case TypeIds.T_long : case TypeIds.T_double : // form 3 frame.addStackItem(info2); frame.addStackItem(info); frame.addStackItem(info3); frame.addStackItem(info2); frame.addStackItem(info); break; default: // form 1 numberOfStackItems = frame.numberOfStackItems; VerificationTypeInfo info4 = frame.stackItems[numberOfStackItems - 1]; frame.numberOfStackItems--; frame.addStackItem(info2); frame.addStackItem(info); frame.addStackItem(info4); frame.addStackItem(info3); frame.addStackItem(info2); frame.addStackItem(info); } } pc++; break; case Opcodes.OPC_swap: numberOfStackItems = frame.numberOfStackItems; info = frame.stackItems[numberOfStackItems - 1]; info2 = frame.stackItems[numberOfStackItems - 2]; frame.stackItems[numberOfStackItems - 1] = info2; frame.stackItems[numberOfStackItems - 2] = info; pc++; break; case Opcodes.OPC_iadd: case Opcodes.OPC_ladd: case Opcodes.OPC_fadd: case Opcodes.OPC_dadd: case Opcodes.OPC_isub: case Opcodes.OPC_lsub: case Opcodes.OPC_fsub: case Opcodes.OPC_dsub: case Opcodes.OPC_imul: case Opcodes.OPC_lmul: case Opcodes.OPC_fmul: case Opcodes.OPC_dmul: case Opcodes.OPC_idiv: case Opcodes.OPC_ldiv: case Opcodes.OPC_fdiv: case Opcodes.OPC_ddiv: case Opcodes.OPC_irem: case Opcodes.OPC_lrem: case Opcodes.OPC_frem: case Opcodes.OPC_drem: case Opcodes.OPC_ishl: case Opcodes.OPC_lshl: case Opcodes.OPC_ishr: case Opcodes.OPC_lshr: case Opcodes.OPC_iushr: case Opcodes.OPC_lushr: case Opcodes.OPC_iand: case Opcodes.OPC_land: case Opcodes.OPC_ior: case Opcodes.OPC_lor: case Opcodes.OPC_ixor: case Opcodes.OPC_lxor: frame.numberOfStackItems--; pc++; break; case Opcodes.OPC_ineg: case Opcodes.OPC_lneg: case Opcodes.OPC_fneg: case Opcodes.OPC_dneg: pc++; break; case Opcodes.OPC_iinc: pc += 3; break; case Opcodes.OPC_i2l: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG); pc++; break; case Opcodes.OPC_i2f: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT); pc++; break; case Opcodes.OPC_i2d: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE); pc++; break; case Opcodes.OPC_l2i: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); pc++; break; case Opcodes.OPC_l2f: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT); pc++; break; case Opcodes.OPC_l2d: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE); pc++; break; case Opcodes.OPC_f2i: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); pc++; break; case Opcodes.OPC_f2l: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG); pc++; break; case Opcodes.OPC_f2d: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE); pc++; break; case Opcodes.OPC_d2i: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); pc++; break; case Opcodes.OPC_d2l: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG); pc++; break; case Opcodes.OPC_d2f: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT); pc++; break; case Opcodes.OPC_i2b: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.BYTE); pc++; break; case Opcodes.OPC_i2c: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.CHAR); pc++; break; case Opcodes.OPC_i2s: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.SHORT); pc++; break; case Opcodes.OPC_lcmp: case Opcodes.OPC_fcmpl: case Opcodes.OPC_fcmpg: case Opcodes.OPC_dcmpl: case Opcodes.OPC_dcmpg: frame.numberOfStackItems-=2; frame.addStackItem(TypeBinding.INT); pc++; break; case Opcodes.OPC_ifeq: case Opcodes.OPC_ifne: case Opcodes.OPC_iflt: case Opcodes.OPC_ifge: case Opcodes.OPC_ifgt: case Opcodes.OPC_ifle: frame.numberOfStackItems--; addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); pc += 3; break; case Opcodes.OPC_if_icmpeq: case Opcodes.OPC_if_icmpne: case Opcodes.OPC_if_icmplt: case Opcodes.OPC_if_icmpge: case Opcodes.OPC_if_icmpgt: case Opcodes.OPC_if_icmple: case Opcodes.OPC_if_acmpeq: case Opcodes.OPC_if_acmpne: frame.numberOfStackItems -= 2; addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); pc += 3; break; case Opcodes.OPC_goto: addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); pc += 3; addRealJumpTarget(realJumpTarget, pc - codeOffset); break; case Opcodes.OPC_tableswitch: pc++; while (((pc - codeOffset) & 0x03) != 0) { pc++; } // default offset addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); pc += 4; // default int low = i4At(bytecodes, 0, pc); pc += 4; int high = i4At(bytecodes, 0, pc); pc += 4; int length = high - low + 1; for (int i = 0; i < length; i++) { // pair offset addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); pc += 4; } frame.numberOfStackItems--; break; case Opcodes.OPC_lookupswitch: pc++; while (((pc - codeOffset) & 0x03) != 0) { pc++; } addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); pc += 4; // default offset int npairs = (int) u4At(bytecodes, 0, pc); pc += 4; // npair value for (int i = 0; i < npairs; i++) { pc += 4; // case value // pair offset addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); pc += 4; } frame.numberOfStackItems--; break; case Opcodes.OPC_ireturn: case Opcodes.OPC_lreturn: case Opcodes.OPC_freturn: case Opcodes.OPC_dreturn: case Opcodes.OPC_areturn: frame.numberOfStackItems--; pc++; addRealJumpTarget(realJumpTarget, pc - codeOffset); break; case Opcodes.OPC_return: pc++; addRealJumpTarget(realJumpTarget, pc - codeOffset); break; case Opcodes.OPC_getstatic: index = u2At(bytecodes, 1, pc); int nameAndTypeIndex = u2At(poolContents, 3, constantPoolOffsets[index]); int utf8index = u2At(poolContents, 3, constantPoolOffsets[nameAndTypeIndex]); char[] descriptor = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); if (descriptor.length == 1) { // base type switch(descriptor[0]) { case 'Z': frame.addStackItem(TypeBinding.BOOLEAN); break; case 'B': frame.addStackItem(TypeBinding.BYTE); break; case 'C': frame.addStackItem(TypeBinding.CHAR); break; case 'D': frame.addStackItem(TypeBinding.DOUBLE); break; case 'F': frame.addStackItem(TypeBinding.FLOAT); break; case 'I': frame.addStackItem(TypeBinding.INT); break; case 'J': frame.addStackItem(TypeBinding.LONG); break; case 'S': frame.addStackItem(TypeBinding.SHORT); break; } } else if (descriptor[0] == '[') { frame.addStackItem(new VerificationTypeInfo(0, descriptor)); } else { frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(descriptor, 1, descriptor.length - 1))); } pc += 3; break; case Opcodes.OPC_putstatic: frame.numberOfStackItems--; pc += 3; break; case Opcodes.OPC_getfield: index = u2At(bytecodes, 1, pc); nameAndTypeIndex = u2At(poolContents, 3, constantPoolOffsets[index]); utf8index = u2At(poolContents, 3, constantPoolOffsets[nameAndTypeIndex]); descriptor = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); frame.numberOfStackItems--; if (descriptor.length == 1) { // base type switch(descriptor[0]) { case 'Z': frame.addStackItem(TypeBinding.BOOLEAN); break; case 'B': frame.addStackItem(TypeBinding.BYTE); break; case 'C': frame.addStackItem(TypeBinding.CHAR); break; case 'D': frame.addStackItem(TypeBinding.DOUBLE); break; case 'F': frame.addStackItem(TypeBinding.FLOAT); break; case 'I': frame.addStackItem(TypeBinding.INT); break; case 'J': frame.addStackItem(TypeBinding.LONG); break; case 'S': frame.addStackItem(TypeBinding.SHORT); break; } } else if (descriptor[0] == '[') { frame.addStackItem(new VerificationTypeInfo(0, descriptor)); } else { frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(descriptor, 1, descriptor.length - 1))); } pc += 3; break; case Opcodes.OPC_putfield: frame.numberOfStackItems -= 2; pc += 3; break; case Opcodes.OPC_invokevirtual: index = u2At(bytecodes, 1, pc); nameAndTypeIndex = u2At(poolContents, 3, constantPoolOffsets[index]); utf8index = u2At(poolContents, 3, constantPoolOffsets[nameAndTypeIndex]); descriptor = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); utf8index = u2At(poolContents, 1, constantPoolOffsets[nameAndTypeIndex]); char[] name = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); frame.numberOfStackItems -= (getParametersCount(descriptor) + 1); char[] returnType = getReturnType(descriptor); if (returnType.length == 1) { // base type switch(returnType[0]) { case 'Z': frame.addStackItem(TypeBinding.BOOLEAN); break; case 'B': frame.addStackItem(TypeBinding.BYTE); break; case 'C': frame.addStackItem(TypeBinding.CHAR); break; case 'D': frame.addStackItem(TypeBinding.DOUBLE); break; case 'F': frame.addStackItem(TypeBinding.FLOAT); break; case 'I': frame.addStackItem(TypeBinding.INT); break; case 'J': frame.addStackItem(TypeBinding.LONG); break; case 'S': frame.addStackItem(TypeBinding.SHORT); break; } } else { if (returnType[0] == '[') { frame.addStackItem(new VerificationTypeInfo(0, returnType)); } else { frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); } } pc += 3; break; case Opcodes.OPC_invokespecial: index = u2At(bytecodes, 1, pc); nameAndTypeIndex = u2At(poolContents, 3, constantPoolOffsets[index]); utf8index = u2At(poolContents, 3, constantPoolOffsets[nameAndTypeIndex]); descriptor = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); utf8index = u2At(poolContents, 1, constantPoolOffsets[nameAndTypeIndex]); name = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); frame.numberOfStackItems -= getParametersCount(descriptor); if (CharOperation.equals(ConstantPool.Init, name)) { // constructor frame.stackItems[frame.numberOfStackItems - 1].tag = VerificationTypeInfo.ITEM_OBJECT; } frame.numberOfStackItems--; returnType = getReturnType(descriptor); if (returnType.length == 1) { // base type switch(returnType[0]) { case 'Z': frame.addStackItem(TypeBinding.BOOLEAN); break; case 'B': frame.addStackItem(TypeBinding.BYTE); break; case 'C': frame.addStackItem(TypeBinding.CHAR); break; case 'D': frame.addStackItem(TypeBinding.DOUBLE); break; case 'F': frame.addStackItem(TypeBinding.FLOAT); break; case 'I': frame.addStackItem(TypeBinding.INT); break; case 'J': frame.addStackItem(TypeBinding.LONG); break; case 'S': frame.addStackItem(TypeBinding.SHORT); break; } } else { if (returnType[0] == '[') { frame.addStackItem(new VerificationTypeInfo(0, returnType)); } else { frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); } } pc += 3; break; case Opcodes.OPC_invokestatic: index = u2At(bytecodes, 1, pc); nameAndTypeIndex = u2At(poolContents, 3, constantPoolOffsets[index]); utf8index = u2At(poolContents, 3, constantPoolOffsets[nameAndTypeIndex]); descriptor = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); utf8index = u2At(poolContents, 1, constantPoolOffsets[nameAndTypeIndex]); name = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); frame.numberOfStackItems -= getParametersCount(descriptor); returnType = getReturnType(descriptor); if (returnType.length == 1) { // base type switch(returnType[0]) { case 'Z': frame.addStackItem(TypeBinding.BOOLEAN); break; case 'B': frame.addStackItem(TypeBinding.BYTE); break; case 'C': frame.addStackItem(TypeBinding.CHAR); break; case 'D': frame.addStackItem(TypeBinding.DOUBLE); break; case 'F': frame.addStackItem(TypeBinding.FLOAT); break; case 'I': frame.addStackItem(TypeBinding.INT); break; case 'J': frame.addStackItem(TypeBinding.LONG); break; case 'S': frame.addStackItem(TypeBinding.SHORT); break; } } else { if (returnType[0] == '[') { frame.addStackItem(new VerificationTypeInfo(0, returnType)); } else { frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); } } pc += 3; break; case Opcodes.OPC_invokeinterface: index = u2At(bytecodes, 1, pc); nameAndTypeIndex = u2At(poolContents, 3, constantPoolOffsets[index]); utf8index = u2At(poolContents, 3, constantPoolOffsets[nameAndTypeIndex]); descriptor = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); utf8index = u2At(poolContents, 1, constantPoolOffsets[nameAndTypeIndex]); name = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); // we don't need count and args // u1At(bytecodes, 3, pc); // count // u1At(bytecodes, 4, pc); // extra args frame.numberOfStackItems -= (getParametersCount(descriptor) + 1); returnType = getReturnType(descriptor); if (returnType.length == 1) { // base type switch(returnType[0]) { case 'Z': frame.addStackItem(TypeBinding.BOOLEAN); break; case 'B': frame.addStackItem(TypeBinding.BYTE); break; case 'C': frame.addStackItem(TypeBinding.CHAR); break; case 'D': frame.addStackItem(TypeBinding.DOUBLE); break; case 'F': frame.addStackItem(TypeBinding.FLOAT); break; case 'I': frame.addStackItem(TypeBinding.INT); break; case 'J': frame.addStackItem(TypeBinding.LONG); break; case 'S': frame.addStackItem(TypeBinding.SHORT); break; } } else { if (returnType[0] == '[') { frame.addStackItem(new VerificationTypeInfo(0, returnType)); } else { frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); } } pc += 5; break; case Opcodes.OPC_new: index = u2At(bytecodes, 1, pc); utf8index = u2At(poolContents, 1, constantPoolOffsets[index]); char[] className = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); VerificationTypeInfo verificationTypeInfo = new VerificationTypeInfo(0, VerificationTypeInfo.ITEM_UNINITIALIZED, className); verificationTypeInfo.offset = currentPC; frame.addStackItem(verificationTypeInfo); pc += 3; break; case Opcodes.OPC_newarray: char[] constantPoolName = null; switch (u1At(bytecodes, 1, pc)) { case ClassFileConstants.INT_ARRAY : constantPoolName = new char[] { '[', 'I' }; break; case ClassFileConstants.BYTE_ARRAY : constantPoolName = new char[] { '[', 'B' }; break; case ClassFileConstants.BOOLEAN_ARRAY : constantPoolName = new char[] { '[', 'Z' }; break; case ClassFileConstants.SHORT_ARRAY : constantPoolName = new char[] { '[', 'S' }; break; case ClassFileConstants.CHAR_ARRAY : constantPoolName = new char[] { '[', 'C' }; break; case ClassFileConstants.LONG_ARRAY : constantPoolName = new char[] { '[', 'J' }; break; case ClassFileConstants.FLOAT_ARRAY : constantPoolName = new char[] { '[', 'F' }; break; case ClassFileConstants.DOUBLE_ARRAY : constantPoolName = new char[] { '[', 'D' }; break; } frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeIds.T_JavaLangObject, constantPoolName); pc += 2; break; case Opcodes.OPC_anewarray: index = u2At(bytecodes, 1, pc); utf8index = u2At(poolContents, 1, constantPoolOffsets[index]); className = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); int classNameLength = className.length; if (className[0] != '[') { // this is a type name (class or interface). So we add appropriate '[', 'L' and ';'. System.arraycopy(className, 0, (constantPoolName = new char[classNameLength + 3]), 2, classNameLength); constantPoolName[0] = '['; constantPoolName[1] = 'L'; constantPoolName[classNameLength + 2] = ';'; } else { // if class name is already an array, we just need to add one dimension System.arraycopy(className, 0, (constantPoolName = new char[classNameLength + 1]), 1, classNameLength); constantPoolName[0] = '['; } frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(0, constantPoolName); pc += 3; break; case Opcodes.OPC_arraylength: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); pc++; break; case Opcodes.OPC_athrow: frame.numberOfStackItems--; pc++; addRealJumpTarget(realJumpTarget, pc - codeOffset); break; case Opcodes.OPC_checkcast: index = u2At(bytecodes, 1, pc); utf8index = u2At(poolContents, 1, constantPoolOffsets[index]); className = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(0, className); pc += 3; break; case Opcodes.OPC_instanceof: // no need to know the class index = u2At(bytecodes, 1, pc); frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); pc += 3; break; case Opcodes.OPC_monitorenter: case Opcodes.OPC_monitorexit: frame.numberOfStackItems--; pc++; break; case Opcodes.OPC_wide: opcode = (byte) u1At(bytecodes, 1, pc); if (opcode == Opcodes.OPC_iinc) { // index = u2At(bytecodes, 2, pc); // i2At(bytecodes, 4, pc); // const // we don't need the index and the const value pc += 6; } else { index = u2At(bytecodes, 2, pc); // need to handle iload, fload, aload, lload, dload, istore, fstore, astore, lstore or dstore switch(opcode) { case Opcodes.OPC_iload : frame.addStackItem(TypeBinding.INT); break; case Opcodes.OPC_fload : frame.addStackItem(TypeBinding.FLOAT); break; case Opcodes.OPC_aload : localsN = frame.locals[index]; if (localsN == null) { localsN = retrieveLocal(currentPC, index); } frame.addStackItem(localsN); break; case Opcodes.OPC_lload : frame.addStackItem(TypeBinding.LONG); break; case Opcodes.OPC_dload : frame.addStackItem(TypeBinding.DOUBLE); break; case Opcodes.OPC_istore : frame.numberOfStackItems--; break; case Opcodes.OPC_fstore : frame.numberOfStackItems--; break; case Opcodes.OPC_astore : frame.locals[index] = frame.stackItems[frame.numberOfStackItems - 1]; frame.numberOfStackItems--; break; case Opcodes.OPC_lstore : frame.numberOfStackItems--; break; case Opcodes.OPC_dstore : frame.numberOfStackItems--; break; } pc += 4; } break; case Opcodes.OPC_multianewarray: index = u2At(bytecodes, 1, pc); utf8index = u2At(poolContents, 1, constantPoolOffsets[index]); className = utf8At(poolContents, constantPoolOffsets[utf8index] + 3, u2At( poolContents, 1, constantPoolOffsets[utf8index])); int dimensions = u1At(bytecodes, 3, pc); // dimensions frame.numberOfStackItems -= dimensions; classNameLength = className.length; constantPoolName = new char[classNameLength + dimensions]; for (int i = 0; i < dimensions; i++) { constantPoolName[i] = '['; } System.arraycopy(className, 0, constantPoolName, dimensions, classNameLength); frame.addStackItem(new VerificationTypeInfo(0, constantPoolName)); pc += 4; break; case Opcodes.OPC_ifnull: case Opcodes.OPC_ifnonnull: frame.numberOfStackItems--; addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); pc += 3; break; case Opcodes.OPC_goto_w: addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 1, pc)); pc += 5; addRealJumpTarget(realJumpTarget, pc - codeOffset); // handle infinite loop break; default: // should not occur this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError( Messages.bind( Messages.abort_invalidOpcode, new Object[] { new Byte(opcode), new Integer(pc), new String(methodBinding.shortReadableName()), }), this.codeStream.methodDeclaration); break; } if (pc >= (codeLength + codeOffset)) { break; } } return filterFakeFrames(realJumpTarget, frames, codeLength); } private void addRealJumpTarget(Set realJumpTarget, int pc) { realJumpTarget.add(new Integer(pc)); } private void add(Map frames, StackMapFrame frame) { frames.put(new Integer(frame.pc), frame); } private final int u1At(byte[] reference, int relativeOffset, int structOffset) { return (reference[relativeOffset + structOffset] & 0xFF); } private final int u2At(byte[] reference, int relativeOffset, int structOffset) { int position = relativeOffset + structOffset; return ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF); } private final long u4At(byte[] reference, int relativeOffset, int structOffset) { int position = relativeOffset + structOffset; return (((reference[position++] & 0xFFL) << 24) + ((reference[position++] & 0xFF) << 16) + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF)); } private final int i2At(byte[] reference, int relativeOffset, int structOffset) { int position = relativeOffset + structOffset; return (reference[position++] << 8) + (reference[position] & 0xFF); } public char[] utf8At(byte[] reference, int absoluteOffset, int bytesAvailable) { int length = bytesAvailable; char outputBuf[] = new char[bytesAvailable]; int outputPos = 0; int readOffset = absoluteOffset; while (length != 0) { int x = reference[readOffset++] & 0xFF; length--; if ((0x80 & x) != 0) { if ((x & 0x20) != 0) { length -= 2; x = ((x & 0xF) << 12) | ((reference[readOffset++] & 0x3F) << 6) | (reference[readOffset++] & 0x3F); } else { length--; x = ((x & 0x1F) << 6) | (reference[readOffset++] & 0x3F); } } outputBuf[outputPos++] = (char) x; } if (outputPos != bytesAvailable) { System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]), 0, outputPos); } return outputBuf; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/batch/0000755000175000001440000000000012251602350025346 5ustar dokousersecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java0000644000175000001440000000472412212041344031755 0ustar dokousers/******************************************************************************* * Copyright (c) 2006, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.batch; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.util.zip.ZipEntry; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.util.Util; public class ClasspathSourceJar extends ClasspathJar { private String encoding; public ClasspathSourceJar(File file, boolean closeZipFileAtEnd, AccessRuleSet accessRuleSet, String encoding, String destinationPath) { super(file, closeZipFileAtEnd, accessRuleSet, destinationPath); this.encoding = encoding; } public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) { if (!isPackage(qualifiedPackageName)) return null; // most common case ZipEntry sourceEntry = this.zipFile.getEntry(qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java); if (sourceEntry != null) { try { InputStream stream = null; char[] contents = null; try { stream = this.zipFile.getInputStream(sourceEntry); contents = Util.getInputStreamAsCharArray(stream, -1, this.encoding); } finally { if (stream != null) stream.close(); } return new NameEnvironmentAnswer( new CompilationUnit( contents, qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java, this.encoding, this.destinationPath), fetchAccessRestriction(qualifiedBinaryFileName)); } catch (IOException e) { // treat as if source file is missing } } return null; } public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) { return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false); } public int getMode() { return SOURCE; } } ecj-3.9.0/src/org.eclipse.jdt.core/org/eclipse/jdt/internal/compiler/batch/messages.properties0000644000175000001440000006110212212041344031270 0ustar dokousers############################################################################### # Copyright (c) 2000, 2013 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # # Contributors: # IBM Corporation - initial API and implementation # Benjamin Muskalla - Contribution for bug 239066 # Stephan Herrmann - Contributions for # bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used # bug 295551 - Add option to automatically promote all warnings to errors # bug 359721 - [options] add command line option for new warning token "resource" # bug 365208 - [compiler][batch] command line options for annotation based null analysis # bug 374605 - Unreasonable warning for enum-based switch statements # bug 388281 - [compiler][null] inheritance of null annotations as an option # Alan Moraes - Contribution for bug 383644 ############################################################################### ### JavaBatchCompiler messages. ### compiler #Format: compiler.name = word1 word2 word3 compiler.name = Eclipse Compiler for Java(TM) #Format: compiler.version = (The placeholder 'bundle_qualifier' will be automatically filled. Do not remove or alter it) compiler.version = bundle_qualifier, 3.9.0 compiler.copyright = Copyright IBM Corp 2000, 2013. All rights reserved. ### progress progress.compiling = Compiling ### compile compile.repetition = [repetition {0}/{1}] compile.instantTime = [compiled {0} lines in {1} ms: {2} lines/s] compile.detailedTime = [parse: {0} ms ({1}%), resolve: {2} ms ({3}%), analyze: {4} ms ({5}%), generate: {6} ms ({7}%) ] compile.ioTime = [i/o: read: {0} ms ({1}%), write: {2} ms ({3}%)] compile.averageTime = [average, excluding min-max {0} lines in {1} ms: {2} lines/s] compile.totalTime = [total compilation time: {0}] compile.oneProblem = 1 problem ({0}) compile.severalProblemsErrorsOrWarnings = {0} problems ({1}) compile.severalProblemsErrorsAndWarnings = {0} problems ({1}, {2}) compile.oneError = 1 error compile.severalErrors = {0} errors compile.oneWarning = 1 warning compile.severalWarnings = {0} warnings compile.oneClassFileGenerated = [1 .class file generated] compile.severalClassFilesGenerated = [{0} .class files generated] ### configure configure.requiresJDK1.2orAbove = Need to use a JVM >= 1.2 configure.duplicateLog = duplicate log specification: {0} configure.duplicateRepeat = duplicate repeat specification: {0} configure.duplicateMaxProblems = duplicate max problems specification: {0} configure.duplicateCompliance = duplicate compliance setting specification: {0} configure.duplicateSource = duplicate source compliance setting specification: {0} configure.duplicateTarget = duplicate target compliance setting specification: {0} configure.source = source level should be comprised in between ''1.3'' and ''1.7'' (or ''5'', ''5.0'', ..., ''7'' or ''7.0''): {0} configure.duplicateOutputPath = duplicate output path specification: {0} configure.duplicateBootClasspath = duplicate bootclasspath specification: {0} configure.duplicateExtDirs = duplicate extdirs specification: {0} configure.duplicateSourcepath = duplicate sourcepath specification: {0} configure.invalidDebugOption = invalid debug option: {0} configure.invalidWarningConfiguration = invalid warning configuration: ''{0}'' configure.invalidWarning = invalid warning token: ''{0}''. Ignoring warning and compiling configure.invalidWarningOption = invalid warning option: ''{0}''. Must specify a warning token configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.7'' (or ''5'', ''5.0'', ..., ''7'' or ''7.0'') or cldc1.1: {0} configure.incompatibleTargetForSource = Target level ''{0}'' is incompatible with source level ''{1}''. A target level ''{1}'' or better is required configure.incompatibleTargetForGenericSource = Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.5'' or better is required configure.incompatibleComplianceForSource = Compliance level ''{0}'' is incompatible with source level ''{1}''. A compliance level ''{1}'' or better is required configure.incompatibleComplianceForTarget = Compliance level ''{0}'' is incompatible with target level ''{1}''. A compliance level ''{1}'' or better is required configure.repetition = repetition must be a positive integer: {0} configure.maxProblems = max problems must be a positive integer: {0} configure.invalidNowarnOption = invalid syntax for nowarn option: {0} configure.invalidErrorConfiguration = invalid error configuration: ''{0}'' configure.invalidError = invalid error token: ''{0}''. Ignoring this error token and compiling configure.invalidErrorOption = invalid error option: ''{0}''. Must specify an error token ## configure.directoryNotExist = directory does not exist: {0} configure.unrecognizedOption = Unrecognized option : {0} configure.noClasspath = no classpath defined, using default directory instead configure.incorrectClasspath = incorrect classpath: {0} configure.invalidexpansionargumentname = expansion argument file {0} does not exist or cannot be read configure.cannotOpenLog = cannot open .log file: {0} configure.cannotOpenLogInvalidEncoding = cannot open .log file: {0}; because UTF-8 is not supported configure.unexpectedCustomEncoding = unexpected custom encoding specification: {0}[{1}] configure.unsupportedEncoding = unsupported encoding format: {0} configure.duplicateDefaultEncoding = duplicate default encoding format specification: {0} configure.invalidTaskTag ={0} is an invalid task tag configure.incorrectExtDirsEntry = incorrect ext dir entry; {0} must be a directory configure.incorrectEndorsedDirsEntry = incorrect endorsed dir entry; {0} must be a directory configure.duplicateEndorsedDirs = duplicate endorseddirs specification: {0} configure.incorrectDestinationPathEntry = incorrect destination path entry: {0} configure.unexpectedBracket = unexpected bracket: {0} configure.unexpectedDestinationPathEntry = unexpected destination path entry in {0} option configure.unexpectedDestinationPathEntryFile = unexpected destination path entry for file: {0} configure.accessRuleAfterDestinationPath = access rules cannot follow destination path entries: {0} configure.duplicateDestinationPathEntry = duplicate destination path entry in {0} option configure.invalidClassName = invalid class name: {0} configure.incorrectVMVersionforAPT = Annotation processing got disabled, since it requires a 1.6 compliant JVM configure.incompatibleSourceForCldcTarget=Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.3'' or lower is required configure.incompatibleComplianceForCldcTarget=Target level ''{0}'' is incompatible with compliance level ''{1}''. A compliance level ''1.4''or lower is required configure.invalidClasspathSection = invalid Class-Path header in manifest of jar file: {0} configure.multipleClasspathSections = multiple Class-Path headers in manifest of jar file: {0} configure.missingwarningspropertiesfile=properties file {0} does not exist configure.ioexceptionwarningspropertiesfile=An IOException occurred while reading the properties file {0} configure.multipleencodings=Multiple encoding specified: {1}. The default encoding has been set to {0} configure.differentencodings=Found encoding {0}. Different encodings were specified: {1} configure.differentencoding=Found encoding {0}. A different encoding was specified: {1} ### null annotations configure.invalidNullAnnot = Token {0} is not in the expected format "nullAnnot( | | )" ### requestor requestor.error = {0}. ERROR in {1} requestor.warning = {0}. WARNING in {1} requestor.extraerror = {0}. ERROR: requestor.extrawarning = {0}. WARNING: requestor.notRetrieveErrorMessage = Cannot retrieve the error message for {0} requestor.noFileNameSpecified = (original file name is not available) ### EMACS STYLE output.emacs.error=error output.emacs.warning=warning ### unit unit.more = File {0} is specified more than once unit.missing = File {0} is missing ### output output.noClassFileCreated = No .class file created for file {1} in {0} because of an IOException: {2} ### miscellaneous misc.version = {0} {1}, {2} misc.usage = {1} {2}\n\ {3}\n\ \ \n\ \ Usage: \n\ \ If directories are specified, then their source contents are compiled.\n\ \ Possible options are listed below. Options enabled by default are prefixed\n\ \ with ''+''.\n\ \ \n\ \ Classpath options:\n\ \ -cp -classpath \n\ \ specify location for application classes and sources.\n\ \ Each directory or file can specify access rules for\n\ \ types between ''['' and '']'' (e.g. [-X] to forbid\n\ \ access to type X, [~X] to discourage access to type X,\n\ \ [+p/X{0}-p/*] to forbid access to all types in package p\n\ \ but allow access to p/X)\n\ \ -bootclasspath \n\ \ specify location for system classes. Each directory or\n\ \ file can specify access rules for types between ''[''\n\ \ and '']''\n\ \ -sourcepath \n\ \ specify location for application sources. Each directory\n\ \ or file can specify access rules for types between ''[''\n\ \ and '']''. Each directory can further specify a specific\n\ \ destination directory using a ''-d'' option between ''[''\n\ \ and '']''; this overrides the general ''-d'' option.\n\ \ .class files created from source files contained in a\n\ \ jar file are put in the user.dir folder in case no\n\ \ general ''-d'' option is specified. ZIP archives cannot\n\ \ override the general ''-d'' option\n\ \ -extdirs \n\ \ specify location for extension ZIP archives\n\ \ -endorseddirs \n\ \ specify location for endorsed ZIP archives\n\ \ -d destination directory (if omitted, no directory is\n\ \ created); this option can be overridden per source\n\ \ directory\n\ \ -d none generate no .class files\n\ \ -encoding specify default encoding for all source files. Each\n\ \ file/directory can override it when suffixed with\n\ \ ''['''']'' (e.g. X.java[utf8]).\n\ \ If multiple default encodings are specified, the last\n\ \ one will be used.\n\ \ \n\ \ Compliance options:\n\ \ -1.3 use 1.3 compliance (-source 1.3 -target 1.1)\n\ \ -1.4 + use 1.4 compliance (-source 1.3 -target 1.2)\n\ \ -1.5 -5 -5.0 use 1.5 compliance (-source 1.5 -target 1.5)\n\ \ -1.6 -6 -6.0 use 1.6 compliance (-source 1.6 -target 1.6)\n\ \ -1.7 -7 -7.0 use 1.7 compliance (-source 1.7 -target 1.7)\n\ \ -source set source level: 1.3 to 1.7 (or 5, 5.0, etc)\n\ \ -target set classfile target: 1.1 to 1.7 (or 5, 5.0, etc)\n\ \ cldc1.1 can also be used to generate the StackMap\n\ \ attribute\n\ \ \n\ \ Warning options:\n\ \ -deprecation + deprecation outside deprecated code (equivalent to\n\ \ -warn:+deprecation)\n\ \ -nowarn -warn:none disable all warnings\n\ \ -nowarn:[]\n\ \ specify directories from which optional problems should\n\ \ be ignored\n\ \ -?:warn -help:warn display advanced warning options\n\ \ \n\ \ Error options:\n\ \ -err: convert exactly the listed warnings\n\ \ to be reported as errors\n\ \ -err:+ enable additional warnings to be\n\ \ reported as errors\n\ \ -err:- disable specific warnings to be\n\ \ reported as errors\n\ \ \n\ \ Setting warning or error options using properties file:\n\ \ -properties set warnings/errors option based on the properties\n\ \ file contents. This option can be used with -nowarn,\n\ \ -err:.. or -warn:.. options, but the last one on the\n\ \ command line sets the options to be used.\n\ \ \n\ \ Debug options:\n\ \ -g[:lines,vars,source] custom debug info\n\ \ -g:lines,source + both lines table and source debug info\n\ \ -g all debug info\n\ \ -g:none no debug info\n\ \ -preserveAllLocals preserve unused local vars for debug purpose\n\ \ \n\ \ Annotation processing options:\n\ \ These options are meaningful only in a 1.6 environment.\n\ \ -Akey[=value] options that are passed to annotation processors\n\ \ -processorpath \n\ \ specify locations where to find annotation processors.\n\ \ If this option is not used, the classpath will be\n\ \ searched for processors\n\ \ -processor \n\ \ qualified names of the annotation processors to run.\n\ \ This bypasses the default annotation discovery process\n\ \ -proc:only run annotation processors, but do not compile\n\ \ -proc:none perform compilation but do not run annotation\n\ \ processors\n\ \ -s destination directory for generated source files\n\ \ -XprintProcessorInfo print information about which annotations and elements\n\ \ a processor is asked to process\n\ \ -XprintRounds print information about annotation processing rounds\n\ \ -classNames \n\ \ qualified names of binary classes to process\n\ \ \n\ \ Advanced options:\n\ \ @ read command line arguments from file\n\ \ -maxProblems max number of problems per compilation unit (100 by\n\ \ default)\n\ \ -log log to a file. If the file extension is ''.xml'', then\n\ \ the log will be a xml file.\n\ \ -proceedOnError[:Fatal]\n\ \ do not stop at first error, dumping class files with\n\ \ problem methods\n\ \ With ":Fatal", all optional errors are treated as fatal\n\ \ -verbose enable verbose output\n\ \ -referenceInfo compute reference info\n\ \ -progress show progress (only in -log mode)\n\ \ -time display speed information \n\ \ -noExit do not call System.exit(n) at end of compilation (n==0\n\ \ if no error)\n\ \ -repeat repeat compilation process times for perf analysis\n\ \ -inlineJSR inline JSR bytecode (implicit if target >= 1.5)\n\ \ -enableJavadoc consider references in javadoc\n\ \ -Xemacs used to enable emacs-style output in the console.\n\ \ It does not affect the xml log output\n\ \ -missingNullDefault report missing default nullness annotation\n\ \ \n\ \ -? -help print this help message\n\ \ -v -version print compiler version\n\ \ -showversion print compiler version and continue\n\ \ \n\ \ Ignored options:\n\ \ -J