blob: 5394f841969df5e067cef918e9bbc1e9c093f0f9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.parser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Locale;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.codeassist.complete.CompletionParser;
import org.eclipse.jdt.internal.codeassist.select.SelectionParser;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.DocumentElementParser;
import org.eclipse.jdt.internal.compiler.IDocumentElementRequestor;
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
import org.eclipse.jdt.internal.compiler.SourceElementParser;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.core.search.indexing.IndexingParser;
import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
public class AbstractSyntaxTreeTest extends AbstractCompilerTest implements IDocumentElementRequestor, ISourceElementRequestor {
protected static final int CHECK_PARSER = 0x1;
protected static final int CHECK_COMPLETION_PARSER = 0x2;
protected static final int CHECK_SELECTION_PARSER = 0x4;
protected static final int CHECK_DOCUMENT_ELEMENT_PARSER = 0x8;
protected static final int CHECK_COMMENT_RECORDER_PARSER = 0x10;
protected static final int CHECK_SOURCE_ELEMENT_PARSER = 0x20;
protected static final int CHECK_INDEXING_PARSER = 0x40;
protected static final int CHECK_JAVAC_PARSER = 0x80;
protected static int CHECK_ALL = (CHECK_PARSER | CHECK_COMPLETION_PARSER | CHECK_SELECTION_PARSER |
CHECK_DOCUMENT_ELEMENT_PARSER | CHECK_COMMENT_RECORDER_PARSER |
//{ObjectTeams: with our grammar testing the IndexingParser is even less useful (creates false positives), just disable it:
/* orig:
CHECK_SOURCE_ELEMENT_PARSER | CHECK_INDEXING_PARSER);
:giro */
CHECK_SOURCE_ELEMENT_PARSER /*| CHECK_INDEXING_PARSER */);
// SH}
public static boolean optimizeStringLiterals = false;
private String referenceCompiler;
private String referenceCompilerTestsScratchArea;
public AbstractSyntaxTreeTest(String name, String referenceCompiler, String referenceCompilerTestsScratchArea) {
super(name);
this.referenceCompiler = referenceCompiler;
this.referenceCompilerTestsScratchArea = referenceCompilerTestsScratchArea;
}
public void checkParse(int parserToCheck, char[] source, String expectedSyntaxErrorDiagnosis,
String testName, String expectedUnitToString, ASTVisitor visitor) throws IOException {
CompilerOptions options = new CompilerOptions(getCompilerOptions());
options.complianceLevel = ClassFileConstants.JDK1_8;
options.sourceLevel = ClassFileConstants.JDK1_8;
options.targetJDK = ClassFileConstants.JDK1_8;
checkParse(parserToCheck, source, expectedSyntaxErrorDiagnosis, testName, expectedUnitToString, visitor, options);
}
public void checkParse(int parserToCheck, char[] source, String expectedSyntaxErrorDiagnosis,
String testName, String expectedUnitToString, ASTVisitor visitor, CompilerOptions options) throws IOException {
ICompilationUnit sourceUnit = null;
CompilationResult compilationResult = null;
CompilationUnitDeclaration unit = null;
if (this.referenceCompiler != null && (parserToCheck & CHECK_JAVAC_PARSER) != 0) {
String javaFilePath = this.referenceCompilerTestsScratchArea + "\\Xyz.java";
File f = new File(javaFilePath);
FileOutputStream o = new FileOutputStream(f);
OutputStreamWriter w = new OutputStreamWriter(o);
w.write(source);
w.close();
Process p = Runtime.getRuntime().exec (new String[] { this.referenceCompiler, "-sourcepath", this.referenceCompilerTestsScratchArea, javaFilePath }, null, new File(this.referenceCompilerTestsScratchArea));
try {
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String line;
while ((line = stderr.readLine())!= null)
System.out.println(line);
while ((line = stdout.readLine())!= null)
System.out.println(line);
assertTrue("javac unhappy", p.waitFor() == 0);
} catch (InterruptedException e) {
System.err.println("Skipped javac behavior check due to interrupt...");
}
}
if ((parserToCheck & CHECK_PARSER) != 0) {
Parser parser1 =
new Parser(
new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
options,
new DefaultProblemFactory(Locale.getDefault())),
optimizeStringLiterals);
sourceUnit = new CompilationUnit(source, testName, null);
compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
unit = parser1.parse(sourceUnit, compilationResult);
parser1.getMethodBodies(unit);
assertDianosticEquals(expectedSyntaxErrorDiagnosis, testName, compilationResult);
assertParseTreeEquals(expectedUnitToString, unit.toString());
if (visitor != null) {
unit.traverse(visitor, (CompilationUnitScope) null);
}
parser1 = null;
}
if ((parserToCheck & CHECK_COMPLETION_PARSER) != 0) {
CompletionParser parser2 = new CompletionParser(
new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
options,
new DefaultProblemFactory(Locale.getDefault())),
false);
compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
unit = parser2.parse(sourceUnit, compilationResult, Integer.MAX_VALUE);
parser2.getMethodBodies(unit);
assertDianosticEquals(expectedSyntaxErrorDiagnosis, testName, compilationResult);
assertParseTreeEquals(expectedUnitToString, unit.toString());
parser2 = null;
}
if ((parserToCheck & CHECK_SELECTION_PARSER) != 0) {
SelectionParser parser3 = new SelectionParser(
new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
options,
new DefaultProblemFactory(Locale.getDefault())));
compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
unit = parser3.parse(sourceUnit, compilationResult, Integer.MAX_VALUE, Integer.MAX_VALUE);
parser3.getMethodBodies(unit);
assertDianosticEquals(expectedSyntaxErrorDiagnosis, testName, compilationResult);
assertParseTreeEquals(expectedUnitToString, unit.toString());
parser3 = null;
}
if ((parserToCheck & CHECK_DOCUMENT_ELEMENT_PARSER) != 0) {
DocumentElementParser parser4 = new DocumentElementParser(
this,
new DefaultProblemFactory(Locale.getDefault()),
options);
compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
unit = parser4.parse(sourceUnit, compilationResult);
parser4.getMethodBodies(unit);
assertDianosticEquals(expectedSyntaxErrorDiagnosis, testName, compilationResult);
assertParseTreeEquals(expectedUnitToString, unit.toString());
parser4 = null;
}
if ((parserToCheck & CHECK_COMMENT_RECORDER_PARSER) != 0) {
CommentRecorderParser parser5 = new CommentRecorderParser(
new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
options,
new DefaultProblemFactory(Locale.getDefault())),
optimizeStringLiterals);
compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
unit = parser5.parse(sourceUnit, compilationResult);
parser5.getMethodBodies(unit);
assertDianosticEquals(expectedSyntaxErrorDiagnosis, testName, compilationResult);
assertParseTreeEquals(expectedUnitToString, unit.toString());
parser5 = null;
}
if ((parserToCheck & CHECK_SOURCE_ELEMENT_PARSER) != 0) {
SourceElementParser parser6 = new SourceElementParser(this,
new DefaultProblemFactory(Locale.getDefault()),
options,
true,
optimizeStringLiterals);
compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
unit = parser6.parse(sourceUnit, compilationResult);
parser6.getMethodBodies(unit);
assertDianosticEquals(expectedSyntaxErrorDiagnosis, testName, compilationResult);
assertParseTreeEquals(expectedUnitToString, unit.toString());
parser6 = null;
}
if ((parserToCheck & CHECK_INDEXING_PARSER) != 0) {
IndexingParser parser7 = new IndexingParser(this,
new DefaultProblemFactory(Locale.getDefault()),
options,
true,
optimizeStringLiterals, false);
compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
unit = parser7.parse(sourceUnit, compilationResult);
parser7.getMethodBodies(unit);
assertDianosticEquals(expectedSyntaxErrorDiagnosis, testName, compilationResult);
assertParseTreeEquals(expectedUnitToString, unit.toString());
parser7 = null;
}
}
public void checkParse(int parserToCheck, char[] source, String expectedSyntaxErrorDiagnosis,
String testName, String expectedUnitToString) throws IOException {
checkParse(parserToCheck, source, expectedSyntaxErrorDiagnosis, testName, expectedUnitToString, null);
}
public void checkParse(char[] source, String expectedSyntaxErrorDiagnosis, String testName, String expectedUnitToString)
throws IOException {
checkParse(CHECK_ALL, source, expectedSyntaxErrorDiagnosis, testName, expectedUnitToString);
}
public void checkParse(char[] source, String expectedSyntaxErrorDiagnosis, String testName,
String expectedUnitToString, ASTVisitor visitor) throws IOException {
checkParse(CHECK_ALL, source, expectedSyntaxErrorDiagnosis, testName, expectedUnitToString, visitor);
}
private void assertParseTreeEquals(String expectedUnitToString, String computedUnitToString) {
if (expectedUnitToString == null) { // just checking that we are able to digest.
return;
}
if (!expectedUnitToString.equals(computedUnitToString)) {
System.out.println(Util.displayString(computedUnitToString));
}
assertEquals("Parse Tree is wrong",
Util.convertToIndependantLineDelimiter(expectedUnitToString),
Util.convertToIndependantLineDelimiter(computedUnitToString));
}
private void assertDianosticEquals(String expectedSyntaxErrorDiagnosis, String testName, CompilationResult compilationResult) {
String computedSyntaxErrorDiagnosis = getCompilerMessages(compilationResult);
assertEquals(
"Invalid syntax error diagnosis" + testName,
Util.convertToIndependantLineDelimiter(expectedSyntaxErrorDiagnosis),
Util.convertToIndependantLineDelimiter(computedSyntaxErrorDiagnosis));
}
private String getCompilerMessages(CompilationResult compilationResult) {
StringBuffer buffer = new StringBuffer(100);
if (compilationResult.hasProblems() || compilationResult.hasTasks()) {
CategorizedProblem[] problems = compilationResult.getAllProblems();
int count = problems.length;
int problemCount = 0;
char[] unitSource = compilationResult.compilationUnit.getContents();
for (int i = 0; i < count; i++) {
if (problems[i] != null) {
if (problemCount == 0)
buffer.append("----------\n");
problemCount++;
buffer.append(problemCount + (problems[i].isError() ? ". ERROR" : ". WARNING"));
buffer.append(" in " + new String(problems[i].getOriginatingFileName()).replace('/', '\\'));
try {
buffer.append(((DefaultProblem)problems[i]).errorReportSource(unitSource));
buffer.append("\n");
buffer.append(problems[i].getMessage());
buffer.append("\n");
} catch (Exception e) {
}
buffer.append("----------\n");
}
}
}
String computedSyntaxErrorDiagnosis = buffer.toString();
return computedSyntaxErrorDiagnosis;
}
public void acceptImport(int declarationStart, int declarationEnd, int[] javaDocPositions,
char[] name, int nameStartPosition, boolean onDemand, int modifiers) {
}
public void acceptInitializer(int declarationStart, int declarationEnd, int[] javaDocPositions,
int modifiers, int modifiersStart, int bodyStart, int bodyEnd) {
}
public void acceptLineSeparatorPositions(int[] positions) {
}
public void acceptPackage(int declarationStart, int declarationEnd, int[] javaDocPositions,
char[] name, int nameStartPosition) {
}
public void acceptProblem(CategorizedProblem problem) {
}
public void enterClass(int declarationStart, int[] javaDocPositions, int modifiers,
int modifiersStart, int classStart, char[] name, int nameStart, int nameEnd,
char[] superclass, int superclassStart, int superclassEnd, char[][] superinterfaces, int[] superinterfaceStarts,
int[] superinterfaceEnds, int bodyStart) {
}
public void enterCompilationUnit() {
}
public void enterConstructor(int declarationStart, int[] javaDocPositions, int modifiers,
int modifiersStart, char[] name, int nameStart, int nameEnd, char[][] parameterTypes,
int[] parameterTypeStarts, int[] parameterTypeEnds, char[][] parameterNames, int[] parameterNameStarts, int[] parameterNameEnds,
int parametersEnd, char[][] exceptionTypes, int[] exceptionTypeStarts, int[] exceptionTypeEnds, int bodyStart) {
}
public void enterField(int declarationStart, int[] javaDocPositions, int modifiers,
int modifiersStart, char[] type, int typeStart, int typeEnd, int typeDimensionCount,
char[] name, int nameStart, int nameEnd, int extendedTypeDimensionCount, int extendedTypeDimensionEnd) {
}
public void enterInterface(int declarationStart, int[] javaDocPositions, int modifiers,
int modifiersStart, int interfaceStart, char[] name, int nameStart, int nameEnd,
char[][] superinterfaces, int[] superinterfaceStarts, int[] superinterfaceEnds, int bodyStart) {
}
public void enterMethod(int declarationStart, int[] javaDocPositions, int modifiers,
int modifiersStart, char[] returnType, int returnTypeStart, int returnTypeEnd, int returnTypeDimensionCount,
char[] name, int nameStart, int nameEnd, char[][] parameterTypes, int[] parameterTypeStarts,
int[] parameterTypeEnds, char[][] parameterNames, int[] parameterNameStarts, int[] parameterNameEnds, int parametersEnd,
int extendedReturnTypeDimensionCount, int extendedReturnTypeDimensionEnd, char[][] exceptionTypes, int[] exceptionTypeStarts, int[] exceptionTypeEnds,
int bodyStart) {
}
public void exitClass(int bodyEnd, int declarationEnd) {
}
public void exitCompilationUnit(int declarationEnd) {
}
public void exitConstructor(int bodyEnd, int declarationEnd) {
}
public void exitField(int bodyEnd, int declarationEnd) {
}
public void exitInterface(int bodyEnd, int declarationEnd) {
}
public void exitMethod(int bodyEnd, int declarationEnd) {
}
public void acceptAnnotationTypeReference(char[][] annotation, int sourceStart,
int sourceEnd) {
}
public void acceptAnnotationTypeReference(char[] annotation, int sourcePosition) {
}
public void acceptConstructorReference(char[] typeName, int argCount,
int sourcePosition) {
}
public void acceptFieldReference(char[] fieldName, int sourcePosition) {
}
public void acceptImport(int declarationStart, int declarationEnd, int nameStart,
int nameEnd, char[][] tokens, boolean onDemand, int modifiers) {
}
public void acceptMethodReference(char[] methodName, int argCount, int sourcePosition) {
}
public void acceptPackage(ImportReference importReference) {
}
public void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd) {
}
public void acceptTypeReference(char[] typeName, int sourcePosition) {
}
public void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd) {
}
public void acceptUnknownReference(char[] name, int sourcePosition) {
}
public void enterConstructor(MethodInfo methodInfo) {
}
public void enterField(FieldInfo fieldInfo) {
}
public void enterInitializer(int declarationStart, int modifiers) {
}
public void enterMethod(MethodInfo methodInfo) {
}
public void enterType(TypeInfo typeInfo) {
}
public void exitConstructor(int declarationEnd) {
}
public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
}
public void exitInitializer(int declarationEnd) {
}
public void exitMethod(int declarationEnd, Expression defaultValue) {
}
public void exitType(int declarationEnd) {
}
@Override
public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
}
//{ObjectTeams: new methods
public void acceptBaseReference(char[][] typeName, int sourceStart, int sourceEnd) {
}
public void enterCalloutMapping(CalloutInfo info) {
}
public void enterCalloutToFieldMapping(CalloutToFieldInfo info) {
}
public void enterCallinMapping(CallinInfo info) {
}
public void exitCalloutMapping(int sourceEnd, int declarationSourceEnd) {
}
public void exitCalloutToFieldMapping(int sourceEnd, int declarationSourceEnd) {
}
public void exitCallinMapping(int sourceEnd, int declarationSourceEnd) {
}
// SH}
}