Example #1
0
        private static async Task <DocumentAnalysisResults> AnalyzeDocumentAsync(
            Project oldProject,
            Document newDocument,
            ActiveStatementsMap activeStatementMap   = null,
            EditAndContinueCapabilities capabilities = EditAndContinueTestHelpers.Net5RuntimeCapabilities)
        {
            var analyzer             = new CSharpEditAndContinueAnalyzer();
            var baseActiveStatements = AsyncLazy.Create(activeStatementMap ?? ActiveStatementsMap.Empty);
            var lazyCapabilities     = AsyncLazy.Create(capabilities);

            return(await analyzer.AnalyzeDocumentAsync(oldProject, baseActiveStatements, newDocument, ImmutableArray <LinePositionSpan> .Empty, lazyCapabilities, CancellationToken.None));
        }
Example #2
0
        public void GetSpansStartingInSpan1(int sl, int sc, int el, int ec, int s, int e)
        {
            var span  = new LinePositionSpan(new(sl, sc), new(el, ec));
            var array = ImmutableArray.Create(
                new LinePositionSpan(new(3, 0), new(3, 1)),
                new LinePositionSpan(new(3, 5), new(3, 6)),
                new LinePositionSpan(new(4, 4), new(4, 18)),
                new LinePositionSpan(new(5, 1), new(5, 2)),
                new LinePositionSpan(new(5, 2), new(5, 8)),
                new LinePositionSpan(new(19, 0), new(19, 42)));

            Assert.Equal(new Range(s, e), ActiveStatementsMap.GetSpansStartingInSpan(span.Start, span.End, array, startPositionComparer: (x, y) => x.Start.CompareTo(y)));
        }
Example #3
0
        public void GetSpansStartingInSpan2()
        {
            var span = TextSpan.FromBounds(8, 11);

            var array = ImmutableArray.Create(
                TextSpan.FromBounds(1, 6),    // does not overlap
                TextSpan.FromBounds(3, 9),    // overlaps
                TextSpan.FromBounds(4, 5),    // does not overlap
                TextSpan.FromBounds(6, 7),    // does not overlap
                TextSpan.FromBounds(7, 9),    // overlaps
                TextSpan.FromBounds(10, 12),  // overlaps
                TextSpan.FromBounds(13, 15)); // does not overlap

            // only one span has start position within the span:
            Assert.Equal(new Range(5, 6), ActiveStatementsMap.GetSpansStartingInSpan(span.Start, span.End, array, startPositionComparer: (x, y) => x.Start.CompareTo(y)));
        }
        public async Task InvalidActiveStatements()
        {
            using var workspace = new TestWorkspace(composition: FeaturesTestCompositions.Features);

            var source = @"
class C
{
    void F()
    {
S1();
    }
}";

            var solution = workspace.CurrentSolution
                           .AddProject("proj", "proj", LanguageNames.CSharp)
                           .AddDocument("doc", SourceText.From(source, Encoding.UTF8), filePath: "a.cs").Project.Solution;

            var project  = solution.Projects.Single();
            var document = project.Documents.Single();
            var analyzer = project.LanguageServices.GetRequiredService <IEditAndContinueAnalyzer>();

            var documentPathMap = new Dictionary <string, ImmutableArray <ActiveStatement> >();

            var moduleId = Guid.NewGuid();
            var token    = 0x06000001;

            ManagedActiveStatementDebugInfo CreateInfo(int startLine, int startColumn, int endLine, int endColumn, string fileName)
            => new(new(new(moduleId, token++, version : 1), ilOffset : 0), fileName, new SourceSpan(startLine, startColumn, endLine, endColumn), ActiveStatementFlags.MethodUpToDate);

            // Create a bad active span that is outside the document, but passes the `TryGetTextSpan` check in ActiveStatementMap
            var debugInfos = ImmutableArray.Create(
                CreateInfo(7, 9, 7, 10, "a.cs")
                );

            var map = ActiveStatementsMap.Create(debugInfos, remapping: ImmutableDictionary <ManagedMethodId, ImmutableArray <NonRemappableRegion> > .Empty);

            var oldSpans = await map.GetOldActiveStatementsAsync(analyzer, document, CancellationToken.None);

            AssertEx.Empty(oldSpans);
        }
