/// <summary> /// Create a new solution instance with the project specified updated to include the /// specified analyzer reference. /// </summary> public Solution AddAnalyzerReference(ProjectId projectId, AnalyzerReference analyzerReference) { var newState = _state.AddAnalyzerReference(projectId, analyzerReference); if (newState == _state) { return(this); } return(new Solution(newState)); }
public void WriteTo(AnalyzerReference reference, ObjectWriter writer, bool usePathFromAssembly, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); switch (reference) { case AnalyzerFileReference file: { // fail to load analyzer assembly var assemblyPath = usePathFromAssembly ? TryGetAnalyzerAssemblyPath(file) : file.FullPath; if (assemblyPath == null) { WriteUnresolvedAnalyzerReferenceTo(reference, writer); return; } writer.WriteString(nameof(AnalyzerFileReference)); writer.WriteInt32((int)SerializationKinds.FilePath); // TODO: remove this kind of host specific knowledge from common layer. // but think moving it to host layer where this implementation detail actually exist. // // analyzer assembly path to load analyzer acts like // snapshot version for analyzer (since it is based on shadow copy) // we can't send over bits and load analyer from memory (image) due to CLR not being able // to find satellite dlls for analyzers. writer.WriteString(file.FullPath); writer.WriteString(assemblyPath); return; } case UnresolvedAnalyzerReference unresolved: { WriteUnresolvedAnalyzerReferenceTo(unresolved, writer); return; } case AnalyzerReference analyzerReference when analyzerReference.GetType().FullName == VisualStudioUnresolvedAnalyzerReference: { WriteUnresolvedAnalyzerReferenceTo(analyzerReference, writer); return; } case AnalyzerImageReference _: { // TODO: think a way to support this or a way to deal with this kind of situation. // https://github.com/dotnet/roslyn/issues/15783 throw new NotSupportedException(nameof(AnalyzerImageReference)); } default: throw ExceptionUtilities.UnexpectedValue(reference); } }
public Checksum CreateChecksum(AnalyzerReference reference, CancellationToken cancellationToken) { using (var stream = SerializableBytes.CreateWritableStream()) using (var writer = new StreamObjectWriter(stream, cancellationToken: cancellationToken)) { WriteTo(reference, writer, cancellationToken); stream.Position = 0; return(Checksum.Create(stream)); } }
private static Checksum CreateChecksum(AnalyzerReference reference) { using (var stream = SerializableBytes.CreateWritableStream()) using (var objectWriter = new ObjectWriter(stream)) { objectWriter.WriteString(WellKnownSynchronizationKinds.AnalyzerReference); objectWriter.WriteString(reference.FullPath); return(Checksum.Create(stream)); } }
public static WorkspaceAnalyzerReferenceAsset Create( AnalyzerReference reference, ISerializerService serializer, IReferenceSerializationService hostSerializationService, CancellationToken cancellationToken) { var checksum = Checksum.Create( WellKnownSynchronizationKind.AnalyzerReference, hostSerializationService.CreateChecksum(reference, usePathFromAssembly, cancellationToken)); return(new WorkspaceAnalyzerReferenceAsset(reference, serializer, checksum)); }
protected override bool TryGetExtensionsFromReference(AnalyzerReference reference, out ImmutableArray <CodeRefactoringProvider> extensions) { // check whether the analyzer reference knows how to return fixers directly. if (reference is ICodeRefactoringProviderFactory codeRefactoringProviderFactory) { extensions = codeRefactoringProviderFactory.GetRefactorings(); return(true); } extensions = default; return(false); }
/// <summary> /// Call this method when an analyzer reference is removed from a project in the host environment. /// </summary> protected internal void OnAnalyzerReferenceRemoved(ProjectId projectId, AnalyzerReference analyzerReference) { using (this.serializationLock.DisposableWait()) { CheckProjectIsInCurrentSolution(projectId); CheckProjectHasAnalyzerReference(projectId, analyzerReference); var oldSolution = this.CurrentSolution; var newSolution = this.SetCurrentSolution(oldSolution.RemoveAnalyzerReference(projectId, analyzerReference)); this.RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind.ProjectChanged, oldSolution, newSolution, projectId); } }
public CpsDiagnosticItemSource(Workspace workspace, ProjectId projectId, IVsHierarchyItem item, IAnalyzersCommandHandler commandHandler, IDiagnosticAnalyzerService analyzerService) : base(workspace, projectId, commandHandler, analyzerService) { _item = item; _analyzerReference = TryGetAnalyzerReference(_workspace.CurrentSolution); if (_analyzerReference == null) { // The workspace doesn't know about the project and/or the analyzer yet. // Hook up an event handler so we can update when it does. _workspace.WorkspaceChanged += OnWorkspaceChangedLookForAnalyzer; } }
public void SonarAnalyzerManager_HasNoCollidingAnalyzerReference_NoAssemblyIdentity() { IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new object(), SonarAnalyzerManager.AnalyzerName) }; SonarAnalyzerManager.HasConflictingAnalyzerReference( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeTrue("If no AssemblyIdentity is present, but the name matches, we should report a conflict"); }
public void SonarAnalyzerManager_HasNoCollidingAnalyzerReference_SameNameVersion() { IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, SonarAnalyzerManager.AnalyzerVersion), SonarAnalyzerManager.AnalyzerName) }; SonarAnalyzerManager.HasConflictingAnalyzerReference( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeFalse("Same named and versioned analyzers should not be reported as conflicting ones"); }
public override void WriteAnalyzerReferenceTo(AnalyzerReference reference, ObjectWriter writer, CancellationToken cancellationToken) { if (reference is TestGeneratorReference generatorReference) { // It's a test reference, we'll just store it in a map and then just write out our GUID _sharedTestGeneratorReferences.TryAdd(generatorReference.Guid, generatorReference); writer.WriteGuid(generatorReference.Guid); } else { writer.WriteGuid(Guid.Empty); base.WriteAnalyzerReferenceTo(reference, writer, cancellationToken); } }
public void WriteTo(AnalyzerReference reference, ObjectWriter writer, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var file = reference as AnalyzerFileReference; if (file != null) { // fail to load analyzer assembly var assemblyPath = TryGetAnalyzerAssemblyPath(file); if (assemblyPath == null) { WriteUnresolvedAnalyzerReferenceTo(reference, writer); return; } writer.WriteString(nameof(AnalyzerFileReference)); writer.WriteInt32((int)SerializationKinds.FilePath); writer.WriteString(file.FullPath); // TODO: remove this kind of host specific knowledge from common layer. // but think moving it to host layer where this implementation detail actually exist. // // analyzer assembly path to load analyzer acts like // snapshot version for analyzer (since it is based on shadow copy) // we can't send over bits and load analyer from memory (image) due to CLR not being able // to find satellite dlls for analyzers. writer.WriteString(assemblyPath); return; } var unresolved = reference as UnresolvedAnalyzerReference; if (unresolved != null) { WriteUnresolvedAnalyzerReferenceTo(reference, writer); return; } var image = reference as AnalyzerImageReference; if (image != null) { // TODO: think a way to support this or a way to deal with this kind of situation. throw new NotSupportedException(nameof(AnalyzerImageReference)); } throw ExceptionUtilities.UnexpectedValue(reference.GetType()); }
public bool HasAnalyzerReference(AnalyzerReference analyzerReference) { Contract.ThrowIfNull(analyzerReference); if (analyzerReference is AnalyzerFileReference) { // Filter out duplicate analyzer references with same assembly name/full path. return analyzerReference.Display != null && _diagnosticAnalyzerIdMap.ContainsKey(analyzerReference.Display); } else { // For non-file references, we will check individual DiagnosticAnalyzer instances for duplicates. return false; } }
public bool HasAnalyzerReference(AnalyzerReference analyzerReference) { Contract.ThrowIfNull(analyzerReference); if (analyzerReference is AnalyzerFileReference) { // Filter out duplicate analyzer references with same assembly name/full path. return(analyzerReference.Display != null && _diagnosticAnalyzerIdMap.ContainsKey(analyzerReference.Display)); } else { // For non-file references, we will check individual DiagnosticAnalyzer instances for duplicates. return(false); } }
public void SonarAnalyzerManager_GetIsBoundWithoutAnalyzer_Unbound_NonConflicting() { this.activeSolutionBoundTracker.IsActiveSolutionBound = false; IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, SonarAnalyzerManager.AnalyzerVersion), SonarAnalyzerManager.AnalyzerName) }; this.testSubject.GetIsBoundWithoutAnalyzer( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeFalse("Unbound solution should never return true"); }
public void RemoveAnalyzerReference(AnalyzerReference reference) { if (reference is AnalyzerFileReference fileRef) { var relativePath = PathUtilities.GetRelativePath(_loadedProject.DirectoryPath, fileRef.FullPath); var analyzers = _loadedProject.GetItems(ItemNames.Analyzer); var item = analyzers.FirstOrDefault(it => PathUtilities.PathsEqual(it.EvaluatedInclude, relativePath) || PathUtilities.PathsEqual(it.EvaluatedInclude, fileRef.FullPath)); if (item != null) { _loadedProject.RemoveItem(item); } } }
public DiagnosticItem( ProjectId projectId, AnalyzerReference analyzerReference, DiagnosticDescriptor descriptor, ReportDiagnostic effectiveSeverity, string language, IAnalyzersCommandHandler commandHandler ) : base(descriptor.Id + ": " + descriptor.Title) { ProjectId = projectId; _analyzerReference = analyzerReference; Descriptor = descriptor; EffectiveSeverity = effectiveSeverity; _language = language; _commandHandler = commandHandler; }
public static void WriteTo(AnalyzerReference reference, ObjectWriter writer, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); switch (reference) { case AnalyzerFileReference file: writer.WriteString(nameof(AnalyzerFileReference)); writer.WriteString(file.FullPath); writer.WriteBoolean(IsAnalyzerReferenceWithShadowCopyLoader(file)); break; default: throw ExceptionUtilities.UnexpectedValue(reference); } }
public AnalyzerReference GetReference() { if (_analyzerReference == null) { if (File.Exists(_fullPath)) { _analyzerReference = new AnalyzerFileReference(_fullPath, InMemoryAssemblyProvider.GetAssembly); ((AnalyzerFileReference)_analyzerReference).AnalyzerLoadFailed += OnAnalyzerLoadError; } else { _analyzerReference = new UnresolvedAnalyzerReference(_fullPath); } } return(_analyzerReference); }
public void SonarAnalyzerManager_HasNoCollidingAnalyzerReference_SameVersionDifferentName() { var name = "Some test name"; name.Should().NotBe(SonarAnalyzerManager.AnalyzerName, "Test input should be different from the expected analyzer name"); IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(name, SonarAnalyzerManager.AnalyzerVersion), name) }; SonarAnalyzerManager.HasConflictingAnalyzerReference( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeFalse("Name is not considered in the conflict checking"); }
public void Reset() { if (_analyzerReference is AnalyzerFileReference analyzerFileReference) { analyzerFileReference.AnalyzerLoadFailed -= OnAnalyzerLoadError; if (_analyzerLoadErrors != null && _analyzerLoadErrors.Count > 0) { _hostDiagnosticUpdateSource.ClearDiagnosticsForProject(_projectId, this); } _hostDiagnosticUpdateSource.ClearAnalyzerReferenceDiagnostics(analyzerFileReference, _language, _projectId); } _analyzerLoadErrors = null; _analyzerReference = null; }
public AnalyzerReference GetReference() { if (_analyzerReference == null) { if (File.Exists(_fullPath)) { _analyzerReference = new AnalyzerFileReference(_fullPath, _loader); ((AnalyzerFileReference)_analyzerReference).AnalyzerLoadFailed += OnAnalyzerLoadError; } else { _analyzerReference = new UnresolvedAnalyzerReference(_fullPath); } } return(_analyzerReference); }
public void RemoveAnalyzerReference(AnalyzerReference reference) { var fileRef = reference as AnalyzerFileReference; if (fileRef != null) { string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, fileRef.FullPath); var analyzers = _loadedProject.GetItems("Analyzer"); var item = analyzers.FirstOrDefault(it => FilePathUtilities.PathsEqual(it.EvaluatedInclude, relativePath) || FilePathUtilities.PathsEqual(it.EvaluatedInclude, fileRef.FullPath)); if (item != null) { _loadedProject.RemoveItem(item); } } }
public void SonarAnalyzerManager_HasNoCollidingAnalyzerReference_NoDisplayName() { var version = new Version("0.1.2.3"); version.Should().NotBe(SonarAnalyzerManager.AnalyzerVersion, "Test input should be different from the expected analyzer version"); IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, version), null) }; SonarAnalyzerManager.HasConflictingAnalyzerReference( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeFalse("Null analyzer name should not report conflict"); }
public void SonarAnalyzerManager_HasCollidingAnalyzerReference() { var version = new Version("0.1.2.3"); version.Should().NotBe(SonarAnalyzerManager.AnalyzerVersion, "Test input should be different from the expected analyzer version"); IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, version), SonarAnalyzerManager.AnalyzerName) }; SonarAnalyzerManager.HasConflictingAnalyzerReference( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeTrue("Conflicting analyzer package not found"); }
public AnalyzerReference GetReference() { if (_analyzerReference == null) { if (File.Exists(_fullPath)) { // Pass down a custom loader that will ensure we are watching for file changes once we actually load the assembly. var assemblyLoaderForFileTracker = new AnalyzerAssemblyLoaderThatEnsuresFileBeingWatched(this); _analyzerReference = new AnalyzerFileReference(_fullPath, assemblyLoaderForFileTracker); ((AnalyzerFileReference)_analyzerReference).AnalyzerLoadFailed += OnAnalyzerLoadError; } else { _analyzerReference = new VisualStudioUnresolvedAnalyzerReference(_fullPath, this); } } return(_analyzerReference); }
public void SonarAnalyzerManager_GetIsBoundWithoutAnalyzer_Unbound_Conflicting() { this.activeSolutionBoundTracker.IsActiveSolutionBound = false; var version = new Version("0.1.2.3"); version.Should().NotBe(SonarAnalyzerManager.AnalyzerVersion, "Test input should be different from the expected analyzer version"); IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, version), SonarAnalyzerManager.AnalyzerName) }; this.testSubject.GetIsBoundWithoutAnalyzer( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeFalse("Unbound solution should never return true"); }
public void SonarAnalyzerManager_GetIsBoundWithoutAnalyzer_Bound_Conflicting() { this.activeSolutionBoundTracker.IsActiveSolutionBound = true; var version = new Version("0.1.2.3"); Assert.AreNotEqual(SonarAnalyzerManager.AnalyzerVersion, version, "Test input should be different from the expected analyzer version"); IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, version), SonarAnalyzerManager.AnalyzerName) }; Assert.IsFalse( this.testSubject.GetIsBoundWithoutAnalyzer( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)), "Bound solution with conflicting analyzer name should never return true"); }
public void SonarAnalyzerManager_MultipleReferencesWithSameName_CollidingVersion() { var version = new Version("0.1.2.3"); version.Should().NotBe(SonarAnalyzerManager.AnalyzerVersion, "Test input should be different from the expected analyzer version"); IEnumerable <AnalyzerReference> references = new AnalyzerReference[] { new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, version), SonarAnalyzerManager.AnalyzerName), new ConfigurableAnalyzerReference( new AssemblyIdentity(SonarAnalyzerManager.AnalyzerName, SonarAnalyzerManager.AnalyzerVersion), SonarAnalyzerManager.AnalyzerName), }; SonarAnalyzerManager.HasConflictingAnalyzerReference( SonarAnalyzerManager.GetProjectAnalyzerConflictStatus(references)) .Should().BeFalse("Having already colliding references should not disable the embedded analyzer if one is of the same version"); }
protected override void ApplyAnalyzerReferenceRemoved(ProjectId projectId, AnalyzerReference analyzerReference) { if (projectId == null) { throw new ArgumentNullException(nameof(projectId)); } if (analyzerReference == null) { throw new ArgumentNullException(nameof(analyzerReference)); } GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); string filePath = GetAnalyzerPath(analyzerReference); if (filePath != null) { VSProject3 vsProject = (VSProject3)project.Object; vsProject.AnalyzerReferences.Remove(filePath); } }
private IEnumerable <BaseDiagnosticItem> GetDiagnosticItems(string language, CompilationOptions options, ImmutableDictionary <string, ReportDiagnostic> analyzerConfigSpecificDiagnosticOptions) { // Within an analyzer assembly, an individual analyzer may report multiple different diagnostics // with the same ID. Or, multiple analyzers may report diagnostics with the same ID. Or a // combination of the two may occur. // We only want to show one node in Solution Explorer for a given ID. So we pick one, but we need // to be consistent in which one we pick. Diagnostics with the same ID may have different // descriptions or messages, and it would be strange if the node's name changed from one run of // VS to another. So we group the diagnostics by ID, sort them within a group, and take the first // one. return(AnalyzerReference.GetAnalyzers(language) .SelectMany(a => _diagnosticAnalyzerService.GetDiagnosticDescriptors(a)) .GroupBy(d => d.Id) .OrderBy(g => g.Key, StringComparer.CurrentCulture) .Select(g => { var selectedDiagnostic = g.OrderBy(d => d, s_comparer).First(); var effectiveSeverity = selectedDiagnostic.GetEffectiveSeverity(options, analyzerConfigSpecificDiagnosticOptions); return CreateItem(selectedDiagnostic, effectiveSeverity); })); }