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.ast.CompilationUnitDeclaration;
34 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
35 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
36 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
37 import net.sourceforge.phpdt.internal.compiler.parser.SourceTypeConverter;
38 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
39 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
40 import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
41 import net.sourceforge.phpdt.internal.core.util.Util;
43 import org.eclipse.core.runtime.IProgressMonitor;
46 * Responsible for resolving types inside a compilation unit being reconciled,
47 * reporting the discovered problems to a given IProblemRequestor.
49 public class CompilationUnitProblemFinder extends Compiler {
52 * Answer a new CompilationUnitVisitor using the given name environment and
53 * compiler options. The environment and options will be in effect for the
54 * lifetime of the compiler. When the compiler is run, compilation results
55 * are sent to the given requestor.
58 * org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
59 * Environment used by the compiler in order to resolve type and
60 * package names. The name environment implements the actual
61 * connection of the compiler to the outside world (e.g. in batch
62 * mode the name environment is performing pure file accesses,
63 * reuse previous build state or connection to repositories).
64 * Note: the name environment is responsible for implementing the
65 * actual classpath rules.
68 * org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
69 * Configurable part for problem handling, allowing the compiler
70 * client to specify the rules for handling problems (stop on
71 * first error or accumulate them all) and at the same time
72 * perform some actions such as opening a dialog in UI when
73 * compiling interactively.
74 * @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
77 * The settings to use for the resolution.
80 * org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
81 * Component which will receive and persist all compilation
82 * results and is intended to consume them as they are produced.
83 * Typically, in a batch compiler, it is responsible for writing
84 * out the actual .class files to the file system.
85 * @see org.eclipse.jdt.internal.compiler.api.CompilationResult
87 * @param problemFactory
88 * org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
89 * Factory used inside the compiler to create problem
90 * descriptors. It allows the compiler client to supply its own
91 * representation of compilation problems in order to avoid
92 * object conversions. Note that the factory is not supposed to
93 * accumulate the created problems, the compiler will gather them
94 * all and hand them back as part of the compilation unit result.
96 protected CompilationUnitProblemFinder(INameEnvironment environment,
97 IErrorHandlingPolicy policy, Map settings,
98 ICompilerRequestor requestor, IProblemFactory problemFactory) {
100 super(environment, policy, settings, requestor, problemFactory, true);
104 * Add additional source types
106 public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
107 // ensure to jump back to toplevel type for first one (could be a
109 // while (sourceTypes[0].getEnclosingType() != null)
110 // sourceTypes[0] = sourceTypes[0].getEnclosingType();
112 CompilationResult result = new CompilationResult(sourceTypes[0]
113 .getFileName(), 1, 1, 10); // this.options.maxProblemsPerUnit);
115 // need to hold onto this
116 CompilationUnitDeclaration unit = SourceTypeConverter
117 .buildCompilationUnit(sourceTypes,// sourceTypes[0] is always
119 true, // need field and methods
120 true, // need member types
121 true, // need field initialization
122 lookupEnvironment.problemReporter, result);
125 this.lookupEnvironment.buildTypeBindings(unit);
126 this.lookupEnvironment.completeTypeBindings(unit, true);
131 * Low-level API performing the actual compilation
133 protected static IErrorHandlingPolicy getHandlingPolicy() {
134 return DefaultErrorHandlingPolicies.proceedWithAllProblems();
137 protected static INameEnvironment getNameEnvironment(
138 ICompilationUnit sourceUnit) throws JavaModelException {
139 return (SearchableEnvironment) ((JavaProject) sourceUnit
140 .getJavaProject()).getSearchableNameEnvironment();
144 * Answer the component to which will be handed back compilation results
147 protected static ICompilerRequestor getRequestor() {
148 return new ICompilerRequestor() {
149 public void acceptResult(CompilationResult compilationResult) {
154 protected static IProblemFactory getProblemFactory(final char[] fileName,
155 final IProblemRequestor problemRequestor,
156 final IProgressMonitor monitor) {
158 return new DefaultProblemFactory(Locale.getDefault()) {
159 public IProblem createProblem(char[] originatingFileName,
160 int problemId, String[] problemArguments,
161 String[] messageArguments, int severity, int startPosition,
162 int endPosition, int lineNumber) {
164 if (monitor != null && monitor.isCanceled()) {
165 throw new AbortCompilation(true, null); // silent abort
168 IProblem problem = super.createProblem(originatingFileName,
169 problemId, problemArguments, messageArguments,
170 severity, startPosition, endPosition, lineNumber);
171 // only report local problems
172 if (CharOperation.equals(originatingFileName, fileName)) {
173 if (JavaModelManager.VERBOSE) {
175 .println("PROBLEM FOUND while reconciling : " + problem.getMessage());//$NON-NLS-1$
177 problemRequestor.acceptProblem(problem);
179 if (monitor != null && monitor.isCanceled()) {
180 throw new AbortCompilation(true, null); // silent abort
188 public static CompilationUnitDeclaration process(
189 CompilationUnitDeclaration unit, ICompilationUnit unitElement,
190 char[] contents, UnitParser parser,
191 WorkingCopyOwner workingCopyOwner,
192 IProblemRequestor problemRequestor, IProblemFactory problemFactory,
193 boolean cleanupCU, IProgressMonitor monitor)
194 throws JavaModelException {
196 char[] fileName = unitElement.getElementName().toCharArray();
198 JavaProject project = (JavaProject) unitElement.getJavaProject();
199 CompilationUnitProblemFinder problemFinder = new CompilationUnitProblemFinder(
200 project.newSearchableNameEnvironment(workingCopyOwner),
201 getHandlingPolicy(), project.getOptions(true), getRequestor(),
203 if (parser != null) {
204 problemFinder.parser = parser;
209 IPackageFragment packageFragment = (IPackageFragment) unitElement
210 .getAncestor(IJavaElement.PACKAGE_FRAGMENT);
211 char[][] expectedPackageName = null;
212 if (packageFragment != null) {
213 expectedPackageName = CharOperation.splitOn('.',
214 packageFragment.getElementName().toCharArray());
217 unit = problemFinder.resolve(
218 new BasicCompilationUnit(contents, expectedPackageName,
219 new String(fileName), unitElement), true, // verify
221 true); // , // analyze code
222 // true); // generate code
224 problemFinder.resolve(unit, null, // no need for source
225 true, // verify methods
226 true); // , // analyze code
227 // true); // generate code
229 reportProblems(unit, problemRequestor, monitor);
231 } catch (RuntimeException e) {
232 // avoid breaking other tools due to internal compiler failure
234 Util.log(e, "Exception occurred during problem detection: "); //$NON-NLS-1$
235 throw new JavaModelException(e,
236 IJavaModelStatusConstants.COMPILER_FAILURE);
238 if (cleanupCU && unit != null) {
241 problemFinder.lookupEnvironment.reset();
245 public static CompilationUnitDeclaration process(
246 ICompilationUnit unitElement, char[] contents,
247 WorkingCopyOwner workingCopyOwner,
248 IProblemRequestor problemRequestor, boolean cleanupCU,
249 IProgressMonitor monitor) throws JavaModelException {
251 return process(null/* no CompilationUnitDeclaration */, unitElement,
252 contents, null/* use default Parser */, workingCopyOwner,
253 problemRequestor, new DefaultProblemFactory(), cleanupCU,
257 public static CompilationUnitDeclaration process(
258 ICompilationUnit unitElement, IProblemRequestor problemRequestor,
259 IProgressMonitor monitor) throws JavaModelException {
261 char[] fileName = unitElement.getElementName().toCharArray();
263 IJavaProject project = unitElement.getJavaProject();
264 CompilationUnitProblemFinder problemFinder = new CompilationUnitProblemFinder(
265 getNameEnvironment(unitElement), getHandlingPolicy(), project
266 .getOptions(true), getRequestor(), getProblemFactory(
267 fileName, problemRequestor, monitor));
269 CompilationUnitDeclaration unit = null;
271 String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
273 IPackageFragment packageFragment = (IPackageFragment) unitElement
274 .getAncestor(IJavaElement.PACKAGE_FRAGMENT);
275 char[][] expectedPackageName = null;
276 if (packageFragment != null) {
277 expectedPackageName = CharOperation.splitOn('.',
278 packageFragment.getElementName().toCharArray());
280 unit = problemFinder.resolve(new BasicCompilationUnit(unitElement
281 .getSource().toCharArray(), expectedPackageName,
282 new String(fileName), encoding), true, // verify methods
283 true); // analyze code
284 // true); // generate code
290 problemFinder.lookupEnvironment.reset();
294 private static void reportProblems(CompilationUnitDeclaration unit,
295 IProblemRequestor problemRequestor, IProgressMonitor monitor) {
296 CompilationResult unitResult = unit.compilationResult;
297 IProblem[] problems = unitResult.getAllProblems();
298 for (int i = 0, problemLength = problems == null ? 0 : problems.length; i < problemLength; i++) {
299 if (JavaModelManager.VERBOSE) {
301 .println("PROBLEM FOUND while reconciling : " + problems[i].getMessage());//$NON-NLS-1$
303 if (monitor != null && monitor.isCanceled())
306 problemRequestor.acceptProblem(problems[i]);