blob: ca389c843859570ef7cbcd0c5fb1efdc33e582e6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core;
import java.util.Locale;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
/**
* Responsible for resolving types inside a compilation unit being reconciled,
* reporting the discovered problems to a given IProblemRequestor.
*/
public class CompilationUnitProblemFinder extends Compiler {
/**
* Answer a new CompilationUnitVisitor using the given name environment and compiler options.
* The environment and options will be in effect for the lifetime of the compiler.
* When the compiler is run, compilation results are sent to the given requestor.
*
* @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
* Environment used by the compiler in order to resolve type and package
* names. The name environment implements the actual connection of the compiler
* to the outside world (e.g. in batch mode the name environment is performing
* pure file accesses, reuse previous build state or connection to repositories).
* Note: the name environment is responsible for implementing the actual classpath
* rules.
*
* @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
* Configurable part for problem handling, allowing the compiler client to
* specify the rules for handling problems (stop on first error or accumulate
* them all) and at the same time perform some actions such as opening a dialog
* in UI when compiling interactively.
* @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
*
* @param settings The settings to use for the resolution.
*
* @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
* Component which will receive and persist all compilation results and is intended
* to consume them as they are produced. Typically, in a batch compiler, it is
* responsible for writing out the actual .class files to the file system.
* @see org.eclipse.jdt.internal.compiler.api.CompilationResult
*
* @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
* Factory used inside the compiler to create problem descriptors. It allows the
* compiler client to supply its own representation of compilation problems in
* order to avoid object conversions. Note that the factory is not supposed
* to accumulate the created problems, the compiler will gather them all and hand
* them back as part of the compilation unit result.
*/
protected CompilationUnitProblemFinder(
INameEnvironment environment,
IErrorHandlingPolicy policy,
Map settings,
ICompilerRequestor requestor,
IProblemFactory problemFactory) {
super(environment, policy, settings, requestor, problemFactory, true);
}
/**
* Add additional source types
*/
public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
// ensure to jump back to toplevel type for first one (could be a member)
// while (sourceTypes[0].getEnclosingType() != null)
// sourceTypes[0] = sourceTypes[0].getEnclosingType();
CompilationResult result =
new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.options.maxProblemsPerUnit);
// need to hold onto this
CompilationUnitDeclaration unit =
SourceTypeConverter.buildCompilationUnit(
sourceTypes,//sourceTypes[0] is always toplevel here
true, // need field and methods
true, // need member types
true, // need field initialization
lookupEnvironment.problemReporter,
result);
if (unit != null) {
this.lookupEnvironment.buildTypeBindings(unit);
this.lookupEnvironment.completeTypeBindings(unit, true);
}
}
/*
* Low-level API performing the actual compilation
*/
protected static IErrorHandlingPolicy getHandlingPolicy() {
return DefaultErrorHandlingPolicies.proceedWithAllProblems();
}
protected static INameEnvironment getNameEnvironment(ICompilationUnit sourceUnit)
throws JavaModelException {
return (SearchableEnvironment) ((JavaProject) sourceUnit.getJavaProject())
.getSearchableNameEnvironment();
}
/*
* Answer the component to which will be handed back compilation results from the compiler
*/
protected static ICompilerRequestor getRequestor() {
return new ICompilerRequestor() {
public void acceptResult(CompilationResult compilationResult) {
}
};
}
protected static IProblemFactory getProblemFactory(
final char[] fileName,
final IProblemRequestor problemRequestor,
final IProgressMonitor monitor) {
return new DefaultProblemFactory(Locale.getDefault()) {
public IProblem createProblem(
char[] originatingFileName,
int problemId,
String[] problemArguments,
String[] messageArguments,
int severity,
int startPosition,
int endPosition,
int lineNumber) {
if (monitor != null && monitor.isCanceled()){
throw new AbortCompilation(true, null); // silent abort
}
IProblem problem =
super.createProblem(
originatingFileName,
problemId,
problemArguments,
messageArguments,
severity,
startPosition,
endPosition,
lineNumber);
// only report local problems
if (CharOperation.equals(originatingFileName, fileName)){
if (JavaModelManager.VERBOSE){
System.out.println("PROBLEM FOUND while reconciling : "+problem.getMessage());//$NON-NLS-1$
}
problemRequestor.acceptProblem(problem);
}
if (monitor != null && monitor.isCanceled()){
throw new AbortCompilation(true, null); // silent abort
}
return problem;
}
};
}
public static CompilationUnitDeclaration process(
ICompilationUnit unitElement,
IProblemRequestor problemRequestor,
IProgressMonitor monitor)
throws JavaModelException {
char[] fileName = unitElement.getElementName().toCharArray();
IJavaProject project = unitElement.getJavaProject();
CompilationUnitProblemFinder problemFinder =
new CompilationUnitProblemFinder(
getNameEnvironment(unitElement),
getHandlingPolicy(),
project.getOptions(true),
getRequestor(),
getProblemFactory(fileName, problemRequestor, monitor));
CompilationUnitDeclaration unit = null;
try {
String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
IPackageFragment packageFragment = (IPackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
char[][] expectedPackageName = null;
if (packageFragment != null){
expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
}
unit = problemFinder.resolve(
new BasicCompilationUnit(
unitElement.getSource().toCharArray(),
expectedPackageName,
new String(fileName),
encoding),
true, // verify methods
true, // analyze code
true); // generate code
return unit;
} finally {
if (unit != null) {
unit.cleanUp();
}
problemFinder.lookupEnvironment.reset();
}
}
}