public async Task AnalyzeDocumentAsync_SemanticError_NoChange() { var source = @" class C { public static void Main() { System.Console.WriteLine(1); Bar(); // semantic error } } "; var analyzer = new CSharpEditAndContinueAnalyzer(); using var workspace = TestWorkspace.CreateCSharp(source); var oldSolution = workspace.CurrentSolution; var oldProject = oldSolution.Projects.Single(); var oldDocument = oldProject.Documents.Single(); var documentId = oldDocument.Id; var baseActiveStatements = ImmutableArray.Create <ActiveStatement>(); var spanTracker = new TestActiveStatementSpanTracker(); var result = await analyzer.AnalyzeDocumentAsync(oldDocument, baseActiveStatements, oldDocument, spanTracker, CancellationToken.None); Assert.False(result.HasChanges); Assert.False(result.HasChangesAndErrors); Assert.False(result.HasChangesAndCompilationErrors); }
public async Task AnalyzeDocumentAsync_Features_NoChange() { var source = @" class C { public static void Main() { System.Console.WriteLine(1); } } "; var analyzer = new CSharpEditAndContinueAnalyzer(); var experimentalFeatures = new Dictionary <string, string>(); // no experimental features to enable var experimental = TestOptions.Regular.WithFeatures(experimentalFeatures); using var workspace = TestWorkspace.CreateCSharp( source, parseOptions: experimental, compilationOptions: null, exportProvider: null); var oldSolution = workspace.CurrentSolution; var oldProject = oldSolution.Projects.Single(); var oldDocument = oldProject.Documents.Single(); var documentId = oldDocument.Id; var baseActiveStatements = ImmutableArray.Create <ActiveStatement>(); var spanTracker = new TestActiveStatementSpanTracker(); var result = await analyzer.AnalyzeDocumentAsync(oldDocument, baseActiveStatements, oldDocument, spanTracker, CancellationToken.None); Assert.False(result.HasChanges); Assert.False(result.HasChangesAndErrors); Assert.False(result.HasChangesAndCompilationErrors); Assert.True(result.RudeEditErrors.IsEmpty); }
public async Task AnalyzeDocumentAsync_AddingNewFileHavingRudeEdits() { var source1 = @" namespace N { class C { public static void Main() { } } } "; var source2 = @" namespace N { public class D { } } "; var analyzer = new CSharpEditAndContinueAnalyzer(); using var workspace = TestWorkspace.CreateCSharp(source1); // fork the solution to introduce a change var oldProject = workspace.CurrentSolution.Projects.Single(); var newDocId = DocumentId.CreateNewId(oldProject.Id); var oldSolution = workspace.CurrentSolution; var newSolution = oldSolution.AddDocument(newDocId, "goo.cs", SourceText.From(source2)); workspace.TryApplyChanges(newSolution); var newProject = newSolution.Projects.Single(); var changes = newProject.GetChanges(oldProject); Assert.Equal(2, newProject.Documents.Count()); Assert.Equal(0, changes.GetChangedDocuments().Count()); Assert.Equal(1, changes.GetAddedDocuments().Count()); var changedDocuments = changes.GetChangedDocuments().Concat(changes.GetAddedDocuments()); var result = new List <DocumentAnalysisResults>(); var baseActiveStatements = ImmutableArray.Create <ActiveStatement>(); var spanTracker = new TestActiveStatementSpanTracker(); foreach (var changedDocumentId in changedDocuments) { result.Add(await analyzer.AnalyzeDocumentAsync(oldProject.GetDocument(changedDocumentId), baseActiveStatements, newProject.GetDocument(changedDocumentId), spanTracker, CancellationToken.None)); } Assert.True(result.IsSingle()); Assert.Equal(1, result.Single().RudeEditErrors.Count()); Assert.Equal(RudeEditKind.Insert, result.Single().RudeEditErrors.Single().Kind); }
public async Task AnalyzeDocumentAsync_Features_Change() { // these are all the experimental features currently implemented var experimentalFeatures = Array.Empty <string>(); foreach (var feature in experimentalFeatures) { var source1 = @" class C { public static void Main() { System.Console.WriteLine(1); } } "; var source2 = @" class C { public static void Main() { System.Console.WriteLine(2); } } "; var analyzer = new CSharpEditAndContinueAnalyzer(); var featuresToEnable = new Dictionary <string, string>() { { feature, "enabled" } }; var experimental = TestOptions.Regular.WithFeatures(featuresToEnable); using var workspace = TestWorkspace.CreateCSharp( source1, parseOptions: experimental, compilationOptions: null, exportProvider: null); var oldSolution = workspace.CurrentSolution; var oldProject = oldSolution.Projects.Single(); var oldDocument = oldProject.Documents.Single(); var documentId = oldDocument.Id; var newSolution = workspace.CurrentSolution.WithDocumentText(documentId, SourceText.From(source2)); var baseActiveStatements = ImmutableArray.Create <ActiveStatement>(); var spanTracker = new TestActiveStatementSpanTracker(); var result = await analyzer.AnalyzeDocumentAsync(oldDocument, baseActiveStatements, newSolution.GetDocument(documentId), spanTracker, CancellationToken.None); Assert.True(result.HasChanges); Assert.True(result.HasChangesAndErrors); Assert.False(result.HasChangesAndCompilationErrors); Assert.Equal(RudeEditKind.ExperimentalFeaturesEnabled, result.RudeEditErrors.Single().Kind); } }
public async Task AnalyzeDocumentAsync_SemanticErrorInMethodBody_Change() { var source1 = @" class C { public static void Main() { System.Console.WriteLine(1); Bar(); // semantic error } } "; var source2 = @" class C { public static void Main() { System.Console.WriteLine(2); Bar(); // semantic error } } "; var analyzer = new CSharpEditAndContinueAnalyzer(); using var workspace = TestWorkspace.CreateCSharp(source1); var oldSolution = workspace.CurrentSolution; var oldProject = oldSolution.Projects.Single(); var oldDocument = oldProject.Documents.Single(); var documentId = oldDocument.Id; var newSolution = workspace.CurrentSolution.WithDocumentText(documentId, SourceText.From(source2)); var baseActiveStatements = ImmutableArray.Create <ActiveStatement>(); var spanTracker = new TestActiveStatementSpanTracker(); var result = await analyzer.AnalyzeDocumentAsync(oldDocument, baseActiveStatements, newSolution.GetDocument(documentId), spanTracker, CancellationToken.None); Assert.True(result.HasChanges); // no declaration errors (error in method body is only reported when emitting): Assert.False(result.HasChangesAndErrors); Assert.False(result.HasChangesAndCompilationErrors); }
public async Task AnalyzeDocumentAsync_InsignificantChangesInMethodBody() { var source1 = @" class C { public static void Main() { // comment System.Console.WriteLine(1); } } "; var source2 = @" class C { public static void Main() { System.Console.WriteLine(1); } } "; var analyzer = new CSharpEditAndContinueAnalyzer(); using var workspace = TestWorkspace.CreateCSharp(source1); var oldSolution = workspace.CurrentSolution; var oldProject = oldSolution.Projects.Single(); var oldDocument = oldProject.Documents.Single(); var oldText = await oldDocument.GetTextAsync(); var oldSyntaxRoot = await oldDocument.GetSyntaxRootAsync(); var documentId = oldDocument.Id; var newSolution = workspace.CurrentSolution.WithDocumentText(documentId, SourceText.From(source2)); var newDocument = newSolution.GetDocument(documentId); var newText = await newDocument.GetTextAsync(); var newSyntaxRoot = await newDocument.GetSyntaxRootAsync(); const string oldStatementSource = "System.Console.WriteLine(1);"; var oldStatementPosition = source1.IndexOf(oldStatementSource, StringComparison.Ordinal); var oldStatementTextSpan = new TextSpan(oldStatementPosition, oldStatementSource.Length); var oldStatementSpan = oldText.Lines.GetLinePositionSpan(oldStatementTextSpan); var oldStatementSyntax = oldSyntaxRoot.FindNode(oldStatementTextSpan); var baseActiveStatements = ImmutableArray.Create(ActiveStatementsDescription.CreateActiveStatement(ActiveStatementFlags.IsLeafFrame, oldStatementSpan, DocumentId.CreateNewId(ProjectId.CreateNewId()))); var spanTracker = new TestActiveStatementSpanTracker(); var result = await analyzer.AnalyzeDocumentAsync(oldDocument, baseActiveStatements, newDocument, spanTracker, CancellationToken.None); Assert.True(result.HasChanges); Assert.True(result.SemanticEdits[0].PreserveLocalVariables); var syntaxMap = result.SemanticEdits[0].SyntaxMap; var newStatementSpan = result.ActiveStatements[0].Span; var newStatementTextSpan = newText.Lines.GetTextSpan(newStatementSpan); var newStatementSyntax = newSyntaxRoot.FindNode(newStatementTextSpan); var oldStatementSyntaxMapped = syntaxMap(newStatementSyntax); Assert.Same(oldStatementSyntax, oldStatementSyntaxMapped); }