1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.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
19 * optionally its principal structure
20 * <li> any problems (errors or warnings) produced
21 * <li> dependency info
24 * The principle structure and binary may be null if the compiler could not
25 * produce them. If neither could be produced, there is no corresponding entry
28 * The dependency info includes type references such as supertypes, field types,
29 * method parameter and return types, local variable types, types of
30 * intermediate expressions, etc. It also includes the namespaces (packages) in
31 * which names were looked up. It does <em>not</em> include finer grained
32 * dependencies such as information about specific fields and methods which were
33 * referenced, but does contain their declaring types and any other types used
34 * to locate such fields or methods.
37 // import java.util.Enumeration;
38 import java.util.Hashtable;
41 import net.sourceforge.phpdt.core.compiler.IProblem;
42 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
43 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
45 public class CompilationResult {
47 public IProblem problems[];
49 public IProblem tasks[];
51 public int problemCount;
55 public ICompilationUnit compilationUnit;
57 private Map problemsMap;
59 private Map firstErrorsMap;
61 private int maxProblemPerUnit;
63 public char[][][] qualifiedReferences;
65 public char[][] simpleNameReferences;
67 public int lineSeparatorPositions[];
69 // public Hashtable compiledTypes = new Hashtable(11);
70 public int unitIndex, totalUnitsKnown;
72 public boolean hasBeenAccepted = false;
74 public char[] fileName;
76 public CompilationResult(char[] fileName, int unitIndex,
77 int totalUnitsKnown, int maxProblemPerUnit) {
79 this.fileName = fileName;
80 this.unitIndex = unitIndex;
81 this.totalUnitsKnown = totalUnitsKnown;
82 this.maxProblemPerUnit = maxProblemPerUnit;
85 public CompilationResult(ICompilationUnit compilationUnit, int unitIndex,
86 int totalUnitsKnown, int maxProblemPerUnit) {
88 this.fileName = compilationUnit.getFileName();
89 this.compilationUnit = compilationUnit;
90 this.unitIndex = unitIndex;
91 this.totalUnitsKnown = totalUnitsKnown;
92 this.maxProblemPerUnit = maxProblemPerUnit;
95 private int computePriority(IProblem problem) {
97 //final int P_STATIC = 1000;
98 final int P_OUTSIDE_METHOD = 4000;
99 final int P_FIRST_ERROR = 2000;
100 final int P_ERROR = 10000;
102 int priority = 1000 - problem.getSourceLineNumber(); // early
107 if (problem.isError()) {
110 ReferenceContext context = problemsMap == null ? null
111 : (ReferenceContext) problemsMap.get(problem);
112 if (context != null) {
113 // if (context instanceof AbstractMethodDeclaration){
114 // AbstractMethodDeclaration method = (AbstractMethodDeclaration)
116 // if (method.isStatic()) {
117 // priority += P_STATIC;
120 priority += P_OUTSIDE_METHOD;
123 priority += P_OUTSIDE_METHOD;
125 if (firstErrorsMap.containsKey(problem)) {
126 priority += P_FIRST_ERROR;
131 public IProblem[] getAllProblems() {
132 IProblem[] problems = this.getProblems();
133 int problemCount = problems != null ? problems.length : 0;
134 IProblem[] tasks = this.getTasks();
135 int taskCount = tasks != null ? tasks.length : 0;
136 if (taskCount == 0) {
139 if (problemCount == 0) {
143 int totalNumberOfProblem = problemCount + taskCount;
144 IProblem[] allProblems = new IProblem[totalNumberOfProblem];
145 int allProblemIndex = 0;
147 int problemIndex = 0;
148 while (taskIndex + problemIndex < totalNumberOfProblem) {
149 IProblem nextTask = null;
150 IProblem nextProblem = null;
151 if (taskIndex < taskCount) {
152 nextTask = tasks[taskIndex];
154 if (problemIndex < problemCount) {
155 nextProblem = problems[problemIndex];
157 // select the next problem
158 IProblem currentProblem = null;
159 if (nextProblem != null) {
160 if (nextTask != null) {
161 if (nextProblem.getSourceStart() < nextTask
163 currentProblem = nextProblem;
166 currentProblem = nextTask;
170 currentProblem = nextProblem;
174 if (nextTask != null) {
175 currentProblem = nextTask;
179 allProblems[allProblemIndex++] = currentProblem;
184 // public ClassFile[] getClassFiles() {
185 // Enumeration enum = compiledTypes.elements();
186 // ClassFile[] classFiles = new ClassFile[compiledTypes.size()];
188 // while (enum.hasMoreElements()){
189 // classFiles[index++] = (ClassFile)enum.nextElement();
191 // return classFiles;
195 * Answer the initial compilation unit corresponding to the present
198 public ICompilationUnit getCompilationUnit() {
199 return compilationUnit;
203 * Answer the initial file name
205 public char[] getFileName() {
210 * Answer the errors encountered during compilation.
212 public IProblem[] getErrors() {
214 IProblem[] problems = getProblems();
216 for (int i = 0; i < this.problemCount; i++) {
217 if (problems[i].isError())
220 if (errorCount == this.problemCount)
222 IProblem[] errors = new IProblem[errorCount];
224 for (int i = 0; i < this.problemCount; i++) {
225 if (problems[i].isError())
226 errors[index++] = problems[i];
232 * Answer the problems (errors and warnings) encountered during compilation.
234 * This is not a compiler internal API - it has side-effects ! It is
235 * intended to be used only once all problems have been detected, and makes
236 * sure the problems slot as the exact size of the number of problems.
238 public IProblem[] getProblems() {
240 // Re-adjust the size of the problems if necessary.
241 if (problems != null) {
243 if (this.problemCount != problems.length) {
244 System.arraycopy(problems, 0,
245 (problems = new IProblem[problemCount]), 0,
249 if (this.maxProblemPerUnit > 0
250 && this.problemCount > this.maxProblemPerUnit) {
251 quickPrioritize(problems, 0, problemCount - 1);
252 this.problemCount = this.maxProblemPerUnit;
253 System.arraycopy(problems, 0,
254 (problems = new IProblem[problemCount]), 0,
258 // Sort problems per source positions.
259 quickSort(problems, 0, problems.length - 1);
265 * Answer the tasks (TO-DO, ...) encountered during compilation.
267 * This is not a compiler internal API - it has side-effects ! It is
268 * intended to be used only once all problems have been detected, and makes
269 * sure the problems slot as the exact size of the number of problems.
271 public IProblem[] getTasks() {
273 // Re-adjust the size of the tasks if necessary.
274 if (this.tasks != null) {
276 if (this.taskCount != this.tasks.length) {
277 System.arraycopy(this.tasks, 0,
278 (this.tasks = new IProblem[this.taskCount]), 0,
281 quickSort(tasks, 0, tasks.length - 1);
286 // public boolean hasErrors() {
288 // if (problems != null)
289 // for (int i = 0; i < problemCount; i++) {
290 // if (problems[i].isError())
296 // public boolean hasProblems() {
298 // return problemCount != 0;
301 public boolean hasSyntaxError() {
303 if (problems != null)
304 for (int i = 0; i < problemCount; i++) {
305 IProblem problem = problems[i];
306 if ((problem.getID() & IProblem.Syntax) != 0
307 && problem.isError())
313 // public boolean hasTasks() {
314 // return this.taskCount != 0;
317 // public boolean hasWarnings() {
319 // if (problems != null)
320 // for (int i = 0; i < problemCount; i++) {
321 // if (problems[i].isWarning())
327 private static void quickSort(IProblem[] list, int left, int right) {
332 // sort the problems by their source start position... starting with 0
333 int original_left = left;
334 int original_right = right;
335 int mid = list[(left + right) / 2].getSourceStart();
337 while (list[left].getSourceStart() < mid)
339 while (mid < list[right].getSourceStart())
342 IProblem tmp = list[left];
343 list[left] = list[right];
348 } while (left <= right);
349 if (original_left < right)
350 quickSort(list, original_left, right);
351 if (left < original_right)
352 quickSort(list, left, original_right);
355 private void quickPrioritize(IProblem[] list, int left, int right) {
360 // sort the problems by their priority... starting with the highest
362 int original_left = left;
363 int original_right = right;
364 int mid = computePriority(list[(left + right) / 2]);
366 while (computePriority(list[right]) < mid)
368 while (mid < computePriority(list[left]))
371 IProblem tmp = list[left];
372 list[left] = list[right];
377 } while (left <= right);
378 if (original_left < right)
379 quickPrioritize(list, original_left, right);
380 if (left < original_right)
381 quickPrioritize(list, left, original_right);
385 * For now, remember the compiled type using its compound name.
387 // public void record(char[] typeName, ClassFile classFile) {
389 // compiledTypes.put(typeName, classFile);
391 public void record(IProblem newProblem, ReferenceContext referenceContext) {
393 if (newProblem.getID() == IProblem.Task) {
394 recordTask(newProblem);
397 if (problemCount == 0) {
398 problems = new IProblem[5];
399 } else if (problemCount == problems.length) {
400 System.arraycopy(problems, 0,
401 (problems = new IProblem[problemCount * 2]), 0,
404 problems[problemCount++] = newProblem;
405 if (referenceContext != null) {
406 if (problemsMap == null)
407 problemsMap = new Hashtable(5);
408 if (firstErrorsMap == null)
409 firstErrorsMap = new Hashtable(5);
410 if (newProblem.isError() && !referenceContext.hasErrors())
411 firstErrorsMap.put(newProblem, newProblem);
412 problemsMap.put(newProblem, referenceContext);
416 private void recordTask(IProblem newProblem) {
417 if (this.taskCount == 0) {
418 this.tasks = new IProblem[5];
419 } else if (this.taskCount == this.tasks.length) {
420 System.arraycopy(this.tasks, 0,
421 (this.tasks = new IProblem[this.taskCount * 2]), 0,
424 this.tasks[this.taskCount++] = newProblem;
427 public CompilationResult tagAsAccepted() {
429 this.hasBeenAccepted = true;
430 this.problemsMap = null; // flush
434 public String toString() {
436 StringBuffer buffer = new StringBuffer();
437 if (this.fileName != null) {
438 buffer.append("Filename : ").append(this.fileName).append('\n'); //$NON-NLS-1$
440 // if (this.compiledTypes != null){
441 // buffer.append("COMPILED type(s) \n"); //$NON-NLS-1$
442 // Enumeration typeNames = this.compiledTypes.keys();
443 // while (typeNames.hasMoreElements()) {
444 // char[] typeName = (char[]) typeNames.nextElement();
445 // buffer.append("\t - ").append(typeName).append('\n'); //$NON-NLS-1$
449 // buffer.append("No COMPILED type\n"); //$NON-NLS-1$
451 if (problems != null) {
452 buffer.append(this.problemCount).append(" PROBLEM(s) detected \n"); //$NON-NLS-1$//$NON-NLS-2$
453 for (int i = 0; i < this.problemCount; i++) {
454 buffer.append("\t - ").append(this.problems[i]).append('\n'); //$NON-NLS-1$
457 buffer.append("No PROBLEM\n"); //$NON-NLS-1$
459 return buffer.toString();