new version with WorkingCopy Management
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / CompilationUnitProblemFinder.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.util.Locale;
14
15 import net.sourceforge.phpdt.core.ICompilationUnit;
16 import net.sourceforge.phpdt.core.IJavaElement;
17 import net.sourceforge.phpdt.core.IJavaProject;
18 import net.sourceforge.phpdt.core.IPackageFragment;
19 import net.sourceforge.phpdt.core.IProblemRequestor;
20 import net.sourceforge.phpdt.core.JavaModelException;
21 import net.sourceforge.phpdt.core.compiler.CharOperation;
22 import net.sourceforge.phpdt.core.compiler.IProblem;
23 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
24 import net.sourceforge.phpdt.internal.compiler.Compiler;
25 import net.sourceforge.phpdt.internal.compiler.DefaultErrorHandlingPolicies;
26 import net.sourceforge.phpdt.internal.compiler.ICompilerRequestor;
27 import net.sourceforge.phpdt.internal.compiler.IErrorHandlingPolicy;
28 import net.sourceforge.phpdt.internal.compiler.IProblemFactory;
29 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
30 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
31 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
32 import net.sourceforge.phpdt.internal.compiler.parser.SourceTypeConverter;
33 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
34 import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
35 import net.sourceforge.phpeclipse.PHPCore;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
37
38 import org.eclipse.core.runtime.IProgressMonitor;
39
40 /**
41  * Responsible for resolving types inside a compilation unit being reconciled,
42  * reporting the discovered problems to a given IProblemRequestor.
43  */
44 public class CompilationUnitProblemFinder extends Compiler {
45
46         /**
47          * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
48          * The environment and options will be in effect for the lifetime of the compiler.
49          * When the compiler is run, compilation results are sent to the given requestor.
50          *
51          *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
52          *      Environment used by the compiler in order to resolve type and package
53          *      names. The name environment implements the actual connection of the compiler
54          *      to the outside world (e.g. in batch mode the name environment is performing
55          *      pure file accesses, reuse previous build state or connection to repositories).
56          *      Note: the name environment is responsible for implementing the actual classpath
57          *            rules.
58          *
59          *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
60          *      Configurable part for problem handling, allowing the compiler client to
61          *      specify the rules for handling problems (stop on first error or accumulate
62          *      them all) and at the same time perform some actions such as opening a dialog
63          *      in UI when compiling interactively.
64          *      @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
65          * 
66          *      @param settings The settings to use for the resolution.
67          *      
68          *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
69          *      Component which will receive and persist all compilation results and is intended
70          *      to consume them as they are produced. Typically, in a batch compiler, it is 
71          *      responsible for writing out the actual .class files to the file system.
72          *      @see org.eclipse.jdt.internal.compiler.api.CompilationResult
73          *
74          *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
75          *      Factory used inside the compiler to create problem descriptors. It allows the
76          *      compiler client to supply its own representation of compilation problems in
77          *      order to avoid object conversions. Note that the factory is not supposed
78          *      to accumulate the created problems, the compiler will gather them all and hand
79          *      them back as part of the compilation unit result.
80          */
81         protected CompilationUnitProblemFinder(
82                 INameEnvironment environment,
83                 IErrorHandlingPolicy policy,
84 //              Map settings,
85                 ICompilerRequestor requestor,
86                 IProblemFactory problemFactory) {
87
88                 super(environment, policy, requestor, problemFactory, true);//settings, requestor, problemFactory, true);
89         }
90
91         /**
92          * Add additional source types
93          */
94         public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
95                 // ensure to jump back to toplevel type for first one (could be a member)
96 //              while (sourceTypes[0].getEnclosingType() != null)
97 //                      sourceTypes[0] = sourceTypes[0].getEnclosingType();
98
99                 CompilationResult result =
100                         new CompilationResult(sourceTypes[0].getFileName(), 1, 1, 10); //this.options.maxProblemsPerUnit);
101
102                 // need to hold onto this
103                 CompilationUnitDeclaration unit =
104                         SourceTypeConverter.buildCompilationUnit(
105                                 sourceTypes,//sourceTypes[0] is always toplevel here
106                                 true, // need field and methods
107                                 true, // need member types
108                                 true, // need field initialization
109                                 lookupEnvironment.problemReporter,
110                                 result);
111
112                 if (unit != null) {
113                         this.lookupEnvironment.buildTypeBindings(unit);
114                         this.lookupEnvironment.completeTypeBindings(unit, true);
115                 }
116         }
117
118         /*
119          *  Low-level API performing the actual compilation
120          */
121         protected static IErrorHandlingPolicy getHandlingPolicy() {
122                 return DefaultErrorHandlingPolicies.proceedWithAllProblems();
123         }
124
125         protected static INameEnvironment getNameEnvironment(ICompilationUnit sourceUnit)
126                 throws JavaModelException {
127                 return (SearchableEnvironment) ((JavaProject) sourceUnit.getJavaProject())
128                         .getSearchableNameEnvironment();
129         }
130
131         /*
132          * Answer the component to which will be handed back compilation results from the compiler
133          */
134         protected static ICompilerRequestor getRequestor() {
135                 return new ICompilerRequestor() {
136                         public void acceptResult(CompilationResult compilationResult) {
137                         }
138                 };
139         }
140
141         protected static IProblemFactory getProblemFactory(
142                 final char[] fileName, 
143                 final IProblemRequestor problemRequestor,
144                 final IProgressMonitor monitor) {
145
146                 return new DefaultProblemFactory(Locale.getDefault()) {
147                         public IProblem createProblem(
148                                 char[] originatingFileName,
149                                 int problemId,
150                                 String[] problemArguments,
151                                 String[] messageArguments,
152                                 int severity,
153                                 int startPosition,
154                                 int endPosition,
155                                 int lineNumber) {
156
157                                 if (monitor != null && monitor.isCanceled()){
158                                         throw new AbortCompilation(true, null); // silent abort
159                                 }
160                                 
161                                 IProblem problem =
162                                         super.createProblem(
163                                                 originatingFileName,
164                                                 problemId,
165                                                 problemArguments,
166                                                 messageArguments,
167                                                 severity,
168                                                 startPosition,
169                                                 endPosition,
170                                                 lineNumber);
171                                 // only report local problems
172                                 if (CharOperation.equals(originatingFileName, fileName)){
173                                         if (JavaModelManager.VERBOSE){
174                                                 System.out.println("PROBLEM FOUND while reconciling : "+problem.getMessage());//$NON-NLS-1$
175                                         }
176                                         problemRequestor.acceptProblem(problem);
177                                 }
178                                 if (monitor != null && monitor.isCanceled()){
179                                         throw new AbortCompilation(true, null); // silent abort
180                                 }
181
182                                 return problem;
183                         }
184                 };
185         }
186
187         public static CompilationUnitDeclaration process(
188                 ICompilationUnit unitElement, 
189                 IProblemRequestor problemRequestor,
190                 IProgressMonitor monitor)
191                 throws JavaModelException {
192
193                 char[] fileName = unitElement.getElementName().toCharArray();
194                 
195                 IJavaProject project = unitElement.getJavaProject();
196                 CompilationUnitProblemFinder problemFinder =
197                         new CompilationUnitProblemFinder(
198                                 getNameEnvironment(unitElement),
199                                 getHandlingPolicy(),
200                         getRequestor(),
201                                                         getProblemFactory(fileName, problemRequestor, monitor));
202 //                              project.getOptions(true),
203 //                              getRequestor(),
204 //                              getProblemFactory(fileName, problemRequestor, monitor));
205
206                 CompilationUnitDeclaration unit = null;
207                 try {
208                         String encoding = project.getOption(PHPCore.CORE_ENCODING, true);
209                         
210                         IPackageFragment packageFragment = (IPackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
211                         char[][] expectedPackageName = null;
212                         if (packageFragment != null){
213                                 expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
214                         }
215                         unit = problemFinder.resolve(
216                                         new BasicCompilationUnit(
217                                                 unitElement.getSource().toCharArray(),
218                                                 expectedPackageName,
219                                                 new String(fileName),
220                                                 encoding),
221                                         true, // verify methods
222                                         true); // analyze code
223 //                                      true); // generate code
224                         return unit;
225                 } finally {
226                         if (unit != null) {
227                                 unit.cleanUp();
228                         }
229                         problemFinder.lookupEnvironment.reset();                        
230                 }
231         }
232 }       
233