protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            AccessorDeclarationSyntax accessorDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            CSharpStructureHelpers.CollectCommentBlockSpans(accessorDeclaration, ref spans, options);

            // fault tolerance
            if (accessorDeclaration.Body == null ||
                accessorDeclaration.Body.OpenBraceToken.IsMissing ||
                accessorDeclaration.Body.CloseBraceToken.IsMissing)
            {
                return;
            }

            SyntaxNodeOrToken current = accessorDeclaration;
            var nextSibling           = current.GetNextSibling();

            // Check IsNode to compress blank lines after this node if it is the last child of the parent.
            //
            // All accessor kinds are grouped together in Metadata as Source.
            var compressEmptyLines = options.IsMetadataAsSource &&
                                     (!nextSibling.IsNode || nextSibling.AsNode() is AccessorDeclarationSyntax);

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   accessorDeclaration,
                                   accessorDeclaration.Keyword,
                                   compressEmptyLines: compressEmptyLines,
                                   autoCollapse: true,
                                   type: BlockTypes.Member,
                                   isCollapsible: true));
        }
Example #2
0
        internal sealed override async Task <ImmutableArray <BlockSpan> > GetBlockSpansWorkerAsync(Document document, int position)
        {
            var root = await document.GetSyntaxRootAsync(CancellationToken.None);

            var token = root.FindToken(position, findInsideTrivia: true);
            var node  = token.Parent.FirstAncestorOrSelf <TSyntaxNode>();

            Assert.NotNull(node);

            // We prefer ancestor nodes if the position is on the edge of the located node's span.
            while (node.Parent is TSyntaxNode)
            {
                if ((position == node.SpanStart && position == node.Parent.SpanStart) ||
                    (position == node.Span.End && position == node.Parent.Span.End))
                {
                    node = (TSyntaxNode)node.Parent;
                }
                else
                {
                    break;
                }
            }

            var outliner = CreateProvider();

            using var actualRegions = TemporaryArray <BlockSpan> .Empty;
            var options = BlockStructureOptions.From(document.Project);
            // Calculate previousToken for tests the same way it is derived in production code
            var previousToken = root.DescendantNodesAndTokens(descendIntoTrivia: true).TakeWhile(nodeOrToken => nodeOrToken != node).LastOrDefault(nodeOrToken => nodeOrToken.IsToken).AsToken();

            outliner.CollectBlockSpans(previousToken, node, ref actualRegions.AsRef(), options, CancellationToken.None);

            // TODO: Determine why we get null outlining spans.
            return(actualRegions.ToImmutableAndClear());
        }
Example #3
0
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            DocumentationCommentTriviaSyntax documentationComment,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            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 = 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));
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            EventDeclarationSyntax eventDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            CSharpStructureHelpers.CollectCommentBlockSpans(eventDeclaration, ref spans, options);

            // fault tolerance
            if (eventDeclaration.AccessorList == null ||
                eventDeclaration.AccessorList.IsMissing ||
                eventDeclaration.AccessorList.OpenBraceToken.IsMissing ||
                eventDeclaration.AccessorList.CloseBraceToken.IsMissing)
            {
                return;
            }

            SyntaxNodeOrToken current = eventDeclaration;
            var nextSibling           = current.GetNextSibling();

            // Check IsNode to compress blank lines after this node if it is the last child of the parent.
            //
            // Full events are grouped together with event field definitions in Metadata as Source.
            var compressEmptyLines = options.IsMetadataAsSource &&
                                     (!nextSibling.IsNode || nextSibling.IsKind(SyntaxKind.EventDeclaration) || nextSibling.IsKind(SyntaxKind.EventFieldDeclaration));

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   eventDeclaration,
                                   eventDeclaration.Identifier,
                                   compressEmptyLines: compressEmptyLines,
                                   autoCollapse: true,
                                   type: BlockTypes.Member,
                                   isCollapsible: true));
        }
