Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
7ca148c8
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7ca148c8
编写于
6月 22, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Support datetime completion in interpolation format clauses.
上级
730e6342
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
524 addition
and
41 deletion
+524
-41
src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DateAndTime.vb
...iSense/CSharpCompletionCommandHandlerTests_DateAndTime.vb
+230
-0
src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests_DateAndTime.vb
...e/VisualBasicCompletionCommandHandlerTests_DateAndTime.vb
+210
-0
src/Features/Core/Portable/EmbeddedLanguages/DateAndTime/DateAndTimeEmbeddedCompletionProvider.cs
...ages/DateAndTime/DateAndTimeEmbeddedCompletionProvider.cs
+10
-2
src/Workspaces/Core/Portable/EmbeddedLanguages/DateAndTime/LanguageServices/DateAndTimeEmbeddedLanguage.cs
...teAndTime/LanguageServices/DateAndTimeEmbeddedLanguage.cs
+31
-4
src/Workspaces/Core/Portable/EmbeddedLanguages/DateAndTime/LanguageServices/DateAndTimePatternDetector.cs
...ateAndTime/LanguageServices/DateAndTimePatternDetector.cs
+31
-25
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/EmbeddedLanguages/VirtualChars/CSharpVirtualCharService.cs
...mbeddedLanguages/VirtualChars/CSharpVirtualCharService.cs
+5
-8
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs
...Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs
+2
-0
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs
...nsions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs
+2
-0
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/EmbeddedLanguages/VirtualChars/VisualBasicVirtualCharService.vb
...edLanguages/VirtualChars/VisualBasicVirtualCharService.vb
+1
-2
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb
...isualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb
+2
-0
未找到文件。
src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DateAndTime.vb
浏览文件 @
7ca148c8
...
...
@@ -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
src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests_DateAndTime.vb
0 → 100644
浏览文件 @
7ca148c8
' 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
src/Features/Core/Portable/EmbeddedLanguages/DateAndTime/DateAndTimeEmbeddedCompletionProvider.cs
浏览文件 @
7ca148c8
...
...
@@ -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
);
...
...
src/Workspaces/Core/Portable/EmbeddedLanguages/DateAndTime/LanguageServices/DateAndTimeEmbeddedLanguage.cs
浏览文件 @
7ca148c8
...
...
@@ -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
;
}
}
}
src/Workspaces/Core/Portable/EmbeddedLanguages/DateAndTime/LanguageServices/DateAndTimePatternDetector.cs
浏览文件 @
7ca148c8
...
...
@@ -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
IsPossiblyDateAndTime
Argument
Token
(
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
(
!
IsPossiblyDateAndTime
Token
(
if
(
IsPossiblyDateAndTimeArgument
Token
(
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
(
I
NamedTypeSymbol
containingT
ype
)
=>
_dateTimeType
.
Equals
(
containingType
)
||
_dateTimeOffsetType
.
Equals
(
containingT
ype
);
private
bool
IsDateTimeType
(
I
TypeSymbol
?
t
ype
)
=>
_dateTimeType
.
Equals
(
type
)
||
_dateTimeOffsetType
.
Equals
(
t
ype
);
private
static
bool
AnalyzeStringLiteral
(
IMethodSymbol
method
,
string
?
argName
,
int
?
argIndex
)
{
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/EmbeddedLanguages/VirtualChars/CSharpVirtualCharService.cs
浏览文件 @
7ca148c8
...
...
@@ -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
)
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs
浏览文件 @
7ca148c8
...
...
@@ -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
;
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs
浏览文件 @
7ca148c8
...
...
@@ -52,6 +52,8 @@ internal interface ISyntaxKinds
#
region
tokens
int
CloseBraceToken
{
get
;
}
int
ColonToken
{
get
;
}
int
DotToken
{
get
;
}
int
EndOfFileToken
{
get
;
}
int
HashToken
{
get
;
}
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/EmbeddedLanguages/VirtualChars/VisualBasicVirtualCharService.vb
浏览文件 @
7ca148c8
...
...
@@ -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
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb
浏览文件 @
7ca148c8
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录