protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            BlockSyntax node,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            var parentKind = node.Parent.Kind();

            // For most types of statements, just consider the block 'attached' to the
            // parent node.  That means we'll show the parent node header when doing
            // things like hovering over the indent guide.
            //
            // This also works nicely as the close brace for these constructs will always
            // align with the start of these statements.
            if (IsNonBlockStatement(node.Parent) ||
                parentKind == SyntaxKind.ElseClause)
            {
                var type = GetType(node.Parent);
                if (type != null)
                {
                    spans.Add(new BlockSpan(
                                  isCollapsible: true,
                                  textSpan: GetTextSpan(node),
                                  hintSpan: GetHintSpan(node),
                                  type: type,
                                  autoCollapse: parentKind == SyntaxKind.LocalFunctionStatement && node.Parent.IsParentKind(SyntaxKind.GlobalStatement)));
                }
            }

            // Nested blocks aren't attached to anything.  Just collapse them as is.
            // Switch sections are also special.  Say you have the following:
            //
            //      case 0:
            //          {
            //
            //          }
            //
            // We don't want to consider the block parented by the case, because
            // that would cause us to draw the following:
            //
            //      case 0:
            //      |   {
            //      |
            //      |   }
            //
            // Which would obviously be wonky.  So in this case, we just use the
            // spanof the block alone, without consideration for the case clause.
            if (parentKind is SyntaxKind.Block or SyntaxKind.SwitchSection)
            {
                var type = GetType(node.Parent);

                spans.Add(new BlockSpan(
                              isCollapsible: true,
                              textSpan: node.Span,
                              hintSpan: node.Span,
                              type: type));
            }
        }
예제 #2
0
        protected override void CollectBlockSpans(
            InitializerExpressionSyntax node,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptionProvider optionProvider,
            CancellationToken cancellationToken
            )
        {
            if (node.Parent is InitializerExpressionSyntax)
            {
                // We have something like:
                //
                //      new Dictionary<int, string>
                //      {
                //          ...
                //          {
                //              ...
                //          },
                //          ...
                //      }
                //
                //  In this case, we want to collapse the "{ ... }," (including the comma).

                var nextToken = node.CloseBraceToken.GetNextToken();
                var end       =
                    nextToken.Kind() == SyntaxKind.CommaToken ? nextToken.Span.End : node.Span.End;

                spans.Add(
                    new BlockSpan(
                        isCollapsible: true,
                        textSpan: TextSpan.FromBounds(node.SpanStart, end),
                        hintSpan: TextSpan.FromBounds(node.SpanStart, end),
                        type: BlockTypes.Expression
                        )
                    );
            }
            else
            {
                // Parent is something like:
                //
                //      new Dictionary<int, string> {
                //          ...
                //      }
                //
                // The collapsed textspan should be from the   >   to the   }
                //
                // However, the hint span should be the entire object creation.

                var previousToken = node.OpenBraceToken.GetPreviousToken();
                spans.Add(
                    new BlockSpan(
                        isCollapsible: true,
                        textSpan: TextSpan.FromBounds(previousToken.Span.End, node.Span.End),
                        hintSpan: node.Parent.Span,
                        type: BlockTypes.Expression
                        )
                    );
            }
        }