Example #5
0
        public override async Task <FoldingRange[]?> HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

            if (document == null)
            {
                return(null);
            }

            var blockStructureService = document.Project.LanguageServices.GetService <BlockStructureService>();

            if (blockStructureService == null)
            {
                return(Array.Empty <FoldingRange>());
            }

            var options        = BlockStructureOptions.From(document.Project);
            var blockStructure = await blockStructureService.GetBlockStructureAsync(document, options, cancellationToken).ConfigureAwait(false);

            if (blockStructure == null)
            {
                return(Array.Empty <FoldingRange>());
            }

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            return(GetFoldingRanges(blockStructure, text));
        }
Example #6
0
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            AnonymousMethodExpressionSyntax anonymousMethod,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            // fault tolerance
            if (anonymousMethod.Block.IsMissing ||
                anonymousMethod.Block.OpenBraceToken.IsMissing ||
                anonymousMethod.Block.CloseBraceToken.IsMissing)
            {
                return;
            }

            var lastToken = CSharpStructureHelpers.GetLastInlineMethodBlockToken(anonymousMethod);

            if (lastToken.Kind() == SyntaxKind.None)
            {
                return;
            }

            var startToken = anonymousMethod.ParameterList != null
                ? anonymousMethod.ParameterList.GetLastToken(includeZeroWidth : true)
                : anonymousMethod.DelegateKeyword;

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   anonymousMethod,
                                   startToken,
                                   lastToken,
                                   compressEmptyLines: false,
                                   autoCollapse: false,
                                   type: BlockTypes.Expression,
                                   isCollapsible: true));
        }
Example #7
0
        internal override async Task <ImmutableArray <BlockSpan> > GetBlockSpansWorkerAsync(Document document, int position)
        {
            var outliningService = document.GetLanguageService <BlockStructureService>();
            var options          = BlockStructureOptions.From(document.Project);

            return((await outliningService.GetBlockStructureAsync(document, options, CancellationToken.None)).Spans);
        }
Example #8
0
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            OperatorDeclarationSyntax operatorDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            CSharpStructureHelpers.CollectCommentBlockSpans(operatorDeclaration, ref spans, options);

            // fault tolerance
            if (operatorDeclaration.Body == null ||
                operatorDeclaration.Body.OpenBraceToken.IsMissing ||
                operatorDeclaration.Body.CloseBraceToken.IsMissing)
            {
                return;
            }

            SyntaxNodeOrToken current = operatorDeclaration;
            var nextSibling           = current.GetNextSibling();

            // Check IsNode to compress blank lines after this node if it is the last child of the parent.
            //
            // Whitespace between operators is collapsed in Metadata as Source.
            var compressEmptyLines = options.IsMetadataAsSource &&
                                     (!nextSibling.IsNode || nextSibling.IsKind(SyntaxKind.OperatorDeclaration));

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   operatorDeclaration,
                                   operatorDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
                                   compressEmptyLines: compressEmptyLines,
                                   autoCollapse: true,
                                   type: BlockTypes.Member,
                                   isCollapsible: true));
        }
Example #9
0
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            DestructorDeclarationSyntax destructorDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            CSharpStructureHelpers.CollectCommentBlockSpans(destructorDeclaration, ref spans, options);

            // fault tolerance
            if (destructorDeclaration.Body == null ||
                destructorDeclaration.Body.OpenBraceToken.IsMissing ||
                destructorDeclaration.Body.CloseBraceToken.IsMissing)
            {
                return;
            }

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   destructorDeclaration,
                                   destructorDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
                                   compressEmptyLines: false,
                                   autoCollapse: true,
                                   type: BlockTypes.Member,
                                   isCollapsible: true));
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            CompilationUnitSyntax compilationUnit,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            CSharpStructureHelpers.CollectCommentBlockSpans(compilationUnit, ref spans, options);

            // extern aliases and usings are outlined in a single region
            var externsAndUsings = new List <SyntaxNode>();

            externsAndUsings.AddRange(compilationUnit.Externs);
            externsAndUsings.AddRange(compilationUnit.Usings);
            externsAndUsings.Sort((node1, node2) => node1.SpanStart.CompareTo(node2.SpanStart));

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   externsAndUsings, compressEmptyLines: false, autoCollapse: true,
                                   type: BlockTypes.Imports, isCollapsible: true));

            if (compilationUnit.Usings.Count > 0 ||
                compilationUnit.Externs.Count > 0 ||
                compilationUnit.Members.Count > 0 ||
                compilationUnit.AttributeLists.Count > 0)
            {
                CSharpStructureHelpers.CollectCommentBlockSpans(compilationUnit.EndOfFileToken.LeadingTrivia, ref spans);
            }
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            RegionDirectiveTriviaSyntax regionDirective,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            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 = options.IsMetadataAsSource || options.CollapseRegionsWhenCollapsingToDefinitions;

                spans.Add(new BlockSpan(
                              isCollapsible: true,
                              textSpan: TextSpan.FromBounds(regionDirective.SpanStart, match.Span.End),
                              type: BlockTypes.PreprocessorRegion,
                              bannerText: GetBannerText(regionDirective),
                              autoCollapse: autoCollapse,
                              isDefaultCollapsed: !options.IsMetadataAsSource));
            }
        }
