I am a developer of Bndtools. A customer sees messages that files are locked when we tried to write them during a build job. The build job is locking the workspace, however, looking at the code the AbstractSonarProjectJob.java
is scheduled without rules. This will make it run in parallel. So when the compiler you use to create an AST opens a Jar, we might just try to write this file. Since you Sonarlint has the file open, we get an error on Windows. (Other operating systems do not lock these files.)
The following stacktrace was gathered with a file leak detector:
#239 D:\Eclipse\iguana\com.example\generated\com.example.application.api.jar by thread:Worker-10: SonarLint processing file /com.example.gms.provider/src/com.example/gms/admin/GmsAdminImpl.java on Thu Jul 23 18:44:52 CEST 2020
at java.util.zip.ZipFile.<init>(ZipFile.java:156)
at java.util.zip.ZipFile.<init>(ZipFile.java:169)
at org.eclipse.jdt.internal.compiler.batch.ClasspathJar.initialize(ClasspathJar.java:199)
at org.eclipse.jdt.internal.compiler.batch.FileSystem.<init>(FileSystem.java:222)
at org.eclipse.jdt.internal.compiler.batch.FileSystem.<init>(FileSystem.java:264)
at org.eclipse.jdt.core.dom.NameEnvironmentWithProgress.<init>(NameEnvironmentWithProgress.java:36)
at org.eclipse.jdt.core.dom.CompilationUnitResolver.resolve(CompilationUnitResolver.java:695)
at org.eclipse.jdt.core.dom.ASTParser.internalCreateAST(ASTParser.java:1217)
at org.eclipse.jdt.core.dom.ASTParser.createAST(ASTParser.java:832)
at org.sonar.java.model.JParser.parse(JParser.java:284)
at org.sonar.java.ast.JavaAstScanner.simpleScan(JavaAstScanner.java:92)
at org.sonar.java.ast.JavaAstScanner.scan(JavaAstScanner.java:64)
at org.sonar.java.JavaSquid.scanSources(JavaSquid.java:120)
at org.sonar.java.JavaSquid.scan(JavaSquid.java:113)
at org.sonar.plugins.java.JavaSquidSensor.execute(JavaSquidSensor.java:103)
at org.sonarsource.sonarlint.core.analyzer.sensor.SensorsExecutor.executeSensor(SensorsExecutor.java:80)
at org.sonarsource.sonarlint.core.analyzer.sensor.SensorsExecutor.execute(SensorsExecutor.java:71)
at org.sonarsource.sonarlint.core.container.analysis.AnalysisContainer.doAfterStart(AnalysisContainer.java:134)
at org.sonarsource.sonarlint.core.container.ComponentContainer.startComponents(ComponentContainer.java:125)
at org.sonarsource.sonarlint.core.container.ComponentContainer.execute(ComponentContainer.java:110)
at org.sonarsource.sonarlint.core.container.storage.StorageAnalyzer.analyze(StorageAnalyzer.java:75)
at org.sonarsource.sonarlint.core.container.storage.StorageContainerHandler.analyze(StorageContainerHandler.java:81)
at org.sonarsource.sonarlint.core.ConnectedSonarLintEngineImpl.lambda$analyze$0(ConnectedSonarLintEngineImpl.java:152)
at org.sonarsource.sonarlint.core.ConnectedSonarLintEngineImpl.withReadLock(ConnectedSonarLintEngineImpl.java:344)
at org.sonarsource.sonarlint.core.ConnectedSonarLintEngineImpl.withReadLock(ConnectedSonarLintEngineImpl.java:334)
at org.sonarsource.sonarlint.core.ConnectedSonarLintEngineImpl.analyze(ConnectedSonarLintEngineImpl.java:149)
at org.sonarlint.eclipse.core.internal.server.Server.runAnalysis(Server.java:306)
at org.sonarlint.eclipse.core.internal.jobs.AnalyzeConnectedProjectJob.runAnalysis(AnalyzeConnectedProjectJob.java:72)
at org.sonarlint.eclipse.core.internal.jobs.AnalyzeConnectedProjectJob.runAnalysis(AnalyzeConnectedProjectJob.java:1)
at org.sonarlint.eclipse.core.internal.jobs.AbstractAnalyzeProjectJob.run(AbstractAnalyzeProjectJob.java:405)
at org.sonarlint.eclipse.core.internal.jobs.AbstractAnalyzeProjectJob.runAnalysisAndUpdateMarkers(AbstractAnalyzeProjectJob.java:208)
at org.sonarlint.eclipse.core.internal.jobs.AbstractAnalyzeProjectJob.doRun(AbstractAnalyzeProjectJob.java:170)
at org.sonarlint.eclipse.core.internal.jobs.AbstractSonarProjectJob.run(AbstractSonarProjectJob.java:45)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Solution
The solution is to provide a scheduling run when a job is scheduled. This rule should come from the root workspace that you can get via org.eclipse.core.resources.ResourcesPlugin.getWorkspace().getRoot()
. You can then use the org.eclipse.core.resources.IWorkspace.getRuleFactory()
to create a rule. I am no expert but I think the org.eclipse.core.resources.IResourceRuleFactory.copyRule(IResource, IResource)
rule would be the best since you are only reading.
I did not look into your code in detail but becoming part of the build and making an incremental builder would probably be simpler & faster.
I tried to create a PR. However, the sonar-java
on Github had test errors:
[ERROR] Failures:
[ERROR] CallToDeprecatedCodeMarkedForRemovalCheckTest.test:34 No issue raised. At least one issue expected
[ERROR] CallToDeprecatedMethodCheckTest.flagged_for_removal_should_not_raise_issue:46 Unexpected at [19, 23, 28, 39]
[ERROR] AssertJChainSimplificationCheckTest.testJava11Cases:42 No issue raised. At least one issue expected
[ERROR] GeneratedCodeFilterTest.test:34 Line #10 has been marked with 'NoIssue' but issue of rule 'java:S100' has been accepted!
[ERROR] SuppressWarningFilterTest.verify:48 Line #184 has been marked with 'WithIssue' but no issue have been raised!
[INFO]
[ERROR] Tests run: 962, Failures: 5, Errors: 0, Skipped: 0
If I can build the Github repositories I can prepare a PR for you.