--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+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.CompilerModifiers;
+
+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(pos >= intervalStarts.length) {
+ System.arraycopy(intervalStarts, 0, intervalStarts = new int[pos * 2], 0, pos);
+ System.arraycopy(intervalEnds, 0, intervalEnds = new int[pos * 2], 0, pos);
+ System.arraycopy(intervalFlags, 0, intervalFlags = new int[pos * 2], 0, pos);
+ }
+ intervalStarts[pos] = start;
+ intervalEnds[pos] = end;
+ intervalFlags[pos] = flags;
+ pos++;
+ }
+
+ int[][] getRanges() {
+ int[] resultStarts = new int[pos];
+ int[] resultEnds = new int[pos];
+ int[] resultFlags = new int[pos];
+
+ System.arraycopy(intervalStarts, 0, resultStarts, 0, pos);
+ System.arraycopy(intervalEnds, 0, resultEnds, 0, pos);
+ System.arraycopy(intervalFlags, 0, resultFlags, 0, 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) / 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.errorInSignature = true;
+ 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.errorInSignature = true;
+ result.addInterval(initializer.declarationSourceStart, initializer.declarationSourceEnd, IGNORE);
+ } else {
+ result.addInterval(initializer.bodyStart, initializer.bodyEnd);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static boolean isInInterval(int start, int end, int[] intervalStart, int[] intervalEnd) {
+ int length = intervalStart.length;
+ for (int i = 0; i < length; i++) {
+ if(intervalStart[i] <= start && intervalEnd[i] >= end) {
+ return true;
+ } else if(intervalStart[i] > end) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public static int getPreviousInterval(int start, int end, int[] intervalStart, int[] intervalEnd) {
+ int length = intervalStart.length;
+ for (int i = 0; i < length; i++) {
+ if(intervalStart[i] > end) {
+ return i - 1;
+ }
+ }
+ return length - 1;
+ }
+
+ public static boolean containsIgnoredBody(AbstractMethodDeclaration method){
+ return !method.isDefaultConstructor()
+ && !method.isClinit()
+ && (method.modifiers & CompilerModifiers.AccSemicolonBody) == 0;
+ }
+}