| /******************************************************************************* |
| * 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} |
| } |