Skip to content

Commit

Permalink
SLI-1805 Avoid non-needed analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
eray-felek-sonarsource committed Jan 27, 2025
1 parent 36e974e commit 070defa
Show file tree
Hide file tree
Showing 16 changed files with 43 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ object SonarLintIntelliJClient : SonarLintRpcClientDelegate {
getService(project, AnalysisSubmitter::class.java).analyzeFileAndTrySelectFinding(findingToShow)
}

getService(project, AnalysisSubmitter::class.java).autoAnalyzeOpenFilesForModule(
getService(project, AnalysisSubmitter::class.java).autoAnalyzeSelectedFilesForModule(
TriggerType.BINDING_UPDATE,
module
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void actionPerformed(AnActionEvent e) {
var issue = e.getData(ISSUE_DATA_KEY);
if (issue != null) {
disableRule(issue.getRuleKey());
runOnPooledThread(project, () -> getService(project, AnalysisSubmitter.class).autoAnalyzeOpenFiles(TriggerType.BINDING_UPDATE));
runOnPooledThread(project, () -> getService(project, AnalysisSubmitter.class).autoAnalyzeSelectedFiles(TriggerType.BINDING_UPDATE));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class ExcludeFileAction : AbstractSonarAction {
if (newExclusions.isNotEmpty()) {
exclusions.addAll(newExclusions)
settings.fileExclusions = exclusions
getService(project, AnalysisSubmitter::class.java).autoAnalyzeOpenFiles(TriggerType.CONFIG_CHANGE)
getService(project, AnalysisSubmitter::class.java).autoAnalyzeSelectedFiles(TriggerType.CONFIG_CHANGE)
val projectListener = project.messageBus.syncPublisher(ProjectConfigurationListener.TOPIC)
projectListener.changed(settings)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ public void analyzeVcsChangedFiles() {
TaskRunnerKt.startBackgroundableModalTask(project, ANALYSIS_TASK_TITLE, analysis::run);
}

public void autoAnalyzeOpenFilesForModule(TriggerType triggerType, @Nullable Module module) {
public void autoAnalyzeSelectedFilesForModule(TriggerType triggerType, @Nullable Module module) {
if (module == null) {
autoAnalyzeOpenFiles(triggerType);
autoAnalyzeSelectedFiles(triggerType);
return;
}

var openFiles = FileEditorManager.getInstance(project).getOpenFiles();
var filesToAnalyze = Arrays.stream(openFiles)
var selectedFiles = FileEditorManager.getInstance(project).getSelectedFiles();
var filesToAnalyze = Arrays.stream(selectedFiles)
.filter(file -> module.equals(findModuleForFile(file, project)))
.toList();

Expand All @@ -109,10 +109,11 @@ public void autoAnalyzeOpenFilesForModule(TriggerType triggerType, @Nullable Mod
}
}

public void autoAnalyzeOpenFiles(TriggerType triggerType) {
var openFiles = FileEditorManager.getInstance(project).getOpenFiles();
if (openFiles.length > 0) {
autoAnalyzeFiles(List.of(openFiles), triggerType);
public void autoAnalyzeSelectedFiles(TriggerType triggerType) {
var selectedFiles = FileEditorManager.getInstance(project).getSelectedFiles();

if (selectedFiles.length > 0) {
autoAnalyzeFiles(List.of(selectedFiles), triggerType);
}
}

Expand All @@ -122,6 +123,9 @@ public Cancelable autoAnalyzeFiles(Collection<VirtualFile> files, TriggerType tr
return null;
}
var callback = new UpdateOnTheFlyFindingsCallable(onTheFlyFindingsHolder);
if (triggerType != TriggerType.SELECTION_CHANGED) {
onTheFlyFindingsHolder.clearNonDirtyAnalyzedFiles();
}
return analyzeInBackground(files, triggerType, callback);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ import org.sonarlint.intellij.finding.LiveFindings
import org.sonarlint.intellij.finding.RawIssueAdapter
import org.sonarlint.intellij.finding.hotspot.LiveSecurityHotspot
import org.sonarlint.intellij.finding.issue.LiveIssue
import org.sonarlint.intellij.trigger.TriggerType
import org.sonarlint.intellij.ui.UiUtils.Companion.runOnUiThread
import org.sonarlint.intellij.util.VirtualFileUtils.uriToVirtualFile
import org.sonarsource.sonarlint.core.rpc.protocol.client.hotspot.RaisedHotspotDto
import org.sonarsource.sonarlint.core.rpc.protocol.client.issue.RaisedIssueDto

class OnTheFlyFindingsHolder(private val project: Project) : FileEditorManagerListener {
private var selectedFile: VirtualFile? = null
private val nonDirtyAnalyzedFiles: MutableSet<VirtualFile> = ConcurrentHashMap.newKeySet()
private val currentIssuesPerOpenFile: MutableMap<VirtualFile, Collection<LiveIssue>> = ConcurrentHashMap()
private val currentSecurityHotspotsPerOpenFile: MutableMap<VirtualFile, Collection<LiveSecurityHotspot>> = ConcurrentHashMap()

Expand All @@ -51,6 +53,8 @@ class OnTheFlyFindingsHolder(private val project: Project) : FileEditorManagerLi
.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, this)
}

fun clearNonDirtyAnalyzedFiles() = nonDirtyAnalyzedFiles.clear()

fun updateOnAnalysisResult(analysisResult: AnalysisResult) =
updateViewsWithNewFindings(analysisResult.findings)

Expand Down Expand Up @@ -111,11 +115,18 @@ class OnTheFlyFindingsHolder(private val project: Project) : FileEditorManagerLi
}

override fun selectionChanged(event: FileEditorManagerEvent) {
selectedFile = event.newFile
val file = event.newFile
selectedFile = file
if (file != null && !nonDirtyAnalyzedFiles.contains(file)) {
getService(project, AnalysisSubmitter::class.java).autoAnalyzeSelectedFiles(TriggerType.SELECTION_CHANGED)
nonDirtyAnalyzedFiles.add(file)
}

updateCurrentFileTab()
}

override fun fileClosed(source: FileEditorManager, file: VirtualFile) {
nonDirtyAnalyzedFiles.remove(file)
currentIssuesPerOpenFile.remove(file)
currentSecurityHotspotsPerOpenFile.remove(file)
// update only Security Hotspots, issues will be updated in reaction to selectionChanged
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public static void analyzeOpenFiles(boolean unboundOnly) {

for (var project : openProjects) {
if (!unboundOnly || !getSettingsFor(project).isBindingEnabled()) {
getService(project, AnalysisSubmitter.class).autoAnalyzeOpenFiles(TriggerType.CONFIG_CHANGE);
getService(project, AnalysisSubmitter.class).autoAnalyzeSelectedFiles(TriggerType.CONFIG_CHANGE);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void apply() throws ConfigurationException {
project.getMessageBus().syncPublisher(ProjectConfigurationListener.TOPIC).changed(projectSettings);

if (exclusionsModified) {
getService(project, AnalysisSubmitter.class).autoAnalyzeOpenFiles(TriggerType.CONFIG_CHANGE);
getService(project, AnalysisSubmitter.class).autoAnalyzeSelectedFiles(TriggerType.CONFIG_CHANGE);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class DisableRuleIntentionAction implements IntentionAction, LowPriorityA
var rulesByKey = getGlobalSettings().getRulesByKey();
runOnPooledThread(project, () -> {
getService(BackendService.class).updateStandaloneRulesConfiguration(rulesByKey);
getService(project, AnalysisSubmitter.class).autoAnalyzeOpenFiles(TriggerType.BINDING_UPDATE);
getService(project, AnalysisSubmitter.class).autoAnalyzeSelectedFiles(TriggerType.BINDING_UPDATE);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class BuildFinishedAnalysisTrigger implements BuildManagerListener {

runOnPooledThread(project, () -> {
getService(project, SonarLintConsole.class).debug("build finished");
getService(project, AnalysisSubmitter.class).autoAnalyzeOpenFiles(TriggerType.COMPILATION);
getService(project, AnalysisSubmitter.class).autoAnalyzeSelectedFiles(TriggerType.COMPILATION);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ public class CompilationFinishedAnalysisTrigger implements CompilationStatusList
public void compilationFinished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
var compiledProject = compileContext.getProject();
getService(compiledProject, SonarLintConsole.class).debug("compilation finished");
runOnPooledThread(compiledProject, () -> getService(compiledProject, AnalysisSubmitter.class).autoAnalyzeOpenFiles(TriggerType.COMPILATION));
runOnPooledThread(compiledProject, () -> getService(compiledProject, AnalysisSubmitter.class).autoAnalyzeSelectedFiles(TriggerType.COMPILATION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile f
if (module != null && FileUtils.Companion.isFileValidForSonarLintWithExtensiveChecks(file, source.getProject())) {
getService(BackendService.class).updateFileSystem(Map.of(module, List.of(new VirtualFileEvent(ModuleFileEvent.Type.CREATED, file))), true);
}
if (source.getProject().equals(myProject)) {
scheduler.notify(file);
}
});
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/sonarlint/intellij/trigger/TriggerType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package org.sonarlint.intellij.trigger
enum class TriggerType(private val displayName: String, private val shouldUpdateServerIssues: Boolean) {

EDITOR_OPEN("Editor open", true),
SELECTION_CHANGED("Selection changed", true),
CURRENT_FILE_ACTION("Current file action", true),
RIGHT_CLICK("Right click", true),
ALL("All files", false),
Expand All @@ -40,7 +41,7 @@ enum class TriggerType(private val displayName: String, private val shouldUpdate

// Non snapshot do not include CHECK_IN analysis and OPEN_FINDING analysis, as they are specific cases
val nonAnalysisSnapshot =
listOf(EDITOR_OPEN, CURRENT_FILE_ACTION, COMPILATION, EDITOR_CHANGE, CONFIG_CHANGE, BINDING_UPDATE, SERVER_SENT_EVENT)
listOf(EDITOR_OPEN, CURRENT_FILE_ACTION, COMPILATION, EDITOR_CHANGE, CONFIG_CHANGE, BINDING_UPDATE, SERVER_SENT_EVENT, SELECTION_CHANGED)
}

fun getName() = displayName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void prepare() {
@Test
void should_trigger_automake() {
trigger.buildFinished(getProject(), UUID.randomUUID(), true);
verify(submitter, timeout(1000)).autoAnalyzeOpenFiles(TriggerType.COMPILATION);
verify(submitter, timeout(1000)).autoAnalyzeSelectedFiles(TriggerType.COMPILATION);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void prepare() {
@Test
void should_trigger_on_compilation() {
trigger.compilationFinished(false, 0, 0, context);
verify(submitter, timeout(1000)).autoAnalyzeOpenFiles(TriggerType.COMPILATION);
verify(submitter, timeout(1000)).autoAnalyzeSelectedFiles(TriggerType.COMPILATION);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ void cleanup() {
@Test
void should_trigger() {
var file = createAndOpenTestVirtualFile("MyClass.java", Language.findLanguageByID("JAVA"), "");
clearInvocations(submitter);

underTest.documentChanged(createEvent(file));

Expand All @@ -96,6 +97,7 @@ void should_trigger_multiple_files() {
@Test
void should_trigger_in_interval() {
var file = createAndOpenTestVirtualFile("MyClass.java", Language.findLanguageByID("JAVA"), "");
clearInvocations(submitter);

var analysisTask = mock(Analysis.class);
when(submitter.autoAnalyzeFiles(any(), any())).thenReturn(analysisTask);
Expand All @@ -115,6 +117,7 @@ void should_trigger_in_interval() {
@Test
void dont_trigger_if_auto_disabled() {
var file = createAndOpenTestVirtualFile("MyClass.java", Language.findLanguageByID("JAVA"), "");
clearInvocations(submitter);
getGlobalSettings().setAutoTrigger(false);

underTest.documentChanged(createEvent(file));
Expand All @@ -137,6 +140,7 @@ void dont_trigger_if_check_fails() {
@Test
void dont_trigger_if_project_is_closed() {
var file = createAndOpenTestVirtualFile("MyClass.java", Language.findLanguageByID("JAVA"), "");
clearInvocations(submitter);

underTest.documentChanged(createEvent(file));

Expand All @@ -146,6 +150,7 @@ void dont_trigger_if_project_is_closed() {
@Test
void dont_trigger_if_no_vfile() {
var file = createAndOpenTestVirtualFile("MyClass.java", Language.findLanguageByID("JAVA"), "");
clearInvocations(submitter);

var doc = mock(Document.class);
var event = createEvent(file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ void cleanup() {
}

@Test
void should_trigger() {
void should_not_trigger() {
editorTrigger.fileOpened(editorManager, file);

verify(analysisSubmitter, timeout(3000)).autoAnalyzeFiles(List.of(file), TriggerType.EDITOR_OPEN);
verifyNoInteractions(analysisSubmitter);
}

@Test
Expand Down

0 comments on commit 070defa

Please sign in to comment.