提交 7ca148c8 编写于 作者: C Cyrus Najmabadi

Support datetime completion in interpolation format clauses.

上级 730e6342
......@@ -162,5 +162,235 @@ class c
End If
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke_StringInterpolation1(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = $"Text {d:$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("G", inlineDescription:=FeaturesResources.general_long_date_time)
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("_ = $""Text {d:G}""", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke_StringInterpolation2(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = @$"Text {d:$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("G", inlineDescription:=FeaturesResources.general_long_date_time)
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("_ = @$""Text {d:G}""", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke_OverwriteExisting_StringInterpolation1(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = $"Text {d:ff$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("ff")
state.SendDownKey()
Await state.AssertSelectedCompletionItem("FF")
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("_ = $""Text {d:FF}""", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke_OverwriteExisting_StringInterpolation2(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = @$"Text {d:ff$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("ff")
state.SendDownKey()
Await state.AssertSelectedCompletionItem("FF")
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("_ = @$""Text {d:FF}""", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_BeginningOfWord_StringInterpolation1(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = $"Text {d:$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendTypeChars("f")
Await state.AssertCompletionSession()
Await state.AssertSelectedCompletionItem("f")
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_BeginningOfWord_StringInterpolation2(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = $@"Text {d:$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendTypeChars("f")
Await state.AssertCompletionSession()
Await state.AssertSelectedCompletionItem("f")
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestExample1_StringInterpolation1(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = $"Text {d:hh:mm:$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendInvokeCompletionList()
state.SendTypeChars("ss")
Await state.AssertSelectedCompletionItem("ss", inlineDescription:=FeaturesResources.second_2_digits)
Dim description = Await state.GetSelectedItemDescriptionAsync()
Dim text = description.Text
If CultureInfo.CurrentCulture.Name <> "en-US" Then
Assert.Contains($"hh:mm:ss (en-US) 01:45:30", text)
Assert.Contains($"hh:mm:ss ({CultureInfo.CurrentCulture.Name}) 01:45:30", text)
Else
Assert.Contains("hh:mm:ss 01:45:30", text)
End If
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestExample1_StringInterpolation2(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = @$"Text {d:hh:mm:$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendInvokeCompletionList()
state.SendTypeChars("ss")
Await state.AssertSelectedCompletionItem("ss", inlineDescription:=FeaturesResources.second_2_digits)
Dim description = Await state.GetSelectedItemDescriptionAsync()
Dim text = description.Text
If CultureInfo.CurrentCulture.Name <> "en-US" Then
Assert.Contains($"hh:mm:ss (en-US) 01:45:30", text)
Assert.Contains($"hh:mm:ss ({CultureInfo.CurrentCulture.Name}) 01:45:30", text)
Else
Assert.Contains("hh:mm:ss 01:45:30", text)
End If
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_MiddleOfWord_StringInterpolation1(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = $"Text {date:f$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendTypeChars("f")
Await state.AssertNoCompletionSession()
End Using
End Function
<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_MiddleOfWord_StringInterpolation2(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
using System;
class c
{
void goo(DateTime d)
{
_ = @$"Text {date:f$$}";
}
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
state.SendTypeChars("f")
Await state.AssertNoCompletionSession()
End Using
End Function
End Class
End Namespace
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
Imports System.Globalization
Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
<[UseExportProvider]>
Public Class VisualBasicCompletionCommandHandlerTests_DateAndTime
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
d.ToString("$$")
end sub
end class
]]></Document>)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("G", inlineDescription:=FeaturesResources.general_long_date_time)
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("d.ToString(""G"")", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke_OverwriteExisting() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
d.ToString(":ff$$")
end sub
end class
]]></Document>)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("ff")
state.SendDownKey()
Await state.AssertSelectedCompletionItem("FF")
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("d.ToString("":FF"")", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_BeginningOfWord() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
d.ToString("$$")
end sub
end class
]]></Document>)
state.SendTypeChars("f")
Await state.AssertCompletionSession()
Await state.AssertSelectedCompletionItem("f")
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_MiddleOfWord() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
d.ToString("f$$")
end sub
end class
]]></Document>)
state.SendTypeChars("f")
Await state.AssertNoCompletionSession()
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestExample1() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
d.ToString("hh:mm:$$")
end sub
end class
]]></Document>)
state.SendInvokeCompletionList()
state.SendTypeChars("ss")
Await state.AssertSelectedCompletionItem("ss", inlineDescription:=FeaturesResources.second_2_digits)
Dim description = Await state.GetSelectedItemDescriptionAsync()
Dim text = description.Text
If CultureInfo.CurrentCulture.Name <> "en-US" Then
Assert.Contains($"hh:mm:ss (en-US) → 01:45:30", text)
Assert.Contains($"hh:mm:ss ({CultureInfo.CurrentCulture.Name}) → 01:45:30", text)
Else
Assert.Contains("hh:mm:ss → 01:45:30", text)
End If
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke_StringInterpolation() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
Dim str = $"Text {d:$$}"
end sub
end class
]]></Document>)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("G", inlineDescription:=FeaturesResources.general_long_date_time)
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("Dim str = $""Text {d:G}""", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function ExplicitInvoke_OverwriteExisting_StringInterpolation() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
Dim str = $"Text {d:ff$$}"
end sub
end class
]]></Document>)
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem("ff")
state.SendDownKey()
Await state.AssertSelectedCompletionItem("FF")
state.SendTab()
Await state.AssertNoCompletionSession()
Assert.Contains("Dim str = $""Text {d:FF}""", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal)
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_BeginningOfWord_StringInterpolation() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
Dim str = $"Text {d:$$}"
end sub
end class
]]></Document>)
state.SendTypeChars("f")
Await state.AssertCompletionSession()
Await state.AssertSelectedCompletionItem("f")
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestExample1_StringInterpolation() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
Dim str = $"Text {d:hh:mm:$$}"
end sub
end class
]]></Document>)
state.SendInvokeCompletionList()
state.SendTypeChars("ss")
Await state.AssertSelectedCompletionItem("ss", inlineDescription:=FeaturesResources.second_2_digits)
Dim description = Await state.GetSelectedItemDescriptionAsync()
Dim text = description.Text
If CultureInfo.CurrentCulture.Name <> "en-US" Then
Assert.Contains($"hh:mm:ss (en-US) → 01:45:30", text)
Assert.Contains($"hh:mm:ss ({CultureInfo.CurrentCulture.Name}) → 01:45:30", text)
Else
Assert.Contains("hh:mm:ss → 01:45:30", text)
End If
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TypeChar_MiddleOfWord_StringInterpolation() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
class c
sub goo(d As Date)
Dim str = $"Text {date:f$$}"
end sub
end class
]]></Document>)
state.SendTypeChars("f")
Await state.AssertNoCompletionSession()
End Using
End Function
End Class
End Namespace
......@@ -10,8 +10,10 @@
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.EmbeddedLanguages.DateAndTime;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
......@@ -80,9 +82,15 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
if (stringTokenOpt == null)
return;
var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>();
var stringToken = stringTokenOpt.Value;
if (position <= stringToken.SpanStart || position >= stringToken.Span.End)
return;
// If we're not in an interpolation, at least make sure we're within the bounds of the string.
if (stringToken.RawKind != syntaxFacts.SyntaxKinds.InterpolatedStringTextToken)
{
if (position <= stringToken.SpanStart || position >= stringToken.Span.End)
return;
}
// Note: it's acceptable if this fails to convert. We just won't show the example in that case.
var virtualChars = _language.Info.VirtualCharService.TryConvertToVirtualChars(stringToken);
......
......@@ -4,6 +4,7 @@
#nullable enable
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification.Classifiers;
......@@ -28,16 +29,42 @@ public DateAndTimeEmbeddedLanguage(EmbeddedLanguageInfo info)
internal async Task<SyntaxToken?> TryGetDateAndTimeTokenAtPositionAsync(
Document document, int position, CancellationToken cancellationToken)
{
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(position);
var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>();
if (!DateAndTimePatternDetector.IsPossiblyDateAndTimeToken(token, syntaxFacts, out _, out _))
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = GetToken(syntaxFacts, root, position);
if (!DateAndTimePatternDetector.IsPossiblyDateAndTimeArgumentToken(token, syntaxFacts, out _, out _) &&
token.RawKind != syntaxFacts.SyntaxKinds.InterpolatedStringTextToken)
{
return null;
}
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var detector = DateAndTimePatternDetector.TryGetOrCreate(semanticModel, this.Info);
return detector != null && detector.IsDateAndTimeToken(token, cancellationToken)
return detector != null && detector.IsDateAndTimeToken(token, syntaxFacts, cancellationToken)
? token : (SyntaxToken?)null;
}
private static SyntaxToken GetToken(ISyntaxFactsService syntaxFacts, SyntaxNode root, int position)
{
var token = root.FindToken(position);
var syntaxKinds = syntaxFacts.SyntaxKinds;
if (token.RawKind == syntaxKinds.CloseBraceToken)
{
// Might be here: $"Date is: {date:$$}" or
// $"Date is: {date:G$$}"
//
// If so, we want to return the InterpolatedStringTextToken following the `:`
var previous = token.GetPreviousToken();
if (previous.RawKind == syntaxKinds.InterpolatedStringTextToken)
return previous;
if (previous.RawKind == syntaxKinds.ColonToken)
return previous.GetNextToken(includeZeroWidth: true);
}
return token;
}
}
}
......@@ -77,7 +77,7 @@ internal sealed class DateAndTimePatternDetector
/// format string passed into an method call. If so, <paramref name="argumentNode"/> and <paramref
/// name="invocationExpression"/> will be the argument and invocatoin the string literal was passed as.
/// </summary>
public static bool IsPossiblyDateAndTimeToken(
public static bool IsPossiblyDateAndTimeArgumentToken(
SyntaxToken token, ISyntaxFacts syntaxFacts,
[NotNullWhen(true)] out SyntaxNode? argumentNode,
[NotNullWhen(true)] out SyntaxNode? invocationExpression)
......@@ -131,34 +131,40 @@ private static bool IsMethodArgument(SyntaxToken token, ISyntaxFacts syntaxFacts
=> syntaxFacts.IsLiteralExpression(token.Parent) &&
syntaxFacts.IsArgument(token.Parent!.Parent);
public bool IsDateAndTimeToken(SyntaxToken token, CancellationToken cancellationToken)
public bool IsDateAndTimeToken(SyntaxToken token, ISyntaxFacts syntaxFacts, CancellationToken cancellationToken)
{
if (!IsPossiblyDateAndTimeToken(
if (IsPossiblyDateAndTimeArgumentToken(
token, _info.SyntaxFacts,
out var argumentNode, out var invocationOrCreation))
{
return false;
}
// if we couldn't determine the arg name or arg index, can't proceed.
var (argName, argIndex) = GetArgumentNameOrIndex(argumentNode);
if (argName == null && argIndex == null)
return false;
// If we had a specified arg name and it isn't 'format', then it's not a DateTime
// 'format' param we care about.
if (argName != null && argName != FormatName)
return false;
var symbolInfo = _semanticModel.GetSymbolInfo(invocationOrCreation, cancellationToken);
var method = symbolInfo.Symbol;
if (TryAnalyzeInvocation(method, argName, argIndex))
return true;
// if we couldn't determine the arg name or arg index, can't proceed.
var (argName, argIndex) = GetArgumentNameOrIndex(argumentNode);
if (argName == null && argIndex == null)
return false;
// If we had a specified arg name and it isn't 'format', then it's not a DateTime
// 'format' param we care about.
if (argName != null && argName != FormatName)
return false;
var symbolInfo = _semanticModel.GetSymbolInfo(invocationOrCreation, cancellationToken);
var method = symbolInfo.Symbol;
if (TryAnalyzeInvocation(method, argName, argIndex))
return true;
foreach (var candidate in symbolInfo.CandidateSymbols)
foreach (var candidate in symbolInfo.CandidateSymbols)
{
if (TryAnalyzeInvocation(candidate, argName, argIndex))
return true;
}
}
else if (token.RawKind == syntaxFacts.SyntaxKinds.InterpolatedStringTextToken)
{
if (TryAnalyzeInvocation(candidate, argName, argIndex))
return true;
var interpolationFormatClause = token.Parent!;
var interpolation = interpolationFormatClause.Parent!;
var expression = syntaxFacts.GetExpressionOfInterpolation(interpolation);
var type = _semanticModel.GetTypeInfo(expression, cancellationToken).Type;
return IsDateTimeType(type);
}
return false;
......@@ -187,8 +193,8 @@ private bool TryAnalyzeInvocation(ISymbol? symbol, string? argName, int? argInde
IsDateTimeType(method.ContainingType) &&
AnalyzeStringLiteral(method, argName, argIndex);
private bool IsDateTimeType(INamedTypeSymbol containingType)
=> _dateTimeType.Equals(containingType) || _dateTimeOffsetType.Equals(containingType);
private bool IsDateTimeType(ITypeSymbol? type)
=> _dateTimeType.Equals(type) || _dateTimeOffsetType.Equals(type);
private static bool AnalyzeStringLiteral(IMethodSymbol method, string? argName, int? argIndex)
{
......
......@@ -39,9 +39,7 @@ protected override VirtualCharSequence TryConvertToVirtualCharsWorker(SyntaxToke
// we won't classify any escape characters. And there is no way that these strings would
// be Regex/Json snippets. So it's easier to just bail out and return nothing.
if (IsInDirective(token.Parent))
{
return default;
}
Debug.Assert(!token.ContainsDiagnostics);
if (token.Kind() == SyntaxKind.StringLiteralToken)
......@@ -52,16 +50,15 @@ protected override VirtualCharSequence TryConvertToVirtualCharsWorker(SyntaxToke
}
if (token.Kind() == SyntaxKind.CharacterLiteralToken)
{
return TryConvertStringToVirtualChars(token, "'", "'", escapeBraces: false);
}
if (token.Kind() == SyntaxKind.InterpolatedStringTextToken)
{
// The sections between `}` and `{` are InterpolatedStringTextToken *as are* the
// format specifiers in an interpolated string. We only want to get the virtual
// chars for this first type.
if (token.Parent.Parent is InterpolatedStringExpressionSyntax interpolatedString)
var parent = token.Parent;
if (parent is InterpolationFormatClauseSyntax)
parent = parent.Parent;
if (parent.Parent is InterpolatedStringExpressionSyntax interpolatedString)
{
return interpolatedString.StringStartToken.Kind() == SyntaxKind.InterpolatedVerbatimStringStartToken
? TryConvertVerbatimStringToVirtualChars(token, "", "", escapeBraces: true)
......
......@@ -28,6 +28,8 @@ protected CSharpSyntaxKinds()
public int SingleLineCommentTrivia => (int)SyntaxKind.SingleLineCommentTrivia;
public int? MultiLineCommentTrivia => (int)SyntaxKind.MultiLineCommentTrivia;
public int CloseBraceToken => (int)SyntaxKind.CloseBraceToken;
public int ColonToken => (int)SyntaxKind.ColonToken;
public int CharacterLiteralToken => (int)SyntaxKind.CharacterLiteralToken;
public int DotToken => (int)SyntaxKind.DotToken;
public int InterpolatedStringTextToken => (int)SyntaxKind.InterpolatedStringTextToken;
......
......@@ -52,6 +52,8 @@ internal interface ISyntaxKinds
#region tokens
int CloseBraceToken { get; }
int ColonToken { get; }
int DotToken { get; }
int EndOfFileToken { get; }
int HashToken { get; }
......
......@@ -32,8 +32,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EmbeddedLanguages.VirtualChars
Return TryConvertSimpleDoubleQuoteString(token, """", """", escapeBraces:=False)
End If
If token.Kind() = SyntaxKind.InterpolatedStringTextToken AndAlso
TypeOf token.Parent.Parent Is InterpolatedStringExpressionSyntax Then
If token.Kind() = SyntaxKind.InterpolatedStringTextToken Then
Return TryConvertSimpleDoubleQuoteString(token, "", "", escapeBraces:=True)
End If
......
......@@ -26,6 +26,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageServices
Public ReadOnly Property SingleLineCommentTrivia As Integer = SyntaxKind.CommentTrivia Implements ISyntaxKinds.SingleLineCommentTrivia
Private ReadOnly Property MultiLineCommentTrivia As Integer? = Nothing Implements ISyntaxKinds.MultiLineCommentTrivia
Public ReadOnly Property CloseBraceToken As Integer = SyntaxKind.CloseBraceToken Implements ISyntaxKinds.CloseBraceToken
Public ReadOnly Property ColonToken As Integer = SyntaxKind.ColonToken Implements ISyntaxKinds.ColonToken
Public ReadOnly Property CharacterLiteralToken As Integer = SyntaxKind.CharacterLiteralToken Implements ISyntaxKinds.CharacterLiteralToken
Public ReadOnly Property DotToken As Integer = SyntaxKind.DotToken Implements ISyntaxKinds.DotToken
Public ReadOnly Property InterpolatedStringTextToken As Integer = SyntaxKind.InterpolatedStringTextToken Implements ISyntaxKinds.InterpolatedStringTextToken
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册