public static Diagnostic ToDiagnostics(this RazorError error, string filePath) { if (error == null) { throw new ArgumentNullException(nameof(error)); } if (filePath == null) { throw new ArgumentNullException(nameof(filePath)); } var descriptor = new DiagnosticDescriptor( id: "Razor", title: "Razor parsing error", messageFormat: error.Message.Replace("{", "{{").Replace("}", "}}"), category: "Razor.Parser", defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); var location = error.Location; if (location.Equals(SourceLocation.Undefined)) { location = SourceLocation.Zero; } var length = Math.Max(0, error.Length); var textSpan = new TextSpan(location.AbsoluteIndex, length); var linePositionStart = new LinePosition(location.LineIndex, location.CharacterIndex); var linePositionEnd = new LinePosition(location.LineIndex, location.CharacterIndex + length); var linePositionSpan = new LinePositionSpan(linePositionStart, linePositionEnd); return Diagnostic.Create(descriptor, Location.Create(filePath, textSpan, linePositionSpan)); }
private bool TryAdjustSpanIfNeededForVenus( DocumentId documentId, FileLinePositionSpan originalLineInfo, FileLinePositionSpan mappedLineInfo, out LinePositionSpan originalSpan, out LinePositionSpan mappedSpan) { var startChanged = true; MappedSpan startLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, out startLineColumn)) { startChanged = false; startLineColumn = new MappedSpan(originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, mappedLineInfo.StartLinePosition.Line, mappedLineInfo.StartLinePosition.Character); } var endChanged = true; MappedSpan endLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, out endLineColumn)) { endChanged = false; endLineColumn = new MappedSpan(originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, mappedLineInfo.EndLinePosition.Line, mappedLineInfo.EndLinePosition.Character); } // start and end position can be swapped when mapped between primary and secondary buffer if start position is within visible span (at the edge) // but end position is outside of visible span. in that case, swap start and end position. originalSpan = GetLinePositionSpan(startLineColumn.OriginalLinePosition, endLineColumn.OriginalLinePosition); mappedSpan = GetLinePositionSpan(startLineColumn.MappedLinePosition, endLineColumn.MappedLinePosition); return startChanged || endChanged; }
public void BeforeCompile(IBeforeCompileContext context) { string keyPath = Environment.GetEnvironmentVariable("NUGET_BUILD_KEY_PATH"); string delaySignString = Environment.GetEnvironmentVariable("NUGET_BUILD_DELAY_SIGN"); if (!string.IsNullOrEmpty(keyPath)) { FileInfo keyFile = new FileInfo(keyPath); if (keyFile.Exists) { bool delaySign = delaySignString != null && StringComparer.OrdinalIgnoreCase.Equals("true", delaySignString); // Console.WriteLine("Signing assembly with: {0} Delay sign: {1}", keyFile.FullName, delaySign ? "true" : "false"); var parms = new CspParameters(); parms.KeyNumber = 2; var provider = new RSACryptoServiceProvider(parms); byte[] array = provider.ExportCspBlob(!provider.PublicOnly); var strongNameProvider = new DesktopStrongNameProvider(); var options = context.Compilation.Options.WithStrongNameProvider(strongNameProvider) .WithCryptoKeyFile(keyFile.FullName) .WithDelaySign(delaySign); // Enfore viral strong naming var specificDiagnosticOptions = new Dictionary<string, ReportDiagnostic>(options.SpecificDiagnosticOptions); specificDiagnosticOptions["CS8002"] = ReportDiagnostic.Error; options = options.WithSpecificDiagnosticOptions(specificDiagnosticOptions); context.Compilation = context.Compilation.WithOptions(options); } else { // The key was not found. Throw a compile error. var descriptor = new DiagnosticDescriptor( id: "SN1001", title: "Missing key file", messageFormat: "Key file '{0}' could not be found", category: "CA1001: \"StrongNaming\"", defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); // TODO: what should this reference for the location? var textSpan = new TextSpan(); var position = new LinePosition(0, 0); var span = new LinePositionSpan(position, position); var location = Location.Create(context.ProjectContext.ProjectFilePath, textSpan, span); var diagnsotic = Diagnostic.Create(descriptor, location, keyPath); context.Diagnostics.Add(diagnsotic); } } }
public void EmptyText_OneSpan() { var text = "[||]"; var markupText = new MarkupText(text); Assert.AreEqual(expected: string.Empty, actual: markupText.Text); Assert.AreEqual(expected: 0, actual: markupText.Positions.Length); Assert.AreEqual(expected: 1, actual: markupText.Spans.Length); var expectedSpan = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 0)); Assert.AreEqual(expected: expectedSpan, actual: markupText.Spans[0]); }
internal static IDocumentPeekResult CreateDocumentPeekResult(string filePath, LinePositionSpan identifierLocation, LinePositionSpan entityOfInterestSpan, PeekResultDisplayInfo displayInfo, IPeekResultFactory peekResultFactory, bool isReadOnly) { return peekResultFactory.Create( displayInfo, filePath: filePath, startLine: entityOfInterestSpan.Start.Line, startIndex: entityOfInterestSpan.Start.Character, endLine: entityOfInterestSpan.End.Line, endIndex: entityOfInterestSpan.End.Character, idLine: identifierLocation.Start.Line, idIndex: identifierLocation.Start.Character, isReadOnly: isReadOnly); }
internal static IDocumentPeekResult CreateDocumentPeekResult(string filePath, LinePositionSpan identifierLocation, LinePositionSpan entityOfInterestSpan, IPeekResultFactory peekResultFactory) { var fileName = Path.GetFileName(filePath); var label = string.Format("{0} - ({1}, {2})", fileName, identifierLocation.Start.Line + 1, identifierLocation.Start.Character + 1); var displayInfo = new PeekResultDisplayInfo(label: label, labelTooltip: filePath, title: fileName, titleTooltip: filePath); return CreateDocumentPeekResult( filePath, identifierLocation, entityOfInterestSpan, displayInfo, peekResultFactory, isReadOnly: false); }
internal override string FormatSourceSpan(LinePositionSpan span, IFormatProvider formatter) { if (_displayEndLocations) { return string.Format(formatter, "({0},{1},{2},{3})", span.Start.Line + 1, span.Start.Character + 1, span.End.Line + 1, span.End.Character + 1); } else { return string.Format(formatter, "({0},{1})", span.Start.Line + 1, span.Start.Character + 1); } }
private bool TryAdjustSpanIfNeededForVenus( DocumentId documentId, FileLinePositionSpan originalLineInfo, FileLinePositionSpan mappedLineInfo, out LinePositionSpan originalSpan, out LinePositionSpan mappedSpan) { var startChanged = true; MappedSpan startLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, out startLineColumn)) { startChanged = false; startLineColumn = new MappedSpan(originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, mappedLineInfo.StartLinePosition.Line, mappedLineInfo.StartLinePosition.Character); } var endChanged = true; MappedSpan endLineColumn; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, out endLineColumn)) { endChanged = false; endLineColumn = new MappedSpan(originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, mappedLineInfo.EndLinePosition.Line, mappedLineInfo.EndLinePosition.Character); } originalSpan = new LinePositionSpan(startLineColumn.OriginalLinePosition, Max(startLineColumn.OriginalLinePosition, endLineColumn.OriginalLinePosition)); mappedSpan = new LinePositionSpan(startLineColumn.MappedLinePosition, Max(startLineColumn.MappedLinePosition, endLineColumn.MappedLinePosition)); return startChanged || endChanged; }
public VsExceptionRegion(uint activeStatementId, int ordinal, uint methodToken, LinePositionSpan span) { this.ActiveStatementId = activeStatementId; this.Span = span; this.MethodToken = methodToken; this.Ordinal = ordinal; }
/// <summary> /// Gets <see cref="DiagnosticData"/> objects for selected error list entries. /// For remove suppression, the method also returns selected external source diagnostics. /// </summary> public async Task <ImmutableArray <DiagnosticData> > GetSelectedItemsAsync(bool isAddSuppression, CancellationToken cancellationToken) { var builder = ArrayBuilder <DiagnosticData> .GetInstance(); Dictionary <string, Project> projectNameToProjectMapOpt = null; Dictionary <Project, ImmutableDictionary <string, Document> > filePathToDocumentMapOpt = null; foreach (var entryHandle in _tableControl.SelectedEntries) { cancellationToken.ThrowIfCancellationRequested(); DiagnosticData diagnosticData = null; int index; var roslynSnapshot = GetEntriesSnapshot(entryHandle, out index); if (roslynSnapshot != null) { diagnosticData = roslynSnapshot.GetItem(index)?.Primary; } else if (!isAddSuppression) { // For suppression removal, we also need to handle FxCop entries. bool isSuppressedEntry; if (!IsNonRoslynEntrySupportingSuppressionState(entryHandle, out isSuppressedEntry) || !isSuppressedEntry) { continue; } string errorCode = null, category = null, message = null, filePath = null, projectName = null; int line = -1; // FxCop only supports line, not column. DiagnosticDataLocation location = null; if (entryHandle.TryGetValue(StandardTableColumnDefinitions.ErrorCode, out errorCode) && !string.IsNullOrEmpty(errorCode) && entryHandle.TryGetValue(StandardTableColumnDefinitions.ErrorCategory, out category) && !string.IsNullOrEmpty(category) && entryHandle.TryGetValue(StandardTableColumnDefinitions.Text, out message) && !string.IsNullOrEmpty(message) && entryHandle.TryGetValue(StandardTableColumnDefinitions.ProjectName, out projectName) && !string.IsNullOrEmpty(projectName)) { if (projectNameToProjectMapOpt == null) { projectNameToProjectMapOpt = new Dictionary <string, Project>(); foreach (var p in _workspace.CurrentSolution.Projects) { projectNameToProjectMapOpt[p.Name] = p; } } cancellationToken.ThrowIfCancellationRequested(); Project project; if (!projectNameToProjectMapOpt.TryGetValue(projectName, out project)) { // bail out continue; } Document document = null; var hasLocation = (entryHandle.TryGetValue(StandardTableColumnDefinitions.DocumentName, out filePath) && !string.IsNullOrEmpty(filePath)) && (entryHandle.TryGetValue(StandardTableColumnDefinitions.Line, out line) && line >= 0); if (hasLocation) { if (string.IsNullOrEmpty(filePath) || line < 0) { // bail out continue; } ImmutableDictionary <string, Document> filePathMap; filePathToDocumentMapOpt = filePathToDocumentMapOpt ?? new Dictionary <Project, ImmutableDictionary <string, Document> >(); if (!filePathToDocumentMapOpt.TryGetValue(project, out filePathMap)) { filePathMap = await GetFilePathToDocumentMapAsync(project, cancellationToken).ConfigureAwait(false); filePathToDocumentMapOpt[project] = filePathMap; } if (!filePathMap.TryGetValue(filePath, out document)) { // bail out continue; } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var linePosition = new LinePosition(line, 0); var linePositionSpan = new LinePositionSpan(start: linePosition, end: linePosition); var textSpan = (await tree.GetTextAsync(cancellationToken).ConfigureAwait(false)).Lines.GetTextSpan(linePositionSpan); location = new DiagnosticDataLocation(document.Id, textSpan, filePath, originalStartLine: linePosition.Line, originalStartColumn: linePosition.Character, originalEndLine: linePosition.Line, originalEndColumn: linePosition.Character); } Contract.ThrowIfNull(project); Contract.ThrowIfFalse((document != null) == (location != null)); // Create a diagnostic with correct values for fields we care about: id, category, message, isSuppressed, location // and default values for the rest of the fields (not used by suppression fixer). diagnosticData = new DiagnosticData( id: errorCode, category: category, message: message, enuMessageForBingSearch: message, severity: DiagnosticSeverity.Warning, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 1, isSuppressed: isSuppressedEntry, title: message, location: location, customTags: SuppressionHelpers.SynthesizedExternalSourceDiagnosticCustomTags, properties: ImmutableDictionary <string, string> .Empty, workspace: _workspace, projectId: project.Id); } } if (IsEntryWithConfigurableSuppressionState(diagnosticData)) { builder.Add(diagnosticData); } } return(builder.ToImmutableAndFree()); }
internal static IDocumentPeekResult CreateDocumentPeekResult(string filePath, LinePositionSpan identifierLocation, LinePositionSpan entityOfInterestSpan, PeekResultDisplayInfo displayInfo, IPeekResultFactory peekResultFactory, bool isReadOnly) { return(peekResultFactory.Create( displayInfo, filePath: filePath, startLine: entityOfInterestSpan.Start.Line, startIndex: entityOfInterestSpan.Start.Character, endLine: entityOfInterestSpan.End.Line, endIndex: entityOfInterestSpan.End.Character, idLine: identifierLocation.Start.Line, idIndex: identifierLocation.Start.Character, isReadOnly: isReadOnly)); }
private static string GetFirstLineText(LinePositionSpan span, SourceText text) => text.Lines[span.Start.Line].ToString().Trim();
public static void PublishHoverPlainTextResponse(this KernelInvocationContext context, RequestHoverText command, string content, LinePositionSpan linePositionSpan) { var response = new HoverPlainTextProduced(command, content, linePositionSpan); context.Publish(response); }
internal static LinePositionSpan AddLineDelta(this LinePositionSpan span, int lineDelta) => new(new LinePosition(span.Start.Line + lineDelta, span.Start.Character), new LinePosition(span.End.Line + lineDelta, span.End.Character));
private protected Diagnostic CreateDiagnostic(TextSpan span, LinePositionSpan lineSpan) { Location location = Location.Create(CreateFileName(), span, lineSpan); return(Diagnostic.Create(Descriptor, location)); }
protected Diagnostic CreateDiagnostic(DiagnosticDescriptor descriptor, TextSpan span, LinePositionSpan lineSpan) { var location = Location.Create($"{DefaultFilePathPrefix}0.{FileExtension}", span, lineSpan); return(Diagnostic.Create(descriptor, location)); }
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); } } }
/// <summary> /// Convert a <see cref="LinePositionSpan"/> to <see cref="TextSpan"/>. /// </summary> public static TextSpan GetTextSpan(this ITextSnapshot snapshot, LinePositionSpan span) { return(TextSpan.FromBounds( GetPosition(snapshot, span.Start.Line, span.Start.Character), GetPosition(snapshot, span.End.Line, span.End.Character))); }
public HoverTextProduced(RequestHoverText command, IReadOnlyCollection <FormattedValue> content, LinePositionSpan linePositionSpan = null) : base(command) { if (content == null) { throw new ArgumentNullException(nameof(content)); } if (content.Count == 0) { throw new ArgumentException("At least one content required.", nameof(content)); } Content = content; _linePositionSpan = linePositionSpan; }
public async Task TrackingService_GetLatestSpansAsync(bool scheduleInitialTrackingBeforeOpenDoc) { var sourceV1 = "class C { void F() => G(1); void G(int a) => System.Console.WriteLine(1); }"; using var workspace = new TestWorkspace(); var span11 = new LinePositionSpan(new LinePosition(0, 10), new LinePosition(0, 15)); var span12 = new LinePositionSpan(new LinePosition(0, 20), new LinePosition(0, 25)); var span21 = new LinePositionSpan(new LinePosition(0, 11), new LinePosition(0, 16)); var span22 = new LinePositionSpan(new LinePosition(0, 21), new LinePosition(0, 26)); var encService = new MockEditAndContinueWorkspaceService(); encService.GetBaseActiveStatementSpansAsyncImpl = documentIds => ImmutableArray.Create(ImmutableArray.Create( (span11, ActiveStatementFlags.IsNonLeafFrame), (span12, ActiveStatementFlags.IsLeafFrame))); encService.GetAdjustedDocumentActiveStatementSpansAsyncImpl = document => ImmutableArray.Create( (span21, ActiveStatementFlags.IsNonLeafFrame), (span22, ActiveStatementFlags.IsLeafFrame)); var testDocument = new TestHostDocument(text: sourceV1, exportProvider: workspace.ExportProvider); workspace.AddTestProject(new TestHostProject(workspace, testDocument)); var textBuffer = testDocument.GetTextBuffer(); var solution = workspace.CurrentSolution; var project = solution.Projects.Single(); var document = project.Documents.Single(); var snapshot = textBuffer.CurrentSnapshot; Assert.Same(snapshot, document.GetTextSynchronously(CancellationToken.None).FindCorrespondingEditorTextSnapshot()); var trackingSession = new ActiveStatementTrackingService.TrackingSession(workspace, encService); if (scheduleInitialTrackingBeforeOpenDoc) { await trackingSession.TrackActiveSpansAsync().ConfigureAwait(false); var spans1 = trackingSession.Test_GetTrackingSpans(); AssertEx.Equal(new[] { $"V0 →←@[10..15): IsNonLeafFrame", $"V0 →←@[20..25): IsLeafFrame" }, spans1[document.Id].Select(s => $"{s.Span}: {s.Flags}")); } var spans2 = await trackingSession.GetAdjustedTrackingSpansAsync(document, snapshot, CancellationToken.None).ConfigureAwait(false); AssertEx.Equal(new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" }, spans2.Select(s => $"{s.Span}: {s.Flags}")); if (!scheduleInitialTrackingBeforeOpenDoc) { await trackingSession.TrackActiveSpansAsync().ConfigureAwait(false); var spans1 = trackingSession.Test_GetTrackingSpans(); AssertEx.Equal(new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" }, spans1[document.Id].Select(s => $"{s.Span}: {s.Flags}")); } // we are not able to determine active statements in a document: encService.GetAdjustedDocumentActiveStatementSpansAsyncImpl = document => default; var spans3 = await trackingSession.GetAdjustedTrackingSpansAsync(document, snapshot, CancellationToken.None).ConfigureAwait(false); AssertEx.Equal(new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" }, spans3.Select(s => $"{s.Span}: {s.Flags}")); }
internal ActiveStatement WithSpan(LinePositionSpan span) =>
public static int GetLineCount(this LinePositionSpan linePositionSpan) { return(linePositionSpan.End.Line - linePositionSpan.Start.Line + 1); }
public void Span_Middle() { var text = "Alpha [|Beta|] Gamma"; var markupText = new MarkupText(text); Assert.AreEqual(expected: "Alpha Beta Gamma", actual: markupText.Text); Assert.AreEqual(expected: 0, actual: markupText.Positions.Length); Assert.AreEqual(expected: 1, actual: markupText.Spans.Length); var expectedSpan = new LinePositionSpan(new LinePosition(0, 6), new LinePosition(0, 10)); Assert.AreEqual(expected: expectedSpan, actual: markupText.Spans[0]); }
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, Match <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)); } }
public void Span_WholeText() { var text = "[|Alpha Beta Gamma|]"; var markupText = new MarkupText(text); Assert.AreEqual(expected: "Alpha Beta Gamma", actual: markupText.Text); Assert.AreEqual(expected: 0, actual: markupText.Positions.Length); Assert.AreEqual(expected: 1, actual: markupText.Spans.Length); var expectedSpan = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 16)); Assert.AreEqual(expected: expectedSpan, actual: markupText.Spans[0]); }
internal ExternalFileLocation(string filePath, TextSpan sourceSpan, LinePositionSpan lineSpan) { _sourceSpan = sourceSpan; _lineSpan = new FileLinePositionSpan(filePath, lineSpan); }
private protected Diagnostic CreateDiagnostic(string source, TextSpan span) { LinePositionSpan lineSpan = span.ToLinePositionSpan(source); return(CreateDiagnostic(span, lineSpan)); }
public LineMapping(LinePositionSpan span, FileLinePositionSpan mappedSpan) { Span = span; MappedSpan = mappedSpan; }
internal FileLinePositionSpan(string path, LinePositionSpan span, bool hasMappedPath) { _path = path; _span = span; _hasMappedPath = hasMappedPath; }
public void Deconstruct(out LinePositionSpan span, out FileLinePositionSpan mappedSpan) { span = Span; mappedSpan = MappedSpan; }
public static LSP.Range LinePositionToRange(LinePositionSpan linePositionSpan) { return(new LSP.Range { Start = LinePositionToPosition(linePositionSpan.Start), End = LinePositionToPosition(linePositionSpan.End) }); }
public async Task when_code_contains_compile_time_error_diagnostics_are_produced(Language language, string code, string diagnosticMessage, string errorMessage) { var kernel = CreateKernel(language); var source = language switch { Language.FSharp => new[] { "open System", "aaaadd" }, Language.CSharp => new[] { "using System;", "aaaadd" } }; await SubmitCode(kernel, source); var diagnosticRange = new LinePositionSpan( new LinePosition(0, 0), new LinePosition(0, 6)); using var _ = new AssertionScope(); // The CommandFailed message is populated KernelEvents .Should() .ContainSingle <CommandFailed>() .Which .Message .Should() .Be(errorMessage); // The Diagnostics of DiagnosticsProduced event are populated KernelEvents .Should() .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0) .Which .Diagnostics .Should() .ContainSingle(diag => diag.LinePositionSpan == diagnosticRange && diag.Code == code && diag.Message == diagnosticMessage); // The FormattedValues are populated of DiagnosticsProduced event are populated KernelEvents .Should() .ContainSingle <DiagnosticsProduced>(d => d.Diagnostics.Count > 0) .Which .FormattedDiagnostics .Should() .ContainSingle(fv => true) .Which .Value .Should() .Be(errorMessage); }
public ActiveStatement WithSpan(LinePositionSpan span) => WithFileSpan(FileSpan.WithSpan(span));
private bool TryAdjustSpanIfNeededForVenus( DocumentId documentId, FileLinePositionSpan originalLineInfo, FileLinePositionSpan mappedLineInfo, out LinePositionSpan originalSpan, out LinePositionSpan mappedSpan) { var startChanged = true; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, out var startLineColumn)) { startChanged = false; startLineColumn = new MappedSpan(originalLineInfo.StartLinePosition.Line, originalLineInfo.StartLinePosition.Character, mappedLineInfo.StartLinePosition.Line, mappedLineInfo.StartLinePosition.Character); } var endChanged = true; if (!TryAdjustSpanIfNeededForVenus(_workspace, documentId, originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, out var endLineColumn)) { endChanged = false; endLineColumn = new MappedSpan(originalLineInfo.EndLinePosition.Line, originalLineInfo.EndLinePosition.Character, mappedLineInfo.EndLinePosition.Line, mappedLineInfo.EndLinePosition.Character); } // start and end position can be swapped when mapped between primary and secondary buffer if start position is within visible span (at the edge) // but end position is outside of visible span. in that case, swap start and end position. originalSpan = GetLinePositionSpan(startLineColumn.OriginalLinePosition, endLineColumn.OriginalLinePosition); mappedSpan = GetLinePositionSpan(startLineColumn.MappedLinePosition, endLineColumn.MappedLinePosition); return(startChanged || endChanged); }
private protected Diagnostic CreateDiagnostic(TextSpan span, LinePositionSpan lineSpan) { Location location = Location.Create(WorkspaceFactory.DefaultDocumentName, span, lineSpan); return(Diagnostic.Create(Descriptor, location)); }
internal static IDocumentPeekResult CreateDocumentPeekResult(string filePath, LinePositionSpan identifierLocation, LinePositionSpan entityOfInterestSpan, IPeekResultFactory peekResultFactory) { var fileName = Path.GetFileName(filePath); var label = string.Format("{0} - ({1}, {2})", fileName, identifierLocation.Start.Line + 1, identifierLocation.Start.Character + 1); var displayInfo = new PeekResultDisplayInfo(label: label, labelTooltip: filePath, title: fileName, titleTooltip: filePath); return(CreateDocumentPeekResult( filePath, identifierLocation, entityOfInterestSpan, displayInfo, peekResultFactory, isReadOnly: false)); }
public async Task Proxy(TestHost testHost) { var localComposition = EditorTestCompositions.EditorFeatures.WithTestHostParts(testHost); if (testHost == TestHost.InProcess) { localComposition = localComposition.AddParts(typeof(MockEditAndContinueWorkspaceService)); } using var localWorkspace = new TestWorkspace(composition: localComposition); var globalOptions = localWorkspace.GetService <IGlobalOptionService>(); MockEditAndContinueWorkspaceService mockEncService; var clientProvider = (InProcRemoteHostClientProvider?)localWorkspace.Services.GetService <IRemoteHostClientProvider>(); if (testHost == TestHost.InProcess) { Assert.Null(clientProvider); mockEncService = (MockEditAndContinueWorkspaceService)localWorkspace.Services.GetRequiredService <IEditAndContinueWorkspaceService>(); } else { Assert.NotNull(clientProvider); clientProvider !.AdditionalRemoteParts = new[] { typeof(MockEditAndContinueWorkspaceService) }; var client = await InProcRemoteHostClient.GetTestClientAsync(localWorkspace).ConfigureAwait(false); var remoteWorkspace = client.TestData.WorkspaceManager.GetWorkspace(); mockEncService = (MockEditAndContinueWorkspaceService)remoteWorkspace.Services.GetRequiredService <IEditAndContinueWorkspaceService>(); } localWorkspace.ChangeSolution(localWorkspace.CurrentSolution. AddProject("proj", "proj", LanguageNames.CSharp). AddMetadataReferences(TargetFrameworkUtil.GetReferences(TargetFramework.Mscorlib40)). AddDocument("test.cs", SourceText.From("class C { }", Encoding.UTF8), filePath: "test.cs").Project.Solution); var solution = localWorkspace.CurrentSolution; var project = solution.Projects.Single(); var document = project.Documents.Single(); var mockDiagnosticService = new MockDiagnosticAnalyzerService(globalOptions); void VerifyReanalyzeInvocation(ImmutableArray <DocumentId> documentIds) { AssertEx.Equal(documentIds, mockDiagnosticService.DocumentsToReanalyze); mockDiagnosticService.DocumentsToReanalyze.Clear(); } var diagnosticUpdateSource = new EditAndContinueDiagnosticUpdateSource(); var emitDiagnosticsUpdated = new List <DiagnosticsUpdatedArgs>(); var emitDiagnosticsClearedCount = 0; diagnosticUpdateSource.DiagnosticsUpdated += (object sender, DiagnosticsUpdatedArgs args) => emitDiagnosticsUpdated.Add(args); diagnosticUpdateSource.DiagnosticsCleared += (object sender, EventArgs args) => emitDiagnosticsClearedCount++; var span1 = new LinePositionSpan(new LinePosition(1, 2), new LinePosition(1, 5)); var moduleId1 = new Guid("{44444444-1111-1111-1111-111111111111}"); var methodId1 = new ManagedMethodId(moduleId1, token: 0x06000003, version: 2); var instructionId1 = new ManagedInstructionId(methodId1, ilOffset: 10); var as1 = new ManagedActiveStatementDebugInfo( instructionId1, documentName: "test.cs", span1.ToSourceSpan(), flags: ActiveStatementFlags.LeafFrame | ActiveStatementFlags.PartiallyExecuted); var methodId2 = new ManagedModuleMethodId(token: 0x06000002, version: 1); var exceptionRegionUpdate1 = new ManagedExceptionRegionUpdate( methodId2, delta: 1, newSpan: new SourceSpan(1, 2, 1, 5)); var document1 = localWorkspace.CurrentSolution.Projects.Single().Documents.Single(); var activeSpans1 = ImmutableArray.Create( new ActiveStatementSpan(0, new LinePositionSpan(new LinePosition(1, 2), new LinePosition(3, 4)), ActiveStatementFlags.NonLeafFrame, document.Id)); var activeStatementSpanProvider = new ActiveStatementSpanProvider((documentId, path, cancellationToken) => { Assert.Equal(document1.Id, documentId); Assert.Equal("test.cs", path); return(new(activeSpans1)); }); var proxy = new RemoteEditAndContinueServiceProxy(localWorkspace); // StartDebuggingSession IManagedHotReloadService?remoteDebuggeeModuleMetadataProvider = null; var debuggingSession = mockEncService.StartDebuggingSessionImpl = (solution, debuggerService, captureMatchingDocuments, captureAllMatchingDocuments, reportDiagnostics) => { Assert.Equal("proj", solution.Projects.Single().Name); AssertEx.Equal(new[] { document1.Id }, captureMatchingDocuments); Assert.False(captureAllMatchingDocuments); Assert.True(reportDiagnostics); remoteDebuggeeModuleMetadataProvider = debuggerService; return(new DebuggingSessionId(1)); }; var sessionProxy = await proxy.StartDebuggingSessionAsync( localWorkspace.CurrentSolution, debuggerService : new MockManagedEditAndContinueDebuggerService() { IsEditAndContinueAvailable = _ => new ManagedHotReloadAvailability(ManagedHotReloadAvailabilityStatus.NotAllowedForModule, "can't do enc"), GetActiveStatementsImpl = () => ImmutableArray.Create(as1) }, captureMatchingDocuments : ImmutableArray.Create(document1.Id), captureAllMatchingDocuments : false, reportDiagnostics : true, CancellationToken.None).ConfigureAwait(false); Contract.ThrowIfNull(sessionProxy); // BreakStateChanged mockEncService.BreakStateOrCapabilitiesChangedImpl = (bool?inBreakState, out ImmutableArray <DocumentId> documentsToReanalyze) => { Assert.True(inBreakState); documentsToReanalyze = ImmutableArray.Create(document.Id); }; await sessionProxy.BreakStateOrCapabilitiesChangedAsync(mockDiagnosticService, diagnosticUpdateSource, inBreakState : true, CancellationToken.None).ConfigureAwait(false); VerifyReanalyzeInvocation(ImmutableArray.Create(document.Id)); Assert.Equal(1, emitDiagnosticsClearedCount); emitDiagnosticsClearedCount = 0; var activeStatement = (await remoteDebuggeeModuleMetadataProvider !.GetActiveStatementsAsync(CancellationToken.None).ConfigureAwait(false)).Single(); Assert.Equal(as1.ActiveInstruction, activeStatement.ActiveInstruction); Assert.Equal(as1.SourceSpan, activeStatement.SourceSpan); Assert.Equal(as1.Flags, activeStatement.Flags); var availability = await remoteDebuggeeModuleMetadataProvider !.GetAvailabilityAsync(moduleId1, CancellationToken.None).ConfigureAwait(false); Assert.Equal(new ManagedHotReloadAvailability(ManagedHotReloadAvailabilityStatus.NotAllowedForModule, "can't do enc"), availability); // EmitSolutionUpdate var diagnosticDescriptor1 = EditAndContinueDiagnosticDescriptors.GetDescriptor(EditAndContinueErrorCode.ErrorReadingFile); mockEncService.EmitSolutionUpdateImpl = (solution, activeStatementSpanProvider) => { var project = solution.Projects.Single(); Assert.Equal("proj", project.Name); AssertEx.Equal(activeSpans1, activeStatementSpanProvider(document1.Id, "test.cs", CancellationToken.None).AsTask().Result); var deltas = ImmutableArray.Create(new ManagedModuleUpdate( module: moduleId1, ilDelta: ImmutableArray.Create <byte>(1, 2), metadataDelta: ImmutableArray.Create <byte>(3, 4), pdbDelta: ImmutableArray.Create <byte>(5, 6), updatedMethods: ImmutableArray.Create(0x06000001), updatedTypes: ImmutableArray.Create(0x02000001), sequencePoints: ImmutableArray.Create(new SequencePointUpdates("file.cs", ImmutableArray.Create(new SourceLineUpdate(1, 2)))), activeStatements: ImmutableArray.Create(new ManagedActiveStatementUpdate(instructionId1.Method.Method, instructionId1.ILOffset, span1.ToSourceSpan())), exceptionRegions: ImmutableArray.Create(exceptionRegionUpdate1), requiredCapabilities: EditAndContinueCapabilities.Baseline)); var syntaxTree = project.Documents.Single().GetSyntaxTreeSynchronously(CancellationToken.None) !; var documentDiagnostic = Diagnostic.Create(diagnosticDescriptor1, Location.Create(syntaxTree, TextSpan.FromBounds(1, 2)), new[] { "doc", "some error" }); var projectDiagnostic = Diagnostic.Create(diagnosticDescriptor1, Location.None, new[] { "proj", "some error" }); var syntaxError = Diagnostic.Create(diagnosticDescriptor1, Location.Create(syntaxTree, TextSpan.FromBounds(1, 2)), new[] { "doc", "syntax error" }); var updates = new ManagedModuleUpdates(ManagedModuleUpdateStatus.Ready, deltas); var diagnostics = ImmutableArray.Create((project.Id, ImmutableArray.Create(documentDiagnostic, projectDiagnostic))); var documentsWithRudeEdits = ImmutableArray.Create((document1.Id, ImmutableArray <RudeEditDiagnostic> .Empty)); return(new(updates, diagnostics, documentsWithRudeEdits, syntaxError)); }; var(updates, _, _, syntaxErrorData) = await sessionProxy.EmitSolutionUpdateAsync(localWorkspace.CurrentSolution, activeStatementSpanProvider, mockDiagnosticService, diagnosticUpdateSource, CancellationToken.None).ConfigureAwait(false); AssertEx.Equal($"[{project.Id}] Error ENC1001: test.cs(0, 1, 0, 2): {string.Format(FeaturesResources.ErrorReadingFile, "doc", "syntax error")}", Inspect(syntaxErrorData !)); VerifyReanalyzeInvocation(ImmutableArray.Create(document1.Id)); Assert.Equal(ManagedModuleUpdateStatus.Ready, updates.Status); Assert.Equal(1, emitDiagnosticsClearedCount); emitDiagnosticsClearedCount = 0; AssertEx.Equal(new[] { $"[{project.Id}] Error ENC1001: test.cs(0, 1, 0, 2): {string.Format(FeaturesResources.ErrorReadingFile, "doc", "some error")}", $"[{project.Id}] Error ENC1001: {string.Format(FeaturesResources.ErrorReadingFile, "proj", "some error")}" }, emitDiagnosticsUpdated.Select(update => Inspect(update.GetPushDiagnostics(globalOptions, InternalDiagnosticsOptions.NormalDiagnosticMode).Single()))); emitDiagnosticsUpdated.Clear(); var delta = updates.Updates.Single(); Assert.Equal(moduleId1, delta.Module); AssertEx.Equal(new byte[] { 1, 2 }, delta.ILDelta); AssertEx.Equal(new byte[] { 3, 4 }, delta.MetadataDelta); AssertEx.Equal(new byte[] { 5, 6 }, delta.PdbDelta); AssertEx.Equal(new[] { 0x06000001 }, delta.UpdatedMethods); AssertEx.Equal(new[] { 0x02000001 }, delta.UpdatedTypes); var lineEdit = delta.SequencePoints.Single(); Assert.Equal("file.cs", lineEdit.FileName); AssertEx.Equal(new[] { new SourceLineUpdate(1, 2) }, lineEdit.LineUpdates); Assert.Equal(exceptionRegionUpdate1, delta.ExceptionRegions.Single()); var activeStatements = delta.ActiveStatements.Single(); Assert.Equal(instructionId1.Method.Method, activeStatements.Method); Assert.Equal(instructionId1.ILOffset, activeStatements.ILOffset); Assert.Equal(span1, activeStatements.NewSpan.ToLinePositionSpan()); // CommitSolutionUpdate mockEncService.CommitSolutionUpdateImpl = (out ImmutableArray <DocumentId> documentsToReanalyze) => { documentsToReanalyze = ImmutableArray.Create(document.Id); }; await sessionProxy.CommitSolutionUpdateAsync(mockDiagnosticService, CancellationToken.None).ConfigureAwait(false); VerifyReanalyzeInvocation(ImmutableArray.Create(document.Id)); // DiscardSolutionUpdate var called = false; mockEncService.DiscardSolutionUpdateImpl = () => called = true; await sessionProxy.DiscardSolutionUpdateAsync(CancellationToken.None).ConfigureAwait(false); Assert.True(called); // GetCurrentActiveStatementPosition mockEncService.GetCurrentActiveStatementPositionImpl = (solution, activeStatementSpanProvider, instructionId) => { Assert.Equal("proj", solution.Projects.Single().Name); Assert.Equal(instructionId1, instructionId); AssertEx.Equal(activeSpans1, activeStatementSpanProvider(document1.Id, "test.cs", CancellationToken.None).AsTask().Result); return(new LinePositionSpan(new LinePosition(1, 2), new LinePosition(1, 5))); }; Assert.Equal(span1, await sessionProxy.GetCurrentActiveStatementPositionAsync( localWorkspace.CurrentSolution, activeStatementSpanProvider, instructionId1, CancellationToken.None).ConfigureAwait(false)); // IsActiveStatementInExceptionRegion mockEncService.IsActiveStatementInExceptionRegionImpl = (solution, instructionId) => { Assert.Equal(instructionId1, instructionId); return(true); }; Assert.True(await sessionProxy.IsActiveStatementInExceptionRegionAsync(localWorkspace.CurrentSolution, instructionId1, CancellationToken.None).ConfigureAwait(false)); // GetBaseActiveStatementSpans var activeStatementSpan1 = new ActiveStatementSpan(0, span1, ActiveStatementFlags.NonLeafFrame | ActiveStatementFlags.PartiallyExecuted, unmappedDocumentId: document1.Id); mockEncService.GetBaseActiveStatementSpansImpl = (solution, documentIds) => { AssertEx.Equal(new[] { document1.Id }, documentIds); return(ImmutableArray.Create(ImmutableArray.Create(activeStatementSpan1))); }; var baseActiveSpans = await sessionProxy.GetBaseActiveStatementSpansAsync(localWorkspace.CurrentSolution, ImmutableArray.Create(document1.Id), CancellationToken.None).ConfigureAwait(false); Assert.Equal(activeStatementSpan1, baseActiveSpans.Single().Single()); // GetDocumentActiveStatementSpans mockEncService.GetAdjustedActiveStatementSpansImpl = (document, activeStatementSpanProvider) => { Assert.Equal("test.cs", document.Name); AssertEx.Equal(activeSpans1, activeStatementSpanProvider(document.Id, "test.cs", CancellationToken.None).AsTask().Result); return(ImmutableArray.Create(activeStatementSpan1)); }; var documentActiveSpans = await sessionProxy.GetAdjustedActiveStatementSpansAsync(document1, activeStatementSpanProvider, CancellationToken.None).ConfigureAwait(false); Assert.Equal(activeStatementSpan1, documentActiveSpans.Single()); // GetDocumentActiveStatementSpans (default array) mockEncService.GetAdjustedActiveStatementSpansImpl = (document, _) => default; documentActiveSpans = await sessionProxy.GetAdjustedActiveStatementSpansAsync(document1, activeStatementSpanProvider, CancellationToken.None).ConfigureAwait(false); Assert.True(documentActiveSpans.IsDefault); // OnSourceFileUpdatedAsync called = false; mockEncService.OnSourceFileUpdatedImpl = updatedDocument => { Assert.Equal(document.Id, updatedDocument.Id); called = true; }; await proxy.OnSourceFileUpdatedAsync(document, CancellationToken.None).ConfigureAwait(false); Assert.True(called); // EndDebuggingSession mockEncService.EndDebuggingSessionImpl = (out ImmutableArray <DocumentId> documentsToReanalyze) => { documentsToReanalyze = ImmutableArray.Create(document.Id); }; await sessionProxy.EndDebuggingSessionAsync(solution, diagnosticUpdateSource, mockDiagnosticService, CancellationToken.None).ConfigureAwait(false); VerifyReanalyzeInvocation(ImmutableArray.Create(document.Id)); Assert.Equal(1, emitDiagnosticsClearedCount); emitDiagnosticsClearedCount = 0; Assert.Empty(emitDiagnosticsUpdated); }
public async Task TrackingService_GetLatestSpansAsync(bool scheduleInitialTrackingBeforeOpenDoc) { var source1 = "class C { void F() => G(1); void G(int a) => System.Console.WriteLine(1); }"; var source2 = "class D { }"; using var workspace = new TestWorkspace(); var span11 = new LinePositionSpan(new LinePosition(0, 10), new LinePosition(0, 15)); var span12 = new LinePositionSpan(new LinePosition(0, 20), new LinePosition(0, 25)); var span21 = new LinePositionSpan(new LinePosition(0, 11), new LinePosition(0, 16)); var span22 = new LinePositionSpan(new LinePosition(0, 21), new LinePosition(0, 26)); var encService = new MockEditAndContinueWorkspaceService(); encService.GetBaseActiveStatementSpansAsyncImpl = documentIds => ImmutableArray.Create( ImmutableArray.Create( (span11, ActiveStatementFlags.IsNonLeafFrame), (span12, ActiveStatementFlags.IsLeafFrame)), ImmutableArray <(LinePositionSpan, ActiveStatementFlags)> .Empty); encService.GetAdjustedDocumentActiveStatementSpansAsyncImpl = document => document.Name switch { "1.cs" => ImmutableArray.Create( (span21, ActiveStatementFlags.IsNonLeafFrame), (span22, ActiveStatementFlags.IsLeafFrame)), "2.cs" => ImmutableArray <(LinePositionSpan, ActiveStatementFlags)> .Empty, _ => throw ExceptionUtilities.Unreachable }; var testDocument1 = new TestHostDocument(text: source1, displayName: "1.cs", exportProvider: workspace.ExportProvider); var testDocument2 = new TestHostDocument(text: source2, displayName: "2.cs", exportProvider: workspace.ExportProvider); workspace.AddTestProject(new TestHostProject(workspace, documents: new[] { testDocument1, testDocument2 })); // opens the documents var textBuffer1 = testDocument1.GetTextBuffer(); var textBuffer2 = testDocument2.GetTextBuffer(); var solution = workspace.CurrentSolution; var project = solution.Projects.Single(); var document1 = project.Documents.Single(d => d.Name == "1.cs"); var document2 = project.Documents.Single(d => d.Name == "2.cs"); var snapshot1 = textBuffer1.CurrentSnapshot; var snapshot2 = textBuffer2.CurrentSnapshot; Assert.Same(snapshot1, document1.GetTextSynchronously(CancellationToken.None).FindCorrespondingEditorTextSnapshot()); Assert.Same(snapshot2, document2.GetTextSynchronously(CancellationToken.None).FindCorrespondingEditorTextSnapshot()); var trackingSession = new ActiveStatementTrackingService.TrackingSession(workspace, encService); if (scheduleInitialTrackingBeforeOpenDoc) { await trackingSession.TrackActiveSpansAsync().ConfigureAwait(false); var spans1 = trackingSession.Test_GetTrackingSpans(); AssertEx.Equal(new[] { $"V0 →←@[10..15): IsNonLeafFrame", $"V0 →←@[20..25): IsLeafFrame" }, spans1[document1.Id].Select(s => $"{s.Span}: {s.Flags}")); var spans2 = await trackingSession.GetSpansAsync(document1, CancellationToken.None).ConfigureAwait(false); AssertEx.Equal(new[] { "[10..15)", "[20..25)" }, spans2.Select(s => s.ToString())); var spans3 = await trackingSession.GetSpansAsync(document2, CancellationToken.None).ConfigureAwait(false); Assert.Empty(spans3); } var spans4 = await trackingSession.GetAdjustedTrackingSpansAsync(document1, snapshot1, CancellationToken.None).ConfigureAwait(false); AssertEx.Equal(new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" }, spans4.Select(s => $"{s.Span}: {s.Flags}")); AssertEx.Empty(await trackingSession.GetAdjustedTrackingSpansAsync(document2, snapshot2, CancellationToken.None).ConfigureAwait(false)); if (!scheduleInitialTrackingBeforeOpenDoc) { await trackingSession.TrackActiveSpansAsync().ConfigureAwait(false); var spans5 = trackingSession.Test_GetTrackingSpans(); AssertEx.Equal(new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" }, spans5[document1.Id].Select(s => $"{s.Span}: {s.Flags}")); } // we are not able to determine active statements in a document: encService.GetAdjustedDocumentActiveStatementSpansAsyncImpl = document => default; var spans6 = await trackingSession.GetAdjustedTrackingSpansAsync(document1, snapshot1, CancellationToken.None).ConfigureAwait(false); AssertEx.Equal(new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" }, spans6.Select(s => $"{s.Span}: {s.Flags}")); } }
internal static ActiveStatement CreateActiveStatement(ActiveStatementFlags flags, LinePositionSpan span, DocumentId documentId) => new ActiveStatement(
/// <summary> /// Creates an instance of a <see cref="Location"/> for a span in a file. /// </summary> public static Location Create(string filePath, TextSpan textSpan, LinePositionSpan lineSpan) { if (filePath == null) { throw new ArgumentNullException("filePath"); } return new ExternalFileLocation(filePath, textSpan, lineSpan); }
internal virtual string FormatSourceSpan(LinePositionSpan span, IFormatProvider formatter) { return string.Format("({0},{1})", span.Start.Line + 1, span.Start.Character + 1); }
public ActiveStatementSpan(ActiveStatementFlags flags, LinePositionSpan span) { this.Flags = flags; this.Span = span; }
public void Span_Multiline() { var text = @"Alpha [|Beta Gamma Delta|] Epsilon"; var markupText = new MarkupText(text); var expectedText = @"Alpha Beta Gamma Delta Epsilon"; Assert.AreEqual(expected: expectedText, actual: markupText.Text); Assert.AreEqual(expected: 0, actual: markupText.Positions.Length); Assert.AreEqual(expected: 1, actual: markupText.Spans.Length); var expectedSpan = new LinePositionSpan(new LinePosition(0, 6), new LinePosition(2, 5)); Assert.AreEqual(expected: expectedSpan, actual: markupText.Spans[0]); }
internal virtual string FormatSourceSpan(LinePositionSpan span, IFormatProvider formatter) { return(string.Format("({0},{1})", span.Start.Line + 1, span.Start.Character + 1)); }
public DiagnosticResultLocation(string path, LinePositionSpan span) { this.Path = path; this.Span = span; }
public void AdditionalLocationsAsRelatedLocations() { var stream = new MemoryStream(); using (var logger = new ErrorLogger(stream, "toolName", "1.2.3.4", new Version(1, 2, 3, 4), new CultureInfo("fr-CA"))) { var span = new TextSpan(0, 0); var position = new LinePositionSpan(LinePosition.Zero, LinePosition.Zero); var mainLocation = Location.Create(@"Z:\Main Location.cs", span, position); var descriptor = new DiagnosticDescriptor("TST", "_TST_", "", "", DiagnosticSeverity.Error, false); IEnumerable<Location> additionalLocations = new[] { Location.Create(@"Relative Additional\Location.cs", span, position), Location.Create(@"a:cannot/interpret/as\uri", span, position), }; logger.LogDiagnostic(Diagnostic.Create(descriptor, mainLocation, additionalLocations)); } string expected = @"{ ""$schema"": ""http://json.schemastore.org/sarif-1.0.0"", ""version"": ""1.0.0"", ""runs"": [ { ""tool"": { ""name"": ""toolName"", ""version"": ""1.2.3.4"", ""fileVersion"": ""1.2.3.4"", ""semanticVersion"": ""1.2.3"", ""language"": ""fr-CA"" }, ""results"": [ { ""ruleId"": ""TST"", ""level"": ""error"", ""locations"": [ { ""resultFile"": { ""uri"": ""file:///Z:/Main%20Location.cs"", ""region"": { ""startLine"": 1, ""startColumn"": 1, ""endLine"": 1, ""endColumn"": 1 } } } ], ""relatedLocations"": [ { ""physicalLocation"": { ""uri"": ""Relative%20Additional/Location.cs"", ""region"": { ""startLine"": 1, ""startColumn"": 1, ""endLine"": 1, ""endColumn"": 1 } } }, { ""physicalLocation"": { ""uri"": ""a%3Acannot%2Finterpret%2Fas%5Curi"", ""region"": { ""startLine"": 1, ""startColumn"": 1, ""endLine"": 1, ""endColumn"": 1 } } } ] } ], ""rules"": { ""TST"": { ""id"": ""TST"", ""shortDescription"": ""_TST_"", ""defaultLevel"": ""error"", ""properties"": { ""isEnabledByDefault"": false } } } } ] }"; string actual = Encoding.UTF8.GetString(stream.ToArray()); Assert.Equal(expected, actual); }
/// <summary> /// Gets <see cref="DiagnosticData"/> objects for selected error list entries. /// For remove suppression, the method also returns selected external source diagnostics. /// </summary> public async Task<ImmutableArray<DiagnosticData>> GetSelectedItemsAsync(bool isAddSuppression, CancellationToken cancellationToken) { var builder = ImmutableArray.CreateBuilder<DiagnosticData>(); Dictionary<string, Project> projectNameToProjectMapOpt = null; Dictionary<Project, ImmutableDictionary<string, Document>> filePathToDocumentMapOpt = null; foreach (var entryHandle in _tableControl.SelectedEntries) { cancellationToken.ThrowIfCancellationRequested(); DiagnosticData diagnosticData = null; int index; var roslynSnapshot = GetEntriesSnapshot(entryHandle, out index); if (roslynSnapshot != null) { diagnosticData = roslynSnapshot.GetItem(index)?.Primary; } else if (!isAddSuppression) { // For suppression removal, we also need to handle FxCop entries. bool isSuppressedEntry; if (!IsNonRoslynEntrySupportingSuppressionState(entryHandle, out isSuppressedEntry) || !isSuppressedEntry) { continue; } string errorCode = null, category = null, message = null, filePath = null, projectName = null; int line = -1; // FxCop only supports line, not column. DiagnosticDataLocation location = null; if (entryHandle.TryGetValue(StandardTableColumnDefinitions.ErrorCode, out errorCode) && !string.IsNullOrEmpty(errorCode) && entryHandle.TryGetValue(StandardTableColumnDefinitions.ErrorCategory, out category) && !string.IsNullOrEmpty(category) && entryHandle.TryGetValue(StandardTableColumnDefinitions.Text, out message) && !string.IsNullOrEmpty(message) && entryHandle.TryGetValue(StandardTableColumnDefinitions.ProjectName, out projectName) && !string.IsNullOrEmpty(projectName)) { if (projectNameToProjectMapOpt == null) { projectNameToProjectMapOpt = new Dictionary<string, Project>(); foreach (var p in _workspace.CurrentSolution.Projects) { projectNameToProjectMapOpt[p.Name] = p; } } cancellationToken.ThrowIfCancellationRequested(); Project project; if (!projectNameToProjectMapOpt.TryGetValue(projectName, out project)) { // bail out continue; } Document document = null; var hasLocation = (entryHandle.TryGetValue(StandardTableColumnDefinitions.DocumentName, out filePath) && !string.IsNullOrEmpty(filePath)) && (entryHandle.TryGetValue(StandardTableColumnDefinitions.Line, out line) && line >= 0); if (hasLocation) { if (string.IsNullOrEmpty(filePath) || line < 0) { // bail out continue; } ImmutableDictionary<string, Document> filePathMap; filePathToDocumentMapOpt = filePathToDocumentMapOpt ?? new Dictionary<Project, ImmutableDictionary<string, Document>>(); if (!filePathToDocumentMapOpt.TryGetValue(project, out filePathMap)) { filePathMap = await GetFilePathToDocumentMapAsync(project, cancellationToken).ConfigureAwait(false); filePathToDocumentMapOpt[project] = filePathMap; } if (!filePathMap.TryGetValue(filePath, out document)) { // bail out continue; } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var linePosition = new LinePosition(line, 0); var linePositionSpan = new LinePositionSpan(start: linePosition, end: linePosition); var textSpan = (await tree.GetTextAsync(cancellationToken).ConfigureAwait(false)).Lines.GetTextSpan(linePositionSpan); location = new DiagnosticDataLocation(document.Id, textSpan, filePath, originalStartLine: linePosition.Line, originalStartColumn: linePosition.Character, originalEndLine: linePosition.Line, originalEndColumn: linePosition.Character); } Contract.ThrowIfNull(project); Contract.ThrowIfFalse((document != null) == (location != null)); // Create a diagnostic with correct values for fields we care about: id, category, message, isSuppressed, location // and default values for the rest of the fields (not used by suppression fixer). diagnosticData = new DiagnosticData( id: errorCode, category: category, message: message, enuMessageForBingSearch: message, severity: DiagnosticSeverity.Warning, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 1, isSuppressed: isSuppressedEntry, title: message, location: location, customTags: SuppressionHelpers.SynthesizedExternalSourceDiagnosticCustomTags, properties: ImmutableDictionary<string, string>.Empty, workspace: _workspace, projectId: project.Id); } } if (IsEntryWithConfigurableSuppressionState(diagnosticData)) { builder.Add(diagnosticData); } } return builder.ToImmutable(); }
private static long CalculateOffset(long line, LinePositionSpan viewportSpan) { var firstLineInViewport = viewportSpan.Start.Line + 1; return(line - firstLineInViewport); }