| /******************************************************************************* |
| * 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; |
| } |
| } |