private static Solution AddDefaultTestSolution( TestWorkspace workspace, string[] markedSources ) { var solution = workspace.CurrentSolution; var project = solution .AddProject("proj", "proj", LanguageNames.CSharp) .WithMetadataReferences( TargetFrameworkUtil.GetReferences(TargetFramework.Standard) ); solution = project.Solution; for (var i = 0; i < markedSources.Length; i++) { var name = $"test{i + 1}.cs"; var text = SourceText.From( ActiveStatementsDescription.ClearTags(markedSources[i]), Encoding.UTF8 ); var id = DocumentId.CreateNewId(project.Id, name); solution = solution.AddDocument( id, name, text, filePath: Path.Combine(TempRoot.Root, name) ); } workspace.ChangeSolution(solution); return solution; }
private void VerifyActiveStatementsAndExceptionRegions( ActiveStatementsDescription description, IReadOnlyList <ActiveStatement> oldActiveStatements, SourceText oldText, SourceText newText, SyntaxNode oldRoot, IReadOnlyList <ActiveStatement> actualNewActiveStatements, IReadOnlyList <ImmutableArray <LinePositionSpan> > actualNewExceptionRegions) { // check active statements: AssertSpansEqual(description.NewSpans, actualNewActiveStatements.Select(s => s.Span), newText); // check old exception regions: for (var i = 0; i < oldActiveStatements.Count; i++) { var oldRegions = Analyzer.GetExceptionRegions( oldText, oldRoot, oldActiveStatements[i].Span, isNonLeaf: oldActiveStatements[i].IsNonLeaf, out _); AssertSpansEqual(description.OldRegions[i], oldRegions, oldText); } // check new exception regions: Assert.Equal(description.NewRegions.Length, actualNewExceptionRegions.Count); for (var i = 0; i < description.NewRegions.Length; i++) { AssertSpansEqual(description.NewRegions[i], actualNewExceptionRegions[i], newText); } }
public Validator( string[] markedSource, ImmutableArray <ActiveStatementDebugInfo> activeStatements, ImmutableDictionary <ActiveMethodId, ImmutableArray <NonRemappableRegion> > nonRemappableRegions = null, Func <Solution, Solution> adjustSolution = null, CommittedSolution.DocumentState initialState = CommittedSolution.DocumentState.MatchesBuildOutput, bool openDocuments = false) { Workspace = TestWorkspace.CreateCSharp(ActiveStatementsDescription.ClearTags(markedSource), composition: s_composition, openDocuments: openDocuments); if (adjustSolution != null) { Workspace.ChangeSolution(adjustSolution(Workspace.CurrentSolution)); } var solution = Workspace.CurrentSolution; var mockDebuggeModuleProvider = new Mock <IDebuggeeModuleMetadataProvider>(MockBehavior.Strict); var mockCompilationOutputsProvider = new Func <Project, CompilationOutputs>(_ => new MockCompilationOutputs(Guid.NewGuid())); var debuggingSession = new DebuggingSession(solution, mockCompilationOutputsProvider); if (initialState != CommittedSolution.DocumentState.None) { EditAndContinueWorkspaceServiceTests.SetDocumentsState(debuggingSession, solution, initialState); } debuggingSession.Test_SetNonRemappableRegions(nonRemappableRegions ?? ImmutableDictionary <ActiveMethodId, ImmutableArray <NonRemappableRegion> > .Empty); var telemetry = new EditSessionTelemetry(); EditSession = new EditSession(debuggingSession, telemetry, cancellationToken => Task.FromResult(activeStatements), mockDebuggeModuleProvider.Object); }
public Validator( string[] markedSource, ImmutableArray <ActiveStatementDebugInfo> activeStatements, ImmutableDictionary <ActiveMethodId, ImmutableArray <NonRemappableRegion> > nonRemappableRegions = null, Func <Solution, Solution> adjustSolution = null, CommittedSolution.DocumentState initialState = CommittedSolution.DocumentState.MatchesBuildOutput) { var exportProviderFactory = ExportProviderCache.GetOrCreateExportProviderFactory( TestExportProvider.MinimumCatalogWithCSharpAndVisualBasic.WithPart(typeof(CSharpEditAndContinueAnalyzer)).WithPart(typeof(DummyLanguageService))); var exportProvider = exportProviderFactory.CreateExportProvider(); Workspace = TestWorkspace.CreateCSharp(ActiveStatementsDescription.ClearTags(markedSource), exportProvider: exportProvider, openDocuments: true); if (adjustSolution != null) { Workspace.ChangeSolution(adjustSolution(Workspace.CurrentSolution)); } var mockDebuggeModuleProvider = new Mock <IDebuggeeModuleMetadataProvider>(); var mockCompilationOutputsProvider = new Func <Project, CompilationOutputs>(_ => new MockCompilationOutputs(Guid.NewGuid())); var debuggingSession = new DebuggingSession(Workspace, mockDebuggeModuleProvider.Object, mockCompilationOutputsProvider); if (initialState != CommittedSolution.DocumentState.None) { EditAndContinueWorkspaceServiceTests.SetDocumentsState(debuggingSession, Workspace.CurrentSolution, initialState); } debuggingSession.Test_SetNonRemappableRegions(nonRemappableRegions ?? ImmutableDictionary <ActiveMethodId, ImmutableArray <NonRemappableRegion> > .Empty); var telemetry = new EditSessionTelemetry(); EditSession = new EditSession(debuggingSession, telemetry, cancellationToken => Task.FromResult(activeStatements)); }
internal static ImmutableArray <ManagedActiveStatementDebugInfo> GetActiveStatementDebugInfos( string[] markedSources, string extension = ".cs", int[] methodRowIds = null, Guid[] modules = null, int[] methodVersions = null, int[] ilOffsets = null, ActiveStatementFlags[] flags = null) { IEnumerable <(TextSpan Span, int Id, SourceText Text, string DocumentName, DocumentId DocumentId)> EnumerateAllSpans() { var sourceIndex = 0; foreach (var markedSource in markedSources) { var documentName = TestWorkspace.GetDefaultTestSourceDocumentName(sourceIndex, extension); var documentId = DocumentId.CreateNewId(ProjectId.CreateNewId(), documentName); var text = SourceText.From(markedSource); foreach (var(span, id) in ActiveStatementsDescription.GetActiveSpans(markedSource)) { yield return(span, id, text, documentName, documentId); } sourceIndex++; } } IEnumerable <ManagedActiveStatementDebugInfo> Enumerate() { var moduleId = new Guid("00000000-0000-0000-0000-000000000001"); var threadId = new Guid("00000000-0000-0000-0000-000000000010"); var index = 0; foreach (var(span, id, text, documentName, documentId) in EnumerateAllSpans().OrderBy(s => s.Id)) { yield return(new ManagedActiveStatementDebugInfo( new ManagedInstructionId( new ManagedMethodId( (modules != null) ? modules[index] : moduleId, new ManagedModuleMethodId( token: 0x06000000 | (methodRowIds != null ? methodRowIds[index] : index + 1), version: (methodVersions != null) ? methodVersions[index] : 1)), ilOffset: (ilOffsets != null) ? ilOffsets[index] : 0), documentName: documentName, sourceSpan: text.Lines.GetLinePositionSpan(span).ToSourceSpan(), flags: (flags != null) ? flags[index] : ((id == 0 ? ActiveStatementFlags.IsLeafFrame : ActiveStatementFlags.IsNonLeafFrame) | ActiveStatementFlags.MethodUpToDate))); index++; } } return(Enumerate().ToImmutableArray()); }
public static ImmutableArray <ManagedActiveStatementDebugInfo> GetActiveStatementDebugInfosCSharp( string[] markedSources, string[]?filePaths = null, int[]?methodRowIds = null, Guid[]?modules = null, int[]?methodVersions = null, int[]?ilOffsets = null, ActiveStatementFlags[]?flags = null) { return(ActiveStatementsDescription.GetActiveStatementDebugInfos( (source, path) => SyntaxFactory.ParseSyntaxTree(source, path: path), markedSources, filePaths, extension: ".cs", methodRowIds, modules, methodVersions, ilOffsets, flags)); }
public Validator( string[] markedSource, ImmutableArray <ManagedActiveStatementDebugInfo> activeStatements, ImmutableDictionary <ManagedMethodId, ImmutableArray <NonRemappableRegion> > nonRemappableRegions = null, Func <Solution, Solution> adjustSolution = null, CommittedSolution.DocumentState initialState = CommittedSolution.DocumentState.MatchesBuildOutput, bool openDocuments = false) { Workspace = TestWorkspace.CreateCSharp(ActiveStatementsDescription.ClearTags(markedSource), composition: s_composition, openDocuments: openDocuments); if (adjustSolution != null) { Workspace.ChangeSolution(adjustSolution(Workspace.CurrentSolution)); } var solution = Workspace.CurrentSolution; var mockDebuggerService = new MockManagedEditAndContinueDebuggerService() { GetActiveStatementsImpl = () => activeStatements }; var mockCompilationOutputsProvider = new Func <Project, CompilationOutputs>(_ => new MockCompilationOutputs(Guid.NewGuid())); var debuggingSession = new DebuggingSession(solution, mockCompilationOutputsProvider, SpecializedCollections.EmptyEnumerable <KeyValuePair <DocumentId, CommittedSolution.DocumentState> >()); if (initialState != CommittedSolution.DocumentState.None) { EditAndContinueWorkspaceServiceTests.SetDocumentsState(debuggingSession, solution, initialState); } debuggingSession.Test_SetNonRemappableRegions(nonRemappableRegions ?? ImmutableDictionary <ManagedMethodId, ImmutableArray <NonRemappableRegion> > .Empty); var telemetry = new EditSessionTelemetry(); EditSession = new EditSession(debuggingSession, telemetry, mockDebuggerService); }
private void VerifyDocumentActiveStatementsAndExceptionRegions( ActiveStatementsDescription description, SyntaxTree oldTree, SyntaxTree newTree, ImmutableArray <ActiveStatement> actualNewActiveStatements, ImmutableArray <ImmutableArray <SourceFileSpan> > actualNewExceptionRegions) { // check active statements: AssertSpansEqual(description.NewMappedSpans, actualNewActiveStatements.OrderBy(x => x.Ordinal).Select(s => s.FileSpan), newTree); var oldRoot = oldTree.GetRoot(); // check old exception regions: foreach (var oldStatement in description.OldStatements) { var oldRegions = Analyzer.GetExceptionRegions( oldRoot, oldStatement.UnmappedSpan, isNonLeaf: oldStatement.Statement.IsNonLeaf, CancellationToken.None); AssertSpansEqual(oldStatement.ExceptionRegions.Spans, oldRegions.Spans, oldTree); } // check new exception regions: if (!actualNewExceptionRegions.IsDefault) { Assert.Equal(actualNewActiveStatements.Length, actualNewExceptionRegions.Length); Assert.Equal(description.NewMappedRegions.Length, actualNewExceptionRegions.Length); for (var i = 0; i < actualNewActiveStatements.Length; i++) { var activeStatement = actualNewActiveStatements[i]; AssertSpansEqual(description.NewMappedRegions[activeStatement.Ordinal], actualNewExceptionRegions[i], newTree); } } }
internal void VerifyRudeDiagnostics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription description, RudeEditDiagnosticDescription[] expectedDiagnostics) { var oldActiveStatements = description.OldStatements; if (description.OldTrackingSpans != null) { Assert.Equal(oldActiveStatements.Length, description.OldTrackingSpans.Length); } string newSource = editScript.Match.NewRoot.SyntaxTree.ToString(); string oldSource = editScript.Match.OldRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); var diagnostics = new List <RudeEditDiagnostic>(); var actualNewActiveStatements = new ActiveStatement[oldActiveStatements.Length]; var actualNewExceptionRegions = new ImmutableArray <LinePositionSpan> [oldActiveStatements.Length]; var updatedActiveMethodMatches = new List <AbstractEditAndContinueAnalyzer.UpdatedMemberInfo>(); var editMap = Analyzer.BuildEditMap(editScript); DocumentId documentId = DocumentId.CreateNewId(ProjectId.CreateNewId("TestEnCProject"), "TestEnCDocument"); TestActiveStatementTrackingService trackingService; if (description.OldTrackingSpans != null) { trackingService = new TestActiveStatementTrackingService(documentId, description.OldTrackingSpans); } else { trackingService = null; } Analyzer.GetTestAccessor().AnalyzeSyntax( editScript, editMap, oldText, newText, documentId, trackingService, oldActiveStatements.AsImmutable(), actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); diagnostics.Verify(newSource, expectedDiagnostics); // check active statements: AssertSpansEqual(description.NewSpans, actualNewActiveStatements.Select(s => s.Span), newSource, newText); if (diagnostics.Count == 0) { // check old exception regions: for (int i = 0; i < oldActiveStatements.Length; i++) { var actualOldExceptionRegions = Analyzer.GetExceptionRegions( oldText, editScript.Match.OldRoot, oldActiveStatements[i].Span, isNonLeaf: oldActiveStatements[i].IsNonLeaf, out _); AssertSpansEqual(description.OldRegions[i], actualOldExceptionRegions, oldSource, oldText); } // check new exception regions: Assert.Equal(description.NewRegions.Length, actualNewExceptionRegions.Length); for (int i = 0; i < description.NewRegions.Length; i++) { AssertSpansEqual(description.NewRegions[i], actualNewExceptionRegions[i], newSource, newText); } } else { for (int i = 0; i < oldActiveStatements.Length; i++) { Assert.Equal(0, description.NewRegions[i].Length); } } if (description.OldTrackingSpans != null) { // Verify that the new tracking spans are equal to the new active statements. AssertEx.Equal(trackingService.TrackingSpans, description.NewSpans.Select(s => (TextSpan?)s)); } }
internal void VerifySemantics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription activeStatements, IEnumerable <string> additionalOldSources = null, IEnumerable <string> additionalNewSources = null, SemanticEditDescription[] expectedSemanticEdits = null, DiagnosticDescription expectedDeclarationError = null, RudeEditDiagnosticDescription[] expectedDiagnostics = null) { var editMap = Analyzer.BuildEditMap(editScript); var oldRoot = editScript.Match.OldRoot; var newRoot = editScript.Match.NewRoot; var oldSource = oldRoot.SyntaxTree.ToString(); var newSource = newRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); IEnumerable <SyntaxTree> oldTrees = new[] { oldRoot.SyntaxTree }; IEnumerable <SyntaxTree> newTrees = new[] { newRoot.SyntaxTree }; if (additionalOldSources != null) { oldTrees = oldTrees.Concat(additionalOldSources.Select(s => ParseText(s))); } if (additionalOldSources != null) { newTrees = newTrees.Concat(additionalNewSources.Select(s => ParseText(s))); } var oldCompilation = CreateLibraryCompilation("Old", oldTrees); var newCompilation = CreateLibraryCompilation("New", newTrees); var oldModel = oldCompilation.GetSemanticModel(oldRoot.SyntaxTree); var newModel = newCompilation.GetSemanticModel(newRoot.SyntaxTree); var oldActiveStatements = activeStatements.OldStatements.AsImmutable(); var updatedActiveMethodMatches = new List <AbstractEditAndContinueAnalyzer.UpdatedMemberInfo>(); var triviaEdits = new List <KeyValuePair <SyntaxNode, SyntaxNode> >(); var actualLineEdits = new List <LineChange>(); var actualSemanticEdits = new List <SemanticEdit>(); var diagnostics = new List <RudeEditDiagnostic>(); var actualNewActiveStatements = new ActiveStatement[activeStatements.OldStatements.Length]; var actualNewExceptionRegions = new ImmutableArray <LinePositionSpan> [activeStatements.OldStatements.Length]; Analyzer.GetTestAccessor().AnalyzeSyntax( editScript, editMap, oldText, newText, null, null, oldActiveStatements, actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); diagnostics.Verify(newSource); Analyzer.GetTestAccessor().AnalyzeTrivia( oldText, newText, editScript.Match, editMap, triviaEdits, actualLineEdits, diagnostics, CancellationToken.None); diagnostics.Verify(newSource); Analyzer.GetTestAccessor().AnalyzeSemantics( editScript, editMap, oldText, oldActiveStatements, triviaEdits, updatedActiveMethodMatches, oldModel, newModel, actualSemanticEdits, diagnostics, out var firstDeclarationErrorOpt, CancellationToken.None); var actualDeclarationErrors = (firstDeclarationErrorOpt != null) ? new[] { firstDeclarationErrorOpt } : Array.Empty <Diagnostic>(); var expectedDeclarationErrors = (expectedDeclarationError != null) ? new[] { expectedDeclarationError } : Array.Empty <DiagnosticDescription>(); actualDeclarationErrors.Verify(expectedDeclarationErrors); diagnostics.Verify(newSource, expectedDiagnostics); if (expectedSemanticEdits == null) { return; } Assert.Equal(expectedSemanticEdits.Length, actualSemanticEdits.Count); for (int i = 0; i < actualSemanticEdits.Count; i++) { var editKind = expectedSemanticEdits[i].Kind; Assert.Equal(editKind, actualSemanticEdits[i].Kind); var expectedOldSymbol = (editKind == SemanticEditKind.Update) ? expectedSemanticEdits[i].SymbolProvider(oldCompilation) : null; var expectedNewSymbol = expectedSemanticEdits[i].SymbolProvider(newCompilation); var actualOldSymbol = actualSemanticEdits[i].OldSymbol; var actualNewSymbol = actualSemanticEdits[i].NewSymbol; Assert.Equal(expectedOldSymbol, actualOldSymbol); Assert.Equal(expectedNewSymbol, actualNewSymbol); var expectedSyntaxMap = expectedSemanticEdits[i].SyntaxMap; var actualSyntaxMap = actualSemanticEdits[i].SyntaxMap; Assert.Equal(expectedSemanticEdits[i].PreserveLocalVariables, actualSemanticEdits[i].PreserveLocalVariables); if (expectedSyntaxMap != null) { Assert.NotNull(actualSyntaxMap); Assert.True(expectedSemanticEdits[i].PreserveLocalVariables); var newNodes = new List <SyntaxNode>(); foreach (var expectedSpanMapping in expectedSyntaxMap) { var newNode = FindNode(newRoot, expectedSpanMapping.Value); var expectedOldNode = FindNode(oldRoot, expectedSpanMapping.Key); var actualOldNode = actualSyntaxMap(newNode); Assert.Equal(expectedOldNode, actualOldNode); newNodes.Add(newNode); } } else if (!expectedSemanticEdits[i].PreserveLocalVariables) { Assert.Null(actualSyntaxMap); } } }
internal void VerifyRudeDiagnostics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription description, RudeEditDiagnosticDescription[] expectedDiagnostics) { var oldActiveStatements = description.OldStatements; if (description.OldTrackingSpans != null) { Assert.Equal(oldActiveStatements.Length, description.OldTrackingSpans.Length); } var newSource = editScript.Match.NewRoot.SyntaxTree.ToString(); var oldSource = editScript.Match.OldRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); var diagnostics = new List <RudeEditDiagnostic>(); var actualNewActiveStatements = new ActiveStatement[oldActiveStatements.Length]; var actualNewExceptionRegions = new ImmutableArray <LinePositionSpan> [oldActiveStatements.Length]; var updatedActiveMethodMatches = new List <UpdatedMemberInfo>(); var editMap = BuildEditMap(editScript); var documentId = DocumentId.CreateNewId(ProjectId.CreateNewId("TestEnCProject"), "TestEnCDocument"); var spanTracker = new TestActiveStatementSpanTracker( (description.OldTrackingSpans != null) ? new Dictionary <DocumentId, TextSpan?[]> { { documentId, description.OldTrackingSpans } } : null); Analyzer.GetTestAccessor().AnalyzeSyntax( editScript, editMap, oldText, newText, documentId, spanTracker, oldActiveStatements.AsImmutable(), actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); diagnostics.Verify(newSource, expectedDiagnostics); // check active statements: AssertSpansEqual(description.NewSpans, actualNewActiveStatements.Select(s => s.Span), newSource, newText); if (diagnostics.Count == 0) { // check old exception regions: for (var i = 0; i < oldActiveStatements.Length; i++) { var actualOldExceptionRegions = Analyzer.GetExceptionRegions( oldText, editScript.Match.OldRoot, oldActiveStatements[i].Span, isNonLeaf: oldActiveStatements[i].IsNonLeaf, out _); AssertSpansEqual(description.OldRegions[i], actualOldExceptionRegions, oldSource, oldText); } // check new exception regions: Assert.Equal(description.NewRegions.Length, actualNewExceptionRegions.Length); for (var i = 0; i < description.NewRegions.Length; i++) { AssertSpansEqual(description.NewRegions[i], actualNewExceptionRegions[i], newSource, newText); } } else { for (var i = 0; i < oldActiveStatements.Length; i++) { Assert.Equal(0, description.NewRegions[i].Length); } } }
internal void VerifyRudeDiagnostics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription description, RudeEditDiagnosticDescription[] expectedDiagnostics) { var oldActiveStatements = description.OldStatements; if (description.OldTrackingSpans != null) { Assert.Equal(oldActiveStatements.Length, description.OldTrackingSpans.Length); } var newSource = editScript.Match.NewRoot.SyntaxTree.ToString(); var oldSource = editScript.Match.OldRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); var diagnostics = new ArrayBuilder <RudeEditDiagnostic>(); var updatedActiveMethodMatches = new ArrayBuilder <UpdatedMemberInfo>(); var actualNewActiveStatements = ImmutableArray.CreateBuilder <ActiveStatement>(oldActiveStatements.Length); actualNewActiveStatements.Count = actualNewActiveStatements.Capacity; var actualNewExceptionRegions = ImmutableArray.CreateBuilder <ImmutableArray <LinePositionSpan> >(oldActiveStatements.Length); actualNewExceptionRegions.Count = actualNewExceptionRegions.Capacity; var editMap = BuildEditMap(editScript); var documentId = DocumentId.CreateNewId(ProjectId.CreateNewId("TestEnCProject"), "TestEnCDocument"); var testAccessor = Analyzer.GetTestAccessor(); testAccessor.AnalyzeMemberBodiesSyntax( editScript, editMap, oldText, newText, oldActiveStatements.AsImmutable(), description.OldTrackingSpans.ToImmutableArrayOrEmpty(), actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); testAccessor.ReportTopLevelSynctactiveRudeEdits(diagnostics, editScript, editMap); diagnostics.Verify(newSource, expectedDiagnostics); // check active statements: AssertSpansEqual(description.NewSpans, actualNewActiveStatements.Select(s => s.Span), newSource, newText); if (diagnostics.Count == 0) { // check old exception regions: for (var i = 0; i < oldActiveStatements.Length; i++) { var actualOldExceptionRegions = Analyzer.GetExceptionRegions( oldText, editScript.Match.OldRoot, oldActiveStatements[i].Span, isNonLeaf: oldActiveStatements[i].IsNonLeaf, out _); AssertSpansEqual(description.OldRegions[i], actualOldExceptionRegions, oldSource, oldText); } // check new exception regions: Assert.Equal(description.NewRegions.Length, actualNewExceptionRegions.Count); for (var i = 0; i < description.NewRegions.Length; i++) { AssertSpansEqual(description.NewRegions[i], actualNewExceptionRegions[i], newSource, newText); } } else { for (var i = 0; i < oldActiveStatements.Length; i++) { Assert.Equal(0, description.NewRegions[i].Length); } } }
internal void VerifySemantics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription activeStatements, IEnumerable <string> additionalOldSources, IEnumerable <string> additionalNewSources, SemanticEditDescription[] expectedSemanticEdits, RudeEditDiagnosticDescription[] expectedDiagnostics) { var editMap = Analyzer.BuildEditMap(editScript); var oldRoot = editScript.Match.OldRoot; var newRoot = editScript.Match.NewRoot; var oldSource = oldRoot.SyntaxTree.ToString(); var newSource = newRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); IEnumerable <SyntaxTree> oldTrees = new[] { oldRoot.SyntaxTree }; IEnumerable <SyntaxTree> newTrees = new[] { newRoot.SyntaxTree }; if (additionalOldSources != null) { oldTrees = oldTrees.Concat(additionalOldSources.Select(s => ParseText(s))); } if (additionalOldSources != null) { newTrees = newTrees.Concat(additionalNewSources.Select(s => ParseText(s))); } var oldCompilation = CreateLibraryCompilation("Old", oldTrees); var newCompilation = CreateLibraryCompilation("New", newTrees); oldTrees.SelectMany(tree => tree.GetDiagnostics()).Where(d => d.Severity == DiagnosticSeverity.Error).Verify(); newTrees.SelectMany(tree => tree.GetDiagnostics()).Where(d => d.Severity == DiagnosticSeverity.Error).Verify(); var oldModel = oldCompilation.GetSemanticModel(oldRoot.SyntaxTree); var newModel = newCompilation.GetSemanticModel(newRoot.SyntaxTree); var oldActiveStatements = activeStatements.OldSpans.AsImmutable(); var updatedActiveMethodMatches = new List <ValueTuple <int, Match <SyntaxNode> > >(); var triviaEdits = new List <KeyValuePair <SyntaxNode, SyntaxNode> >(); var actualLineEdits = new List <LineChange>(); var actualSemanticEdits = new List <SemanticEdit>(); var diagnostics = new List <RudeEditDiagnostic>(); var actualNewActiveStatements = new LinePositionSpan[activeStatements.OldSpans.Length]; var actualNewExceptionRegions = new ImmutableArray <LinePositionSpan> [activeStatements.OldSpans.Length]; Analyzer.AnalyzeSyntax( editScript, editMap, oldText, newText, null, null, oldActiveStatements, actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); diagnostics.Verify(newSource); Analyzer.AnalyzeTrivia( oldText, newText, editScript.Match, editMap, triviaEdits, actualLineEdits, diagnostics, default(CancellationToken)); diagnostics.Verify(newSource); Analyzer.AnalyzeSemantics( editScript, editMap, oldText, oldActiveStatements, triviaEdits, updatedActiveMethodMatches, oldModel, newModel, actualSemanticEdits, diagnostics, default(CancellationToken)); diagnostics.Verify(newSource, expectedDiagnostics); if (expectedSemanticEdits == null) { return; } Assert.Equal(expectedSemanticEdits.Length, actualSemanticEdits.Count); for (int i = 0; i < actualSemanticEdits.Count; i++) { var editKind = expectedSemanticEdits[i].Kind; Assert.Equal(editKind, actualSemanticEdits[i].Kind); var expectedOldSymbol = (editKind == SemanticEditKind.Update) ? expectedSemanticEdits[i].SymbolProvider(oldCompilation) : null; var expectedNewSymbol = expectedSemanticEdits[i].SymbolProvider(newCompilation); var actualOldSymbol = actualSemanticEdits[i].OldSymbol; var actualNewSymbol = actualSemanticEdits[i].NewSymbol; Assert.Equal(expectedOldSymbol, actualOldSymbol); Assert.Equal(expectedNewSymbol, actualNewSymbol); var expectedSyntaxMap = expectedSemanticEdits[i].SyntaxMap; var actualSyntaxMap = actualSemanticEdits[i].SyntaxMap; Assert.Equal(expectedSemanticEdits[i].PreserveLocalVariables, actualSemanticEdits[i].PreserveLocalVariables); if (expectedSyntaxMap != null) { Assert.NotNull(actualSyntaxMap); Assert.True(expectedSemanticEdits[i].PreserveLocalVariables); var newNodes = new List <SyntaxNode>(); foreach (var expectedSpanMapping in expectedSyntaxMap) { var newNode = FindNode(newRoot, expectedSpanMapping.Value); var expectedOldNode = FindNode(oldRoot, expectedSpanMapping.Key); var actualOldNode = actualSyntaxMap(newNode); Assert.Equal(expectedOldNode, actualOldNode); newNodes.Add(newNode); } AssertEx.SetEqual(newNodes, GetDeclarators(actualNewSymbol)); } else { Assert.Null(actualSyntaxMap); } } }
internal void VerifyRudeDiagnostics( EditScript <SyntaxNode> editScript, ActiveStatementsDescription description, RudeEditDiagnosticDescription[] expectedDiagnostics) { var oldActiveStatements = description.OldSpans; if (description.TrackingSpans != null) { Assert.Equal(oldActiveStatements.Length, description.TrackingSpans.Length); } string newSource = editScript.Match.NewRoot.SyntaxTree.ToString(); string oldSource = editScript.Match.OldRoot.SyntaxTree.ToString(); var oldText = SourceText.From(oldSource); var newText = SourceText.From(newSource); var diagnostics = new List <RudeEditDiagnostic>(); var actualNewActiveStatements = new LinePositionSpan[oldActiveStatements.Length]; var actualNewExceptionRegions = new ImmutableArray <LinePositionSpan> [oldActiveStatements.Length]; var updatedActiveMethodMatches = new List <ValueTuple <int, IReadOnlyDictionary <SyntaxNode, SyntaxNode> > >(); var editMap = Analyzer.BuildEditMap(editScript); DocumentId documentId = DocumentId.CreateNewId(ProjectId.CreateNewId("TestEnCProject"), "TestEnCDocument"); TestActiveStatementTrackingService trackingService; if (description.TrackingSpans != null) { trackingService = new TestActiveStatementTrackingService(documentId, description.TrackingSpans); } else { trackingService = null; } Analyzer.AnalyzeSyntax( editScript, editMap, oldText, newText, documentId, trackingService, oldActiveStatements.AsImmutable(), actualNewActiveStatements, actualNewExceptionRegions, updatedActiveMethodMatches, diagnostics); diagnostics.Verify(newSource, expectedDiagnostics); // check active statements: AssertSpansEqual(description.NewSpans, actualNewActiveStatements, newSource, newText); if (diagnostics.Count == 0) { // check old exception regions: for (int i = 0; i < oldActiveStatements.Length; i++) { var actualOldExceptionRegions = Analyzer.GetExceptionRegions( oldText, editScript.Match.OldRoot, oldActiveStatements[i].Span, isLeaf: (oldActiveStatements[i].Flags & ActiveStatementFlags.LeafFrame) != 0); AssertSpansEqual(description.OldRegions[i], actualOldExceptionRegions, oldSource, oldText); } // check new exception regions: Assert.Equal(description.NewRegions.Length, actualNewExceptionRegions.Length); for (int i = 0; i < description.NewRegions.Length; i++) { AssertSpansEqual(description.NewRegions[i], actualNewExceptionRegions[i], newSource, newText); } } else { for (int i = 0; i < oldActiveStatements.Length; i++) { Assert.Equal(0, description.NewRegions[i].Length); } } if (description.TrackingSpans != null) { AssertEx.Equal(trackingService.TrackingSpans, description.NewSpans.Select(s => (TextSpan?)s)); } }