Skip to content

Commit f6a6857

Browse files
Incremental PR analysis: Cache the hash only for CSharp and VbNet files (#6551)
1 parent 383fc59 commit f6a6857

11 files changed

Lines changed: 262 additions & 20 deletions

File tree

its/src/test/java/com/sonar/it/shared/ScannerCliTest.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ public void givenRazorPagesMainCode_whenScannerForCliIsUsed_logsCSharpWarning()
5252
.containsExactlyInAnyOrder(
5353
"WARN: Your project contains C# files which cannot be analyzed with the scanner you are using. To analyze C# or VB.NET, you must use the SonarScanner for .NET 5.x or higher, see https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html",
5454
"WARN: Incremental PR analysis: Could not determine common base path, cache will not be computed. Consider setting 'sonar.projectBaseDir' property.",
55-
"WARN: Your project contains VB.NET files which cannot be analyzed with the scanner you are using. To analyze C# or VB.NET, you must use the SonarScanner for .NET 5.x or higher, see https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html");
55+
"WARN: Your project contains VB.NET files which cannot be analyzed with the scanner you are using. To analyze C# or VB.NET, you must use the SonarScanner for .NET 5.x or higher, see https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html",
56+
"WARN: Incremental PR analysis: Could not determine common base path, cache will not be computed. Consider setting 'sonar.projectBaseDir' property.");
5657
// The HTML plugin works
5758
assertThat(TestUtils.getMeasureAsInt(ORCHESTRATOR, RAZOR_PAGES_PROJECT, "violations")).isEqualTo(2);
5859
TestUtils.verifyNoGuiWarnings(ORCHESTRATOR, result);
@@ -98,10 +99,7 @@ public void givenTestHtmlCode_whenScannerForCliIsUsed_doesNotLogCsharpWarning()
9899
.setProperty("sonar.cs.file.suffixes=", ".no_extension");
99100
BuildResult result = ORCHESTRATOR.executeBuild(scanner);
100101

101-
assertThat(result.getLogsLines(l -> l.contains("WARN")))
102-
.containsExactlyInAnyOrder(
103-
"WARN: Incremental PR analysis: Could not determine common base path, cache will not be computed. Consider setting 'sonar.projectBaseDir' property."
104-
);
102+
assertThat(result.getLogsLines(l -> l.contains("WARN"))).isEmpty();
105103
TestUtils.verifyNoGuiWarnings(ORCHESTRATOR, result);
106104
}
107105

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* SonarC#
3+
* Copyright (C) 2014-2022 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.plugins.csharp;
21+
22+
import org.sonarsource.dotnet.shared.plugins.AbstractFileCacheSensor;
23+
import org.sonarsource.dotnet.shared.plugins.HashProvider;
24+
25+
public class CSharpFileCacheSensor extends AbstractFileCacheSensor {
26+
public CSharpFileCacheSensor(CSharp cSharp, HashProvider hashProvider) {
27+
super(cSharp, hashProvider);
28+
}
29+
}