예제 #3
0
            private async Task UpdateReferencesAsync(Project project, CancellationToken cancellationToken)
            {
                // Process all metadata references. If it remote workspace, do this in parallel.
                using var pendingTasks = new TemporaryArray <Task>();

                foreach (var reference in project.MetadataReferences)
                {
                    if (reference is not PortableExecutableReference portableExecutableReference)
                    {
                        continue;
                    }

                    if (cancellationToken.IsCancellationRequested)
                    {
                        // Break out of this loop to make sure other pending operations process cancellation before
                        // returning.
                        break;
                    }

                    var updateTask = UpdateReferenceAsync(_metadataIdToInfo, project, portableExecutableReference, cancellationToken);
                    if (updateTask.Status != TaskStatus.RanToCompletion)
                    {
                        pendingTasks.Add(updateTask);
                    }
                }

                if (pendingTasks.Count > 0)
                {
                    // If any update operations did not complete synchronously (including any cancelled operations),
                    // wait for them to complete now.
                    await Task.WhenAll(pendingTasks.ToImmutableAndClear()).ConfigureAwait(false);
                }
        protected override void CollectBlockSpans(
            RegionDirectiveTriviaSyntax regionDirective,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptionProvider optionProvider,
            CancellationToken cancellationToken)
        {
            var match = regionDirective.GetMatchingDirective(cancellationToken);

            if (match != null)
            {
                // Always auto-collapse regions for Metadata As Source. These generated files only have one region at
                // the top of the file, which has content like the following:
                //
                //   #region Assembly System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
                //   // C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.dll
                //   #endregion
                //
                // For other files, auto-collapse regions based on the user option.
                var autoCollapse = optionProvider.IsMetadataAsSource || optionProvider.GetOption(
                    BlockStructureOptions.CollapseRegionsWhenCollapsingToDefinitions, LanguageNames.CSharp);

                spans.Add(new BlockSpan(
                              isCollapsible: true,
                              textSpan: TextSpan.FromBounds(regionDirective.SpanStart, match.Span.End),
                              type: BlockTypes.PreprocessorRegion,
                              bannerText: GetBannerText(regionDirective),
                              autoCollapse: autoCollapse,
                              isDefaultCollapsed: !optionProvider.IsMetadataAsSource));
            }
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            DocumentationCommentTriviaSyntax documentationComment,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptionProvider optionProvider,
            CancellationToken cancellationToken)
        {
            var startPos = documentationComment.FullSpan.Start;

            // The trailing newline is included in XmlDocCommentSyntax, so we need to strip it.
            var endPos = documentationComment.SpanStart + documentationComment.ToString().TrimEnd().Length;

            var span = TextSpan.FromBounds(startPos, endPos);

            var bannerLength = optionProvider.GetOption(BlockStructureOptions.MaximumBannerLength, LanguageNames.CSharp);
            var bannerText   = CSharpSyntaxFacts.Instance.GetBannerText(
                documentationComment, bannerLength, cancellationToken);

            spans.Add(new BlockSpan(
                          isCollapsible: true,
                          textSpan: span,
                          type: BlockTypes.Comment,
                          bannerText: bannerText,
                          autoCollapse: true));
        }
예제 #6
0
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            DocumentationCommentTriviaSyntax documentationComment,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            // In metadata as source we want to treat documentation comments slightly differently, and collapse them
            // to just "..." in front of the decalaration they're attached to. That happens in CSharpStructureHelper.CollectCommentBlockSpans
            // so we don't need to do anything here
            if (options.IsMetadataAsSource)
            {
                return;
            }

            var startPos = documentationComment.FullSpan.Start;

            // The trailing newline is included in XmlDocCommentSyntax, so we need to strip it.
            var endPos = documentationComment.SpanStart + documentationComment.ToString().TrimEnd().Length;

            var span = TextSpan.FromBounds(startPos, endPos);

            var bannerLength = options.MaximumBannerLength;
            var bannerText   = CSharpFileBannerFacts.Instance.GetBannerText(
                documentationComment, bannerLength, cancellationToken);

            spans.Add(new BlockSpan(
                          isCollapsible: true,
                          textSpan: span,
                          type: BlockTypes.Comment,
                          bannerText: bannerText,
                          autoCollapse: true));
        }
