-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: Update to sonar-java 6.9.0 #156
Changes from all commits
8f0ebc9
cb7a334
c136067
f6bd695
05db8af
7cc7297
462d205
6e3e2b7
1a721d9
163e4c2
ac530a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package sorald; | ||
|
||
import java.io.File; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
|
||
public class FileUtils { | ||
|
||
/** | ||
* Compare the two given paths as absolute, normalized paths. | ||
* | ||
* @param lhs A path. | ||
* @param rhs A path. | ||
* @return Whether or not the paths are equal as absolute, normalized paths. | ||
*/ | ||
public static boolean pathAbsNormEqual(String lhs, String rhs) { | ||
return pathAbsNormEqual(Paths.get(lhs), Paths.get(rhs)); | ||
} | ||
|
||
/** | ||
* Compare the two given paths as absolute, normalized paths. | ||
* | ||
* @param lhs A path. | ||
* @param rhs A path. | ||
* @return Whether or not the paths are equal as absolute, normalized paths. | ||
*/ | ||
public static boolean pathAbsNormEqual(Path lhs, Path rhs) { | ||
return lhs.toAbsolutePath().normalize().equals(rhs.toAbsolutePath().normalize()); | ||
} | ||
|
||
/** | ||
* @param file A file. | ||
* @return The given file if it is a directory, or its parent directory if it is not a | ||
* directory. | ||
*/ | ||
public static File getClosestDirectory(File file) { | ||
return file.isDirectory() ? file : file.getParentFile(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,26 @@ | ||
package sorald.sonar; | ||
|
||
import java.util.Arrays; | ||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Paths; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import org.sonar.java.checks.verifier.MultipleFilesJavaCheckVerifier; | ||
import org.sonar.api.batch.fs.InputFile; | ||
import org.sonar.api.batch.fs.internal.DefaultFileSystem; | ||
import org.sonar.api.batch.fs.internal.TestInputFileBuilder; | ||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | ||
import org.sonar.java.AnalyzerMessage; | ||
import org.sonar.java.SonarComponents; | ||
import org.sonar.java.ast.JavaAstScanner; | ||
import org.sonar.java.checks.verifier.JavaCheckVerifier; | ||
import org.sonar.java.model.VisitorsBridge; | ||
import org.sonar.java.se.SymbolicExecutionMode; | ||
import org.sonar.plugins.java.api.JavaFileScanner; | ||
|
||
/** Adapter class for interfacing with sonar-java's verification and analysis facilities. */ | ||
|
@@ -18,7 +34,7 @@ public class RuleVerifier { | |
*/ | ||
@SuppressWarnings("UnstableApiUsage") | ||
public static void verifyHasIssue(String filename, JavaFileScanner check) { | ||
verifyHasIssue(Arrays.asList(filename), check); | ||
JavaCheckVerifier.newVerifier().onFile(filename).withCheck(check).verifyIssues(); | ||
} | ||
|
||
/** | ||
|
@@ -29,19 +45,32 @@ public static void verifyHasIssue(String filename, JavaFileScanner check) { | |
*/ | ||
@SuppressWarnings("UnstableApiUsage") | ||
public static void verifyHasIssue(List<String> filesToScan, JavaFileScanner check) { | ||
MultipleFilesJavaCheckVerifier.verify(filesToScan, check, true); | ||
filesToScan.forEach(filename -> verifyHasIssue(filename, check)); | ||
} | ||
|
||
/** | ||
* Analyze the files with respect to check. | ||
* | ||
* @param filesToScan A list of paths to files. | ||
* @param baseDir The base directory of the current project. | ||
* @param check A Sonar check. | ||
* @return All messages produced by the analyzer, for all files. | ||
*/ | ||
@SuppressWarnings("UnstableApiUsage") | ||
public static Set<RuleViolation> analyze(List<String> filesToScan, JavaFileScanner check) { | ||
return MultipleFilesJavaCheckVerifier.verify(filesToScan, check, false).stream() | ||
public static Set<RuleViolation> analyze( | ||
List<String> filesToScan, File baseDir, JavaFileScanner check) { | ||
List<InputFile> inputFiles = | ||
filesToScan.stream() | ||
.map(filename -> toInputFile(baseDir, filename)) | ||
.collect(Collectors.toList()); | ||
|
||
SoraldSonarComponents sonarComponents = createSonarComponents(baseDir); | ||
JavaAstScanner scanner = | ||
createAstScanner(sonarComponents, Collections.singletonList(check)); | ||
|
||
scanner.scan(inputFiles); | ||
|
||
return sonarComponents.getMessages().stream() | ||
.map(RuleViolation::new) | ||
.collect(Collectors.toSet()); | ||
} | ||
|
@@ -54,6 +83,78 @@ public static Set<RuleViolation> analyze(List<String> filesToScan, JavaFileScann | |
*/ | ||
@SuppressWarnings("UnstableApiUsage") | ||
public static void verifyNoIssue(String filename, JavaFileScanner check) { | ||
MultipleFilesJavaCheckVerifier.verifyNoIssue(Arrays.asList(filename), check); | ||
JavaCheckVerifier.newVerifier().onFile(filename).withCheck(check).verifyNoIssues(); | ||
} | ||
|
||
private static InputFile toInputFile(File baseDir, String filename) { | ||
// must append a separator to the basedir string as Sonar appends the filenames directly to | ||
// it | ||
final String baseDirStr = baseDir.toString() + File.separator; | ||
try { | ||
return new TestInputFileBuilder(baseDirStr, filename) | ||
.setContents(new String(Files.readAllBytes(Paths.get(filename)), UTF_8)) | ||
.setCharset(UTF_8) | ||
.setLanguage("java") | ||
.build(); | ||
} catch (IOException e) { | ||
throw new RuntimeException("failed to read file " + filename); | ||
} | ||
} | ||
|
||
@SuppressWarnings("UnstableApiUsage") | ||
private static JavaAstScanner createAstScanner( | ||
SonarComponents sonarComponents, List<JavaFileScanner> checks) { | ||
JavaAstScanner scanner = new JavaAstScanner(sonarComponents); | ||
VisitorsBridge visitorsBridge = | ||
new VisitorsBridge( | ||
checks, | ||
// TODO set the classpath to something reasonable | ||
Collections.emptyList(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This argument sets the classpath for the VisitorsBridge. It's later supplied to the parser, so I'm assuming that it's used to resolve types etc (but I haven't checked inside the parser). We will probably want to set it to something reasonable in the context. For example, when analyzing a project that uses maven, the full classpath can be generated with |
||
sonarComponents, | ||
SymbolicExecutionMode.getMode(checks.toArray(new JavaFileScanner[0]))); | ||
// TODO we may want to set the version of the visitors bridge, as without setting it the | ||
// implementation defaults to the highest version supported by the parser (currently | ||
// Java 14) | ||
// visitorsBridge.setJavaVersion(new JavaVersionImpl(8)); | ||
scanner.setVisitorBridge(visitorsBridge); | ||
return scanner; | ||
} | ||
|
||
private static SoraldSonarComponents createSonarComponents(File baseDir) { | ||
// FIXME The SensorContextTester is an internal and unstable component in sonar, | ||
// we should implement our own SensorContext | ||
SensorContextTester context = SensorContextTester.create(baseDir); | ||
Comment on lines
+124
to
+126
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like the comment in the code says, we shouldn't be using the internal |
||
SoraldSonarComponents sonarComponents = new SoraldSonarComponents(context.fileSystem()); | ||
sonarComponents.setSensorContext(context); | ||
return sonarComponents; | ||
} | ||
|
||
/** | ||
* A simple subclass of SonarComponents that stores all analyzer messages. These are by default | ||
* stored in a storage container, but it seems easier for our use case to just intercept them. | ||
* | ||
* <p>This IS a bit of a hack, so it wouldn't be unreasonable to try to do this the "proper | ||
* way". | ||
*/ | ||
private static class SoraldSonarComponents extends SonarComponents { | ||
private final List<AnalyzerMessage> messages; | ||
|
||
public SoraldSonarComponents(DefaultFileSystem fs) { | ||
// FIXME I'm very unsure about supplying null for all of these constructor values. | ||
// They should not be null, but at this time I don't know that to put there, and | ||
// with our current usage this hack appears to work. | ||
super(null, fs, null, null, null, null); | ||
Comment on lines
+143
to
+146
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like the comment says, this is a pretty nasty hack. It appears to work, but it's definitely not pretty nor safe as it initializes fields that should not be |
||
messages = new ArrayList<>(); | ||
} | ||
|
||
@Override | ||
public void reportIssue(AnalyzerMessage analyzerMessage) { | ||
super.reportIssue(analyzerMessage); | ||
messages.add(analyzerMessage); | ||
} | ||
|
||
public List<AnalyzerMessage> getMessages() { | ||
return Collections.unmodifiableList(messages); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@slarse Do you remember what problems were arising in the absence of its exclusion? I am using the local build of spoon with this change in the comment, but sorald throws an error that it cannot find the
.get
method forHashtableOfPackage
. I am assuming it is because of this line.I tried removing the exclusion and now it throws
OutOfMemory: Java heap space
. Weird.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I recall, Sonar-java 6.9 pulled in (or bundled, maybe) an unsigned
jdt
package, while the one pulled in from Spoon is signed. Signed as in there's a GPG signature on it.That caused errors on building it.
As both Spoon and Sonar-Java use jdt, you need to make sure that the version they depend on is the same. Otherwise you'll get strange errors.