Esempio n. 1
0
        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]);
        }
Esempio n. 5
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);
 }
Esempio n. 6
0
        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());
        }
Esempio n. 11
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));
 }
 private static string GetFirstLineText(LinePositionSpan span, SourceText text)
 => text.Lines[span.Start.Line].ToString().Trim();
Esempio n. 13
0
        public static void PublishHoverPlainTextResponse(this KernelInvocationContext context, RequestHoverText command, string content, LinePositionSpan linePositionSpan)
        {
            var response = new HoverPlainTextProduced(command, content, linePositionSpan);

            context.Publish(response);
        }
Esempio n. 14
0
 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));
Esempio n. 15
0
        private protected Diagnostic CreateDiagnostic(TextSpan span, LinePositionSpan lineSpan)
        {
            Location location = Location.Create(CreateFileName(), span, lineSpan);

            return(Diagnostic.Create(Descriptor, location));
        }
Esempio n. 16
0
        protected Diagnostic CreateDiagnostic(DiagnosticDescriptor descriptor, TextSpan span, LinePositionSpan lineSpan)
        {
            var location = Location.Create($"{DefaultFilePathPrefix}0.{FileExtension}", span, lineSpan);

            return(Diagnostic.Create(descriptor, location));
        }
Esempio n. 17
0
        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);
                }
            }
        }
Esempio n. 18
0
 /// <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}"));
        }
Esempio n. 21
0
 internal ActiveStatement WithSpan(LinePositionSpan span) =>
Esempio n. 22
0
 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]);
        }
Esempio n. 24
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]);
        }
Esempio n. 26
0
 internal ExternalFileLocation(string filePath, TextSpan sourceSpan, LinePositionSpan lineSpan)
 {
     _sourceSpan = sourceSpan;
     _lineSpan   = new FileLinePositionSpan(filePath, lineSpan);
 }
Esempio n. 27
0
        private protected Diagnostic CreateDiagnostic(string source, TextSpan span)
        {
            LinePositionSpan lineSpan = span.ToLinePositionSpan(source);

            return(CreateDiagnostic(span, lineSpan));
        }
Esempio n. 28
0
 public LineMapping(LinePositionSpan span, FileLinePositionSpan mappedSpan)
 {
     Span       = span;
     MappedSpan = mappedSpan;
 }
Esempio n. 29
0
 internal FileLinePositionSpan(string path, LinePositionSpan span, bool hasMappedPath)
 {
     _path          = path;
     _span          = span;
     _hasMappedPath = hasMappedPath;
 }
Esempio n. 30
0
 public void Deconstruct(out LinePositionSpan span, out FileLinePositionSpan mappedSpan)
 {
     span       = Span;
     mappedSpan = MappedSpan;
 }
Esempio n. 31
0
 public static LSP.Range LinePositionToRange(LinePositionSpan linePositionSpan)
 {
     return(new LSP.Range {
         Start = LinePositionToPosition(linePositionSpan.Start), End = LinePositionToPosition(linePositionSpan.End)
     });
 }
Esempio n. 32
0
        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);
        }
Esempio n. 33
0
 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);
        }
Esempio n. 35
0
        private protected Diagnostic CreateDiagnostic(TextSpan span, LinePositionSpan lineSpan)
        {
            Location location = Location.Create(WorkspaceFactory.DefaultDocumentName, span, lineSpan);

            return(Diagnostic.Create(Descriptor, location));
        }
Esempio n. 36
0
        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));
        }
Esempio n. 37
0
        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);
        }
Esempio n. 38
0
        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(
Esempio n. 40
0
        /// <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);
        }
Esempio n. 41
0
 internal virtual string FormatSourceSpan(LinePositionSpan span, IFormatProvider formatter)
 {
     return string.Format("({0},{1})", span.Start.Line + 1, span.Start.Character + 1);
 }
Esempio n. 42
0
 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]);
        }
Esempio n. 44
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;
 }
Esempio n. 46
0
        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();
        }
Esempio n. 48
0
        private static long CalculateOffset(long line, LinePositionSpan viewportSpan)
        {
            var firstLineInViewport = viewportSpan.Start.Line + 1;

            return(line - firstLineInViewport);
        }