001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.parser.diagnose;
011:
012: import org.eclipse.jdt.internal.compiler.ast.ASTNode;
013: import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
014: import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
015: import org.eclipse.jdt.internal.compiler.ast.Initializer;
016: import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
017: import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
018:
019: public class RangeUtil {
020:
021: // flags
022: public static final int NO_FLAG = 0;
023: public static final int LBRACE_MISSING = 1;
024: public static final int IGNORE = 2;
025:
026: static class RangeResult {
027: private static final int INITIAL_SIZE = 10;
028: int pos;
029: int[] intervalStarts;
030: int[] intervalEnds;
031: int[] intervalFlags;
032:
033: RangeResult() {
034: this .pos = 0;
035: this .intervalStarts = new int[INITIAL_SIZE];
036: this .intervalEnds = new int[INITIAL_SIZE];
037: this .intervalFlags = new int[INITIAL_SIZE];
038: }
039:
040: void addInterval(int start, int end) {
041: addInterval(start, end, NO_FLAG);
042: }
043:
044: void addInterval(int start, int end, int flags) {
045: if (pos >= intervalStarts.length) {
046: System.arraycopy(intervalStarts, 0,
047: intervalStarts = new int[pos * 2], 0, pos);
048: System.arraycopy(intervalEnds, 0,
049: intervalEnds = new int[pos * 2], 0, pos);
050: System.arraycopy(intervalFlags, 0,
051: intervalFlags = new int[pos * 2], 0, pos);
052: }
053: intervalStarts[pos] = start;
054: intervalEnds[pos] = end;
055: intervalFlags[pos] = flags;
056: pos++;
057: }
058:
059: int[][] getRanges() {
060: int[] resultStarts = new int[pos];
061: int[] resultEnds = new int[pos];
062: int[] resultFlags = new int[pos];
063:
064: System.arraycopy(intervalStarts, 0, resultStarts, 0, pos);
065: System.arraycopy(intervalEnds, 0, resultEnds, 0, pos);
066: System.arraycopy(intervalFlags, 0, resultFlags, 0, pos);
067:
068: if (resultStarts.length > 1) {
069: quickSort(resultStarts, resultEnds, resultFlags, 0,
070: resultStarts.length - 1);
071: }
072: return new int[][] { resultStarts, resultEnds, resultFlags };
073: }
074:
075: private void quickSort(int[] list, int[] list2, int[] list3,
076: int left, int right) {
077: int original_left = left;
078: int original_right = right;
079: int mid = list[left + (right - left) / 2];
080: do {
081: while (compare(list[left], mid) < 0) {
082: left++;
083: }
084: while (compare(mid, list[right]) < 0) {
085: right--;
086: }
087: if (left <= right) {
088: int tmp = list[left];
089: list[left] = list[right];
090: list[right] = tmp;
091:
092: tmp = list2[left];
093: list2[left] = list2[right];
094: list2[right] = tmp;
095:
096: tmp = list3[left];
097: list3[left] = list3[right];
098: list3[right] = tmp;
099:
100: left++;
101: right--;
102: }
103: } while (left <= right);
104:
105: if (original_left < right) {
106: quickSort(list, list2, list3, original_left, right);
107: }
108: if (left < original_right) {
109: quickSort(list, list2, list3, left, original_right);
110: }
111: }
112:
113: private int compare(int i1, int i2) {
114: return i1 - i2;
115: }
116: }
117:
118: public static boolean containsErrorInSignature(
119: AbstractMethodDeclaration method) {
120: return method.sourceEnd + 1 == method.bodyStart
121: || method.bodyEnd == method.declarationSourceEnd;
122: }
123:
124: public static int[][] computeDietRange(TypeDeclaration[] types) {
125: if (types == null || types.length == 0) {
126: return new int[3][0];
127: } else {
128: RangeResult result = new RangeResult();
129: computeDietRange0(types, result);
130: return result.getRanges();
131: }
132: }
133:
134: private static void computeDietRange0(TypeDeclaration[] types,
135: RangeResult result) {
136: for (int j = 0; j < types.length; j++) {
137: //members
138: TypeDeclaration[] memberTypeDeclarations = types[j].memberTypes;
139: if (memberTypeDeclarations != null
140: && memberTypeDeclarations.length > 0) {
141: computeDietRange0(types[j].memberTypes, result);
142: }
143: //methods
144: AbstractMethodDeclaration[] methods = types[j].methods;
145: if (methods != null) {
146: int length = methods.length;
147: for (int i = 0; i < length; i++) {
148: AbstractMethodDeclaration method = methods[i];
149: if (containsIgnoredBody(method)) {
150: if (containsErrorInSignature(method)) {
151: method.bits |= ASTNode.ErrorInSignature;
152: result
153: .addInterval(
154: method.declarationSourceStart,
155: method.declarationSourceEnd,
156: IGNORE);
157: } else {
158: int flags = method.sourceEnd + 1 == method.bodyStart ? LBRACE_MISSING
159: : NO_FLAG;
160: result.addInterval(method.bodyStart,
161: method.bodyEnd, flags);
162: }
163: }
164: }
165: }
166:
167: //initializers
168: FieldDeclaration[] fields = types[j].fields;
169: if (fields != null) {
170: int length = fields.length;
171: for (int i = 0; i < length; i++) {
172: if (fields[i] instanceof Initializer) {
173: Initializer initializer = (Initializer) fields[i];
174: if (initializer.declarationSourceEnd == initializer.bodyEnd
175: && initializer.declarationSourceStart != initializer.declarationSourceEnd) {
176: initializer.bits |= ASTNode.ErrorInSignature;
177: result.addInterval(
178: initializer.declarationSourceStart,
179: initializer.declarationSourceEnd,
180: IGNORE);
181: } else {
182: result.addInterval(initializer.bodyStart,
183: initializer.bodyEnd);
184: }
185: }
186: }
187: }
188: }
189: }
190:
191: public static boolean containsIgnoredBody(
192: AbstractMethodDeclaration method) {
193: return !method.isDefaultConstructor()
194: && !method.isClinit()
195: && (method.modifiers & ExtraCompilerModifiers.AccSemicolonBody) == 0;
196: }
197: }
|