Example #12
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));
        }
        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));
            }
        }
 public override void CollectBlockSpans(
     SyntaxTrivia trivia,
     ref TemporaryArray <BlockSpan> spans,
     BlockStructureOptions options,
     CancellationToken cancellationToken)
 {
     CollectBlockSpans(trivia.SyntaxTree, trivia, ref spans, cancellationToken);
 }
 protected override void CollectBlockSpans(
     SyntaxToken previousToken,
     EventFieldDeclarationSyntax eventFieldDeclaration,
     ref TemporaryArray <BlockSpan> spans,
     BlockStructureOptions options,
     CancellationToken cancellationToken)
 {
     CSharpStructureHelpers.CollectCommentBlockSpans(eventFieldDeclaration, ref spans, options);
 }
Example #16
0
        private static async Task <ImmutableArray <BlockSpan> > GetSpansFromWorkspaceAsync(
            TestWorkspace workspace)
        {
            var hostDocument     = workspace.Documents.First();
            var document         = workspace.CurrentSolution.GetDocument(hostDocument.Id);
            var outliningService = document.GetLanguageService <BlockStructureService>();
            var options          = BlockStructureOptions.From(document.Project);

            var structure = await outliningService.GetBlockStructureAsync(document, options, CancellationToken.None);

            return(structure.Spans);
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            InitializerExpressionSyntax node,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            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.

                spans.Add(new BlockSpan(
                              isCollapsible: true,
                              textSpan: TextSpan.FromBounds(previousToken.Span.End, node.Span.End),
                              hintSpan: node.Parent.Span,
                              type: BlockTypes.Expression));
            }
        }
 protected override void CollectBlockSpans(
     SyntaxToken previousToken,
     SwitchStatementSyntax node,
     ref TemporaryArray <BlockSpan> spans,
     BlockStructureOptions options,
     CancellationToken cancellationToken)
 {
     spans.Add(new BlockSpan(
                   isCollapsible: true,
                   textSpan: TextSpan.FromBounds((node.CloseParenToken != default) ? node.CloseParenToken.Span.End : node.Expression.Span.End, node.CloseBraceToken.Span.End),
                   hintSpan: node.Span,
                   type: BlockTypes.Conditional));
 }
 protected override void CollectBlockSpans(
     SyntaxToken previousToken,
     ArrowExpressionClauseSyntax node,
     ref TemporaryArray <BlockSpan> spans,
     BlockStructureOptions options,
     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)));
 }
        internal sealed override async Task <ImmutableArray <BlockSpan> > GetBlockSpansWorkerAsync(Document document, int position)
        {
            var root = await document.GetSyntaxRootAsync();

            var trivia = root.FindTrivia(position, findInsideTrivia: true);

            var outliner = CreateProvider();

            using var actualRegions = TemporaryArray <BlockSpan> .Empty;
            var options = BlockStructureOptions.From(document.Project);

            outliner.CollectBlockSpans(trivia, ref actualRegions.AsRef(), options, CancellationToken.None);

            // TODO: Determine why we get null outlining spans.
            return(actualRegions.ToImmutableAndClear());
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            NamespaceDeclarationSyntax namespaceDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            // add leading comments
            CSharpStructureHelpers.CollectCommentBlockSpans(namespaceDeclaration, ref spans, options);

            if (!namespaceDeclaration.OpenBraceToken.IsMissing &&
                !namespaceDeclaration.CloseBraceToken.IsMissing)
            {
                spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                       namespaceDeclaration,
                                       namespaceDeclaration.Name.GetLastToken(includeZeroWidth: true),
                                       compressEmptyLines: false,
                                       autoCollapse: false,
                                       type: BlockTypes.Namespace,
                                       isCollapsible: true));
            }

            // extern aliases and usings are outlined in a single region
            var externsAndUsings = Enumerable.Union <SyntaxNode>(namespaceDeclaration.Externs, namespaceDeclaration.Usings)
                                   .OrderBy(node => node.SpanStart)
                                   .ToList();

            // add any leading comments before the extern aliases and usings
            if (externsAndUsings.Count > 0)
            {
                CSharpStructureHelpers.CollectCommentBlockSpans(externsAndUsings.First(), ref spans, options);
            }

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   externsAndUsings, compressEmptyLines: false, autoCollapse: true,
                                   type: BlockTypes.Imports, isCollapsible: true));

            // finally, add any leading comments before the end of the namespace block
            if (!namespaceDeclaration.CloseBraceToken.IsMissing)
            {
                CSharpStructureHelpers.CollectCommentBlockSpans(
                    namespaceDeclaration.CloseBraceToken.LeadingTrivia, ref spans);
            }
        }