예제 #7
0
        public static void CollectBlockSpans(
            SyntaxTree syntaxTree,
            SyntaxTrivia trivia,
            ref TemporaryArray <BlockSpan> spans,
            CancellationToken cancellationToken
            )
        {
            // We'll always be leading trivia of some token.
            var startPos = trivia.FullSpan.Start;

            var parentTriviaList = trivia.Token.LeadingTrivia;
            var indexInParent    = parentTriviaList.IndexOf(trivia);

            // Note: in some error cases (for example when all future tokens end up being skipped)
            // the parser may end up attaching pre-processor directives as trailing trivia to a
            // preceding token.
            if (indexInParent < 0)
            {
                parentTriviaList = trivia.Token.TrailingTrivia;
                indexInParent    = parentTriviaList.IndexOf(trivia);
            }

            if (indexInParent <= 0)
            {
                return;
            }

            if (
                !parentTriviaList[indexInParent - 1].IsKind(SyntaxKind.IfDirectiveTrivia) &&
                !parentTriviaList[indexInParent - 1].IsKind(SyntaxKind.ElifDirectiveTrivia) &&
                !parentTriviaList[indexInParent - 1].IsKind(SyntaxKind.ElseDirectiveTrivia)
                )
            {
                return;
            }

            var endTrivia = GetCorrespondingEndTrivia(trivia, parentTriviaList, indexInParent);
            var endPos    = GetEndPositionExludingLastNewLine(
                syntaxTree,
                endTrivia,
                cancellationToken
                );

            var span = TextSpan.FromBounds(startPos, endPos);

            spans.Add(
                new BlockSpan(
                    isCollapsible: true,
                    textSpan: span,
                    type: BlockTypes.PreprocessorRegion,
                    bannerText: CSharpStructureHelpers.Ellipsis,
                    autoCollapse: true
                    )
                );
        }
예제 #8
0
 protected override void CollectBlockSpans(
     SyntaxToken previousToken,
     ArrowExpressionClauseSyntax node,
     ref TemporaryArray <BlockSpan> spans,
     BlockStructureOptionProvider optionProvider,
     CancellationToken cancellationToken)
 {
     spans.Add(new BlockSpan(
                   isCollapsible: true,
                   textSpan: TextSpan.FromBounds(previousToken.Span.End, node.Parent.Span.End),
                   hintSpan: node.Parent.Span,
                   type: BlockTypes.Nonstructural,
                   autoCollapse: !node.IsParentKind(SyntaxKind.LocalFunctionStatement)));
 }
예제 #9
0
        public static void AddParts(string text, bool word, ref TemporaryArray <TextSpan> parts)
        {
            for (var start = 0; start < text.Length;)
            {
                var span = StringBreaker.GenerateSpan(text, start, word);
                if (span.IsEmpty)
                {
                    // All done
                    break;
                }

                Debug.Assert(span.Start >= start, "Bad generator.");

                parts.Add(span);
                start = span.End;
            }
        }
예제 #10
0
 protected override void CollectBlockSpans(
     LiteralExpressionSyntax node,
     ref TemporaryArray <BlockSpan> spans,
     BlockStructureOptionProvider optionProvider,
     CancellationToken cancellationToken)
 {
     if (node.IsKind(SyntaxKind.StringLiteralExpression) &&
         !node.ContainsDiagnostics)
     {
         spans.Add(new BlockSpan(
                       isCollapsible: true,
                       textSpan: node.Span,
                       hintSpan: node.Span,
                       type: BlockTypes.Expression,
                       autoCollapse: true,
                       isDefaultCollapsed: false));
     }
 }
        protected override void CollectBlockSpans(
            InterpolatedStringExpressionSyntax node,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptionProvider optionProvider,
            CancellationToken cancellationToken)
        {
            if (node.StringStartToken.IsMissing ||
                node.StringEndToken.IsMissing)
            {
                return;
            }

            spans.Add(new BlockSpan(
                          isCollapsible: true,
                          textSpan: node.Span,
                          hintSpan: node.Span,
                          type: BlockTypes.Expression,
                          autoCollapse: true,
                          isDefaultCollapsed: false));
        }