提交 414d2efe 编写于 作者: B Brett Forsgren

Merge pull request #5019 from brettfo/classify-shebang

properly classify shebang comments in the IDE
...@@ -13,7 +13,7 @@ Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax.WithIsActive(bool ...@@ -13,7 +13,7 @@ Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax.WithIsActive(bool
Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax.WithLoadKeyword(Microsoft.CodeAnalysis.SyntaxToken loadKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax.WithLoadKeyword(Microsoft.CodeAnalysis.SyntaxToken loadKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax
Microsoft.CodeAnalysis.CSharp.SyntaxKind.LoadDirectiveTrivia = 8923 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.LoadDirectiveTrivia = 8923 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.LoadKeyword = 8485 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.LoadKeyword = 8485 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.ShebangCommentTrivia = 8922 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.ShebangTrivia = 8922 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
override Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.CommonWithKind(Microsoft.CodeAnalysis.SourceCodeKind kind) -> Microsoft.CodeAnalysis.ParseOptions override Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.CommonWithKind(Microsoft.CodeAnalysis.SourceCodeKind kind) -> Microsoft.CodeAnalysis.ParseOptions
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitLoadDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitLoadDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void override Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
...@@ -30,4 +30,4 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxExtensions.NormalizeWhitespace(this M ...@@ -30,4 +30,4 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxExtensions.NormalizeWhitespace(this M
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LoadDirectiveTrivia(Microsoft.CodeAnalysis.SyntaxToken file, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LoadDirectiveTrivia(Microsoft.CodeAnalysis.SyntaxToken file, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LoadDirectiveTrivia(Microsoft.CodeAnalysis.SyntaxToken hashToken, Microsoft.CodeAnalysis.SyntaxToken loadKeyword, Microsoft.CodeAnalysis.SyntaxToken file, Microsoft.CodeAnalysis.SyntaxToken endOfDirectiveToken, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LoadDirectiveTrivia(Microsoft.CodeAnalysis.SyntaxToken hashToken, Microsoft.CodeAnalysis.SyntaxToken loadKeyword, Microsoft.CodeAnalysis.SyntaxToken file, Microsoft.CodeAnalysis.SyntaxToken endOfDirectiveToken, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitLoadDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax node) -> void virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitLoadDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult>.VisitLoadDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax node) -> TResult virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult>.VisitLoadDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LoadDirectiveTriviaSyntax node) -> TResult
\ No newline at end of file
...@@ -94,7 +94,7 @@ internal static SyntaxTrivia Comment(string text) ...@@ -94,7 +94,7 @@ internal static SyntaxTrivia Comment(string text)
} }
else if (text.StartsWith("#", StringComparison.Ordinal)) else if (text.StartsWith("#", StringComparison.Ordinal))
{ {
return SyntaxTrivia.Create(SyntaxKind.ShebangCommentTrivia, text); return SyntaxTrivia.Create(SyntaxKind.ShebangTrivia, text);
} }
else else
{ {
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Collections;
using Roslyn.Utilities; using Roslyn.Utilities;
using System.Diagnostics; using System.Diagnostics;
...@@ -347,7 +345,8 @@ public override Microsoft.CodeAnalysis.SyntaxToken CreateSeparator<TNode>(Syntax ...@@ -347,7 +345,8 @@ public override Microsoft.CodeAnalysis.SyntaxToken CreateSeparator<TNode>(Syntax
public override bool IsTriviaWithEndOfLine() public override bool IsTriviaWithEndOfLine()
{ {
return this.Kind == SyntaxKind.EndOfLineTrivia return this.Kind == SyntaxKind.EndOfLineTrivia
|| this.Kind == SyntaxKind.SingleLineCommentTrivia; || this.Kind == SyntaxKind.SingleLineCommentTrivia
|| this.Kind == SyntaxKind.ShebangTrivia;
} }
// Use conditional weak table so we always return same identity for structured trivia // Use conditional weak table so we always return same identity for structured trivia
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
using System.Threading; using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using InternalSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax; using InternalSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
namespace Microsoft.CodeAnalysis.CSharp namespace Microsoft.CodeAnalysis.CSharp
...@@ -168,14 +167,16 @@ public static SyntaxTrivia PreprocessingMessage(string text) ...@@ -168,14 +167,16 @@ public static SyntaxTrivia PreprocessingMessage(string text)
} }
/// <summary> /// <summary>
/// Trivia nodes represents parts of the program text that are not parts of the /// Trivia nodes represent parts of the program text that are not parts of the
/// syntactic grammar, such as spaces, newlines, comments, preprocessors /// syntactic grammar, such as spaces, newlines, comments, preprocessor
/// directives, and disabled code. /// directives, and disabled code.
/// </summary> /// </summary>
/// <param name="kind"> /// <param name="kind">
/// A <cref c="SyntaxKind"/> representing the specific kind of SyntaxTrivia. One of /// A <see cref="SyntaxKind"/> representing the specific kind of <see cref="SyntaxTrivia"/>. One of
/// WhitespaceTrivia, EndOfLineTrivia, CommentTrivia, /// <see cref="SyntaxKind.WhitespaceTrivia"/>, <see cref="SyntaxKind.EndOfLineTrivia"/>,
/// DocumentationCommentExteriorTrivia, DisabledTextTrivia. /// <see cref="SyntaxKind.SingleLineCommentTrivia"/>, <see cref="SyntaxKind.MultiLineCommentTrivia"/>,
/// <see cref="SyntaxKind.DocumentationCommentExteriorTrivia"/>, <see cref="SyntaxKind.DisabledTextTrivia"/>,
/// <see cref="SyntaxKind.ShebangTrivia"/>
/// </param> /// </param>
/// <param name="text"> /// <param name="text">
/// The actual text of this token. /// The actual text of this token.
...@@ -194,6 +195,7 @@ public static SyntaxTrivia SyntaxTrivia(SyntaxKind kind, string text) ...@@ -194,6 +195,7 @@ public static SyntaxTrivia SyntaxTrivia(SyntaxKind kind, string text)
case SyntaxKind.EndOfLineTrivia: case SyntaxKind.EndOfLineTrivia:
case SyntaxKind.MultiLineCommentTrivia: case SyntaxKind.MultiLineCommentTrivia:
case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.SingleLineCommentTrivia:
case SyntaxKind.ShebangTrivia:
case SyntaxKind.WhitespaceTrivia: case SyntaxKind.WhitespaceTrivia:
return new SyntaxTrivia(default(SyntaxToken), new Syntax.InternalSyntax.SyntaxTrivia(kind, text, null, null), 0, 0); return new SyntaxTrivia(default(SyntaxToken), new Syntax.InternalSyntax.SyntaxTrivia(kind, text, null, null), 0, 0);
......
...@@ -530,7 +530,7 @@ public enum SyntaxKind : ushort ...@@ -530,7 +530,7 @@ public enum SyntaxKind : ushort
InterpolationAlignmentClause = 8920, InterpolationAlignmentClause = 8920,
InterpolationFormatClause = 8921, InterpolationFormatClause = 8921,
ShebangCommentTrivia = 8922, ShebangTrivia = 8922,
LoadDirectiveTrivia = 8923, LoadDirectiveTrivia = 8923,
} }
} }
...@@ -209,6 +209,7 @@ public static bool IsTrivia(SyntaxKind kind) ...@@ -209,6 +209,7 @@ public static bool IsTrivia(SyntaxKind kind)
case SyntaxKind.WhitespaceTrivia: case SyntaxKind.WhitespaceTrivia:
case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.SingleLineCommentTrivia:
case SyntaxKind.MultiLineCommentTrivia: case SyntaxKind.MultiLineCommentTrivia:
case SyntaxKind.ShebangTrivia:
case SyntaxKind.SingleLineDocumentationCommentTrivia: case SyntaxKind.SingleLineDocumentationCommentTrivia:
case SyntaxKind.MultiLineDocumentationCommentTrivia: case SyntaxKind.MultiLineDocumentationCommentTrivia:
case SyntaxKind.DisabledTextTrivia: case SyntaxKind.DisabledTextTrivia:
......
...@@ -110,10 +110,16 @@ private void AddEndOfLine() ...@@ -110,10 +110,16 @@ private void AddEndOfLine()
} }
} }
/// <summary>
/// Returns whether the specified <see cref="SyntaxTrivia"/> token is also the end of the line. This will
/// be true for <see cref="SyntaxKind.EndOfLineTrivia"/>, <see cref="SyntaxKind.SingleLineCommentTrivia"/>,
/// <see cref="SyntaxKind.ShebangTrivia"/>, and all preprocessor directives.
/// </summary>
private static bool IsEndOfLine(SyntaxTrivia trivia) private static bool IsEndOfLine(SyntaxTrivia trivia)
{ {
return trivia.Kind() == SyntaxKind.EndOfLineTrivia return trivia.Kind() == SyntaxKind.EndOfLineTrivia
|| trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || trivia.Kind() == SyntaxKind.SingleLineCommentTrivia
|| trivia.Kind() == SyntaxKind.ShebangTrivia
|| trivia.IsDirective; || trivia.IsDirective;
} }
......
...@@ -666,6 +666,7 @@ private static bool NeedsLineBreakAfter(SyntaxTrivia trivia, bool isTrailingTriv ...@@ -666,6 +666,7 @@ private static bool NeedsLineBreakAfter(SyntaxTrivia trivia, bool isTrailingTriv
switch (kind) switch (kind)
{ {
case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.SingleLineCommentTrivia:
case SyntaxKind.ShebangTrivia:
return true; return true;
case SyntaxKind.MultiLineCommentTrivia: case SyntaxKind.MultiLineCommentTrivia:
return !isTrailingTrivia; return !isTrailingTrivia;
......
...@@ -8446,7 +8446,7 @@ public void Shebang() ...@@ -8446,7 +8446,7 @@ public void Shebang()
Assert.Empty(root.ChildNodes()); Assert.Empty(root.ChildNodes());
var eof = root.EndOfFileToken; var eof = root.EndOfFileToken;
Assert.Equal(SyntaxKind.EndOfFileToken, eof.Kind()); Assert.Equal(SyntaxKind.EndOfFileToken, eof.Kind());
Assert.Equal(SyntaxKind.ShebangCommentTrivia, eof.GetLeadingTrivia().Single().Kind()); Assert.Equal(SyntaxKind.ShebangTrivia, eof.GetLeadingTrivia().Single().Kind());
tree = ParseAndValidate("#! /usr/bin/env scriptcs\r\n ", TestOptions.Script); tree = ParseAndValidate("#! /usr/bin/env scriptcs\r\n ", TestOptions.Script);
root = tree.GetCompilationUnitRoot(); root = tree.GetCompilationUnitRoot();
...@@ -8456,7 +8456,7 @@ public void Shebang() ...@@ -8456,7 +8456,7 @@ public void Shebang()
Assert.Equal(SyntaxKind.EndOfFileToken, eof.Kind()); Assert.Equal(SyntaxKind.EndOfFileToken, eof.Kind());
var leading = eof.GetLeadingTrivia().ToArray(); var leading = eof.GetLeadingTrivia().ToArray();
Assert.Equal(3, leading.Length); Assert.Equal(3, leading.Length);
Assert.Equal(SyntaxKind.ShebangCommentTrivia, leading[0].Kind()); Assert.Equal(SyntaxKind.ShebangTrivia, leading[0].Kind());
Assert.Equal(SyntaxKind.EndOfLineTrivia, leading[1].Kind()); Assert.Equal(SyntaxKind.EndOfLineTrivia, leading[1].Kind());
Assert.Equal(SyntaxKind.WhitespaceTrivia, leading[2].Kind()); Assert.Equal(SyntaxKind.WhitespaceTrivia, leading[2].Kind());
...@@ -8469,7 +8469,7 @@ public void Shebang() ...@@ -8469,7 +8469,7 @@ public void Shebang()
Assert.Equal(SyntaxKind.GlobalStatement, statement.Kind()); Assert.Equal(SyntaxKind.GlobalStatement, statement.Kind());
leading = statement.GetLeadingTrivia().ToArray(); leading = statement.GetLeadingTrivia().ToArray();
Assert.Equal(2, leading.Length); Assert.Equal(2, leading.Length);
Assert.Equal(SyntaxKind.ShebangCommentTrivia, leading[0].Kind()); Assert.Equal(SyntaxKind.ShebangTrivia, leading[0].Kind());
Assert.Equal(SyntaxKind.EndOfLineTrivia, leading[1].Kind()); Assert.Equal(SyntaxKind.EndOfLineTrivia, leading[1].Kind());
} }
......
...@@ -999,6 +999,68 @@ class Bar { ...@@ -999,6 +999,68 @@ class Bar {
Punctuation.CloseCurly); Punctuation.CloseCurly);
} }
[Fact, Trait(Traits.Feature, Traits.Features.Classification)]
public void ShebangAsFirstCommentInScript()
{
var code = @"#!/usr/bin/env scriptcs
System.Console.WriteLine();";
var expected = new[]
{
Comment("#!/usr/bin/env scriptcs"),
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Operators.Dot,
Identifier("WriteLine"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon
};
Test(code, code, expected, Options.Script);
}
[Fact, Trait(Traits.Feature, Traits.Features.Classification)]
public void ShebangAsFirstCommentInNonScript()
{
var code = @"#!/usr/bin/env scriptcs
System.Console.WriteLine();";
var expected = new[]
{
PPKeyword("#"),
PPText("!/usr/bin/env scriptcs"),
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Operators.Dot,
Identifier("WriteLine"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon
};
Test(code, code, expected, Options.Regular);
}
[Fact, Trait(Traits.Feature, Traits.Features.Classification)]
public void ShebangNotAsFirstCommentInScript()
{
var code = @" #!/usr/bin/env scriptcs
System.Console.WriteLine();";
var expected = new[]
{
PPKeyword("#"),
PPText("!/usr/bin/env scriptcs"),
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Operators.Dot,
Identifier("WriteLine"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon
};
Test(code, code, expected, Options.Script);
}
[Fact, Trait(Traits.Feature, Traits.Features.Classification)] [Fact, Trait(Traits.Feature, Traits.Features.Classification)]
public void CommentAsMethodBodyContent() public void CommentAsMethodBodyContent()
{ {
......
...@@ -8367,5 +8367,12 @@ class Class2 ...@@ -8367,5 +8367,12 @@ class Class2
}"; }";
VerifyItemExists(markup, "Property1"); VerifyItemExists(markup, "Property1");
} }
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public void NoCompletionInShebangComments()
{
VerifyNoItemsExist("#!$$", sourceCodeKind: SourceCodeKind.Script);
VerifyNoItemsExist("#! S$$", sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: true);
}
} }
} }
...@@ -318,10 +318,7 @@ private SyntaxTriviaList GetTriviaToPreserve(SyntaxTriviaList syntaxTriviaList) ...@@ -318,10 +318,7 @@ private SyntaxTriviaList GetTriviaToPreserve(SyntaxTriviaList syntaxTriviaList)
private static bool ShouldPreserve(SyntaxTriviaList trivia) private static bool ShouldPreserve(SyntaxTriviaList trivia)
{ {
return trivia.Any( return trivia.Any(t => t.IsRegularComment() || t.IsDirective);
t => t.Kind() == SyntaxKind.SingleLineCommentTrivia ||
t.Kind() == SyntaxKind.MultiLineCommentTrivia ||
t.IsDirective);
} }
private SyntaxNode RemoveDeclaratorFromVariableList(VariableDeclaratorSyntax variableDeclarator, VariableDeclarationSyntax variableDeclaration) private SyntaxNode RemoveDeclaratorFromVariableList(VariableDeclaratorSyntax variableDeclarator, VariableDeclarationSyntax variableDeclaration)
......
...@@ -1180,8 +1180,7 @@ private IList<SyntaxTrivia> CollectComments(IList<SyntaxTrivia> triviaList) ...@@ -1180,8 +1180,7 @@ private IList<SyntaxTrivia> CollectComments(IList<SyntaxTrivia> triviaList)
for (int i = triviaList.Count - 1; i >= 0; i--) for (int i = triviaList.Count - 1; i >= 0; i--)
{ {
var trivia = triviaList[i]; var trivia = triviaList[i];
if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || if (trivia.IsRegularComment())
trivia.Kind() == SyntaxKind.MultiLineCommentTrivia)
{ {
commentList.Add(trivia); commentList.Add(trivia);
} }
...@@ -1210,8 +1209,7 @@ public override string GetComment(SyntaxNode node) ...@@ -1210,8 +1209,7 @@ public override string GetComment(SyntaxNode node)
var textBuilder = new StringBuilder(); var textBuilder = new StringBuilder();
foreach (var trivia in commentList) foreach (var trivia in commentList)
{ {
if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || if (trivia.IsRegularComment())
trivia.Kind() == SyntaxKind.MultiLineCommentTrivia)
{ {
textBuilder.AppendLine(trivia.GetCommentText()); textBuilder.AppendLine(trivia.GetCommentText());
} }
......
...@@ -8,11 +8,9 @@ ...@@ -8,11 +8,9 @@
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Implementation.F1Help; using Microsoft.VisualStudio.LanguageServices.Implementation.F1Help;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -77,7 +75,7 @@ public override async Task<string> GetHelpTermAsync(Document document, TextSpan ...@@ -77,7 +75,7 @@ public override async Task<string> GetHelpTermAsync(Document document, TextSpan
return "#region"; return "#region";
} }
if (trivia.MatchesKind(SyntaxKind.MultiLineDocumentationCommentTrivia, SyntaxKind.SingleLineDocumentationCommentTrivia, SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia)) if (trivia.IsRegularOrDocComment())
{ {
// just find the first "word" that intersects with our position // just find the first "word" that intersects with our position
var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false);
......
...@@ -121,7 +121,7 @@ private void ClassifyToken(SyntaxToken token) ...@@ -121,7 +121,7 @@ private void ClassifyToken(SyntaxToken token)
private void ClassifyTrivia(SyntaxTrivia trivia) private void ClassifyTrivia(SyntaxTrivia trivia)
{ {
if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || trivia.Kind() == SyntaxKind.MultiLineCommentTrivia) if (trivia.IsRegularComment())
{ {
AddClassification(trivia, ClassificationTypeNames.Comment); AddClassification(trivia, ClassificationTypeNames.Comment);
} }
......
...@@ -175,9 +175,10 @@ static SyntaxNodeExtensions() ...@@ -175,9 +175,10 @@ static SyntaxNodeExtensions()
var endOfLine = Match(SyntaxKind.EndOfLineTrivia, "\\n"); var endOfLine = Match(SyntaxKind.EndOfLineTrivia, "\\n");
var singleBlankLine = Matcher.Sequence(whitespace, endOfLine); var singleBlankLine = Matcher.Sequence(whitespace, endOfLine);
var shebangComment = Match(SyntaxKind.ShebangTrivia, "#!");
var singleLineComment = Match(SyntaxKind.SingleLineCommentTrivia, "//"); var singleLineComment = Match(SyntaxKind.SingleLineCommentTrivia, "//");
var multiLineComment = Match(SyntaxKind.MultiLineCommentTrivia, "/**/"); var multiLineComment = Match(SyntaxKind.MultiLineCommentTrivia, "/**/");
var anyCommentMatcher = Matcher.Choice(singleLineComment, multiLineComment); var anyCommentMatcher = Matcher.Choice(shebangComment, singleLineComment, multiLineComment);
var commentLine = Matcher.Sequence(whitespace, anyCommentMatcher, whitespace, endOfLine); var commentLine = Matcher.Sequence(whitespace, anyCommentMatcher, whitespace, endOfLine);
......
...@@ -348,7 +348,7 @@ public static bool IsEntirelyWithinCrefSyntax(this SyntaxTree syntaxTree, int po ...@@ -348,7 +348,7 @@ public static bool IsEntirelyWithinCrefSyntax(this SyntaxTree syntaxTree, int po
trivia = trivia.GetPreviousTrivia(syntaxTree, cancellationToken); trivia = trivia.GetPreviousTrivia(syntaxTree, cancellationToken);
} }
if (trivia.IsSingleLineComment()) if (trivia.IsSingleLineComment() || trivia.IsShebang())
{ {
var span = trivia.FullSpan; var span = trivia.FullSpan;
......
...@@ -32,12 +32,12 @@ public static bool MatchesKind(this SyntaxTrivia trivia, params SyntaxKind[] kin ...@@ -32,12 +32,12 @@ public static bool MatchesKind(this SyntaxTrivia trivia, params SyntaxKind[] kin
public static bool IsRegularComment(this SyntaxTrivia trivia) public static bool IsRegularComment(this SyntaxTrivia trivia)
{ {
return trivia.IsSingleLineComment() || trivia.IsMultiLineComment(); return trivia.IsSingleLineComment() || trivia.IsMultiLineComment() || trivia.IsShebang();
} }
public static bool IsRegularOrDocComment(this SyntaxTrivia trivia) public static bool IsRegularOrDocComment(this SyntaxTrivia trivia)
{ {
return trivia.IsSingleLineComment() || trivia.IsMultiLineComment() || trivia.IsDocComment(); return trivia.IsRegularComment() || trivia.IsDocComment();
} }
public static bool IsSingleLineComment(this SyntaxTrivia trivia) public static bool IsSingleLineComment(this SyntaxTrivia trivia)
...@@ -50,6 +50,11 @@ public static bool IsMultiLineComment(this SyntaxTrivia trivia) ...@@ -50,6 +50,11 @@ public static bool IsMultiLineComment(this SyntaxTrivia trivia)
return trivia.Kind() == SyntaxKind.MultiLineCommentTrivia; return trivia.Kind() == SyntaxKind.MultiLineCommentTrivia;
} }
public static bool IsShebang(this SyntaxTrivia trivia)
{
return trivia.Kind() == SyntaxKind.ShebangTrivia;
}
public static bool IsCompleteMultiLineComment(this SyntaxTrivia trivia) public static bool IsCompleteMultiLineComment(this SyntaxTrivia trivia)
{ {
if (trivia.Kind() != SyntaxKind.MultiLineCommentTrivia) if (trivia.Kind() != SyntaxKind.MultiLineCommentTrivia)
......
...@@ -2,10 +2,6 @@ ...@@ -2,10 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Extensions namespace Microsoft.CodeAnalysis.CSharp.Extensions
...@@ -35,7 +31,7 @@ public static bool Any(this SyntaxTriviaList triviaList, params SyntaxKind[] kin ...@@ -35,7 +31,7 @@ public static bool Any(this SyntaxTriviaList triviaList, params SyntaxKind[] kin
public static SyntaxTrivia? GetLastComment(this SyntaxTriviaList triviaList) public static SyntaxTrivia? GetLastComment(this SyntaxTriviaList triviaList)
{ {
return triviaList return triviaList
.Where(t => t.MatchesKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia)) .Where(t => t.IsRegularComment())
.LastOrNullable(); .LastOrNullable();
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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.Collections.Generic;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Shared.Utilities namespace Microsoft.CodeAnalysis.Shared.Utilities
{ {
...@@ -9,25 +8,30 @@ internal partial class Matcher<T> ...@@ -9,25 +8,30 @@ internal partial class Matcher<T>
{ {
private class ChoiceMatcher : Matcher<T> private class ChoiceMatcher : Matcher<T>
{ {
private readonly Matcher<T> _matcher1; private readonly IEnumerable<Matcher<T>> _matchers;
private readonly Matcher<T> _matcher2;
public ChoiceMatcher(Matcher<T> matcher1, Matcher<T> matcher2) public ChoiceMatcher(params Matcher<T>[] matchers)
{ {
_matcher1 = matcher1; _matchers = matchers;
_matcher2 = matcher2;
} }
public override bool TryMatch(IList<T> sequence, ref int index) public override bool TryMatch(IList<T> sequence, ref int index)
{ {
return // we can't use .Any() here because ref parameters can't be used in lambdas
_matcher1.TryMatch(sequence, ref index) || foreach (var matcher in _matchers)
_matcher2.TryMatch(sequence, ref index); {
if (matcher.TryMatch(sequence, ref index))
{
return true;
}
}
return false;
} }
public override string ToString() public override string ToString()
{ {
return string.Format("({0}|{1})", _matcher1, _matcher2); return $"({string.Join("|", _matchers)})";
} }
} }
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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; using System;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Shared.Utilities namespace Microsoft.CodeAnalysis.Shared.Utilities
{ {
...@@ -24,11 +23,11 @@ public static Matcher<T> OneOrMore<T>(Matcher<T> matcher) ...@@ -24,11 +23,11 @@ public static Matcher<T> OneOrMore<T>(Matcher<T> matcher)
} }
/// <summary> /// <summary>
/// Matcher equivalent to (m_1|m_2) /// Matcher equivalent to (m_1|m_2|...|m_n)
/// </summary> /// </summary>
public static Matcher<T> Choice<T>(Matcher<T> matcher1, Matcher<T> matcher2) public static Matcher<T> Choice<T>(params Matcher<T>[] matchers)
{ {
return Matcher<T>.Choice(matcher1, matcher2); return Matcher<T>.Choice(matchers);
} }
/// <summary> /// <summary>
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Shared.Utilities namespace Microsoft.CodeAnalysis.Shared.Utilities
{ {
...@@ -29,9 +28,9 @@ internal static Matcher<T> OneOrMore(Matcher<T> matcher) ...@@ -29,9 +28,9 @@ internal static Matcher<T> OneOrMore(Matcher<T> matcher)
return Sequence(matcher, Repeat(matcher)); return Sequence(matcher, Repeat(matcher));
} }
internal static Matcher<T> Choice(Matcher<T> matcher1, Matcher<T> matcher2) internal static Matcher<T> Choice(params Matcher<T>[] matchers)
{ {
return new ChoiceMatcher(matcher1, matcher2); return new ChoiceMatcher(matchers);
} }
internal static Matcher<T> Sequence(params Matcher<T>[] matchers) internal static Matcher<T> Sequence(params Matcher<T>[] matchers)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册