Example #22
0
 protected override void CollectBlockSpans(
     SyntaxToken previousToken,
     LiteralExpressionSyntax node,
     ref TemporaryArray <BlockSpan> spans,
     BlockStructureOptions options,
     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(
            SyntaxToken previousToken,
            TypeDeclarationSyntax typeDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            CSharpStructureHelpers.CollectCommentBlockSpans(typeDeclaration, ref spans, options);

            if (!typeDeclaration.OpenBraceToken.IsMissing &&
                !typeDeclaration.CloseBraceToken.IsMissing)
            {
                var lastToken = typeDeclaration.TypeParameterList == null
                    ? typeDeclaration.Identifier
                    : typeDeclaration.TypeParameterList.GetLastToken(includeZeroWidth: true);

                SyntaxNodeOrToken current = typeDeclaration;
                var nextSibling           = current.GetNextSibling();

                // Check IsNode to compress blank lines after this node if it is the last child of the parent.
                //
                // Collapse to Definitions doesn't collapse type nodes, but a Toggle All Outlining would collapse groups
                // of types to the compressed form of not showing blank lines. All kinds of types are grouped together
                // in Metadata as Source.
                var compressEmptyLines = options.IsMetadataAsSource &&
                                         (!nextSibling.IsNode || nextSibling.AsNode() is BaseTypeDeclarationSyntax);

                spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                       typeDeclaration,
                                       lastToken,
                                       compressEmptyLines: compressEmptyLines,
                                       autoCollapse: false,
                                       type: BlockTypes.Type,
                                       isCollapsible: true));
            }

            // add any leading comments before the end of the type block
            if (!typeDeclaration.CloseBraceToken.IsMissing)
            {
                var leadingTrivia = typeDeclaration.CloseBraceToken.LeadingTrivia;
                CSharpStructureHelpers.CollectCommentBlockSpans(leadingTrivia, ref spans);
            }
        }
