blob: 7e6072708cda0fae34583e775032bf011c56ca2f [file] [log] [blame]
/*******************************************************************************
* 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 Eclipse Public License v1.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.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.declarationSourceStart != initializer.declarationSourceEnd){
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;
}
}