1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler;
14 * A compilation result consists of all information returned by the compiler for
15 * a single compiled compilation source unit. This includes:
17 * <li> the compilation unit that was compiled
18 * <li> for each type produced by compiling the compilation unit, its binary and optionally its principal structure
19 * <li> any problems (errors or warnings) produced
20 * <li> dependency info
23 * The principle structure and binary may be null if the compiler could not produce them.
24 * If neither could be produced, there is no corresponding entry for the type.
26 * The dependency info includes type references such as supertypes, field types, method
27 * parameter and return types, local variable types, types of intermediate expressions, etc.
28 * It also includes the namespaces (packages) in which names were looked up.
29 * It does <em>not</em> include finer grained dependencies such as information about
30 * specific fields and methods which were referenced, but does contain their
31 * declaring types and any other types used to locate such fields or methods.
34 import java.util.Enumeration;
35 import java.util.HashSet;
36 import java.util.Hashtable;
39 import net.sourceforge.phpdt.core.compiler.IProblem;
40 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
41 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
42 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
44 public class CompilationResult {
46 public IProblem problems[];
47 public int problemCount;
48 public ICompilationUnit compilationUnit;
49 private Map problemsMap;
50 private Map firstErrorsMap;
51 private HashSet duplicateProblems;
52 private int maxProblemPerUnit;
53 public char[][][] qualifiedReferences;
54 public char[][] simpleNameReferences;
56 public int lineSeparatorPositions[];
57 public Hashtable compiledTypes = new Hashtable(11);
58 public int unitIndex, totalUnitsKnown;
59 public boolean hasBeenAccepted = false;
60 public char[] fileName;
62 public CompilationResult(
66 int maxProblemPerUnit){
68 this.fileName = fileName;
69 this.unitIndex = unitIndex;
70 this.totalUnitsKnown = totalUnitsKnown;
71 this.maxProblemPerUnit = maxProblemPerUnit;
75 public CompilationResult(
76 ICompilationUnit compilationUnit,
79 int maxProblemPerUnit){
81 this.fileName = compilationUnit.getFileName();
82 this.compilationUnit = compilationUnit;
83 this.unitIndex = unitIndex;
84 this.totalUnitsKnown = totalUnitsKnown;
85 this.maxProblemPerUnit = maxProblemPerUnit;
88 private int computePriority(IProblem problem){
90 final int P_STATIC = 1000;
91 final int P_OUTSIDE_METHOD = 4000;
92 final int P_FIRST_ERROR = 2000;
93 final int P_ERROR = 10000;
95 int priority = 1000 - problem.getSourceLineNumber(); // early problems first
96 if (priority < 0) priority = 0;
97 if (problem.isError()){
100 ReferenceContext context = problemsMap == null ? null : (ReferenceContext) problemsMap.get(problem);
101 if (context != null){
102 if (context instanceof AbstractMethodDeclaration){
103 AbstractMethodDeclaration method = (AbstractMethodDeclaration) context;
104 if (method.isStatic()) {
105 priority += P_STATIC;
108 priority += P_OUTSIDE_METHOD;
111 priority += P_OUTSIDE_METHOD;
113 if (firstErrorsMap.containsKey(problem)){
114 priority += P_FIRST_ERROR;
118 public ClassFile[] getClassFiles() {
119 Enumeration enum = compiledTypes.elements();
120 ClassFile[] classFiles = new ClassFile[compiledTypes.size()];
122 while (enum.hasMoreElements()){
123 classFiles[index++] = (ClassFile)enum.nextElement();
128 * Answer the initial compilation unit corresponding to the present compilation result
130 public ICompilationUnit getCompilationUnit(){
131 return compilationUnit;
134 * Answer the initial file name
136 public char[] getFileName(){
140 * Answer the problems (errors and warnings) encountered during compilation.
142 * This is not a compiler internal API - it has side-effects !
143 * It is intended to be used only once all problems have been detected,
144 * and makes sure the problems slot as the exact size of the number of
147 public IProblem[] getProblems() {
149 // Re-adjust the size of the problems if necessary.
150 if (problems != null) {
152 if (this.problemCount != problems.length) {
153 System.arraycopy(problems, 0, (problems = new IProblem[problemCount]), 0, problemCount);
156 if (this.maxProblemPerUnit > 0 && this.problemCount > this.maxProblemPerUnit){
157 quickPrioritize(problems, 0, problemCount - 1);
158 this.problemCount = this.maxProblemPerUnit;
159 System.arraycopy(problems, 0, (problems = new IProblem[problemCount]), 0, problemCount);
162 // Sort problems per source positions.
163 quicksort(problems, 0, problems.length-1);
168 public boolean hasErrors() {
169 if (problems != null)
170 for (int i = 0; i < problemCount; i++) {
171 if (problems[i].isError())
176 public boolean hasProblems() {
177 return problemCount != 0;
179 public boolean hasWarnings() {
180 if (problems != null)
181 for (int i = 0; i < problemCount; i++) {
182 if (problems[i].isWarning())
188 private static void quicksort(IProblem arr[], int left, int right) {
192 /* do nothing if array contains fewer than two */
197 swap(arr, left, (left + right) / 2);
199 pos = arr[left].getSourceStart();
201 for (i = left + 1; i <= right; i++) {
202 if (arr[i].getSourceStart() < pos) {
203 swap(arr, ++last, i);
207 swap(arr, left, last);
208 quicksort(arr, left, last - 1);
209 quicksort(arr, last + 1, right);
212 private void quickPrioritize(IProblem arr[], int left, int right) {
216 /* do nothing if array contains fewer than two */
221 swap(arr, left, (left + right) / 2);
223 prio = computePriority(arr[left]);
225 for (i = left + 1; i <= right; i++) {
226 if (computePriority(arr[i]) > prio) {
227 swap(arr, ++last, i);
231 swap(arr, left, last);
232 quickPrioritize(arr, left, last - 1);
233 quickPrioritize(arr, last + 1, right);
237 * For now, remember the compiled type using its compound name.
239 public void record(char[] typeName, ClassFile classFile) {
240 compiledTypes.put(typeName, classFile);
242 public void record(IProblem newProblem, ReferenceContext referenceContext) {
243 if (problemCount == 0) {
244 problems = new IProblem[5];
246 if (problemCount == problems.length)
247 System.arraycopy(problems, 0, (problems = new IProblem[problemCount * 2]), 0, problemCount);
249 problems[problemCount++] = newProblem;
250 if (referenceContext != null){
251 if (problemsMap == null) problemsMap = new Hashtable(5);
252 if (firstErrorsMap == null) firstErrorsMap = new Hashtable(5);
253 if (newProblem.isError() && !referenceContext.hasErrors()) firstErrorsMap.put(newProblem, newProblem);
254 problemsMap.put(newProblem, referenceContext);
257 private static void swap(IProblem arr[], int i, int j) {
263 CompilationResult tagAsAccepted(){
264 this.hasBeenAccepted = true;
265 this.problemsMap = null; // flush
269 public String toString(){
270 StringBuffer buffer = new StringBuffer();
271 if (this.fileName != null){
272 buffer.append("Filename : ").append(this.fileName).append('\n'); //$NON-NLS-1$
274 if (this.compiledTypes != null){
275 buffer.append("COMPILED type(s) \n"); //$NON-NLS-1$
276 Enumeration typeNames = this.compiledTypes.keys();
277 while (typeNames.hasMoreElements()) {
278 char[] typeName = (char[]) typeNames.nextElement();
279 buffer.append("\t - ").append(typeName).append('\n'); //$NON-NLS-1$
283 buffer.append("No COMPILED type\n"); //$NON-NLS-1$
285 if (problems != null){
286 buffer.append(this.problemCount).append(" PROBLEM(s) detected \n"); //$NON-NLS-1$//$NON-NLS-2$
287 for (int i = 0; i < this.problemCount; i++){
288 buffer.append("\t - ").append(this.problems[i]).append('\n'); //$NON-NLS-1$
291 buffer.append("No PROBLEM\n"); //$NON-NLS-1$
293 return buffer.toString();