/******************************************************************************* * 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.wst.jsdt.internal.compiler.parser.diagnose; import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement; import org.eclipse.wst.jsdt.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(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 - 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(ProgramElement[] statements) { if(statements == null || statements.length == 0) { return new int[3][0]; } else { RangeResult result = new RangeResult(); computeDietRange0(statements, result); return result.getRanges(); } } private static void computeDietRange0(ProgramElement[] statements, RangeResult result) { for (int j = 0; j < statements.length; j++) { //members // TypeDeclaration[] memberTypeDeclarations = types[j].memberTypes; // if(memberTypeDeclarations != null && memberTypeDeclarations.length > 0) { // computeDietRange0(types[j].memberTypes, result); // } //methods if (statements[j] instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration method = (AbstractMethodDeclaration) statements[j]; // 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 containsIgnoredBody(AbstractMethodDeclaration method){ return !method.isDefaultConstructor() && !method.isClinit() && (method.modifiers & ExtraCompilerModifiers.AccSemicolonBody) == 0; } }