Example #5
0
        public async Task Ordering()
        {
            using var workspace = new TestWorkspace(composition: FeaturesTestCompositions.Features);

            var source = @"
class C
{
    void F()
    {
#line 2 ""x""
S1();
S2();
S3();
#line 1 ""x""    
S0();
S1();
S2();
#line 5 ""x""
S4();
S5();
S5();
#line default
    }
}";

            var solution = workspace.CurrentSolution
                           .AddProject("proj", "proj", LanguageNames.CSharp)
                           .AddDocument("doc", SourceText.From(source, Encoding.UTF8), filePath: "a.cs").Project.Solution;

            var project  = solution.Projects.Single();
            var document = project.Documents.Single();
            var analyzer = project.LanguageServices.GetRequiredService <IEditAndContinueAnalyzer>();

            var documentPathMap = new Dictionary <string, ImmutableArray <ActiveStatement> >();

            var moduleId = Guid.NewGuid();
            var token    = 0x06000001;

            ManagedActiveStatementDebugInfo CreateInfo(int startLine, int startColumn, int endLine, int endColumn, string fileName)
            => new(new(new(moduleId, token++, version : 1), ilOffset : 0), fileName, new SourceSpan(startLine, startColumn, endLine, endColumn), ActiveStatementFlags.MethodUpToDate);

            var debugInfos = ImmutableArray.Create(
                CreateInfo(3, 0, 3, 4, "x"),
                CreateInfo(6, 0, 6, 4, "x"),
                CreateInfo(4, 0, 4, 4, "x"),
                CreateInfo(2, 0, 2, 4, "x"),
                CreateInfo(5, 0, 5, 4, "x"),
                CreateInfo(0, 0, 0, 4, "x"),
                CreateInfo(1, 0, 1, 4, "x")
                );

            var map = ActiveStatementsMap.Create(debugInfos, remapping: ImmutableDictionary <ManagedMethodId, ImmutableArray <NonRemappableRegion> > .Empty);

            var oldSpans = await map.GetOldActiveStatementsAsync(analyzer, document, CancellationToken.None);

            AssertEx.Equal(new[]
            {
                "[48..52) -> (1,0)-(1,4) #6",
                "[55..59) -> (2,0)-(2,4) #3",
                "[62..66) -> (3,0)-(3,4) #0",
                "[86..90) -> (0,0)-(0,4) #5",
                "[120..124) -> (4,0)-(4,4) #2",
                "[127..131) -> (5,0)-(5,4) #4",
                "[134..138) -> (6,0)-(6,4) #1"
            }, oldSpans.Select(s => $"{s.UnmappedSpan} -> {s.Statement.Span} #{s.Statement.Ordinal}"));
        }
        public void ExpandMultiLineSpan()
        {
            using var workspace = new TestWorkspace(composition: FeaturesTestCompositions.Features);

            var source = @"
using System;

class C
{
    void F()
    {
        G(() =>
        {
            Console.WriteLine(1);
        });
    }

    static void F(Action a)
    {
        a();
    }
}";

            var solution = workspace.CurrentSolution
                           .AddProject("proj", "proj", LanguageNames.CSharp)
                           .AddDocument("doc", SourceText.From(source, Encoding.UTF8), filePath: "a.cs").Project.Solution;

            var project  = solution.Projects.Single();
            var document = project.Documents.Single();
            var analyzer = project.LanguageServices.GetRequiredService <IEditAndContinueAnalyzer>();

            var documentPathMap = new Dictionary <string, ImmutableArray <ActiveStatement> >();

            var moduleId = Guid.NewGuid();
            var token    = 0x06000001;

            ManagedActiveStatementDebugInfo CreateInfo(int startLine, int startColumn, int endLine, int endColumn)
            => new(new(new(moduleId, token++, version : 1), ilOffset : 0), "a.cs", new SourceSpan(startLine, startColumn, endLine, endColumn), ActiveStatementFlags.NonLeafFrame);

            var debugInfos = ImmutableArray.Create(
                CreateInfo(9, 0, 9, 34),                               // Console.WriteLine(1)
                CreateInfo(7, 0, 10, 12),                              // Lambda
                CreateInfo(15, 0, 15, 13)                              // a()
                );

            var remapping = ImmutableDictionary.CreateBuilder <ManagedMethodId, ImmutableArray <NonRemappableRegion> >();

            CreateRegion(0, Span(9, 0, 10, 34), Span(9, 0, 9, 34));    // Current active statement doesn't move
            CreateRegion(1, Span(7, 0, 10, 12), Span(7, 0, 15, 12));   // Insert 5 lines inside the lambda
            CreateRegion(2, Span(15, 0, 15, 13), Span(20, 0, 20, 13)); // a() call moves down 5 lines

            var map = ActiveStatementsMap.Create(debugInfos, remapping.ToImmutable());

            AssertEx.Equal(new[]
            {
                "(7,0)-(15,12)",
                "(9,0)-(9,34)",
                "(20,0)-(20,13)"
            }, map.DocumentPathMap["a.cs"].OrderBy(s => s.Span.Start.Line).Select(s => $"{s.Span}"));

            void CreateRegion(int ordinal, SourceFileSpan oldSpan, SourceFileSpan newSpan)
            => remapping.Add(debugInfos[ordinal].ActiveInstruction.Method, ImmutableArray.Create(new NonRemappableRegion(oldSpan, newSpan, isExceptionRegion: false)));

            SourceFileSpan Span(int startLine, int startColumn, int endLine, int endColumn)
            => new("a.cs", new(new(startLine, startColumn), new(endLine, endColumn)));
        }