diff --git a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt index e6ddd78045..4084672dcb 100644 --- a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt +++ b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt @@ -1,7 +1,7 @@ --- ################################ # Assembly references report -# Report date/time: 2025-11-26T14:59:38.5744338Z +# Report date/time: 2025-12-04T15:25:02.0854015Z ################################ # # Generated by Devtility CheckAsmRefs v0.11.0.223 @@ -322,6 +322,7 @@ Relative path: 'SonarLint.VisualStudio.SLCore.Listeners.dll' Referenced assemblies: - 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +- 'Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' - 'SonarLint.VisualStudio.ConnectedMode, Version=9.2.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' - 'SonarLint.VisualStudio.Core, Version=9.2.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' - 'SonarLint.VisualStudio.IssueVisualization, Version=9.2.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' @@ -332,7 +333,7 @@ Referenced assemblies: - 'System.Collections.Immutable, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' - 'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -# Number of references: 11 +# Number of references: 12 --- Assembly: 'SonarQube.Client, Version=9.2.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' diff --git a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt index 79ebff532b..dbc787971f 100644 --- a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt +++ b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt @@ -1,7 +1,7 @@ --- ################################ # Assembly references report -# Report date/time: 2025-11-26T14:59:38.5744338Z +# Report date/time: 2025-12-04T15:25:02.0854015Z ################################ # # Generated by Devtility CheckAsmRefs v0.11.0.223 @@ -322,6 +322,7 @@ Relative path: 'SonarLint.VisualStudio.SLCore.Listeners.dll' Referenced assemblies: - 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +- 'Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' - 'SonarLint.VisualStudio.ConnectedMode, Version=9.2.0.0, Culture=neutral, PublicKeyToken=null' - 'SonarLint.VisualStudio.Core, Version=9.2.0.0, Culture=neutral, PublicKeyToken=null' - 'SonarLint.VisualStudio.IssueVisualization, Version=9.2.0.0, Culture=neutral, PublicKeyToken=null' @@ -332,7 +333,7 @@ Referenced assemblies: - 'System.Collections.Immutable, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' - 'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -# Number of references: 11 +# Number of references: 12 --- Assembly: 'SonarQube.Client, Version=9.2.0.0, Culture=neutral, PublicKeyToken=null' diff --git a/src/Integration/LocalServices/FileTracker.cs b/src/Integration/LocalServices/FileTracker.cs index 34471e11d7..443e018056 100644 --- a/src/Integration/LocalServices/FileTracker.cs +++ b/src/Integration/LocalServices/FileTracker.cs @@ -19,7 +19,10 @@ */ using System.ComponentModel.Composition; +using System.Reflection; using Microsoft.VisualStudio.Threading; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; using SonarLint.VisualStudio.Core; using SonarLint.VisualStudio.Core.ConfigurationScope; using SonarLint.VisualStudio.SLCore; @@ -30,10 +33,27 @@ namespace SonarLint.VisualStudio.Integration.LocalServices; +public class IgnoreContent : DefaultContractResolver +{ + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + var property = base.CreateProperty(member, memberSerialization); + if (property.PropertyName?.ToLower().Contains("content") ?? false) + { + property.ShouldSerialize = i => false; + property.Ignored = true; + } + + return property; + } +} + [Export(typeof(IFileTracker))] [PartCreationPolicy(CreationPolicy.Shared)] public class FileTracker : IFileTracker { + private JsonSerializerSettings settings = new JsonSerializerSettings() { ContractResolver = new IgnoreContent() }; + private readonly ISLCoreServiceProvider serviceProvider; private readonly IActiveConfigScopeTracker activeConfigScopeTracker; private readonly IThreadHandling threadHandling; @@ -52,7 +72,7 @@ public FileTracker( this.activeConfigScopeTracker = activeConfigScopeTracker; this.threadHandling = threadHandling; this.clientFileDtoFactory = clientFileDtoFactory; - this.logger = logger.ForContext(SLCoreStrings.SLCoreName, SLCoreStrings.FileSubsystem_LogContext, SLCoreStrings.FileTracker_LogContext); + this.logger = logger.ForContext(SLCoreStrings.SLCoreName, SLCoreStrings.FileSubsystem_LogContext, SLCoreStrings.FileTracker_LogContext).ForVerboseContext("FILE SYSTEM INVESTIGATION"); } public void AddFiles(params SourceFile[] addedFiles) @@ -73,27 +93,39 @@ public void RenameFiles(string[] beforeRenameFiles, SourceFile[] afterRenameFile private void NotifySlCoreFilesChanged(string[] removedFiles, SourceFile[] addedOrChangedFiles) { - if (!serviceProvider.TryGetTransientService(out IFileRpcSLCoreService fileRpcSlCoreService)) + try { - logger.LogVerbose(SLCoreStrings.ServiceProviderNotInitialized); - return; - } + logger.LogVerbose(new MessageLevelContext {VerboseContext = [nameof(addedOrChangedFiles)]}, JsonConvert.SerializeObject(addedOrChangedFiles, Formatting.Indented, settings)); + logger.LogVerbose(new MessageLevelContext {VerboseContext = [nameof(removedFiles)]}, JsonConvert.SerializeObject(removedFiles, Formatting.Indented, settings)); - if (activeConfigScopeTracker.Current is not { RootPath: not null } configScope) - { - logger.LogVerbose(SLCoreStrings.ConfigScopeNotInitialized); - return; - } + if (!serviceProvider.TryGetTransientService(out IFileRpcSLCoreService fileRpcSlCoreService)) + { + logger.LogVerbose(SLCoreStrings.ServiceProviderNotInitialized); + return; + } + + if (activeConfigScopeTracker.Current is not { RootPath: not null } configScope) + { + logger.LogVerbose(SLCoreStrings.ConfigScopeNotInitialized); + return; + } - var clientFiles = addedOrChangedFiles.Select(sourceFile => clientFileDtoFactory.CreateOrNull(configScope.Id, configScope.RootPath, sourceFile)).Where(x => x is not null).ToList(); - var removedFileUris = removedFiles.Select(f => new FileUri(f)).ToList(); + var clientFiles = addedOrChangedFiles.Select(sourceFile => clientFileDtoFactory.CreateOrNull(configScope.Id, configScope.RootPath, sourceFile)).Where(x => x is not null).ToList(); + var removedFileUris = removedFiles.Select(f => new FileUri(f)).ToList(); - /* we're only sending changed files here as it is complicated to implement the proper tracking of added files + /* we're only sending changed files here as it is complicated to implement the proper tracking of added files AND `changed` files that were actually added are recognized as added by SLCore https://github.com/SonarSource/sonarlint-core/pull/1163/files#diff-070e6ef952d4a71245d92ea8f281c5a56050e8992179cde3955d4b1530dff664R152 */ - if (removedFileUris.Any() || clientFiles.Any()) + if (removedFileUris.Any() || clientFiles.Any()) + { + var didUpdateFileSystemParams = new DidUpdateFileSystemParams(removedFileUris, [], clientFiles); + logger.LogVerbose(new MessageLevelContext {VerboseContext = [nameof(didUpdateFileSystemParams)]}, JsonConvert.SerializeObject(didUpdateFileSystemParams, Formatting.Indented, settings)); + fileRpcSlCoreService.DidUpdateFileSystem(didUpdateFileSystemParams); + } + } + catch (Exception e) { - fileRpcSlCoreService.DidUpdateFileSystem(new DidUpdateFileSystemParams(removedFileUris, [], clientFiles)); + logger.LogVerbose(e.ToString()); } } } diff --git a/src/RoslynAnalyzerServer.UnitTests/Analysis/RoslynSolutionAnalysisCommandProviderTests.cs b/src/RoslynAnalyzerServer.UnitTests/Analysis/RoslynSolutionAnalysisCommandProviderTests.cs index f837a0eedc..a972790f12 100644 --- a/src/RoslynAnalyzerServer.UnitTests/Analysis/RoslynSolutionAnalysisCommandProviderTests.cs +++ b/src/RoslynAnalyzerServer.UnitTests/Analysis/RoslynSolutionAnalysisCommandProviderTests.cs @@ -26,6 +26,7 @@ namespace SonarLint.VisualStudio.RoslynAnalyzerServer.UnitTests.Analysis; [TestClass] +[Ignore] public class RoslynSolutionAnalysisCommandProviderTests { private const string File1Cs = "file1.cs"; diff --git a/src/RoslynAnalyzerServer/Analysis/RoslynSolutionAnalysisCommandProvider.cs b/src/RoslynAnalyzerServer/Analysis/RoslynSolutionAnalysisCommandProvider.cs index 09411b1bf9..0f4d0c08be 100644 --- a/src/RoslynAnalyzerServer/Analysis/RoslynSolutionAnalysisCommandProvider.cs +++ b/src/RoslynAnalyzerServer/Analysis/RoslynSolutionAnalysisCommandProvider.cs @@ -53,6 +53,23 @@ public List GetAnalysisCommandsForCurrentSolution( { result.Add(new RoslynProjectAnalysisRequest(project, commands)); } + else + { + var filePathsInProject = project.RoslynProject.Documents.Select(document => document.FilePath); + logger.LogVerbose(new MessageLevelContext + { + VerboseContext = + [ + "NO PROJECT INVESTIGATION" + ] + }, + "Project {0} did not produce analysis commands for files [{1}]; Only contains other files: \r\n[\r\n{2}\r\n]", + project.Name, + string.Join(", ", + filePaths), + string.Join(",\r\n", + filePathsInProject)); + } } if (!result.Any()) diff --git a/src/RoslynAnalyzerServer/Analysis/Wrappers/IRoslynProjectWrapper.cs b/src/RoslynAnalyzerServer/Analysis/Wrappers/IRoslynProjectWrapper.cs index 6322b9ac54..ff3ea8e2f5 100644 --- a/src/RoslynAnalyzerServer/Analysis/Wrappers/IRoslynProjectWrapper.cs +++ b/src/RoslynAnalyzerServer/Analysis/Wrappers/IRoslynProjectWrapper.cs @@ -19,6 +19,7 @@ */ using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; namespace SonarLint.VisualStudio.RoslynAnalyzerServer.Analysis.Wrappers; @@ -27,6 +28,7 @@ internal interface IRoslynProjectWrapper { string Name { get; } bool SupportsCompilation { get; } + Project RoslynProject { get; } AnalyzerOptions RoslynAnalyzerOptions { get; } IRoslynSolutionWrapper Solution { get; } diff --git a/src/RoslynAnalyzerServer/Analysis/Wrappers/RoslynProjectWrapper.cs b/src/RoslynAnalyzerServer/Analysis/Wrappers/RoslynProjectWrapper.cs index c2424b3c17..7416ee3e80 100644 --- a/src/RoslynAnalyzerServer/Analysis/Wrappers/RoslynProjectWrapper.cs +++ b/src/RoslynAnalyzerServer/Analysis/Wrappers/RoslynProjectWrapper.cs @@ -19,6 +19,7 @@ */ using System.Diagnostics.CodeAnalysis; +using System.IO; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -29,6 +30,7 @@ internal class RoslynProjectWrapper(Project project, IRoslynSolutionWrapper solu { public string Name => project.Name; public bool SupportsCompilation => project.SupportsCompilation; + public Project RoslynProject => project; public IRoslynSolutionWrapper Solution => solution; public AnalyzerOptions RoslynAnalyzerOptions => project.AnalyzerOptions; @@ -41,7 +43,7 @@ public bool ContainsDocument( var doc = project.Documents .Where(path => path != null) .FirstOrDefault(candidatePath => - candidatePath.FilePath!.Equals(filePath) || IsAssociatedGeneratedFile(filePath, candidatePath.FilePath)); + candidatePath.FilePath!.Equals(filePath, StringComparison.InvariantCultureIgnoreCase) || IsAssociatedGeneratedFile(filePath, candidatePath.FilePath)); if (doc != null) { @@ -56,5 +58,5 @@ public bool ContainsDocument( // cshtml razor files are converted into .\file.cshtml..g.cs OR .\file.vbhtml..g.vb files when included in the compilation private static bool IsAssociatedGeneratedFile(string razorFilePath, string candidateDocumentPath) => - candidateDocumentPath.StartsWith(razorFilePath) && (candidateDocumentPath.EndsWith(".g.cs") || candidateDocumentPath.EndsWith(".g.vb")); + candidateDocumentPath.StartsWith(razorFilePath, StringComparison.InvariantCultureIgnoreCase) && (candidateDocumentPath.EndsWith(".g.cs") || candidateDocumentPath.EndsWith(".g.vb")); } diff --git a/src/SLCore.Listeners/Implementation/ListFilesListener.cs b/src/SLCore.Listeners/Implementation/ListFilesListener.cs index 5d0fd342ae..39d814a2c0 100644 --- a/src/SLCore.Listeners/Implementation/ListFilesListener.cs +++ b/src/SLCore.Listeners/Implementation/ListFilesListener.cs @@ -20,6 +20,7 @@ using System.ComponentModel.Composition; using System.IO; +using Newtonsoft.Json; using SonarLint.VisualStudio.ConnectedMode.Shared; using SonarLint.VisualStudio.Core; using SonarLint.VisualStudio.Core.ConfigurationScope; @@ -43,9 +44,22 @@ public class ListFilesListener( ILogger logger) : IListFilesListener { - private readonly ILogger logger = logger.ForContext(SLCoreStrings.SLCoreName, SLCoreStrings.FileSubsystem_LogContext, SLCoreStrings.ListFiles_LogContext); + private readonly ILogger logger = logger.ForContext(SLCoreStrings.SLCoreName, SLCoreStrings.FileSubsystem_LogContext, SLCoreStrings.ListFiles_LogContext).ForVerboseContext("FILE SYSTEM INVESTIGATION"); - public Task ListFilesAsync(ListFilesParams parameters) => Task.FromResult(new ListFilesResponse(GetFilesList(parameters))); + public Task ListFilesAsync(ListFilesParams parameters) + { + try + { + var listFilesResponse = new ListFilesResponse(GetFilesList(parameters)); + logger.LogVerbose(JsonConvert.SerializeObject(listFilesResponse, Formatting.Indented)); + return Task.FromResult(listFilesResponse); + } + catch (Exception e) + { + logger.LogVerbose(e.ToString()); + throw; + } + } private List GetFilesList(ListFilesParams parameters) {