Skip to content

Commit

Permalink
Merge pull request dotnet#1826 from heejaechang/errorsource
Browse files Browse the repository at this point in the history
added error source support

...

now, error list will have column (which is off by default) that shows source of each errors in a format "assembly name" or "assembly name [vsix name]"
  • Loading branch information
heejaechang committed Apr 11, 2015
2 parents 0235ccb + fc3b082 commit 2ad8197
Show file tree
Hide file tree
Showing 35 changed files with 635 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,9 @@ class Test
}
}

private class LiveId : UpdateArgsId
private class LiveId : ISupportLiveUpdate
{
// use just a random analyzer
public LiveId() : base(new CSharpSimplifyTypeNamesDiagnosticAnalyzer())
public LiveId()
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void AppendIntersectingSpans(int start, int length, IntervalIntrospector
}

// only follow minimum length for live diagnostic. otherwise, let it be zero length.
var minimumLegnth = _id is UpdateArgsId ? _owner.MinimumLength : 0;
var minimumLegnth = _id is ISupportLiveUpdate ? _owner.MinimumLength : 0;

foreach (var data in result)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ private DiagnosticsUpdatedArgs MakeArgs(
DebuggingSession session, object errorId, Workspace workspace, Solution solution, ProjectId projectId, DocumentId documentId, ImmutableArray<DiagnosticData> items)
{
return new DiagnosticsUpdatedArgs(
id: Tuple.Create(session, errorId),
id: new EnCId(session, errorId),
workspace: workspace,
solution: solution,
projectId: projectId,
Expand All @@ -110,5 +110,18 @@ private void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs args)
updated(this, args);
}
}

