Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
aa6d5fa
split things in multiple files.
heejaechang Mar 3, 2016
f8491ab
doing more basic arrangement for oop
heejaechang Mar 4, 2016
2c86c83
fixed merge conflict from master
heejaechang Mar 21, 2016
2e819f9
made solution to build after merge
heejaechang Mar 21, 2016
fec6319
fixed merge conflict
heejaechang Mar 23, 2016
c632be8
made solution to compile without v1 engine.
heejaechang Mar 23, 2016
3cd50f0
made argsId to be shared between engine v1 and v2
heejaechang Mar 23, 2016
f161613
removed unused usings
heejaechang Mar 29, 2016
82c9de9
full implementation of engine v2
heejaechang Apr 11, 2016
1362e5b
added unit tests for diagnostic data serializer
heejaechang Apr 11, 2016
6185f75
made all test pass
heejaechang Apr 12, 2016
7e4d071
use compilation based concurrency (async) rather than driver based on…
heejaechang Apr 12, 2016
11199c4
some clean up
heejaechang Apr 12, 2016
27c20e4
fixed merge issue upstream/master
heejaechang Apr 12, 2016
eb3aa8d
fixed merge issue 2
heejaechang Apr 12, 2016
96a13f4
PR feedback
heejaechang Apr 12, 2016
96ace4c
GetEffectiveDiagnostics is not needed for CompilationWithAnalyzer API
heejaechang Apr 12, 2016
c18332f
added comment for AddExternalDiagnostics
heejaechang Apr 12, 2016
2a436df
PR feedback.
heejaechang Apr 12, 2016
060de6a
use semantic based IsCompilerAnalyzer rather than the hacky string ba…
heejaechang Apr 12, 2016
7fb3292
CR feedback.
heejaechang Apr 12, 2016
2920c15
CR feedback.
heejaechang Apr 12, 2016
60e41b2
added comment based on PR.
heejaechang Apr 12, 2016
5122239
added some comment
heejaechang Apr 12, 2016
1410c34
make analyzer driver won't get into action execution when there is ac…
heejaechang Apr 14, 2016
ef26030
CR feedback.
heejaechang Apr 14, 2016
e8dde0d
Merge branch 'master' of https://github.com/dotnet/roslyn into oop2
heejaechang Apr 14, 2016
ba9daa6
restore +x
heejaechang Apr 14, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,11 @@ private void ExecuteDeclaringReferenceActions(
ImmutableDictionary<TLanguageKindEnum, ImmutableArray<SyntaxNodeAnalyzerAction<TLanguageKindEnum>>> nodeActionsByKind;
if (this.NodeActionsByAnalyzerAndKind.TryGetValue(analyzer, out nodeActionsByKind))
{
if (nodeActionsByKind.IsEmpty)
{
continue;
}

analyzerExecutor.ExecuteSyntaxNodeActions(nodesToAnalyze, nodeActionsByKind,
analyzer, semanticModel, _getKind, declarationAnalysisData.TopmostNodeForAnalysis.FullSpan,
decl, declarationIndex, symbol, analysisScope, analysisStateOpt, isInGeneratedCode);
Expand Down Expand Up @@ -1610,6 +1615,11 @@ private void ExecuteDeclaringReferenceActions(
ImmutableDictionary<OperationKind, ImmutableArray<OperationAnalyzerAction>> operationActionsByKind;
if (this.OperationActionsByAnalyzerAndKind.TryGetValue(analyzer, out operationActionsByKind))
{
if (operationActionsByKind.IsEmpty)
{
continue;
}

analyzerExecutor.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind,
analyzer, semanticModel, declarationAnalysisData.TopmostNodeForAnalysis.FullSpan,
decl, declarationIndex, symbol, analysisScope, analysisStateOpt, isInGeneratedCode);
Expand All @@ -1621,6 +1631,13 @@ private void ExecuteDeclaringReferenceActions(
{
foreach (var analyzerActions in codeBlockActions)
{
if (analyzerActions.OperationBlockStartActions.IsEmpty &&
analyzerActions.OperationBlockActions.IsEmpty &&
analyzerActions.OpererationBlockEndActions.IsEmpty)
{
continue;
}

analyzerExecutor.ExecuteOperationBlockActions(
analyzerActions.OperationBlockStartActions, analyzerActions.OperationBlockActions,
analyzerActions.OpererationBlockEndActions, analyzerActions.Analyzer, declarationAnalysisData.TopmostNodeForAnalysis, symbol,
Expand All @@ -1639,6 +1656,13 @@ private void ExecuteDeclaringReferenceActions(
{
foreach (var analyzerActions in codeBlockActions)
{
if (analyzerActions.CodeBlockStartActions.IsEmpty &&
analyzerActions.CodeBlockActions.IsEmpty &&
analyzerActions.CodeBlockEndActions.IsEmpty)
{
continue;
}

analyzerExecutor.ExecuteCodeBlockActions(
analyzerActions.CodeBlockStartActions, analyzerActions.CodeBlockActions,
analyzerActions.CodeBlockEndActions, analyzerActions.Analyzer, declarationAnalysisData.TopmostNodeForAnalysis, symbol,
Expand Down
291 changes: 291 additions & 0 deletions src/EditorFeatures/Test/Diagnostics/DiagnosticDataSerializerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
// 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.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.EngineV2;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using Traits = Microsoft.CodeAnalysis.Test.Utilities.Traits;

namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics
{
public class DiagnosticDataSerializerTests : TestBase
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these new tests being added? Are they specific to v2 engine?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

{
[Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
public async Task SerializationTest_Document()
{
using (var workspace = new TestWorkspace(TestExportProvider.ExportProviderWithCSharpAndVisualBasic, workspaceKind: "DiagnosticDataSerializerTest"))
{
var document = workspace.CurrentSolution.AddProject("TestProject", "TestProject", LanguageNames.CSharp).AddDocument("TestDocument", "");

var diagnostics = new[]
{
new DiagnosticData(
"test1", "Test", "test1 message", "test1 message format",
DiagnosticSeverity.Info, DiagnosticSeverity.Info, false, 1,
ImmutableArray<string>.Empty, ImmutableDictionary<string, string>.Empty,
workspace, document.Project.Id, new DiagnosticDataLocation(document.Id,
new TextSpan(10, 20), "originalFile1", 30, 30, 40, 40, "mappedFile1", 10, 10, 20, 20)),
new DiagnosticData(
"test2", "Test", "test2 message", "test2 message format",
DiagnosticSeverity.Warning, DiagnosticSeverity.Warning, true, 0,
ImmutableArray.Create<string>("Test2"), ImmutableDictionary<string, string>.Empty.Add("propertyKey", "propertyValue"),
workspace, document.Project.Id, new DiagnosticDataLocation(document.Id,
new TextSpan(30, 40), "originalFile2", 70, 70, 80, 80, "mappedFile2", 50, 50, 60, 60), title: "test2 title", description: "test2 description", helpLink: "http://test2link"),
new DiagnosticData(
"test3", "Test", "test3 message", "test3 message format",
DiagnosticSeverity.Error, DiagnosticSeverity.Warning, true, 2,
ImmutableArray.Create<string>("Test3", "Test3_2"), ImmutableDictionary<string, string>.Empty.Add("p1Key", "p1Value").Add("p2Key", "p2Value"),
workspace, document.Project.Id, new DiagnosticDataLocation(document.Id,
new TextSpan(50, 60), "originalFile3", 110, 110, 120, 120, "mappedFile3", 90, 90, 100, 100), title: "test3 title", description: "test3 description", helpLink: "http://test3link"),
}.ToImmutableArray();

var utcTime = DateTime.UtcNow;
var analyzerVersion = VersionStamp.Create(utcTime);
var version = VersionStamp.Create(utcTime.AddDays(1));

var key = "document";
var serializer = new DiagnosticDataSerializer(analyzerVersion, version);

Assert.True(await serializer.SerializeAsync(document, key, diagnostics, CancellationToken.None).ConfigureAwait(false));
var recovered = await serializer.DeserializeAsync(document, key, CancellationToken.None);

AssertDiagnostics(diagnostics, recovered);
}
}

[Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
public async Task SerializationTest_Project()
{
using (var workspace = new TestWorkspace(TestExportProvider.ExportProviderWithCSharpAndVisualBasic, workspaceKind: "DiagnosticDataSerializerTest"))
{
var document = workspace.CurrentSolution.AddProject("TestProject", "TestProject", LanguageNames.CSharp).AddDocument("TestDocument", "");

var diagnostics = new[]
{
new DiagnosticData(
"test1", "Test", "test1 message", "test1 message format",
DiagnosticSeverity.Info, DiagnosticSeverity.Info, false, 1,
ImmutableArray<string>.Empty, ImmutableDictionary<string, string>.Empty,
workspace, document.Project.Id, description: "test1 description", helpLink: "http://test1link"),
new DiagnosticData(
"test2", "Test", "test2 message", "test2 message format",
DiagnosticSeverity.Warning, DiagnosticSeverity.Warning, true, 0,
ImmutableArray.Create<string>("Test2"), ImmutableDictionary<string, string>.Empty.Add("p1Key", "p2Value"),
workspace, document.Project.Id),
new DiagnosticData(
"test3", "Test", "test3 message", "test3 message format",
DiagnosticSeverity.Error, DiagnosticSeverity.Warning, true, 2,
ImmutableArray.Create<string>("Test3", "Test3_2"), ImmutableDictionary<string, string>.Empty.Add("p2Key", "p2Value").Add("p1Key", "p1Value"),
workspace, document.Project.Id, description: "test3 description", helpLink: "http://test3link"),
}.ToImmutableArray();

var utcTime = DateTime.UtcNow;
var analyzerVersion = VersionStamp.Create(utcTime);
var version = VersionStamp.Create(utcTime.AddDays(1));

var key = "project";
var serializer = new DiagnosticDataSerializer(analyzerVersion, version);

Assert.True(await serializer.SerializeAsync(document, key, diagnostics, CancellationToken.None).ConfigureAwait(false));
var recovered = await serializer.DeserializeAsync(document, key, CancellationToken.None);

AssertDiagnostics(diagnostics, recovered);
}
}

[WorkItem(6104, "https://github.com/dotnet/roslyn/issues/6104")]
[Fact]
public void DiagnosticEquivalence()
{
#if DEBUG
var source =
@"class C
{
static int F(string s) { return 1; }
static int x = F(new { });
static int y = F(new { A = 1 });
}";
var tree = SyntaxFactory.ParseSyntaxTree(source);
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, concurrentBuild: false);
var compilation = CSharpCompilation.Create(GetUniqueName(), new[] { tree }, new[] { MscorlibRef }, options);
var model = compilation.GetSemanticModel(tree);

// Each call to GetDiagnostics will bind field initializers
// (see https://github.com/dotnet/roslyn/issues/6264).
var diagnostics1 = model.GetDiagnostics().ToArray();
var diagnostics2 = model.GetDiagnostics().ToArray();

diagnostics1.Verify(
// (4,22): error CS1503: Argument 1: cannot convert from '<empty anonymous type>' to 'string'
// static int x = F(new { });
Diagnostic(1503, "new { }").WithArguments("1", "<empty anonymous type>", "string").WithLocation(4, 22),
// (5,22): error CS1503: Argument 1: cannot convert from '<anonymous type: int A>' to 'string'
// static int y = F(new { A = 1 });
Diagnostic(1503, "new { A = 1 }").WithArguments("1", "<anonymous type: int A>", "string").WithLocation(5, 22));

Assert.NotSame(diagnostics1[0], diagnostics2[0]);
Assert.NotSame(diagnostics1[1], diagnostics2[1]);
Assert.Equal(diagnostics1, diagnostics2);
Assert.True(DiagnosticIncrementalAnalyzer.AreEquivalent(diagnostics1, diagnostics2));

// Verify that not all collections are treated as equivalent.
diagnostics1 = new[] { diagnostics1[0] };
diagnostics2 = new[] { diagnostics2[1] };

Assert.NotEqual(diagnostics1, diagnostics2);
Assert.False(DiagnosticIncrementalAnalyzer.AreEquivalent(diagnostics1, diagnostics2));
#endif
}

private static void AssertDiagnostics(ImmutableArray<DiagnosticData> items1, ImmutableArray<DiagnosticData> items2)
{
Assert.Equal(items1.Length, items2.Length);

for (var i = 0; i < items1.Length; i++)
{
AssertDiagnostics(items1[i], items2[i]);
}
}

private static void AssertDiagnostics(DiagnosticData item1, DiagnosticData item2)
{
Assert.Equal(item1.Id, item2.Id);
Assert.Equal(item1.Category, item2.Category);
Assert.Equal(item1.Message, item2.Message);
Assert.Equal(item1.ENUMessageForBingSearch, item2.ENUMessageForBingSearch);
Assert.Equal(item1.Severity, item2.Severity);
Assert.Equal(item1.IsEnabledByDefault, item2.IsEnabledByDefault);
Assert.Equal(item1.WarningLevel, item2.WarningLevel);
Assert.Equal(item1.DefaultSeverity, item2.DefaultSeverity);

Assert.Equal(item1.CustomTags.Count, item2.CustomTags.Count);
for (var j = 0; j < item1.CustomTags.Count; j++)
{
Assert.Equal(item1.CustomTags[j], item2.CustomTags[j]);
}

Assert.Equal(item1.Properties.Count, item2.Properties.Count);
Assert.True(item1.Properties.SetEquals(item2.Properties));

Assert.Equal(item1.Workspace, item2.Workspace);
Assert.Equal(item1.ProjectId, item2.ProjectId);
Assert.Equal(item1.DocumentId, item2.DocumentId);

Assert.Equal(item1.HasTextSpan, item2.HasTextSpan);
if (item1.HasTextSpan)
{
Assert.Equal(item1.TextSpan, item2.TextSpan);
}

Assert.Equal(item1.DataLocation?.MappedFilePath, item2.DataLocation?.MappedFilePath);
Assert.Equal(item1.DataLocation?.MappedStartLine, item2.DataLocation?.MappedStartLine);
Assert.Equal(item1.DataLocation?.MappedStartColumn, item2.DataLocation?.MappedStartColumn);
Assert.Equal(item1.DataLocation?.MappedEndLine, item2.DataLocation?.MappedEndLine);
Assert.Equal(item1.DataLocation?.MappedEndColumn, item2.DataLocation?.MappedEndColumn);

Assert.Equal(item1.DataLocation?.OriginalFilePath, item2.DataLocation?.OriginalFilePath);
Assert.Equal(item1.DataLocation?.OriginalStartLine, item2.DataLocation?.OriginalStartLine);
Assert.Equal(item1.DataLocation?.OriginalStartColumn, item2.DataLocation?.OriginalStartColumn);
Assert.Equal(item1.DataLocation?.OriginalEndLine, item2.DataLocation?.OriginalEndLine);
Assert.Equal(item1.DataLocation?.OriginalEndColumn, item2.DataLocation?.OriginalEndColumn);

Assert.Equal(item1.Description, item2.Description);
Assert.Equal(item1.HelpLink, item2.HelpLink);
}

[ExportWorkspaceServiceFactory(typeof(IPersistentStorageService), "DiagnosticDataSerializerTest"), Shared]
public class PersistentStorageServiceFactory : IWorkspaceServiceFactory
{
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
return new Service();
}

public class Service : IPersistentStorageService
{
private readonly Storage _instance = new Storage();

IPersistentStorage IPersistentStorageService.GetStorage(Solution solution)
{
return _instance;
}

internal class Storage : IPersistentStorage
{
private readonly Dictionary<object, Stream> _map = new Dictionary<object, Stream>();

public Task<Stream> ReadStreamAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
{
var stream = _map[name];
stream.Position = 0;

return Task.FromResult(stream);
}

public Task<Stream> ReadStreamAsync(Project project, string name, CancellationToken cancellationToken = default(CancellationToken))
{
var stream = _map[Tuple.Create(project, name)];
stream.Position = 0;

return Task.FromResult(stream);
}

public Task<Stream> ReadStreamAsync(Document document, string name, CancellationToken cancellationToken = default(CancellationToken))
{
var stream = _map[Tuple.Create(document, name)];
stream.Position = 0;

return Task.FromResult(stream);
}

public Task<bool> WriteStreamAsync(string name, Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
_map[name] = new MemoryStream();
stream.CopyTo(_map[name]);

return SpecializedTasks.True;
}

public Task<bool> WriteStreamAsync(Project project, string name, Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
_map[Tuple.Create(project, name)] = new MemoryStream();
stream.CopyTo(_map[Tuple.Create(project, name)]);

return SpecializedTasks.True;
}

public Task<bool> WriteStreamAsync(Document document, string name, Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
_map[Tuple.Create(document, name)] = new MemoryStream();
stream.CopyTo(_map[Tuple.Create(document, name)]);

return SpecializedTasks.True;
}

protected virtual void Dispose(bool disposing)
{
}

public void Dispose()
{
Dispose(true);
}
}
}
}
}
}
Loading