sonar-csharp-plugin/src/main/java/org/sonar/plugins/csharp/CSharpPlugin.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.sonarsource.dotnet.shared.plugins.DotNetPluginMetadata;
2727
import org.sonarsource.dotnet.shared.plugins.DotNetSensor;
2828
import org.sonarsource.dotnet.shared.plugins.EncodingPerFile;
29-
import org.sonarsource.dotnet.shared.plugins.FileCacheSensor;
3029
import org.sonarsource.dotnet.shared.plugins.FileTypeSensor;
3130
import org.sonarsource.dotnet.shared.plugins.GeneratedFileFilter;
3231
import org.sonarsource.dotnet.shared.plugins.HashProvider;
@@ -83,7 +82,7 @@ public void define(Context context) {
8382
// importers / exporters
8483
// Analysis warnings sensor is registered only here, without a language filter, to avoid pushing warnings multiple times.
8584
AnalysisWarningsSensor.class,
86-
FileCacheSensor.class,
85+
CSharpFileCacheSensor.class,
8786
ProtobufDataImporter.class,
8887
RoslynDataImporter.class,
8988
RoslynProfileExporter.class,
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* SonarC#
3+
* Copyright (C) 2014-2022 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.plugins.csharp;
21+
22+
import org.junit.Rule;
23+
import org.junit.Test;
24+
import org.junit.rules.TemporaryFolder;
25+
import org.sonar.api.batch.fs.InputFile;
26+
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
27+
import org.sonar.api.batch.sensor.cache.WriteCache;
28+
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
29+
import org.sonar.api.batch.sensor.internal.SensorContextTester;
30+
import org.sonar.api.config.internal.MapSettings;
31+
import org.sonar.api.utils.log.LogTester;
32+
import org.sonar.api.utils.log.LoggerLevel;
33+
import org.sonarsource.dotnet.shared.plugins.HashProvider;
34+
35+
import java.io.File;
36+
import java.io.IOException;
37+
import java.security.NoSuchAlgorithmException;
38+
39+
import static org.assertj.core.api.Assertions.assertThat;
40+
import static org.mockito.ArgumentMatchers.any;
41+
import static org.mockito.Mockito.mock;
42+
import static org.mockito.Mockito.when;
43+
44+
public class CSharpFileCacheSensorTest {
45+
@Rule
46+
public TemporaryFolder temp = new TemporaryFolder();
47+
48+
@Rule
49+
public LogTester logTester = new LogTester();
50+
51+
@Test
52+
public void execute_whenCacheIsEnabled_itAddsOnlyTheLanguageFiles() throws IOException, NoSuchAlgorithmException {
53+
var basePath = temp.newFolder();
54+
var settings = new MapSettings();
55+
settings.setProperty(CSharpPlugin.FILE_SUFFIXES_KEY, ".cs");
56+
settings.setProperty("sonar.pullrequest.cache.basepath", basePath.getCanonicalPath());
57+
var hashProvider = mock(HashProvider.class);
58+
when(hashProvider.computeHash(any())).thenReturn(new byte[] {42} );
59+
var context = SensorContextTester.create(basePath);
60+
context.setCacheEnabled(true);
61+
context.setSettings(settings);
62+
context.setNextCache(mock(WriteCache.class));
63+
AddFile(context, basePath, "CSharp/Foo.cs", CSharpPlugin.LANGUAGE_KEY);
64+
AddFile(context, basePath, "VB/Bar.vb", "other-language-key");
65+
var sut = new CSharpFileCacheSensor(new CSharp(settings.asConfig()), hashProvider);
66+
67+
sut.execute(context);
68+
69+
assertThat(logTester.logs(LoggerLevel.WARN)).isEmpty();
70+
assertThat(logTester.logs(LoggerLevel.DEBUG)).containsExactly(
71+
"Incremental PR analysis: Preparing to upload file hashes.",
72+
"Incremental PR analysis: Adding hash for 'CSharp/Foo.cs' to the cache."
73+
);
74+
}
75+
76+
private static void AddFile(SensorContextTester context, File basePath, String filePath, String languageKey) {
77+
context.fileSystem().add(new TestInputFileBuilder("project-key", basePath, new File(basePath, filePath)).setLanguage(languageKey).setType(InputFile.Type.MAIN).build());
78+
}
79+
}

sonar-csharp-plugin/src/test/java/org/sonar/plugins/csharp/CSharpPluginTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.sonarsource.dotnet.shared.plugins.CodeCoverageProvider;
3434
import org.sonarsource.dotnet.shared.plugins.DotNetSensor;
3535
import org.sonarsource.dotnet.shared.plugins.EncodingPerFile;
36-
import org.sonarsource.dotnet.shared.plugins.FileCacheSensor;
3736
import org.sonarsource.dotnet.shared.plugins.FileTypeSensor;
3837
import org.sonarsource.dotnet.shared.plugins.GeneratedFileFilter;
3938
import org.sonarsource.dotnet.shared.plugins.HashProvider;
@@ -64,14 +63,14 @@ public void getExtensions() {
6463
Object[] expectedExtensions = new Object[] {
6564
AnalysisWarningsSensor.class,
6665
CSharp.class,
66+
CSharpFileCacheSensor.class,
6767
CSharpGlobalProtobufFileProcessor.class,
6868
CSharpLanguageConfiguration.class,
6969
CSharpModuleConfiguration.class,
7070
CSharpPlugin.METADATA,
7171
CSharpSonarRulesDefinition.class,
7272
DotNetSensor.class,
7373
EncodingPerFile.class,
74-
FileCacheSensor.class,
7574
FileTypeSensor.class,
7675
GeneratedFileFilter.class,
7776
HashProvider.class,

sonar-dotnet-shared-library/src/main/java/org/sonarsource/dotnet/shared/plugins/FileCacheSensor.java renamed to sonar-dotnet-shared-library/src/main/java/org/sonarsource/dotnet/shared/plugins/AbstractFileCacheSensor.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.sonar.api.batch.sensor.SensorContext;
2323
import org.sonar.api.batch.sensor.SensorDescriptor;
24+
import org.sonar.api.resources.AbstractLanguage;
2425
import org.sonar.api.scanner.ScannerSide;
2526
import org.sonar.api.scanner.sensor.ProjectSensor;
2627
import org.sonar.api.utils.log.Logger;
@@ -30,17 +31,20 @@
3031
import java.nio.file.Paths;
3132

3233
@ScannerSide
33-
public class FileCacheSensor implements ProjectSensor {
34-
private static final Logger LOG = Loggers.get(FileCacheSensor.class);
34+
public abstract class AbstractFileCacheSensor implements ProjectSensor {
35+
private static final Logger LOG = Loggers.get(AbstractFileCacheSensor.class);
36+
private final AbstractLanguage language;
3537
private final HashProvider hashProvider;
3638

37-
public FileCacheSensor(HashProvider hashProvider) {
39+
protected AbstractFileCacheSensor(AbstractLanguage language, HashProvider hashProvider) {
40+
this.language = language;
3841
this.hashProvider = hashProvider;
3942
}
4043

4144
@Override
4245
public void describe(SensorDescriptor descriptor) {
43-
descriptor.name("File Hash Caching Sensor");
46+
descriptor.name(language.getName() + " File Caching Sensor");
47+
descriptor.onlyOnLanguage(language.getKey());
4448
}
4549

4650
@Override
@@ -66,7 +70,7 @@ public void execute(SensorContext context) {
6670

6771
LOG.debug("Incremental PR analysis: Preparing to upload file hashes.");
6872
var fileSystem = context.fileSystem();
69-
fileSystem.inputFiles(fileSystem.predicates().all()).forEach(inputFile -> {
73+
fileSystem.inputFiles(fileSystem.predicates().hasLanguage(language.getKey())).forEach(inputFile -> {
7074
// Normalize to unix style separators. The scanner should be able to read the files on both windows and unix.
7175
var uri = inputFile.uri();
7276
var key = basePath.get().relativize(uri).getPath().replace('\\','/');

sonar-dotnet-shared-library/src/test/java/org/sonarsource/dotnet/shared/plugins/FileCacheSensorTest.java renamed to sonar-dotnet-shared-library/src/test/java/org/sonarsource/dotnet/shared/plugins/AbstractFileCacheSensorTest.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
*/
2020
package org.sonarsource.dotnet.shared.plugins;
2121

22-
import org.junit.Ignore;
2322
import org.junit.Rule;
2423
import org.junit.Test;
2524
import org.junit.rules.TemporaryFolder;
@@ -30,6 +29,7 @@
3029
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
3130
import org.sonar.api.batch.sensor.internal.SensorContextTester;
3231
import org.sonar.api.config.internal.MapSettings;
32+
import org.sonar.api.resources.AbstractLanguage;
3333
import org.sonar.api.utils.log.LogTester;
3434
import org.sonar.api.utils.log.LoggerLevel;
3535

@@ -42,7 +42,10 @@
4242
import static org.mockito.Mockito.mock;
4343
import static org.mockito.Mockito.when;
4444

45-
public class FileCacheSensorTest {
45+
public class AbstractFileCacheSensorTest {
46+
private static final String LANGUAGE_KEY = "language-key";
47+
private static final String LANGUAGE_NAME = "Language Name";
48+
4649
@Rule
4750
public TemporaryFolder temp = new TemporaryFolder();
4851

@@ -55,8 +58,8 @@ public void should_describe() {
5558
var sensor = new FileCacheSensor(new HashProvider());
5659
sensor.describe(sensorDescriptor);
5760

58-
assertThat(sensorDescriptor.name()).isEqualTo("File Hash Caching Sensor");
59-
assertThat(sensorDescriptor.languages()).isEmpty();
61+
assertThat(sensorDescriptor.name()).isEqualTo("Language Name File Caching Sensor");
62+
assertThat(sensorDescriptor.languages()).containsOnly(LANGUAGE_KEY);
6063
}
6164

6265
@Test
@@ -141,9 +144,27 @@ private SensorContext CreateContextForCaching() throws IOException {
141144
context.setCacheEnabled(true);
142145
context.setSettings(settings);
143146
context.setNextCache(mock(WriteCache.class));
144-
context.fileSystem().add(new TestInputFileBuilder("foo", basePath, new File(basePath, "CSharp/Foo.cs")).setLanguage("cs").setType(InputFile.Type.MAIN).build());
145-
context.fileSystem().add(new TestInputFileBuilder("bar", basePath, new File(basePath, "VB\\Bar.vb")).setLanguage("vbnet").setType(InputFile.Type.MAIN).build());
147+
context.fileSystem().add(new TestInputFileBuilder("foo", basePath, new File(basePath, "CSharp/Foo.cs")).setLanguage(LANGUAGE_KEY).setType(InputFile.Type.MAIN).build());
148+
context.fileSystem().add(new TestInputFileBuilder("bar", basePath, new File(basePath, "VB\\Bar.vb")).setLanguage(LANGUAGE_KEY).setType(InputFile.Type.MAIN).build());
146149

147150
return context;
148151
}
152+
153+
private static class FileCacheSensor extends AbstractFileCacheSensor {
154+
public FileCacheSensor(HashProvider hashProvider) {
155+
super(new Language(), hashProvider);
156+
}
157+
}
158+
159+
private static class Language extends AbstractLanguage {
160+
161+
public Language() {
162+
super(LANGUAGE_KEY, LANGUAGE_NAME);
163+
}
164+
165+
@Override
166+
public String[] getFileSuffixes() {
167+
return new String[] {".cs", ".vb" };
168+
}
169+
}
149170
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* SonarVB
3+
* Copyright (C) 2012-2022 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.plugins.vbnet;
21+
22+
import org.sonarsource.dotnet.shared.plugins.AbstractFileCacheSensor;
23+
import org.sonarsource.dotnet.shared.plugins.HashProvider;
24+
25+
public class VbNetFileCacheSensor extends AbstractFileCacheSensor {
26+
public VbNetFileCacheSensor(VbNet vbNet, HashProvider hashProvider) {
27+
super(vbNet, hashProvider);
28+
}
29+
}

sonar-vbnet-plugin/src/main/java/org/sonar/plugins/vbnet/VbNetPlugin.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.sonarsource.dotnet.shared.plugins.EncodingPerFile;
2828
import org.sonarsource.dotnet.shared.plugins.FileTypeSensor;
2929
import org.sonarsource.dotnet.shared.plugins.GeneratedFileFilter;
30+
import org.sonarsource.dotnet.shared.plugins.HashProvider;
3031
import org.sonarsource.dotnet.shared.plugins.LogSensor;
3132
import org.sonarsource.dotnet.shared.plugins.ProjectTypeCollector;
3233
import org.sonarsource.dotnet.shared.plugins.PropertiesSensor;
@@ -64,8 +65,10 @@ public void define(Context context) {
6465
// collectors - they are populated by the module-level sensors
6566
ProjectTypeCollector.class,
6667
ReportPathCollector.class,
68+
HashProvider.class,
6769
// sensor
6870
DotNetSensor.class,
71+
VbNetFileCacheSensor.class,
6972
// language-specific
7073
METADATA,
7174
VbNet.class,

0 commit comments

Comments
 (0)