forked from eclipse-jdt/eclipse.jdt.core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide ability to track unused dependencies
- Loading branch information
Showing
3 changed files
with
231 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
210 changes: 210 additions & 0 deletions
210
...src/org/eclipse/jdt/core/tests/compiler/regression/NameEnvironmentAnswerListenerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2000, 2024 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 | ||
* Stephan Herrmann - Contributions for | ||
* bug 295551 - Add option to automatically promote all warnings to error | ||
* bug 185682 - Increment/decrement operators mark local variables as read | ||
* bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639) | ||
* bug 384663 - Package Based Annotation Compilation Error in JDT 3.8/4.2 (works in 3.7.2) | ||
* bug 386356 - Type mismatch error with annotations and generics | ||
* bug 331649 - [compiler][null] consider null annotations for fields | ||
* bug 376590 - Private fields with @Inject are ignored by unused field validation | ||
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis | ||
* Bug 469584 - ClassCastException in Annotation.detectStandardAnnotation (320) | ||
* Jesper S Moller - Contributions for | ||
* bug 384567 - [1.5][compiler] Compiler accepts illegal modifiers on package declaration | ||
* bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable | ||
* Ulrich Grave <[email protected]> - Contributions for | ||
* bug 386692 - Missing "unused" warning on "autowired" fields | ||
* Pierre-Yves B. <[email protected]> - Contributions for | ||
* bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource | ||
* bug 546084 - Using Junit 5s MethodSource leads to ClassCastException | ||
*******************************************************************************/ | ||
package org.eclipse.jdt.core.tests.compiler.regression; | ||
|
||
import static java.util.stream.Collectors.joining; | ||
|
||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.io.PrintWriter; | ||
import java.net.URI; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.LinkedHashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import org.eclipse.jdt.core.JavaCore; | ||
import org.eclipse.jdt.core.tests.util.Util; | ||
import org.eclipse.jdt.internal.compiler.batch.FileSystem; | ||
import org.eclipse.jdt.internal.compiler.batch.Main; | ||
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; | ||
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; | ||
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; | ||
import org.junit.Assert; | ||
|
||
@SuppressWarnings({ "rawtypes" }) | ||
public class NameEnvironmentAnswerListenerTest extends AbstractComparableTest { | ||
|
||
public NameEnvironmentAnswerListenerTest(String name) { | ||
super(name); | ||
} | ||
|
||
// public static Test suite() { | ||
// return buildMinimalComplianceTestSuite(testClass(), F_11); | ||
// } | ||
|
||
public static Class testClass() { | ||
return NameEnvironmentAnswerListenerTest.class; | ||
} | ||
|
||
static class EclipseBatchCompiler extends Main { | ||
|
||
Set<String> answeredFileNames = new LinkedHashSet<>(); | ||
|
||
public EclipseBatchCompiler(PrintWriter errAndOutWriter) { | ||
super(errAndOutWriter, errAndOutWriter, false /* systemExitWhenFinished */, null /* customDefaultOptions */, | ||
null /* compilationProgress */); | ||
|
||
setSeverity(CompilerOptions.OPTION_ReportForbiddenReference, ProblemSeverities.Error, true); | ||
setSeverity(CompilerOptions.OPTION_ReportDiscouragedReference, ProblemSeverities.Error, true); | ||
} | ||
|
||
@Override | ||
public FileSystem getLibraryAccess() { | ||
// we use this to collect information about all used dependencies during | ||
// compilation | ||
FileSystem nameEnvironment = super.getLibraryAccess(); | ||
nameEnvironment.setNameEnvironmentAnswerListener(this::recordNameEnvironmentAnswer); | ||
return nameEnvironment; | ||
} | ||
|
||
protected void recordNameEnvironmentAnswer(NameEnvironmentAnswer answer) { | ||
Assert.assertNotNull("don't call without answer", answer); | ||
|
||
char[] fileName = null; | ||
if(answer.getBinaryType() != null) { | ||
URI uri = answer.getBinaryType().getURI(); | ||
this.answeredFileNames.add(uri.toString()); | ||
return; | ||
} else if(answer.getCompilationUnit() != null) { | ||
fileName = answer.getCompilationUnit().getFileName(); | ||
} else if(answer.getSourceTypes() != null && answer.getSourceTypes().length > 0) { | ||
fileName = answer.getSourceTypes()[0].getFileName(); // the first type is guaranteed to be the requested type | ||
} else if(answer.getResolvedBinding() != null) { | ||
fileName = answer.getResolvedBinding().getFileName(); | ||
} | ||
if (fileName != null) this.answeredFileNames.add(new String(fileName)); | ||
} | ||
} | ||
|
||
public void testNameEnvironmentAnswerListener() throws IOException { | ||
String path = LIB_DIR; | ||
if(!path.endsWith(File.separator)) { | ||
path += File.separator; | ||
} | ||
String libPath = path + "lib.jar"; | ||
Util.createJar( | ||
new String[] { | ||
"p/Color.java", | ||
"package p;\n" + | ||
"public enum Color {\n" + | ||
" R, Y;\n" + | ||
" public static Color getColor() {\n" + | ||
" return R;\n" + | ||
" }\n" + | ||
"}", | ||
}, | ||
libPath, JavaCore.VERSION_17); | ||
|
||
String unusedLibPath = path + "lib_unused.jar"; | ||
Util.createJar( | ||
new String[] { | ||
"p2/Color.java", | ||
"package p2;\n" + | ||
"public enum Color {\n" + | ||
" R, Y;\n" + | ||
" public static Color getColor() {\n" + | ||
" return R;\n" + | ||
" }\n" + | ||
"}", | ||
}, | ||
unusedLibPath, JavaCore.VERSION_17); | ||
|
||
String srcDir = path + "src"; | ||
String[] pathsAndContents = | ||
new String[] { | ||
"s/X.java", | ||
"package s;\n" + | ||
"import p.Color;\n" + | ||
"public class X {\n" + | ||
" public static final Color MY = Color.R;\n" + | ||
"}" | ||
}; | ||
Util.createSourceDir(pathsAndContents, srcDir); | ||
|
||
List<String> classpath = new ArrayList<>(Arrays.asList(getDefaultClassPaths())); | ||
classpath.add(libPath); | ||
classpath.add(unusedLibPath); | ||
|
||
File outputDirectory = new File(Util.getOutputDirectory()); | ||
if (!outputDirectory.isDirectory()) { | ||
outputDirectory.mkdirs(); | ||
} | ||
|
||
List<String> ecjArguments = new ArrayList<>(); | ||
|
||
ecjArguments.add("-classpath"); | ||
ecjArguments.add(classpath.stream() | ||
.map(jar -> jar.equals(unusedLibPath) ? String.format("%s[-**/*]", jar) : jar) | ||
.collect(joining(File.pathSeparator))); | ||
|
||
|
||
ecjArguments.add("-d"); | ||
ecjArguments.add(outputDirectory.getAbsolutePath()); | ||
|
||
ecjArguments.add("--release"); | ||
ecjArguments.add("17"); | ||
|
||
ecjArguments.add(srcDir+ File.separator + "s"+ File.separator + "X.java"); | ||
|
||
EclipseBatchCompiler compiler; | ||
boolean compileOK; | ||
File logFile = new File(outputDirectory, "compile.log"); | ||
try(PrintWriter log = new PrintWriter(new FileOutputStream(logFile))) { | ||
compiler = new EclipseBatchCompiler(log); | ||
} catch (FileNotFoundException e) { | ||
System.out.println(getClass().getName() + '#' + getName()); | ||
e.printStackTrace(); | ||
throw new RuntimeException(e); | ||
} | ||
try { | ||
compileOK = compiler.compile(ecjArguments.toArray(new String[ecjArguments.size()])); | ||
} catch (RuntimeException e) { | ||
compileOK = false; | ||
System.out.println(getClass().getName() + '#' + getName()); | ||
e.printStackTrace(); | ||
throw e; | ||
} | ||
String logOutputString = Util.fileContent(logFile.getAbsolutePath()); | ||
|
||
if(!compileOK) { | ||
System.out.println(logOutputString); | ||
Assert.fail("Compile failed!"); | ||
} | ||
|
||
Assert.assertTrue("must reference p.Color", compiler.answeredFileNames.stream().anyMatch(s -> s.contains(libPath))); | ||
Assert.assertFalse("must not reference p2.Color", compiler.answeredFileNames.stream().anyMatch(s -> s.contains(unusedLibPath))); | ||
} | ||
} |