blob: 83be48c65fd9f60dd57f5519ecf3a2c3310e8bac [file] [log] [blame]
/*
* Copyright (c) 2015 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
package org.eclipse.scout.sdk.core.model.ecj;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies.proceedWithAllProblems;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.scout.sdk.core.log.SdkLog;
import org.eclipse.scout.sdk.core.util.Strings;
public class EcjAstCompiler extends org.eclipse.jdt.internal.compiler.Compiler {
private final Map<CompilationUnitDeclaration, ICompilationUnit> m_sources = new HashMap<>();
@SuppressWarnings("resource")
protected EcjAstCompiler(INameEnvironment nameEnv, CompilerOptions opts) {
super(nameEnv, proceedWithAllProblems(), opts, new EmptyCompilerRequestor(), new CollectingProblemFactory(), new PrintWriter(new SdkLogWriter()), null);
lookupEnvironment.completeTypeBindings(); // must be called once so that the initial state is ready
}
static CompilerOptions createDefaultOptions() {
CompilerOptions result = new CompilerOptions();
result.produceDebugAttributes = 0;
result.complianceLevel = ClassFileConstants.JDK11;
result.originalComplianceLevel = result.complianceLevel;
result.sourceLevel = result.complianceLevel;
result.originalSourceLevel = result.complianceLevel;
result.targetJDK = result.complianceLevel;
result.verbose = SdkLog.isDebugEnabled();
result.preserveAllLocalVariables = true;
result.parseLiteralExpressionsAsConstants = false;
result.reportUnusedParameterIncludeDocCommentReference = false;
result.reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable = false;
result.suppressOptionalErrors = true;
result.performMethodsFullRecovery = false;
result.performStatementsRecovery = true;
result.generateClassFiles = false;
result.reportMissingOverrideAnnotationForInterfaceMethodImplementation = false;
result.ignoreSourceFolderWarningOption = true;
result.analyseResourceLeaks = false;
result.ignoreMethodBodies = true;
result.docCommentSupport = true; //we want javadoc start and end positions
result.isAnnotationBasedNullAnalysisEnabled = false; // do not enable (performance and NPE in JDT compiler)
result.storeAnnotations = true; // also parse annotations
return result;
}
@Override
protected synchronized void addCompilationUnit(ICompilationUnit sourceUnit, CompilationUnitDeclaration parsedUnit) {
super.addCompilationUnit(sourceUnit, parsedUnit);
m_sources.put(parsedUnit, sourceUnit);
}
public ICompilationUnit getSource(CompilationUnitDeclaration decl) {
return m_sources.get(decl);
}
/**
* @return null when no errors
*/
public synchronized List<String> getCompileErrors(CompilationUnitDeclaration unit) {
process(unit, 0);
CategorizedProblem[] errors = unit.compilationResult().getErrors();
if (errors == null || errors.length < 1) {
return emptyList();
}
return Arrays.stream(errors)
.map(CategorizedProblem::getMessage)
.collect(toList());
}
static final class CollectingProblemFactory extends DefaultProblemFactory {
@Override
public CategorizedProblem createProblem(char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition,
int lineNumber, int columnNumber) {
return createProblem(originatingFileName, problemId, problemArguments, 0, messageArguments, severity, startPosition, endPosition, lineNumber, columnNumber);
}
@Override
public CategorizedProblem createProblem(char[] originatingFileName, int problemId, String[] problemArguments,
int elaborationId, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber, int columnNumber) {
if ((severity & (ProblemSeverities.Error | ProblemSeverities.Fatal | ProblemSeverities.InternalError)) != 0) {
String txt = getLocalizedMessage(problemId, elaborationId, messageArguments);
StringBuilder msg = new StringBuilder(txt.length() + 128);
if (originatingFileName != null) {
msg.append(originatingFileName).append(':');
}
if (lineNumber > 0) {
msg.append(lineNumber);
}
if (msg.length() > 0) {
msg.append(' ');
}
msg.append(txt);
return new DefaultProblem(originatingFileName, msg.toString(), problemId, problemArguments, severity, startPosition, endPosition, lineNumber, columnNumber);
}
return null;
}
}
static final class EmptyCompilerRequestor implements ICompilerRequestor {
@Override
public void acceptResult(CompilationResult result) {
// we are not interested in the results
}
}
static final class SdkLogWriter extends Writer {
@Override
public void write(char[] cbuf, int off, int len) {
if (!SdkLog.isDebugEnabled()) {
return;
}
String msg = new String(cbuf, off, len);
if (Strings.hasText(msg)) {
SdkLog.debug(msg);
}
}
@Override
public void flush() {
// nothing to flush
}
@Override
public void close() {
// nothing to close
}
}
}