提交 e4e1e202 编写于 作者: C CyrusNajmabadi

Implement indent guides for the current set of nodes we have outlining for in C# and VB.

上级 3b4e5f9d
......@@ -24,11 +24,11 @@ internal override async Task<BlockSpan[]> GetBlockSpansAsync(Document document,
if (token.LeadingTrivia.Contains(trivia))
{
return CSharpStructureHelpers.CreateCommentRegions(token.LeadingTrivia).ToArray();
return CSharpStructureHelpers.CreateCommentBlockSpan(token.LeadingTrivia).ToArray();
}
else if (token.TrailingTrivia.Contains(trivia))
{
return CSharpStructureHelpers.CreateCommentRegions(token.TrailingTrivia).ToArray();
return CSharpStructureHelpers.CreateCommentBlockSpan(token.TrailingTrivia).ToArray();
}
else
{
......
......@@ -568,7 +568,7 @@
<Compile Include="Implementation\Organizing\OrganizeDocumentCommandHandler.cs" />
<Compile Include="Implementation\Structure\OutliningCommandHandler.cs" />
<Compile Include="Implementation\Structure\VisualStudio14StructureTaggerProvider.cs" />
<Compile Include="Implementation\Structure\AbstractStructureTaggerProvider.RegionTag.cs" />
<Compile Include="Implementation\Structure\RoslynOutliningRegionTag.cs" />
<Compile Include="Implementation\Peek\DefinitionPeekableItem.cs" />
<Compile Include="Implementation\Peek\ExternalFilePeekableItem.cs" />
<Compile Include="Implementation\Peek\PeekableItem.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Windows.Media;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Structure;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Projection;
using Microsoft.VisualStudio.Text.Tagging;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Structure
{
internal abstract partial class AbstractStructureTaggerProvider<TRegionTag>
{
// Our implementation of an outlining region tag. The collapsedHintForm
// is dynamically created using an elision buffer over the actual text
// we are collapsing.
protected class RegionTag : IOutliningRegionTag
{
private const string Ellipsis = "...";
private const int MaxPreviewText = 1000;
private readonly AbstractStructureTaggerProvider<TRegionTag> _provider;
private readonly ITextBuffer _subjectBuffer;
private readonly ITrackingSpan _hintSpan;
public bool IsDefaultCollapsed => BlockSpan.IsDefaultCollapsed;
public bool IsImplementation => BlockSpan.AutoCollapse;
public object CollapsedForm => BlockSpan.BannerText;
protected readonly BlockSpan BlockSpan;
public RegionTag(
AbstractStructureTaggerProvider<TRegionTag> provider,
ITextSnapshot snapshot,
BlockSpan outliningSpan)
{
_provider = provider;
_subjectBuffer = snapshot.TextBuffer;
BlockSpan = outliningSpan;
_hintSpan = snapshot.CreateTrackingSpan(BlockSpan.HintSpan.ToSpan(), SpanTrackingMode.EdgeExclusive);
}
public object CollapsedHintForm =>
new ViewHostingControl(CreateElisionBufferView, CreateElisionBuffer);
private IWpfTextView CreateElisionBufferView(ITextBuffer finalBuffer)
{
var roles = _provider.TextEditorFactoryService.CreateTextViewRoleSet(OutliningRegionTextViewRole);
var view = _provider.TextEditorFactoryService.CreateTextView(finalBuffer, roles);
view.Background = Brushes.Transparent;
view.SizeToFit();
// Zoom out a bit to shrink the text.
view.ZoomLevel *= 0.75;
return view;
}
private ITextBuffer CreateElisionBuffer()
{
// Remove any starting whitespace.
var span = TrimStartingNewlines(_hintSpan.GetSpan(_subjectBuffer.CurrentSnapshot));
// Trim the length if it's too long.
var shortSpan = span;
if (span.Length > MaxPreviewText)
{
shortSpan = ComputeShortSpan(span);
}
// Create an elision buffer for that span, also trimming the
// leading whitespace.
var elisionBuffer = CreateElisionBufferWithoutIndentation(_subjectBuffer, shortSpan);
var finalBuffer = elisionBuffer;
// If we trimmed the length, then make a projection buffer that
// has the above elision buffer and follows it with "..."
if (span.Length != shortSpan.Length)
{
finalBuffer = CreateTrimmedProjectionBuffer(elisionBuffer);
}
return finalBuffer;
}
private ITextBuffer CreateTrimmedProjectionBuffer(ITextBuffer elisionBuffer)
{
// The elision buffer is too long. We've already trimmed it, but now we want to add
// a "..." to it. We do that by creating a projection of both the elision buffer and
// a new text buffer wrapping the ellipsis.
var elisionSpan = elisionBuffer.CurrentSnapshot.GetFullSpan();
var sourceSpans = new List<object>()
{
elisionSpan.Snapshot.CreateTrackingSpan(elisionSpan, SpanTrackingMode.EdgeExclusive),
Ellipsis
};
var projectionBuffer = _provider.ProjectionBufferFactoryService.CreateProjectionBuffer(
projectionEditResolver: null,
sourceSpans: sourceSpans,
options: ProjectionBufferOptions.None);
return projectionBuffer;
}
private Span ComputeShortSpan(Span span)
{
var endIndex = span.Start + MaxPreviewText;
var line = _subjectBuffer.CurrentSnapshot.GetLineFromPosition(endIndex);
return Span.FromBounds(span.Start, line.EndIncludingLineBreak);
}
private Span TrimStartingNewlines(Span span)
{
while (span.Length > 1 && char.IsWhiteSpace(_subjectBuffer.CurrentSnapshot[span.Start]))
{
span = new Span(span.Start + 1, span.Length - 1);
}
return span;
}
private ITextBuffer CreateElisionBufferWithoutIndentation(
ITextBuffer dataBuffer, Span shortHintSpan)
{
return _provider.ProjectionBufferFactoryService.CreateElisionBufferWithoutIndentation(
_provider.EditorOptionsFactoryService.GlobalOptions,
contentType: null,
exposedSpans: new SnapshotSpan(dataBuffer.CurrentSnapshot, shortHintSpan));
}
}
}
}
\ No newline at end of file
......@@ -34,8 +34,6 @@ internal abstract partial class AbstractStructureTaggerProvider<TRegionTag> :
IEqualityComparer<TRegionTag>
where TRegionTag : class, ITag
{
public const string OutliningRegionTextViewRole = nameof(OutliningRegionTextViewRole);
private static IComparer<BlockSpan> s_blockSpanComparer =
Comparer<BlockSpan>.Create((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Windows.Media;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Structure;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Projection;
using Microsoft.VisualStudio.Text.Tagging;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Structure
{
// Our implementation of an outlining region tag. The collapsedHintForm
// is dynamically created using an elision buffer over the actual text
// we are collapsing.
internal class RoslynOutliningRegionTag : IOutliningRegionTag
{
private const string OutliningRegionTextViewRole = nameof(OutliningRegionTextViewRole);
private const string Ellipsis = "...";
private const int MaxPreviewText = 1000;
private readonly ITextEditorFactoryService _textEditorFactoryService;
private readonly IProjectionBufferFactoryService _projectionBufferFactoryService;
private readonly IEditorOptionsFactoryService _editorOptionsFactoryService;
private readonly ITextBuffer _subjectBuffer;
private readonly ITrackingSpan _hintSpan;
public bool IsDefaultCollapsed => BlockSpan.IsDefaultCollapsed;
public bool IsImplementation => BlockSpan.AutoCollapse;
public object CollapsedForm => BlockSpan.BannerText;
protected readonly BlockSpan BlockSpan;
public RoslynOutliningRegionTag(
ITextEditorFactoryService textEditorFactoryService,
IProjectionBufferFactoryService projectionBufferFactoryService,
IEditorOptionsFactoryService editorOptionsFactoryService,
ITextSnapshot snapshot,
BlockSpan outliningSpan)
{
_textEditorFactoryService = textEditorFactoryService;
_projectionBufferFactoryService = projectionBufferFactoryService;
_editorOptionsFactoryService = editorOptionsFactoryService;
_subjectBuffer = snapshot.TextBuffer;
BlockSpan = outliningSpan;
_hintSpan = snapshot.CreateTrackingSpan(BlockSpan.HintSpan.ToSpan(), SpanTrackingMode.EdgeExclusive);
}
public object CollapsedHintForm =>
new ViewHostingControl(CreateElisionBufferView, CreateElisionBuffer);
private IWpfTextView CreateElisionBufferView(ITextBuffer finalBuffer)
{
var roles = _textEditorFactoryService.CreateTextViewRoleSet(OutliningRegionTextViewRole);
var view = _textEditorFactoryService.CreateTextView(finalBuffer, roles);
view.Background = Brushes.Transparent;
view.SizeToFit();
// Zoom out a bit to shrink the text.
view.ZoomLevel *= 0.75;
return view;
}
private ITextBuffer CreateElisionBuffer()
{
// Remove any starting whitespace.
var span = TrimStartingNewlines(_hintSpan.GetSpan(_subjectBuffer.CurrentSnapshot));
// Trim the length if it's too long.
var shortSpan = span;
if (span.Length > MaxPreviewText)
{
shortSpan = ComputeShortSpan(span);
}
// Create an elision buffer for that span, also trimming the
// leading whitespace.
var elisionBuffer = CreateElisionBufferWithoutIndentation(_subjectBuffer, shortSpan);
var finalBuffer = elisionBuffer;
// If we trimmed the length, then make a projection buffer that
// has the above elision buffer and follows it with "..."
if (span.Length != shortSpan.Length)
{
finalBuffer = CreateTrimmedProjectionBuffer(elisionBuffer);
}
return finalBuffer;
}
private ITextBuffer CreateTrimmedProjectionBuffer(ITextBuffer elisionBuffer)
{
// The elision buffer is too long. We've already trimmed it, but now we want to add
// a "..." to it. We do that by creating a projection of both the elision buffer and
// a new text buffer wrapping the ellipsis.
var elisionSpan = elisionBuffer.CurrentSnapshot.GetFullSpan();
var sourceSpans = new List<object>()
{
elisionSpan.Snapshot.CreateTrackingSpan(elisionSpan, SpanTrackingMode.EdgeExclusive),
Ellipsis
};
var projectionBuffer = _projectionBufferFactoryService.CreateProjectionBuffer(
projectionEditResolver: null,
sourceSpans: sourceSpans,
options: ProjectionBufferOptions.None);
return projectionBuffer;
}
private Span ComputeShortSpan(Span span)
{
var endIndex = span.Start + MaxPreviewText;
var line = _subjectBuffer.CurrentSnapshot.GetLineFromPosition(endIndex);
return Span.FromBounds(span.Start, line.EndIncludingLineBreak);
}
private Span TrimStartingNewlines(Span span)
{
while (span.Length > 1 && char.IsWhiteSpace(_subjectBuffer.CurrentSnapshot[span.Start]))
{
span = new Span(span.Start + 1, span.Length - 1);
}
return span;
}
private ITextBuffer CreateElisionBufferWithoutIndentation(
ITextBuffer dataBuffer, Span shortHintSpan)
{
return _projectionBufferFactoryService.CreateElisionBufferWithoutIndentation(
_editorOptionsFactoryService.GlobalOptions,
contentType: null,
exposedSpans: new SnapshotSpan(dataBuffer.CurrentSnapshot, shortHintSpan));
}
}
}
\ No newline at end of file
......@@ -55,7 +55,11 @@ public override int GetHashCode(IOutliningRegionTag obj)
protected override IOutliningRegionTag CreateTag(
IOutliningRegionTag parentTag, ITextSnapshot snapshot, BlockSpan region)
{
return new RegionTag(this, snapshot, region);
return new RoslynOutliningRegionTag(
this.TextEditorFactoryService,
this.ProjectionBufferFactoryService,
this.EditorOptionsFactoryService,
snapshot, region);
}
}
}
\ No newline at end of file
......@@ -71,6 +71,7 @@
<Compile Include="IntelliSense\Completion\Presentation\VisualStudio15CompletionSetFactory.cs" />
<Compile Include="IntelliSense\Completion\Presentation\VisualStudio15CompletionSet.cs" />
<Compile Include="NavigateTo\Dev15NavigateToOptionsService.cs" />
<Compile Include="Structure\BlockContextProvider.cs" />
<Compile Include="Structure\VisualStudio15StructureTaggerProvider.cs" />
</ItemGroup>
<ItemGroup />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.ComponentModel.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Implementation.Structure;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Adornments;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Structure
{
[Name(nameof(RoslynBlockContextProvider)), Order]
[Export(typeof(IBlockContextProvider))]
[ContentType(ContentTypeNames.RoslynContentType)]
internal class RoslynBlockContextProvider : ForegroundThreadAffinitizedObject, IBlockContextProvider
{
public Task<IBlockContextSource> TryCreateBlockContextSourceAsync(
ITextBuffer textBuffer, CancellationToken token)
{
this.AssertIsForeground();
var result = textBuffer.Properties.GetOrCreateSingletonProperty(
() => new BlockContextSource());
return Task.FromResult<IBlockContextSource>(result);
}
private class BlockContextSource : IBlockContextSource
{
public void Dispose()
{
}
public Task<IBlockContext> GetBlockContextAsync(
IBlockTag blockTag, ITextView view, CancellationToken token)
{
if (blockTag is RoslynOutliningRegionTag)
{
var result = new RoslynBlockContext(blockTag, view);
return Task.FromResult<IBlockContext>(result);
}
return SpecializedTasks.Default<IBlockContext>();
}
}
private class RoslynBlockContext : ForegroundThreadAffinitizedObject, IBlockContext
{
public IBlockTag BlockTag { get; }
public ITextView TextView { get; }
public RoslynBlockContext(IBlockTag blockTag, ITextView textView)
{
BlockTag = blockTag;
TextView = textView;
}
public object Content
{
get
{
this.AssertIsForeground();
return BlockTag.CollapsedHintForm;
}
}
}
}
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.Editor.Structure
[Export(typeof(VisualStudio15StructureTaggerProvider))]
[TagType(typeof(IBlockTag))]
[ContentType(ContentTypeNames.RoslynContentType)]
internal partial class VisualStudio15StructureTaggerProvider :
internal partial class VisualStudio15StructureTaggerProvider :
AbstractStructureTaggerProvider<IBlockTag>
{
[ImportingConstructor]
......@@ -49,31 +49,90 @@ public override int GetHashCode(IBlockTag obj)
protected override IBlockTag CreateTag(
IBlockTag parentTag, ITextSnapshot snapshot, BlockSpan region)
{
return new RoslynRegionTag(this, parentTag, snapshot, region);
return new RoslynBlockTag(
this.TextEditorFactoryService,
this.ProjectionBufferFactoryService,
this.EditorOptionsFactoryService,
parentTag, snapshot, region);
}
private class RoslynRegionTag : RegionTag, IBlockTag
private class RoslynBlockTag : RoslynOutliningRegionTag, IBlockTag
{
public IBlockTag Parent { get; }
public int Level { get; }
public SnapshotSpan Span { get; }
public SnapshotSpan StatementSpan { get; }
public string Type => BlockSpan.Type;
public string Type => ConvertType(BlockSpan.Type);
public bool IsCollapsible => true;
public RoslynRegionTag(
AbstractStructureTaggerProvider<IBlockTag> provider,
public RoslynBlockTag(
ITextEditorFactoryService textEditorFactoryService,
IProjectionBufferFactoryService projectionBufferFactoryService,
IEditorOptionsFactoryService editorOptionsFactoryService,
IBlockTag parent,
ITextSnapshot snapshot,
BlockSpan outliningSpan) :
base(provider, snapshot, outliningSpan)
BlockSpan outliningSpan) :
base(textEditorFactoryService,
projectionBufferFactoryService,
editorOptionsFactoryService,
snapshot, outliningSpan)
{
Parent = parent;
Level = parent == null ? 0 : parent.Level + 1;
Span = outliningSpan.TextSpan.ToSnapshotSpan(snapshot);
StatementSpan = outliningSpan.HintSpan.ToSnapshotSpan(snapshot);
}
private string ConvertType(string type)
{
switch (type)
{
// Basic types.
case BlockTypes.Structural: return PredefinedStructureTypes.Structural;
case BlockTypes.Nonstructural: return PredefinedStructureTypes.Nonstructural;
// Top level declarations. Note that Enum is not currently supported
// and that we map Module down to Class.
case BlockTypes.Namespace: return PredefinedStructureTypes.Namespace;
case BlockTypes.Structure: return PredefinedStructureTypes.Struct;
case BlockTypes.Interface: return PredefinedStructureTypes.Interface;
case BlockTypes.Module:
case BlockTypes.Class: return PredefinedStructureTypes.Class;
// Member declarations
case BlockTypes.Accessor: return PredefinedStructureTypes.AccessorBlock;
case BlockTypes.Constructor: return PredefinedStructureTypes.Constructor;
case BlockTypes.Destructor: return PredefinedStructureTypes.Destructor;
case BlockTypes.Method: return PredefinedStructureTypes.Method;
case BlockTypes.Operator: return PredefinedStructureTypes.Operator;
// Map events/indexers/properties all to the 'property' type.
case BlockTypes.Event:
case BlockTypes.Indexer:
case BlockTypes.Property: return PredefinedStructureTypes.PropertyBlock;
// Statements
case BlockTypes.Case: return PredefinedStructureTypes.Case;
case BlockTypes.Conditional: return PredefinedStructureTypes.Conditional;
case BlockTypes.Lock: return PredefinedStructureTypes.Lock;
case BlockTypes.Loop: return PredefinedStructureTypes.Loop;
case BlockTypes.TryCatchFinally: return PredefinedStructureTypes.TryCatchFinally;
case BlockTypes.Standalone: return PredefinedStructureTypes.Standalone;
// Expressions
case BlockTypes.AnonymousMethod: return PredefinedStructureTypes.AnonymousMethodBlock;
// These types don't currently map to any editor types. Just make them
// the 'Unknown' type for now.
case BlockTypes.Enum:
case BlockTypes.Other:
case BlockTypes.Xml:
default:
return PredefinedStructureTypes.Unknown;
}
}
}
}
}
\ No newline at end of file
......@@ -133,7 +133,8 @@ private static string GetCommentBannerText(SyntaxTrivia comment)
}
}
private static BlockSpan CreateCommentRegion(SyntaxTrivia startComment, SyntaxTrivia endComment)
private static BlockSpan CreateCommentBlockSpan(
SyntaxTrivia startComment, SyntaxTrivia endComment)
{
var span = TextSpan.FromBounds(startComment.SpanStart, endComment.Span.End);
......@@ -142,18 +143,20 @@ private static BlockSpan CreateCommentRegion(SyntaxTrivia startComment, SyntaxTr
textSpan: span,
hintSpan: span,
bannerText: GetCommentBannerText(startComment),
autoCollapse: true);
autoCollapse: true,
type: BlockTypes.Nonstructural);
}
// For testing purposes
internal static ImmutableArray<BlockSpan> CreateCommentRegions(SyntaxTriviaList triviaList)
internal static ImmutableArray<BlockSpan> CreateCommentBlockSpan(
SyntaxTriviaList triviaList)
{
var result = ImmutableArray.CreateBuilder<BlockSpan>();
CollectCommentRegions(triviaList, result);
CollectCommentBlockSpans(triviaList, result);
return result.ToImmutable();
}
public static void CollectCommentRegions(
public static void CollectCommentBlockSpans(
SyntaxTriviaList triviaList, ImmutableArray<BlockSpan>.Builder spans)
{
if (triviaList.Count > 0)
......@@ -165,7 +168,7 @@ internal static ImmutableArray<BlockSpan> CreateCommentRegions(SyntaxTriviaList
{
if (startComment != null)
{
var singleLineCommentGroupRegion = CreateCommentRegion(startComment.Value, endComment.Value);
var singleLineCommentGroupRegion = CreateCommentBlockSpan(startComment.Value, endComment.Value);
spans.Add(singleLineCommentGroupRegion);
startComment = null;
endComment = null;
......@@ -186,7 +189,7 @@ internal static ImmutableArray<BlockSpan> CreateCommentRegions(SyntaxTriviaList
{
completeSingleLineCommentGroup();
var multilineCommentRegion = CreateCommentRegion(trivia, trivia);
var multilineCommentRegion = CreateCommentBlockSpan(trivia, trivia);
spans.Add(multilineCommentRegion);
}
else if (!trivia.MatchesKind(SyntaxKind.WhitespaceTrivia,
......@@ -201,7 +204,7 @@ internal static ImmutableArray<BlockSpan> CreateCommentRegions(SyntaxTriviaList
}
}
public static void CollectCommentRegions(
public static void CollectCommentBlockSpans(
SyntaxNode node, ImmutableArray<BlockSpan>.Builder spans)
{
if (node == null)
......@@ -211,43 +214,62 @@ internal static ImmutableArray<BlockSpan> CreateCommentRegions(SyntaxTriviaList
var triviaList = node.GetLeadingTrivia();
CollectCommentRegions(triviaList, spans);
CollectCommentBlockSpans(triviaList, spans);
}
private static BlockSpan CreateRegion(TextSpan textSpan, string bannerText, bool autoCollapse)
private static BlockSpan CreateBlockSpan(
TextSpan textSpan, string bannerText, bool autoCollapse,
string type, bool isCollapsible)
{
return CreateRegion(textSpan, textSpan, bannerText, autoCollapse);
return CreateBlockSpan(
textSpan, textSpan, bannerText, autoCollapse, type, isCollapsible);
}
private static BlockSpan CreateRegion(TextSpan textSpan, TextSpan hintSpan, string bannerText, bool autoCollapse)
private static BlockSpan CreateBlockSpan(
TextSpan textSpan, TextSpan hintSpan,
string bannerText, bool autoCollapse,
string type, bool isCollapsible)
{
return new BlockSpan(
isCollapsible: true,
textSpan: textSpan,
hintSpan: hintSpan,
bannerText: bannerText,
autoCollapse: autoCollapse);
autoCollapse: autoCollapse,
type: type,
isCollapsible: isCollapsible);
}
public static BlockSpan CreateRegion(SyntaxNode node, string bannerText, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
SyntaxNode node, string bannerText, bool autoCollapse,
string type, bool isCollapsible)
{
return CreateRegion(
return CreateBlockSpan(
node.Span,
bannerText,
autoCollapse);
autoCollapse,
type,
isCollapsible);
}
public static BlockSpan CreateRegion(SyntaxNode node, SyntaxToken syntaxToken, string bannerText, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
SyntaxNode node, SyntaxToken syntaxToken,
string bannerText, bool autoCollapse,
string type, bool isCollapsible)
{
return CreateRegion(
return CreateBlockSpan(
node,
syntaxToken,
node.GetLastToken(),
bannerText,
autoCollapse);
autoCollapse,
type,
isCollapsible);
}
public static BlockSpan CreateRegion(SyntaxNode node, SyntaxToken startToken, int endPos, string bannerText, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
SyntaxNode node, SyntaxToken startToken,
int endPos, string bannerText, bool autoCollapse,
string type, bool isCollapsible)
{
// If the SyntaxToken is actually missing, don't attempt to create an outlining region.
if (startToken.IsMissing)
......@@ -262,55 +284,75 @@ public static BlockSpan CreateRegion(SyntaxNode node, SyntaxToken startToken, in
var span = TextSpan.FromBounds(GetCollapsibleStart(startToken), endPos);
var hintSpan = TextSpan.FromBounds(node.SpanStart, endPos);
return CreateRegion(
return CreateBlockSpan(
span,
hintSpan,
bannerText,
autoCollapse);
autoCollapse,
type,
isCollapsible);
}
public static BlockSpan CreateRegion(SyntaxNode node, SyntaxToken startToken, SyntaxToken endToken, string bannerText, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
SyntaxNode node, SyntaxToken startToken,
SyntaxToken endToken, string bannerText, bool autoCollapse,
string type, bool isCollapsible)
{
return CreateRegion(
return CreateBlockSpan(
node,
startToken,
GetCollapsibleEnd(endToken),
bannerText,
autoCollapse);
autoCollapse,
type,
isCollapsible);
}
public static BlockSpan CreateRegion(SyntaxNode node, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
SyntaxNode node, bool autoCollapse, string type, bool isCollapsible)
{
return CreateRegion(
return CreateBlockSpan(
node,
bannerText: Ellipsis,
autoCollapse: autoCollapse);
autoCollapse: autoCollapse,
type: type,
isCollapsible: isCollapsible);
}
// Adds everything after 'syntaxToken' up to and including the end
// of node as a region. The snippet to display is just "..."
public static BlockSpan CreateRegion(SyntaxNode node, SyntaxToken syntaxToken, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
SyntaxNode node, SyntaxToken syntaxToken,
bool autoCollapse, string type, bool isCollapsible)
{
return CreateRegion(
return CreateBlockSpan(
node, syntaxToken,
bannerText: Ellipsis,
autoCollapse: autoCollapse);
autoCollapse: autoCollapse,
type: type,
isCollapsible: isCollapsible);
}
// Adds everything after 'syntaxToken' up to and including the end
// of node as a region. The snippet to display is just "..."
public static BlockSpan CreateRegion(SyntaxNode node, SyntaxToken startToken, SyntaxToken endToken, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
SyntaxNode node, SyntaxToken startToken, SyntaxToken endToken,
bool autoCollapse, string type, bool isCollapsible)
{
return CreateRegion(
return CreateBlockSpan(
node, startToken, endToken,
bannerText: Ellipsis,
autoCollapse: autoCollapse);
autoCollapse: autoCollapse,
type: type,
isCollapsible: isCollapsible);
}
// Adds the span surrounding the syntax list as a region. The
// snippet shown is the text from the first line of the first
// node in the list.
public static BlockSpan CreateRegion(IEnumerable<SyntaxNode> syntaxList, bool autoCollapse)
public static BlockSpan CreateBlockSpan(
IEnumerable<SyntaxNode> syntaxList, bool autoCollapse,
string type, bool isCollapsible)
{
if (syntaxList.IsEmpty())
{
......@@ -329,11 +371,13 @@ public static BlockSpan CreateRegion(IEnumerable<SyntaxNode> syntaxList, bool au
? end
: hintSpanStart;
return CreateRegion(
return CreateBlockSpan(
textSpan: TextSpan.FromBounds(spanStart, spanEnd),
hintSpan: TextSpan.FromBounds(hintSpanStart, hintSpanEnd),
bannerText: Ellipsis,
autoCollapse: autoCollapse);
autoCollapse: autoCollapse,
type: type,
isCollapsible: isCollapsible);
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class AccessorDeclarationStructureProvider : AbstractSyntaxNodeStructur
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(accessorDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(accessorDeclaration, spans);
// fault tolerance
if (accessorDeclaration.Body == null ||
......@@ -24,10 +24,12 @@ internal class AccessorDeclarationStructureProvider : AbstractSyntaxNodeStructur
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
accessorDeclaration,
accessorDeclaration.Keyword,
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Accessor,
isCollapsible: true));
}
}
}
......@@ -32,11 +32,13 @@ internal class AnonymousMethodExpressionStructureProvider : AbstractSyntaxNodeSt
? anonymousMethod.ParameterList.GetLastToken(includeZeroWidth: true)
: anonymousMethod.DelegateKeyword;
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
anonymousMethod,
startToken,
lastToken,
autoCollapse: false));
autoCollapse: false,
type: BlockTypes.AnonymousMethod,
isCollapsible: true));
}
}
}
......@@ -15,7 +15,7 @@ internal class CompilationUnitStructureProvider : AbstractSyntaxNodeStructurePro
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(compilationUnit, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(compilationUnit, spans);
// extern aliases and usings are outlined in a single region
var externsAndUsings = new List<SyntaxNode>();
......@@ -23,14 +23,16 @@ internal class CompilationUnitStructureProvider : AbstractSyntaxNodeStructurePro
externsAndUsings.AddRange(compilationUnit.Usings);
externsAndUsings.Sort((node1, node2) => node1.SpanStart.CompareTo(node2.SpanStart));
spans.Add(CSharpStructureHelpers.CreateRegion(externsAndUsings, autoCollapse: true));
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
externsAndUsings, autoCollapse: true,
type: BlockTypes.Nonstructural, isCollapsible: true));
if (compilationUnit.Usings.Count > 0 ||
compilationUnit.Externs.Count > 0 ||
compilationUnit.Members.Count > 0 ||
compilationUnit.AttributeLists.Count > 0)
{
CSharpStructureHelpers.CollectCommentRegions(compilationUnit.EndOfFileToken.LeadingTrivia, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(compilationUnit.EndOfFileToken.LeadingTrivia, spans);
}
}
......
......@@ -14,7 +14,7 @@ internal class ConstructorDeclarationStructureProvider : AbstractSyntaxNodeStruc
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(constructorDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(constructorDeclaration, spans);
// fault tolerance
if (constructorDeclaration.Body == null ||
......@@ -24,10 +24,12 @@ internal class ConstructorDeclarationStructureProvider : AbstractSyntaxNodeStruc
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
constructorDeclaration,
constructorDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Constructor,
isCollapsible: true));
}
}
}
......@@ -14,7 +14,7 @@ internal class ConversionOperatorDeclarationStructureProvider : AbstractSyntaxNo
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(operatorDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(operatorDeclaration, spans);
// fault tolerance
if (operatorDeclaration.Body == null ||
......@@ -24,10 +24,12 @@ internal class ConversionOperatorDeclarationStructureProvider : AbstractSyntaxNo
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
operatorDeclaration,
operatorDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Operator,
isCollapsible: true));
}
}
}
......@@ -14,7 +14,7 @@ internal class DelegateDeclarationStructureProvider : AbstractSyntaxNodeStructur
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(delegateDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(delegateDeclaration, spans);
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class DestructorDeclarationStructureProvider : AbstractSyntaxNodeStruct
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(destructorDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(destructorDeclaration, spans);
// fault tolerance
if (destructorDeclaration.Body == null ||
......@@ -24,10 +24,12 @@ internal class DestructorDeclarationStructureProvider : AbstractSyntaxNodeStruct
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
destructorDeclaration,
destructorDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Destructor,
isCollapsible: true));
}
}
}
\ No newline at end of file
......@@ -14,22 +14,24 @@ internal class EnumDeclarationStructureProvider : AbstractSyntaxNodeStructurePro
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(enumDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(enumDeclaration, spans);
if (!enumDeclaration.OpenBraceToken.IsMissing &&
!enumDeclaration.CloseBraceToken.IsMissing)
{
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
enumDeclaration,
enumDeclaration.Identifier,
autoCollapse: false));
autoCollapse: false,
type: BlockTypes.Enum,
isCollapsible: true));
}
// add any leading comments before the end of the type block
if (!enumDeclaration.CloseBraceToken.IsMissing)
{
var leadingTrivia = enumDeclaration.CloseBraceToken.LeadingTrivia;
CSharpStructureHelpers.CollectCommentRegions(leadingTrivia, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(leadingTrivia, spans);
}
}
}
......
......@@ -14,7 +14,7 @@ internal class EventDeclarationStructureProvider : AbstractSyntaxNodeStructurePr
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(eventDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(eventDeclaration, spans);
// fault tolerance
if (eventDeclaration.AccessorList.IsMissing ||
......@@ -24,10 +24,12 @@ internal class EventDeclarationStructureProvider : AbstractSyntaxNodeStructurePr
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
eventDeclaration,
eventDeclaration.Identifier,
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Event,
isCollapsible: true));
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class EventFieldDeclarationStructureProvider : AbstractSyntaxNodeStruct
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(eventFieldDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(eventFieldDeclaration, spans);
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class FieldDeclarationStructureProvider : AbstractSyntaxNodeStructurePr
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(fieldDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(fieldDeclaration, spans);
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class IndexerDeclarationStructureProvider : AbstractSyntaxNodeStructure
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(indexerDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(indexerDeclaration, spans);
// fault tolerance
if (indexerDeclaration.AccessorList == null ||
......@@ -25,10 +25,12 @@ internal class IndexerDeclarationStructureProvider : AbstractSyntaxNodeStructure
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
indexerDeclaration,
indexerDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Indexer,
isCollapsible: true));
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class MethodDeclarationStructureProvider : AbstractSyntaxNodeStructureP
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(methodDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(methodDeclaration, spans);
// fault tolerance
if (methodDeclaration.Body == null ||
......@@ -24,10 +24,12 @@ internal class MethodDeclarationStructureProvider : AbstractSyntaxNodeStructureP
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
methodDeclaration,
methodDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Method,
isCollapsible: true));
}
}
}
\ No newline at end of file
......@@ -16,15 +16,17 @@ internal class NamespaceDeclarationStructureProvider : AbstractSyntaxNodeStructu
CancellationToken cancellationToken)
{
// add leading comments
CSharpStructureHelpers.CollectCommentRegions(namespaceDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(namespaceDeclaration, spans);
if (!namespaceDeclaration.OpenBraceToken.IsMissing &&
!namespaceDeclaration.CloseBraceToken.IsMissing)
{
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
namespaceDeclaration,
namespaceDeclaration.Name.GetLastToken(includeZeroWidth: true),
autoCollapse: false));
autoCollapse: false,
type: BlockTypes.Namespace,
isCollapsible: true));
}
// extern aliases and usings are outlined in a single region
......@@ -35,15 +37,17 @@ internal class NamespaceDeclarationStructureProvider : AbstractSyntaxNodeStructu
// add any leading comments before the extern aliases and usings
if (externsAndUsings.Count > 0)
{
CSharpStructureHelpers.CollectCommentRegions(externsAndUsings.First(), spans);
CSharpStructureHelpers.CollectCommentBlockSpans(externsAndUsings.First(), spans);
}
spans.Add(CSharpStructureHelpers.CreateRegion(externsAndUsings, autoCollapse: true));
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
externsAndUsings, autoCollapse: true,
type: BlockTypes.Nonstructural, isCollapsible: true));
// finally, add any leading comments before the end of the namespace block
if (!namespaceDeclaration.CloseBraceToken.IsMissing)
{
CSharpStructureHelpers.CollectCommentRegions(namespaceDeclaration.CloseBraceToken.LeadingTrivia, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(namespaceDeclaration.CloseBraceToken.LeadingTrivia, spans);
}
}
......
......@@ -14,7 +14,7 @@ internal class OperatorDeclarationStructureProvider : AbstractSyntaxNodeStructur
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(operatorDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(operatorDeclaration, spans);
// fault tolerance
if (operatorDeclaration.Body == null ||
......@@ -24,10 +24,12 @@ internal class OperatorDeclarationStructureProvider : AbstractSyntaxNodeStructur
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
operatorDeclaration,
operatorDeclaration.ParameterList.GetLastToken(includeZeroWidth: true),
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Operator,
isCollapsible: true));
}
}
}
\ No newline at end of file
......@@ -34,11 +34,13 @@ internal class ParenthesizedLambdaExpressionStructureProvider : AbstractSyntaxNo
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
lambdaExpression,
lambdaExpression.ArrowToken,
lastToken,
autoCollapse: false));
autoCollapse: false,
type: BlockTypes.AnonymousMethod,
isCollapsible: true));
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class PropertyDeclarationStructureProvider : AbstractSyntaxNodeStructur
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(propertyDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(propertyDeclaration, spans);
// fault tolerance
if (propertyDeclaration.AccessorList == null ||
......@@ -24,10 +24,12 @@ internal class PropertyDeclarationStructureProvider : AbstractSyntaxNodeStructur
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
propertyDeclaration,
propertyDeclaration.Identifier,
autoCollapse: true));
autoCollapse: true,
type: BlockTypes.Property,
isCollapsible: true));
}
}
}
......@@ -34,11 +34,13 @@ internal class SimpleLambdaExpressionStructureProvider : AbstractSyntaxNodeStruc
return;
}
spans.Add(CSharpStructureHelpers.CreateRegion(
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
lambdaExpression,
lambdaExpression.ArrowToken,
lastToken,
autoCollapse: false));
autoCollapse: false,
type: BlockTypes.AnonymousMethod,
isCollapsible: true));
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ internal class TypeDeclarationStructureProvider : AbstractSyntaxNodeStructurePro
ImmutableArray<BlockSpan>.Builder spans,
CancellationToken cancellationToken)
{
CSharpStructureHelpers.CollectCommentRegions(typeDeclaration, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(typeDeclaration, spans);
if (!typeDeclaration.OpenBraceToken.IsMissing &&
!typeDeclaration.CloseBraceToken.IsMissing)
......@@ -23,17 +23,24 @@ internal class TypeDeclarationStructureProvider : AbstractSyntaxNodeStructurePro
? typeDeclaration.Identifier
: typeDeclaration.TypeParameterList.GetLastToken(includeZeroWidth: true);
spans.Add(CSharpStructureHelpers.CreateRegion(
var type = typeDeclaration.Kind() == SyntaxKind.InterfaceDeclaration
? BlockTypes.Interface
: typeDeclaration.Kind() == SyntaxKind.StructDeclaration
? BlockTypes.Structure
: BlockTypes.Class;
spans.Add(CSharpStructureHelpers.CreateBlockSpan(
typeDeclaration,
lastToken,
autoCollapse: false));
autoCollapse: false,
type: type,
isCollapsible: true));
}
// add any leading comments before the end of the type block
if (!typeDeclaration.CloseBraceToken.IsMissing)
{
var leadingTrivia = typeDeclaration.CloseBraceToken.LeadingTrivia;
CSharpStructureHelpers.CollectCommentRegions(leadingTrivia, spans);
CSharpStructureHelpers.CollectCommentBlockSpans(leadingTrivia, spans);
}
}
}
......
......@@ -4,25 +4,40 @@ namespace Microsoft.CodeAnalysis.Structure
{
internal static class BlockTypes
{
public const string AccessorBlock = "AccessorBlock";
public const string AnonymousMethodBlock = "AnonymousMethodBlock";
public const string Case = "Case";
public const string Class = "Class";
public const string Conditional = "Conditional";
public const string Constructor = "Constructor";
public const string Destructor = "Destructor";
public const string Interface = "Interface";
public const string Lock = "Context";
public const string Loop = "Loop";
public const string Method = "Method";
public const string Namespace = "Namespace";
public const string Nonstructural = "Nonstructural";
public const string Operator = "Operator";
public const string PropertyBlock = "PropertyBlock";
public const string Standalone = "Standalone";
public const string Struct = "Struct";
public const string Structural = "Structural";
public const string TryCatchFinally = "TryCatchFinally";
public const string Unknown = "Unknown";
// Basic types.
public const string Structural = nameof(Structural);
public const string Nonstructural = nameof(Nonstructural);
// Top level declarations.
public const string Namespace = nameof(Namespace);
public const string Class = nameof(Class);
public const string Enum = nameof(Enum);
public const string Interface = nameof(Interface);
public const string Module = nameof(Module);
public const string Structure = nameof(Structure);
// Type level declarations.
public const string Accessor = nameof(Accessor);
public const string Constructor = nameof(Constructor);
public const string Destructor = nameof(Destructor);
public const string Event = nameof(Event);
public const string Indexer = nameof(Indexer);
public const string Method = nameof(Method);
public const string Operator = nameof(Operator);
public const string Property = nameof(Property);
// Statements
public const string Case = nameof(Case);
public const string Conditional = nameof(Conditional);
public const string Lock = nameof(Lock);
public const string Loop = nameof(Loop);
public const string TryCatchFinally = nameof(TryCatchFinally);
public const string Standalone = nameof(Standalone);
// Expressions
public const string AnonymousMethod = nameof(AnonymousMethod);
public const string Xml = nameof(Xml);
public const string Other = nameof(Other);
}
}
\ No newline at end of file
......@@ -16,8 +16,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(accessorDeclaration.Parent, AccessorBlockSyntax)
If Not block?.EndBlockStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=accessorDeclaration, autoCollapse:=True))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=accessorDeclaration,
autoCollapse:=True, type:=BlockTypes.Accessor, isCollapsible:=True))
End If
End Sub
End Class
......
......@@ -15,7 +15,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim regions As New List(Of BlockSpan)
CollectCommentsRegions(compilationUnit, spans)
spans.Add(CreateRegion(compilationUnit.Imports, bannerText:="Imports" & SpaceEllipsis, autoCollapse:=True))
spans.Add(CreateRegion(
compilationUnit.Imports, bannerText:="Imports" & SpaceEllipsis,
autoCollapse:=True, type:=BlockTypes.Nonstructural, isCollapsible:=True))
CollectCommentsRegions(compilationUnit.EndOfFileToken.LeadingTrivia, spans)
End Sub
......
......@@ -18,8 +18,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(constructorDeclaration.Parent, ConstructorBlockSyntax)
If Not block?.EndBlockStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=constructorDeclaration, autoCollapse:=True))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=constructorDeclaration, autoCollapse:=True,
type:=BlockTypes.Constructor, isCollapsible:=True))
End If
End Sub
End Class
......
......@@ -18,11 +18,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim startPos = nodeSpan.Start
Dim endPos = startPos + trivia.ToString().TrimEnd().Length
spans.Add(
CreateRegion(
span:=TextSpan.FromBounds(startPos, endPos),
bannerText:=Ellipsis,
autoCollapse:=True))
spans.Add(CreateRegion(
span:=TextSpan.FromBounds(startPos, endPos),
bannerText:=Ellipsis, autoCollapse:=True,
type:=BlockTypes.Nonstructural, isCollapsible:=True))
End If
End Sub
End Class
......
......@@ -87,8 +87,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim fullSpan = TextSpan.FromBounds(startPos, endPos)
spans.Add(
CreateRegion(fullSpan, GetBannerText(documentationComment, cancellationToken), autoCollapse:=True))
spans.Add(CreateRegion(
fullSpan, GetBannerText(documentationComment, cancellationToken),
autoCollapse:=True, type:=BlockTypes.Nonstructural, isCollapsible:=True))
End Sub
End Class
End Namespace
\ No newline at end of file
......@@ -16,8 +16,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(enumDeclaration.Parent, EnumBlockSyntax)
If Not block?.EndEnumStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=enumDeclaration, autoCollapse:=True))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=enumDeclaration, autoCollapse:=True,
type:=BlockTypes.Enum, isCollapsible:=True))
CollectCommentsRegions(block.EndEnumStatement, spans)
End If
......
......@@ -16,8 +16,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(eventDeclaration.Parent, EventBlockSyntax)
If Not block?.EndEventStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=eventDeclaration, autoCollapse:=True))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=eventDeclaration, autoCollapse:=True,
type:=BlockTypes.Event, isCollapsible:=True))
CollectCommentsRegions(block.EndEventStatement, spans)
End If
......
......@@ -25,11 +25,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure.MetadataAsSource
cancellationToken As CancellationToken)
Dim match = regionDirective.GetMatchingStartOrEndDirective(cancellationToken)
If match IsNot Nothing Then
spans.Add(
VisualBasicOutliningHelpers.CreateRegion(
TextSpan.FromBounds(regionDirective.SpanStart, match.Span.End),
GetBannerText(regionDirective),
autoCollapse:=True))
spans.Add(CreateRegion(
TextSpan.FromBounds(regionDirective.SpanStart, match.Span.End),
GetBannerText(regionDirective),
autoCollapse:=True,
type:=BlockTypes.Nonstructural, isCollapsible:=True))
End If
End Sub
......
......@@ -16,8 +16,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(methodDeclaration.Parent, MethodBlockSyntax)
If Not block?.EndBlockStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=methodDeclaration, autoCollapse:=True))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=methodDeclaration, autoCollapse:=True,
type:=BlockTypes.Method, isCollapsible:=True))
End If
End Sub
End Class
......
......@@ -13,8 +13,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
spans As ImmutableArray(Of BlockSpan).Builder,
cancellationToken As CancellationToken)
If Not lambdaExpression.EndSubOrFunctionStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(lambdaExpression, bannerNode:=lambdaExpression.SubOrFunctionHeader, autoCollapse:=False))
spans.Add(CreateRegionFromBlock(
lambdaExpression, bannerNode:=lambdaExpression.SubOrFunctionHeader, autoCollapse:=False,
type:=BlockTypes.AnonymousMethod, isCollapsible:=True))
End If
End Sub
End Class
......
......@@ -16,8 +16,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(namespaceDeclaration.Parent, NamespaceBlockSyntax)
If Not block?.EndNamespaceStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=namespaceDeclaration, autoCollapse:=False))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=namespaceDeclaration, autoCollapse:=False,
type:=BlockTypes.Namespace, isCollapsible:=True))
CollectCommentsRegions(block.EndNamespaceStatement, spans)
End If
......
......@@ -16,8 +16,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(operatorDeclaration.Parent, OperatorBlockSyntax)
If Not block?.EndBlockStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=operatorDeclaration, autoCollapse:=True))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=operatorDeclaration, autoCollapse:=True,
type:=BlockTypes.Operator, isCollapsible:=True))
End If
End Sub
End Class
......
......@@ -16,8 +16,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(propertyDeclaration.Parent, PropertyBlockSyntax)
If Not block?.EndPropertyStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=propertyDeclaration, autoCollapse:=True))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=propertyDeclaration, autoCollapse:=True,
type:=BlockTypes.Property, isCollapsible:=True))
CollectCommentsRegions(block.EndPropertyStatement, spans)
End If
......
......@@ -25,12 +25,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
cancellationToken As CancellationToken)
Dim matchingDirective = regionDirective.GetMatchingStartOrEndDirective(cancellationToken)
If matchingDirective IsNot Nothing Then
spans.Add(
CreateRegion(
TextSpan.FromBounds(regionDirective.SpanStart, matchingDirective.Span.End),
GetBannerText(regionDirective),
autoCollapse:=False,
isDefaultCollapsed:=True))
spans.Add(CreateRegion(
TextSpan.FromBounds(regionDirective.SpanStart, matchingDirective.Span.End),
GetBannerText(regionDirective),
autoCollapse:=False,
isDefaultCollapsed:=True,
type:=BlockTypes.Nonstructural,
isCollapsible:=True))
End If
End Sub
......
......@@ -16,8 +16,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim block = TryCast(typeDeclaration.Parent, TypeBlockSyntax)
If Not block?.EndBlockStatement.IsMissing Then
spans.Add(
CreateRegionFromBlock(block, bannerNode:=typeDeclaration, autoCollapse:=False))
Dim type =
If(typeDeclaration.Kind() = SyntaxKind.InterfaceStatement, BlockTypes.Interface,
If(typeDeclaration.Kind() = SyntaxKind.StructureStatement, BlockTypes.Structure,
If(typeDeclaration.Kind() = SyntaxKind.ModuleStatement, BlockTypes.Module,
BlockTypes.Class)))
spans.Add(CreateRegionFromBlock(
block, bannerNode:=typeDeclaration, autoCollapse:=False,
type:=type, isCollapsible:=True))
CollectCommentsRegions(block.EndBlockStatement, spans)
End If
......
......@@ -23,8 +23,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Dim lineText = line.ToString().Substring(span.Start - line.Start)
Dim bannerText = lineText & SpaceEllipsis
spans.Add(
CreateRegion(span, bannerText, autoCollapse:=False))
spans.Add(CreateRegion(
span, bannerText, autoCollapse:=False,
type:=BlockTypes.Xml, isCollapsible:=True))
End Sub
End Class
End Namespace
\ No newline at end of file
......@@ -22,7 +22,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
Return CreateRegion(
TextSpan.FromBounds(startComment.SpanStart, endComment.Span.End),
GetCommentBannerText(startComment),
autoCollapse:=True)
autoCollapse:=True,
type:=BlockTypes.Nonstructural,
isCollapsible:=True)
End Function
' For testing purposes
......@@ -72,31 +74,56 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Structure
CollectCommentsRegions(triviaList, spans)
End Sub
Friend Function CreateRegion(span As TextSpan, bannerText As String, autoCollapse As Boolean, Optional isDefaultCollapsed As Boolean = False) As BlockSpan
Friend Function CreateRegion(
span As TextSpan,
bannerText As String,
autoCollapse As Boolean,
type As String,
isCollapsible As Boolean,
Optional isDefaultCollapsed As Boolean = False) As BlockSpan
Return New BlockSpan(
isCollapsible:=True,
textSpan:=span,
bannerText:=bannerText,
autoCollapse:=autoCollapse,
isDefaultCollapsed:=isDefaultCollapsed)
isDefaultCollapsed:=isDefaultCollapsed,
type:=type,
isCollapsible:=isCollapsible)
End Function
Friend Function CreateRegionFromBlock(blockNode As SyntaxNode, bannerText As String, autoCollapse As Boolean) As BlockSpan
Return CreateRegion(blockNode.Span, bannerText, autoCollapse)
Friend Function CreateRegionFromBlock(
blockNode As SyntaxNode,
bannerText As String,
autoCollapse As Boolean,
type As String,
isCollapsible As Boolean) As BlockSpan
Return CreateRegion(blockNode.Span, bannerText, autoCollapse, type, isCollapsible)
End Function
Friend Function CreateRegionFromBlock(blockNode As SyntaxNode, bannerNode As SyntaxNode, autoCollapse As Boolean) As BlockSpan
Return CreateRegion(blockNode.Span, GetNodeBannerText(bannerNode), autoCollapse)
Friend Function CreateRegionFromBlock(
blockNode As SyntaxNode,
bannerNode As SyntaxNode,
autoCollapse As Boolean,
type As String,
isCollapsible As Boolean) As BlockSpan
Return CreateRegion(
blockNode.Span, GetNodeBannerText(bannerNode),
autoCollapse, type, isCollapsible)
End Function
Friend Function CreateRegion(syntaxList As IEnumerable(Of SyntaxNode), bannerText As String, autoCollapse As Boolean) As BlockSpan
Friend Function CreateRegion(syntaxList As IEnumerable(Of SyntaxNode),
bannerText As String,
autoCollapse As Boolean,
type As String,
isCollapsible As Boolean) As BlockSpan
If syntaxList.IsEmpty() Then
Return Nothing
End If
Dim startPos = syntaxList.First().SpanStart
Dim endPos = syntaxList.Last().Span.End
Return CreateRegion(TextSpan.FromBounds(startPos, endPos), bannerText, autoCollapse)
Return CreateRegion(
TextSpan.FromBounds(startPos, endPos), bannerText,
autoCollapse, type, isCollapsible)
End Function
End Module
End Namespace
\ No newline at end of file
......@@ -242,6 +242,7 @@
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.InteractiveEditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures.Next" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures.Text" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Features" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.InteractiveEditorFeatures" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册