private class EnCId : ErrorSourceId.Base<DebuggingSession, object>
{
public EnCId(DebuggingSession session, object errorId) :
base(session, errorId)
{
}

public override string ErrorSource
{
get { return PredefinedErrorSources.EnC; }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ internal TestDiagnosticAnalyzerService(ImmutableDictionary<string, ImmutableArra
}

internal TestDiagnosticAnalyzerService(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null)
: base(workspaceAnalyzerAssemblies: SpecializedCollections.EmptyEnumerable<string>(), hostDiagnosticUpdateSource: hostDiagnosticUpdateSource)
: base(SpecializedCollections.EmptyEnumerable<HostDiagnosticAnalyzerPackage>(), hostDiagnosticUpdateSource)
{
_onAnalyzerException = onAnalyzerException;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.CodeAnalysis;
Expand All @@ -11,12 +12,12 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.Preview
[Export(typeof(IWorkspaceDiagnosticAnalyzerProviderService))]
internal class TestOnly_CompilerDiagnosticAnalyzerProviderService : IWorkspaceDiagnosticAnalyzerProviderService
{
private readonly IEnumerable<string> _compilerAnalyzerAssemblies;
private readonly HostDiagnosticAnalyzerPackage _info;

[ImportingConstructor]
public TestOnly_CompilerDiagnosticAnalyzerProviderService()
{
_compilerAnalyzerAssemblies = GetCompilerAnalyzerAssemblies().Distinct();
_info = new HostDiagnosticAnalyzerPackage("Compiler", GetCompilerAnalyzerAssemblies().Distinct().ToImmutableArray());
}

private static IEnumerable<string> GetCompilerAnalyzerAssemblies()
Expand All @@ -31,9 +32,9 @@ private static IEnumerable<string> GetCompilerAnalyzerAssemblies()
}
}

public IEnumerable<string> GetWorkspaceAnalyzerAssemblies()
public IEnumerable<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages()
{
return _compilerAnalyzerAssemblies;
yield return _info;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private void ClearAnalyzerDiagnostics(DiagnosticAnalyzer analyzer, ProjectId pro
private DiagnosticsUpdatedArgs MakeArgs(DiagnosticAnalyzer analyzer, ImmutableHashSet<DiagnosticData> items, Project project)
{
return new DiagnosticsUpdatedArgs(
id: Tuple.Create(this, analyzer, project?.Id),
id: new HostArgsId(this, analyzer, project?.Id),
workspace: this.Workspace,
solution: project?.Solution,
projectId: project?.Id,
Expand All @@ -142,5 +142,33 @@ internal ImmutableHashSet<DiagnosticData> TestOnly_GetReportedDiagnostics(Diagno

return diagnostics;
}

private class HostArgsId : AnalyzerUpdateArgsId
{
private readonly AbstractHostDiagnosticUpdateSource _source;
private readonly ProjectId _projectId;

public HostArgsId(AbstractHostDiagnosticUpdateSource source, DiagnosticAnalyzer analyzer, ProjectId id) : base(analyzer)
{
this._source = source;
this._projectId = id;
}

public override bool Equals(object obj)
{
var other = obj as HostArgsId;
if (other == null)
{
return false;
}

return _source == other._source && _projectId == other._projectId && base.Equals(obj);
}

public override int GetHashCode()
{
return Hash.Combine(_source.GetHashCode(), Hash.Combine(_projectId.GetHashCode(), base.GetHashCode()));
}
}
}
}
6 changes: 6 additions & 0 deletions src/Features/Core/Diagnostics/AnalyzerHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public static ValueTuple<string, VersionStamp> GetAnalyzerIdAndVersion(this Diag
return ValueTuple.Create(GetAssemblyQualifiedNameWithoutVersion(type), GetAnalyzerVersion(type.Assembly.Location));
}

public static string GetAnalyzerAssemblyName(this DiagnosticAnalyzer analyzer)
{
var type = analyzer.GetType();
return type.Assembly.GetName().Name;
}

private static string GetAssemblyQualifiedNameWithoutVersion(Type type)
{
var name = type.AssemblyQualifiedName;
Expand Down
30 changes: 30 additions & 0 deletions src/Features/Core/Diagnostics/AnalyzerUpdateArgsId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.CodeAnalysis.Diagnostics
{
/// <summary>
/// Base type of a type that is used as <see cref="DiagnosticsUpdatedArgs.Id"/> for live diagnostic
/// </summary>
internal class AnalyzerUpdateArgsId : ErrorSourceId.Base<DiagnosticAnalyzer>, ISupportLiveUpdate
{
public DiagnosticAnalyzer Analyzer => _Field1;

protected AnalyzerUpdateArgsId(DiagnosticAnalyzer analyzer) :
base(analyzer)
{
}

public override string ErrorSource
{
get
{
if (Analyzer == null)
{
return string.Empty;
}

return Analyzer.GetAnalyzerAssemblyName();
}
}
}
}
20 changes: 14 additions & 6 deletions src/Features/Core/Diagnostics/DiagnosticAnalyzerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,18 @@ public DiagnosticAnalyzerService(
[ImportMany] IEnumerable<Lazy<IAsynchronousOperationListener, FeatureMetadata>> asyncListeners,
[Import(AllowDefault = true)]IWorkspaceDiagnosticAnalyzerProviderService diagnosticAnalyzerProviderService = null,
[Import(AllowDefault = true)]AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null)
: this(workspaceAnalyzerAssemblies: diagnosticAnalyzerProviderService != null ?
diagnosticAnalyzerProviderService.GetWorkspaceAnalyzerAssemblies() :
SpecializedCollections.EmptyEnumerable<string>(),
hostDiagnosticUpdateSource: hostDiagnosticUpdateSource)
: this(diagnosticAnalyzerProviderService != null ? diagnosticAnalyzerProviderService.GetHostDiagnosticAnalyzerPackages() : SpecializedCollections.EmptyEnumerable<HostDiagnosticAnalyzerPackage>(),
hostDiagnosticUpdateSource)
{
_listener = new AggregateAsynchronousOperationListener(asyncListeners, FeatureAttribute.DiagnosticService);
}

public IAsynchronousOperationListener Listener => _listener;

// protected for testing purposes.
protected DiagnosticAnalyzerService(IEnumerable<string> workspaceAnalyzerAssemblies, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : this()
protected DiagnosticAnalyzerService(IEnumerable<HostDiagnosticAnalyzerPackage> workspaceAnalyzerPackages, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : this()
{
_hostAnalyzerManager = new HostAnalyzerManager(workspaceAnalyzerAssemblies, hostDiagnosticUpdateSource);
_hostAnalyzerManager = new HostAnalyzerManager(workspaceAnalyzerPackages, hostDiagnosticUpdateSource);
_hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
}

Expand Down Expand Up @@ -174,6 +172,16 @@ public bool IsCompilerDiagnostic(string language, DiagnosticData diagnostic)
return _hostAnalyzerManager.IsCompilerDiagnostic(language, diagnostic);
}

public DiagnosticAnalyzer GetCompilerDiagnosticAnalyzer(string language)
{
return _hostAnalyzerManager.GetCompilerDiagnosticAnalyzer(language);
}

public bool IsCompilerDiagnosticAnalyzer(string language, DiagnosticAnalyzer analyzer)
{
return _hostAnalyzerManager.IsCompilerDiagnosticAnalyzer(language, analyzer);
}

// virtual for testing purposes.
internal virtual Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException(ProjectId projectId, DiagnosticLogAggregator diagnosticLogAggregator)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Immutable;
using Roslyn.Utilities;

Expand Down Expand Up @@ -81,14 +82,33 @@ public VersionArgument(VersionStamp textVersion, VersionStamp dataVersion, Versi
}
}

public class ArgumentKey : UpdateArgsId
public class HostAnalyzerKey : ArgumentKey
{
private readonly string _analyzerPackageName;

public HostAnalyzerKey(DiagnosticAnalyzer analyzer, StateType stateType, object key, string analyzerPackageName) :
base(analyzer, stateType, key)
{
_analyzerPackageName = analyzerPackageName;
}

public override string ErrorSource
{
get
{
return _analyzerPackageName;
}
}
}

public class ArgumentKey : AnalyzerUpdateArgsId
{
public readonly StateType StateType;
public readonly object Key;

public ArgumentKey(DiagnosticAnalyzer analyzer, StateType stateTypeId, object key) : base(analyzer)
public ArgumentKey(DiagnosticAnalyzer analyzer, StateType stateType, object key) : base(analyzer)
{
this.StateType = stateTypeId;
this.StateType = stateType;
this.Key = key;
}

Expand All @@ -100,12 +120,12 @@ public override bool Equals(object obj)
return false;
}

return base.Equals(obj) && StateType == other.StateType && Key == other.Key;
return StateType == other.StateType && Key == other.Key && base.Equals(obj);
}

public override int GetHashCode()
{
return Hash.Combine(Key, Hash.Combine(base.GetHashCode(), (int)StateType));
return Hash.Combine(Key, Hash.Combine((int)StateType, base.GetHashCode()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private ImmutableDictionary<DiagnosticAnalyzer, StateSet> CreateLanguageSpecific
{
var analyzersPerReference = _owner.AnalyzerManager.GetHostDiagnosticAnalyzersPerReference(language);

var analyzerMap = CreateAnalyzerMap(language, analyzersPerReference.Values);
var analyzerMap = CreateAnalyzerMap(_owner.AnalyzerManager, language, analyzersPerReference.Values);
VerifyDiagnosticStates(analyzerMap.Values);

return analyzerMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private ImmutableDictionary<DiagnosticAnalyzer, StateSet> GetOrUpdateAnalyzerMap
}

var newAnalyzersPerReference = _owner.AnalyzerManager.CreateProjectDiagnosticAnalyzersPerReference(project);
var newMap = StateManager.CreateAnalyzerMap(project.Language, newAnalyzersPerReference.Values);
var newMap = StateManager.CreateAnalyzerMap(_owner.AnalyzerManager, project.Language, newAnalyzersPerReference.Values);

RaiseProjectAnalyzerReferenceChangedIfNeeded(project, newAnalyzersPerReference, newMap);

Expand Down Expand Up @@ -135,7 +135,7 @@ private ImmutableDictionary<DiagnosticAnalyzer, StateSet> CreateAnalyzerMap(Proj
return ImmutableDictionary<DiagnosticAnalyzer, StateSet>.Empty;
}

return StateManager.CreateAnalyzerMap(project.Language, analyzersPerReference.Values);
return StateManager.CreateAnalyzerMap(_owner.AnalyzerManager, project.Language, analyzersPerReference.Values);
}

private void RaiseProjectAnalyzerReferenceChangedIfNeeded(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ private void RaiseProjectAnalyzerReferenceChanged(ProjectAnalyzerReferenceChange
}

private static ImmutableDictionary<DiagnosticAnalyzer, StateSet> CreateAnalyzerMap(
string language, IEnumerable<ImmutableArray<DiagnosticAnalyzer>> analyzerCollection)
HostAnalyzerManager analyzerManager, string language, IEnumerable<ImmutableArray<DiagnosticAnalyzer>> analyzerCollection)
{
var compilerAnalyzer = analyzerManager.GetCompilerDiagnosticAnalyzer(language);

var builder = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, StateSet>();
foreach (var analyzers in analyzerCollection)
{
Expand All @@ -128,13 +130,27 @@ private static ImmutableDictionary<DiagnosticAnalyzer, StateSet> CreateAnalyzerM
continue;
}

builder.Add(analyzer, new StateSet(language, analyzer));
var errorSourceName = analyzer == compilerAnalyzer ?
PredefinedErrorSources.Compiler : GetErrorSourceName(analyzerManager, language, analyzer);

builder.Add(analyzer, new StateSet(language, analyzer, errorSourceName));
}
}

return builder.ToImmutable();
}

private static string GetErrorSourceName(HostAnalyzerManager analyzerManager, string language, DiagnosticAnalyzer analyzer)
{
var packageName = analyzerManager.GetDiagnosticAnalyzerPackageName(language, analyzer);
if (packageName == null)
{
return null;
}

return $"{analyzer.GetAnalyzerAssemblyName()} [{packageName}]";
}

[Conditional("DEBUG")]
private static void VerifyDiagnosticStates(IEnumerable<StateSet> stateSets)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ private class StateSet

private readonly string _language;
private readonly DiagnosticAnalyzer _analyzer;
private readonly string _errorSourceName;

private readonly DiagnosticState[] _state;

public StateSet(string language, DiagnosticAnalyzer analyzer)
public StateSet(string language, DiagnosticAnalyzer analyzer, string errorSourceName)
{
_language = language;
_analyzer = analyzer;
_errorSourceName = errorSourceName;

_state = CreateDiagnosticStates(language, analyzer);
}

public string ErrorSourceName => _errorSourceName;
public string Language => _language;
public DiagnosticAnalyzer Analyzer => _analyzer;

Expand Down
Loading

0 comments on commit 2ad8197

Please sign in to comment.