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.core;
13 import java.util.Locale;
16 import net.sourceforge.phpdt.core.ICompilationUnit;
17 import net.sourceforge.phpdt.core.IJavaElement;
18 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
19 import net.sourceforge.phpdt.core.IJavaProject;
20 import net.sourceforge.phpdt.core.IPackageFragment;
21 import net.sourceforge.phpdt.core.IProblemRequestor;
22 import net.sourceforge.phpdt.core.JavaCore;
23 import net.sourceforge.phpdt.core.JavaModelException;
24 import net.sourceforge.phpdt.core.WorkingCopyOwner;
25 import net.sourceforge.phpdt.core.compiler.CharOperation;
26 import net.sourceforge.phpdt.core.compiler.IProblem;
27 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
28 import net.sourceforge.phpdt.internal.compiler.Compiler;
29 import net.sourceforge.phpdt.internal.compiler.DefaultErrorHandlingPolicies;
30 import net.sourceforge.phpdt.internal.compiler.ICompilerRequestor;
31 import net.sourceforge.phpdt.internal.compiler.IErrorHandlingPolicy;
32 import net.sourceforge.phpdt.internal.compiler.IProblemFactory;
33 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
34 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
35 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
36 import net.sourceforge.phpdt.internal.compiler.parser.SourceTypeConverter;
37 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
38 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
39 import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
40 import net.sourceforge.phpdt.internal.compiler.problem.ProblemHandler;
41 import net.sourceforge.phpdt.internal.core.util.Util;
42 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
44 import org.eclipse.core.runtime.IProgressMonitor;
47 * Responsible for resolving types inside a compilation unit being reconciled,
48 * reporting the discovered problems to a given IProblemRequestor.
50 public class CompilationUnitProblemFinder extends Compiler {
53 * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
54 * The environment and options will be in effect for the lifetime of the compiler.
55 * When the compiler is run, compilation results are sent to the given requestor.
57 * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
58 * Environment used by the compiler in order to resolve type and package
59 * names. The name environment implements the actual connection of the compiler
60 * to the outside world (e.g. in batch mode the name environment is performing
61 * pure file accesses, reuse previous build state or connection to repositories).
62 * Note: the name environment is responsible for implementing the actual classpath
65 * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
66 * Configurable part for problem handling, allowing the compiler client to
67 * specify the rules for handling problems (stop on first error or accumulate
68 * them all) and at the same time perform some actions such as opening a dialog
69 * in UI when compiling interactively.
70 * @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
72 * @param settings The settings to use for the resolution.
74 * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
75 * Component which will receive and persist all compilation results and is intended
76 * to consume them as they are produced. Typically, in a batch compiler, it is
77 * responsible for writing out the actual .class files to the file system.
78 * @see org.eclipse.jdt.internal.compiler.api.CompilationResult
80 * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
81 * Factory used inside the compiler to create problem descriptors. It allows the
82 * compiler client to supply its own representation of compilation problems in
83 * order to avoid object conversions. Note that the factory is not supposed
84 * to accumulate the created problems, the compiler will gather them all and hand
85 * them back as part of the compilation unit result.
87 protected CompilationUnitProblemFinder(
88 INameEnvironment environment,
89 IErrorHandlingPolicy policy,
91 ICompilerRequestor requestor,
92 IProblemFactory problemFactory) {
94 super(environment, policy, settings, requestor, problemFactory, true);
98 * Add additional source types
100 public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
101 // ensure to jump back to toplevel type for first one (could be a member)
102 // while (sourceTypes[0].getEnclosingType() != null)
103 // sourceTypes[0] = sourceTypes[0].getEnclosingType();
105 CompilationResult result =
106 new CompilationResult(sourceTypes[0].getFileName(), 1, 1, 10); //this.options.maxProblemsPerUnit);
108 // need to hold onto this
109 CompilationUnitDeclaration unit =
110 SourceTypeConverter.buildCompilationUnit(
111 sourceTypes,//sourceTypes[0] is always toplevel here
112 true, // need field and methods
113 true, // need member types
114 true, // need field initialization
115 lookupEnvironment.problemReporter,
119 this.lookupEnvironment.buildTypeBindings(unit);
120 this.lookupEnvironment.completeTypeBindings(unit, true);
125 * Low-level API performing the actual compilation
127 protected static IErrorHandlingPolicy getHandlingPolicy() {
128 return DefaultErrorHandlingPolicies.proceedWithAllProblems();
131 protected static INameEnvironment getNameEnvironment(ICompilationUnit sourceUnit)
132 throws JavaModelException {
133 return (SearchableEnvironment) ((JavaProject) sourceUnit.getJavaProject())
134 .getSearchableNameEnvironment();
138 * Answer the component to which will be handed back compilation results from the compiler
140 protected static ICompilerRequestor getRequestor() {
141 return new ICompilerRequestor() {
142 public void acceptResult(CompilationResult compilationResult) {
147 protected static IProblemFactory getProblemFactory(
148 final char[] fileName,
149 final IProblemRequestor problemRequestor,
150 final IProgressMonitor monitor) {
152 return new DefaultProblemFactory(Locale.getDefault()) {
153 public IProblem createProblem(
154 char[] originatingFileName,
156 String[] problemArguments,
157 String[] messageArguments,
163 if (monitor != null && monitor.isCanceled()){
164 throw new AbortCompilation(true, null); // silent abort
177 // only report local problems
178 if (CharOperation.equals(originatingFileName, fileName)){
179 if (JavaModelManager.VERBOSE){
180 System.out.println("PROBLEM FOUND while reconciling : "+problem.getMessage());//$NON-NLS-1$
182 problemRequestor.acceptProblem(problem);
184 if (monitor != null && monitor.isCanceled()){
185 throw new AbortCompilation(true, null); // silent abort
193 public static CompilationUnitDeclaration process(
194 CompilationUnitDeclaration unit,
195 ICompilationUnit unitElement,
198 WorkingCopyOwner workingCopyOwner,
199 IProblemRequestor problemRequestor,
200 IProblemFactory problemFactory,
202 IProgressMonitor monitor)
203 throws JavaModelException {
205 char[] fileName = unitElement.getElementName().toCharArray();
207 JavaProject project = (JavaProject) unitElement.getJavaProject();
208 CompilationUnitProblemFinder problemFinder =
209 new CompilationUnitProblemFinder(
210 project.newSearchableNameEnvironment(workingCopyOwner),
212 project.getOptions(true),
215 if (parser != null) {
216 problemFinder.parser = parser;
221 IPackageFragment packageFragment = (IPackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
222 char[][] expectedPackageName = null;
223 if (packageFragment != null){
224 expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
227 unit = problemFinder.resolve(
228 new BasicCompilationUnit(
231 new String(fileName),
233 true, // verify methods
234 true); //, // analyze code
235 //true); // generate code
237 problemFinder.resolve(
239 null, // no need for source
240 true, // verify methods
241 true); //, // analyze code
242 // true); // generate code
244 reportProblems(unit, problemRequestor, monitor);
246 } catch(RuntimeException e) {
247 // avoid breaking other tools due to internal compiler failure (40334)
248 Util.log(e, "Exception occurred during problem detection: "); //$NON-NLS-1$
249 throw new JavaModelException(e, IJavaModelStatusConstants.COMPILER_FAILURE);
251 if (cleanupCU && unit != null) {
254 problemFinder.lookupEnvironment.reset();
257 public static CompilationUnitDeclaration process(
258 ICompilationUnit unitElement,
260 WorkingCopyOwner workingCopyOwner,
261 IProblemRequestor problemRequestor,
263 IProgressMonitor monitor)
264 throws JavaModelException {
266 return process(null/*no CompilationUnitDeclaration*/, unitElement, contents, null/*use default Parser*/, workingCopyOwner, problemRequestor, new DefaultProblemFactory(), cleanupCU, monitor);
268 public static CompilationUnitDeclaration process(
269 ICompilationUnit unitElement,
270 IProblemRequestor problemRequestor,
271 IProgressMonitor monitor)
272 throws JavaModelException {
274 char[] fileName = unitElement.getElementName().toCharArray();
276 IJavaProject project = unitElement.getJavaProject();
277 CompilationUnitProblemFinder problemFinder =
278 new CompilationUnitProblemFinder(
279 getNameEnvironment(unitElement),
281 project.getOptions(true),
283 getProblemFactory(fileName, problemRequestor, monitor));
285 CompilationUnitDeclaration unit = null;
287 String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
289 IPackageFragment packageFragment = (IPackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
290 char[][] expectedPackageName = null;
291 if (packageFragment != null){
292 expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
294 unit = problemFinder.resolve(
295 new BasicCompilationUnit(
296 unitElement.getSource().toCharArray(),
298 new String(fileName),
300 true, // verify methods
301 true); // analyze code
302 // true); // generate code
308 problemFinder.lookupEnvironment.reset();
311 private static void reportProblems(CompilationUnitDeclaration unit, IProblemRequestor problemRequestor, IProgressMonitor monitor) {
312 CompilationResult unitResult = unit.compilationResult;
313 IProblem[] problems = unitResult.getAllProblems();
314 for (int i = 0, problemLength = problems == null ? 0 : problems.length; i < problemLength; i++) {
315 if (JavaModelManager.VERBOSE){
316 System.out.println("PROBLEM FOUND while reconciling : "+problems[i].getMessage());//$NON-NLS-1$
318 if (monitor != null && monitor.isCanceled()) break;
320 problemRequestor.acceptProblem(problems[i]);