Example #24
0
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            InterpolatedStringExpressionSyntax node,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            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));
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            // add leading comments
            CSharpStructureHelpers.CollectCommentBlockSpans(fileScopedNamespaceDeclaration, ref spans, options);

            // extern aliases and usings are outlined in a single region
            var externsAndUsings = Enumerable.Union <SyntaxNode>(fileScopedNamespaceDeclaration.Externs, fileScopedNamespaceDeclaration.Usings).ToImmutableArray();

            // add any leading comments before the extern aliases and usings
            if (externsAndUsings.Any())
            {
                CSharpStructureHelpers.CollectCommentBlockSpans(externsAndUsings.First(), ref spans, options);
            }

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   externsAndUsings, compressEmptyLines: false, autoCollapse: true,
                                   type: BlockTypes.Imports, isCollapsible: true, isDefaultCollapsed: options.CollapseImportsWhenFirstOpened));
        }
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            EnumDeclarationSyntax enumDeclaration,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            CSharpStructureHelpers.CollectCommentBlockSpans(enumDeclaration, ref spans, options);

            if (!enumDeclaration.OpenBraceToken.IsMissing &&
                !enumDeclaration.CloseBraceToken.IsMissing)
            {
                SyntaxNodeOrToken current = enumDeclaration;
                var nextSibling           = current.GetNextSibling();

                // Check IsNode to compress blank lines after this node if it is the last child of the parent.
                //
                // Whitespace between type declarations is collapsed in Metadata as Source.
                var compressEmptyLines = options.IsMetadataAsSource &&
                                         (!nextSibling.IsNode || nextSibling.AsNode() is BaseTypeDeclarationSyntax);

                spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                       enumDeclaration,
                                       enumDeclaration.Identifier,
                                       compressEmptyLines: compressEmptyLines,
                                       autoCollapse: false,
                                       type: BlockTypes.Member,
                                       isCollapsible: true));
            }

            // add any leading comments before the end of the type block
            if (!enumDeclaration.CloseBraceToken.IsMissing)
            {
                var leadingTrivia = enumDeclaration.CloseBraceToken.LeadingTrivia;
                CSharpStructureHelpers.CollectCommentBlockSpans(leadingTrivia, ref spans);
            }
        }
Example #27
0
        protected override void CollectBlockSpans(
            SyntaxToken previousToken,
            SimpleLambdaExpressionSyntax lambdaExpression,
            ref TemporaryArray <BlockSpan> spans,
            BlockStructureOptions options,
            CancellationToken cancellationToken)
        {
            // fault tolerance
            if (lambdaExpression.Body.IsMissing)
            {
                return;
            }

            if (lambdaExpression.Body is not BlockSyntax lambdaBlock ||
                lambdaBlock.OpenBraceToken.IsMissing ||
                lambdaBlock.CloseBraceToken.IsMissing)
            {
                return;
            }

            var lastToken = CSharpStructureHelpers.GetLastInlineMethodBlockToken(lambdaExpression);

            if (lastToken.Kind() == SyntaxKind.None)
            {
                return;
            }

            spans.AddIfNotNull(CSharpStructureHelpers.CreateBlockSpan(
                                   lambdaExpression,
                                   lambdaExpression.ArrowToken,
                                   lastToken,
                                   compressEmptyLines: false,
                                   autoCollapse: false,
                                   type: BlockTypes.Expression,
                                   isCollapsible: true));
        }
        internal override async Task <ImmutableArray <BlockSpan> > GetBlockSpansWorkerAsync(Document document, BlockStructureOptions options, int position)
        {
            var root = await document.GetSyntaxRootAsync();

            var trivia = root.FindTrivia(position, findInsideTrivia: true);

            var token = trivia.Token;

            if (token.LeadingTrivia.Contains(trivia))
            {
                return(CSharpStructureHelpers.CreateCommentBlockSpan(token.LeadingTrivia));
            }
            else if (token.TrailingTrivia.Contains(trivia))
            {
                return(CSharpStructureHelpers.CreateCommentBlockSpan(token.TrailingTrivia));
            }

            throw Roslyn.Utilities.ExceptionUtilities.Unreachable;
        }
Example #29
0
        public override async Task <BlockStructure> GetBlockStructureAsync(Document document, BlockStructureOptions options, CancellationToken cancellationToken)
        {
            var blockStructure = await _service.GetBlockStructureAsync(document, cancellationToken).ConfigureAwait(false);

            if (blockStructure != null)
            {
                return(new BlockStructure(blockStructure.Spans.SelectAsArray(x => new BlockSpan(x.Type, x.IsCollapsible, x.TextSpan, x.HintSpan, x.BannerText, x.AutoCollapse, x.IsDefaultCollapsed))));
            }
            else
            {
                return(null);
            }
        }