Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
3df54594
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,发现更多精彩内容 >>
提交
3df54594
编写于
3月 20, 2017
作者:
L
lorcanmooney
提交者:
Sam Harwell
8月 31, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Feedback from CyrusNajmabadi
上级
accff1e2
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
162 addition
and
91 deletion
+162
-91
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs
...oviders/XmlDocumentationCommentCompletionProviderTests.cs
+39
-1
src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb
...mpletionProviders/XmlDocCommentCompletionProviderTests.vb
+31
-0
src/Features/CSharp/Portable/Completion/CompletionProviders/XmlDocCommentCompletionProvider.cs
...on/CompletionProviders/XmlDocCommentCompletionProvider.cs
+62
-61
src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs
...pletion/Providers/AbstractDocCommentCompletionProvider.cs
+18
-20
src/Features/VisualBasic/Portable/Completion/CompletionProviders/XmlDocCommentCompletionProvider.vb
...on/CompletionProviders/XmlDocCommentCompletionProvider.vb
+12
-4
src/Workspaces/CSharp/Portable/Extensions/SyntaxTokenExtensions.cs
...paces/CSharp/Portable/Extensions/SyntaxTokenExtensions.cs
+0
-5
未找到文件。
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs
浏览文件 @
3df54594
...
...
@@ -1203,7 +1203,26 @@ public class Inner<TInner>
await
VerifyItemsExistAsync
(
text
,
"TOuter"
,
"TInner"
,
"TMethod"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
[
WorkItem
(
17872
,
"https://github.com/dotnet/roslyn/issues/17872"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
TypeParamRefNamesPartiallyTyped
()
{
var
text
=
@"
public class Outer<TOuter>
{
public class Inner<TInner>
{
/// <summary>
/// <typeparamref name=""T$$""/>
/// </summary>
public int Method<TMethod>(T green) { }
}
}"
;
await
VerifyItemsExistAsync
(
text
,
"TOuter"
,
"TInner"
,
"TMethod"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
TypeParamNames
()
{
var
text
=
@"
...
...
@@ -1222,6 +1241,25 @@ public class Inner<TInner>
await
VerifyItemsAbsentAsync
(
text
,
"TOuter"
,
"TInner"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
TypeParamNamesPartiallyTyped
()
{
var
text
=
@"
public class Outer<TOuter>
{
public class Inner<TInner>
{
/// <summary>
/// <typeparam name=""T$$""/>
/// </summary>
public int Method<TMethod>(T green) { }
}
}"
;
await
VerifyItemsExistAsync
(
text
,
"TMethod"
);
await
VerifyItemsAbsentAsync
(
text
,
"TOuter"
,
"TInner"
);
}
[
WorkItem
(
8322
,
"https://github.com/dotnet/roslyn/issues/8322"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
PartialTagCompletion
()
...
...
src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb
浏览文件 @
3df54594
...
...
@@ -818,6 +818,19 @@ End Class
Await
VerifyItemsAbsentAsync
(
text
,
"TClass"
,
"i"
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)
>
Public
Async
Function
TestTypeParamNamesPartiallyTyped
()
As
Task
Dim
text
=
"
Class C(Of TClass)
''' <typeparam name=
""
T$$
""
Sub Goo(Of TMethod)(i as TMethod)
End Sub
End Class
"
Await
VerifyItemsExistAsync
(
text
,
"TMethod"
)
Await
VerifyItemsAbsentAsync
(
text
,
"TClass"
,
"i"
)
End
Function
<
WorkItem
(
17872
,
"https://github.com/dotnet/roslyn/issues/17872"
)
>
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)
>
Public
Async
Function
TestTypeParamRefNames
()
As
Task
...
...
@@ -831,6 +844,24 @@ Class Outer(Of TOuter)
End Sub
End Class
End Class
"
Await
VerifyItemsExistAsync
(
text
,
"TOuter"
,
"TInner"
,
"TMethod"
)
Await
VerifyItemsAbsentAsync
(
text
,
"i"
)
End
Function
<
WorkItem
(
17872
,
"https://github.com/dotnet/roslyn/issues/17872"
)
>
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)
>
Public
Async
Function
TestTypeParamRefNamesPartiallyTyped
()
As
Task
Dim
text
=
"
Class Outer(Of TOuter)
Class Inner(Of TInner)
''' <summary>
''' <typeparamref name=
""
T$$
""
''' </summary>
Sub Goo(Of TMethod)(i as Integer)
End Sub
End Class
End Class
"
Await
VerifyItemsExistAsync
(
text
,
"TOuter"
,
"TInner"
,
"TMethod"
)
Await
VerifyItemsAbsentAsync
(
text
,
"i"
)
...
...
src/Features/CSharp/Portable/Completion/CompletionProviders/XmlDocCommentCompletionProvider.cs
浏览文件 @
3df54594
...
...
@@ -62,21 +62,28 @@ internal override bool IsInsertionTrigger(SourceText text, int characterPosition
}
}
string
elementName
,
attributeName
;
if
(!(
trigger
.
Kind
==
CompletionTriggerKind
.
Insertion
&&
trigger
.
Character
==
' '
)
&&
IsAttributeValueContext
(
token
,
out
elementName
,
out
attributeName
))
if
(
IsAttributeNameContext
(
token
,
position
,
out
string
elementName
,
out
ISet
<
string
>
existingAttributes
))
{
return
GetAttribute
ValueItems
(
declaredSymbol
,
elementName
,
attributeName
);
return
GetAttribute
Items
(
elementName
,
existingAttributes
);
}
ISet
<
string
>
existingAttributes
;
if
(
IsAttributeNameContext
(
token
,
position
,
out
elementName
,
out
existingAttributes
)
)
var
wasTriggeredAfterSpace
=
trigger
.
Kind
==
CompletionTriggerKind
.
Insertion
&&
trigger
.
Character
==
' '
;
if
(
wasTriggeredAfterSpace
)
{
return
GetAttributeItems
(
elementName
,
existingAttributes
);
// Nothing below this point should triggered by a space character
// (only attribute names should be triggered by <SPACE>)
return
null
;
}
if
(
IsAttributeValueContext
(
token
,
out
elementName
,
out
string
attributeName
))
{
return
GetAttributeValueItems
(
declaredSymbol
,
elementName
,
attributeName
);
}
if
(
trigger
.
Kind
==
CompletionTriggerKind
.
Insertion
&&
trigger
.
Character
!=
'<'
)
{
// With the use of IsTriggerAfterSpaceOrStartOfWordCharacter, the code below is much
// too aggressive at suggesting tags, so exit early before degrading the experience
return
null
;
}
...
...
@@ -158,26 +165,27 @@ private bool IsAttributeNameContext(SyntaxToken token, int position, out string
// Handle the <elem$$ case by going back one token (the subsequent checks need to account for this)
token
=
token
.
GetPreviousTokenIfTouchingWord
(
position
);
SyntaxList
<
XmlAttributeSyntax
>
attributes
=
default
(
SyntaxList
<
XmlAttributeSyntax
>);
var
attributes
=
default
(
SyntaxList
<
XmlAttributeSyntax
>);
if
(
token
.
IsKind
(
SyntaxKind
.
IdentifierToken
)
&&
token
.
IsParent
Kind
(
SyntaxKind
.
XmlName
))
if
(
token
.
IsKind
(
SyntaxKind
.
IdentifierToken
)
&&
token
.
Parent
.
Is
Kind
(
SyntaxKind
.
XmlName
))
{
// <elem $$
// <elem attr$$
elementName
=
GetElementNameAndAttributes
(
token
.
Parent
.
Parent
,
out
attributes
);
(
elementName
,
attributes
)
=
GetElementNameAndAttributes
(
token
.
Parent
.
Parent
);
}
else
if
(
token
.
IsParent
Kind
(
SyntaxKind
.
XmlCrefAttribute
)
||
token
.
IsParent
Kind
(
SyntaxKind
.
XmlNameAttribute
)
||
token
.
IsParent
Kind
(
SyntaxKind
.
XmlTextAttribute
))
else
if
(
token
.
Parent
.
Is
Kind
(
SyntaxKind
.
XmlCrefAttribute
)
||
token
.
Parent
.
Is
Kind
(
SyntaxKind
.
XmlNameAttribute
)
||
token
.
Parent
.
Is
Kind
(
SyntaxKind
.
XmlTextAttribute
))
{
// <elem attr="" $$
// <elem attr="" $$attr
// <elem attr="" attr$$
// In the following, 'attr1' may be a regular text attribute, or one of the special 'cref' or 'name' attributes
// <elem attr1="" $$
// <elem attr1="" $$attr2
// <elem attr1="" attr2$$
var
attributeSyntax
=
(
XmlAttributeSyntax
)
token
.
Parent
;
if
(
token
==
attributeSyntax
.
EndQuoteToken
)
{
elementName
=
GetElementNameAndAttributes
(
attributeSyntax
.
Parent
,
out
attributes
);
(
elementName
,
attributes
)
=
GetElementNameAndAttributes
(
attributeSyntax
.
Parent
);
}
}
...
...
@@ -185,24 +193,26 @@ private bool IsAttributeNameContext(SyntaxToken token, int position, out string
return
elementName
!=
null
;
}
private
string
GetElementNameAndAttributes
(
SyntaxNode
node
,
out
SyntaxList
<
XmlAttributeSyntax
>
attributes
)
private
(
string
name
,
SyntaxList
<
XmlAttributeSyntax
>
attributes
)
GetElementNameAndAttributes
(
SyntaxNode
node
)
{
XmlNameSyntax
nameSyntax
;
SyntaxList
<
XmlAttributeSyntax
>
attributes
;
switch
(
node
.
Kind
()
)
switch
(
node
)
{
case
SyntaxKind
.
XmlEmptyElement
:
var
emptyElementSyntax
=
(
XmlEmptyElementSyntax
)
node
;
// Self contained empty element <tag />
case
XmlEmptyElementSyntax
emptyElementSyntax
:
nameSyntax
=
emptyElementSyntax
.
Name
;
attributes
=
emptyElementSyntax
.
Attributes
;
break
;
case
SyntaxKind
.
XmlElement
:
node
=
((
XmlElementSyntax
)
node
).
StartTag
;
goto
case
SyntaxKind
.
XmlElementStartTag
;
// Parent node of a non-empty element: <tag></tag>
case
XmlElementSyntax
elementSyntax
:
// Defer to the start-tag logic
return
GetElementNameAndAttributes
(
elementSyntax
.
StartTag
);
case
SyntaxKind
.
XmlElementStartTag
:
var
startTagSyntax
=
(
XmlElementStartTagSyntax
)
node
;
// Start tag of a non-empty element: <tag>
case
XmlElementStartTagSyntax
startTagSyntax
:
nameSyntax
=
startTagSyntax
.
Name
;
attributes
=
startTagSyntax
.
Attributes
;
break
;
...
...
@@ -213,27 +223,28 @@ private string GetElementNameAndAttributes(SyntaxNode node, out SyntaxList<XmlAt
break
;
}
return
nameSyntax
?.
LocalName
.
ValueText
;
return
(
name
:
nameSyntax
?.
LocalName
.
ValueText
,
attributes
:
attributes
)
;
}
private
bool
IsAttributeValueContext
(
SyntaxToken
token
,
out
string
tagName
,
out
string
attributeName
)
{
XmlAttributeSyntax
attributeSyntax
=
null
;
if
(
token
.
IsParent
Kind
(
SyntaxKind
.
IdentifierName
)
&&
token
.
Parent
.
IsParentKind
(
SyntaxKind
.
XmlNameAttribute
))
if
(
token
.
Parent
.
Is
Kind
(
SyntaxKind
.
IdentifierName
)
&&
token
.
Parent
.
IsParentKind
(
SyntaxKind
.
XmlNameAttribute
))
{
// name="bar$$
//
Handle the special 'name' attributes:
name="bar$$
attributeSyntax
=
(
XmlNameAttributeSyntax
)
token
.
Parent
.
Parent
;
}
else
if
(
token
.
IsKind
(
SyntaxKind
.
XmlTextLiteralToken
)
&&
token
.
IsParent
Kind
(
SyntaxKind
.
XmlTextAttribute
))
else
if
(
token
.
IsKind
(
SyntaxKind
.
XmlTextLiteralToken
)
&&
token
.
Parent
.
Is
Kind
(
SyntaxKind
.
XmlTextAttribute
))
{
// foo="bar$$
//
Handle the other general text attributes:
foo="bar$$
attributeSyntax
=
(
XmlTextAttributeSyntax
)
token
.
Parent
;
}
else
if
(
token
.
IsParentKind
(
SyntaxKind
.
XmlNameAttribute
)
||
token
.
IsParent
Kind
(
SyntaxKind
.
XmlTextAttribute
))
else
if
(
token
.
Parent
.
IsKind
(
SyntaxKind
.
XmlNameAttribute
)
||
token
.
Parent
.
Is
Kind
(
SyntaxKind
.
XmlTextAttribute
))
{
// name="$$
// foo="$$
// When there's no attribute value yet, the parent attribute is returned:
// name="$$
// foo="$$
attributeSyntax
=
(
XmlAttributeSyntax
)
token
.
Parent
;
if
(
token
!=
attributeSyntax
.
StartQuoteToken
)
{
...
...
@@ -241,7 +252,6 @@ private bool IsAttributeValueContext(SyntaxToken token, out string tagName, out
}
}
if
(
attributeSyntax
!=
null
)
{
attributeName
=
attributeSyntax
.
Name
.
LocalName
.
ValueText
;
...
...
@@ -249,17 +259,17 @@ private bool IsAttributeValueContext(SyntaxToken token, out string tagName, out
var
emptyElement
=
attributeSyntax
.
GetAncestor
<
XmlEmptyElementSyntax
>();
if
(
emptyElement
!=
null
)
{
// Empty element tags: <tag attr=... />
tagName
=
emptyElement
.
Name
.
LocalName
.
Text
;
return
true
;
}
else
var
startTagSyntax
=
token
.
GetAncestor
<
XmlElementStartTagSyntax
>();
if
(
startTagSyntax
!=
null
)
{
var
startTagSyntax
=
token
.
GetAncestor
<
XmlElementStartTagSyntax
>();
if
(
startTagSyntax
!=
null
)
{
tagName
=
startTagSyntax
.
Name
.
LocalName
.
Text
;
return
true
;
}
// Non-empty element start tags: <tag attr=... >
tagName
=
startTagSyntax
.
Name
.
LocalName
.
Text
;
return
true
;
}
}
...
...
@@ -268,15 +278,11 @@ private bool IsAttributeValueContext(SyntaxToken token, out string tagName, out
return
false
;
}
protected
override
IEnumerable
<
string
>
GetKeywordNames
()
{
return
SyntaxFacts
.
GetKeywordKinds
().
Select
(
SyntaxFacts
.
GetText
);
}
protected
override
IEnumerable
<
string
>
GetKeywordNames
()
=>
SyntaxFacts
.
GetKeywordKinds
().
Select
(
SyntaxFacts
.
GetText
);
protected
override
IEnumerable
<
string
>
GetExistingTopLevelElementNames
(
DocumentationCommentTriviaSyntax
syntax
)
{
return
syntax
.
Content
.
Select
(
GetElementName
);
}
protected
override
IEnumerable
<
string
>
GetExistingTopLevelElementNames
(
DocumentationCommentTriviaSyntax
syntax
)
=>
syntax
.
Content
.
Select
(
GetElementName
);
protected
override
IEnumerable
<
string
>
GetExistingTopLevelAttributeValues
(
DocumentationCommentTriviaSyntax
syntax
,
string
elementName
,
string
attributeName
)
{
...
...
@@ -284,8 +290,9 @@ protected override IEnumerable<string> GetExistingTopLevelAttributeValues(Docume
foreach
(
var
node
in
syntax
.
Content
)
{
SyntaxList
<
XmlAttributeSyntax
>
attributes
;
if
(
GetElementNameAndAttributes
(
node
,
out
attributes
)
==
elementName
)
(
var
name
,
var
attributes
)
=
GetElementNameAndAttributes
(
node
);
if
(
name
==
elementName
)
{
attributeValues
=
attributeValues
.
Concat
(
attributes
.
Where
(
attribute
=>
GetAttributeName
(
attribute
)
==
attributeName
)
...
...
@@ -296,22 +303,16 @@ protected override IEnumerable<string> GetExistingTopLevelAttributeValues(Docume
return
attributeValues
;
}
private
string
GetElementName
(
XmlNodeSyntax
node
)
{
SyntaxList
<
XmlAttributeSyntax
>
attributes
;
return
GetElementNameAndAttributes
(
node
,
out
attributes
);
}
private
string
GetElementName
(
XmlNodeSyntax
node
)
=>
GetElementNameAndAttributes
(
node
).
name
;
private
string
GetAttributeName
(
XmlAttributeSyntax
attribute
)
{
return
attribute
.
Name
.
LocalName
.
ValueText
;
}
private
string
GetAttributeName
(
XmlAttributeSyntax
attribute
)
=>
attribute
.
Name
.
LocalName
.
ValueText
;
private
string
GetAttributeValue
(
XmlAttributeSyntax
attribute
)
{
switch
(
attribute
)
{
case
XmlTextAttributeSyntax
textAttribute
:
// Decode any XML enities and concatentate the results
return
textAttribute
.
TextTokens
.
GetValueText
();
case
XmlNameAttributeSyntax
nameAttribute
:
...
...
src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs
浏览文件 @
3df54594
...
...
@@ -24,19 +24,19 @@ internal abstract class AbstractDocCommentCompletionProvider<TSyntax> : CommonCo
private
static
readonly
ImmutableArray
<
string
>
s_topLevelRepeatableTagNames
=
ImmutableArray
.
Create
(
ExceptionElementName
,
IncludeElementName
,
PermissionElementName
);
private
static
readonly
ImmutableArray
<
string
>
s_topLevelSingleUseTagNames
=
ImmutableArray
.
Create
(
SummaryElementName
,
RemarksElementName
,
ExampleElementName
,
CompletionListElementName
);
private
static
readonly
Dictionary
<
string
,
string
[
]
>
s_tagMap
=
new
Dictionary
<
string
,
string
[
]
>
private
static
readonly
Dictionary
<
string
,
(
string
tagOpen
,
string
textBeforeCaret
,
string
textAfterCaret
,
string
tagClose
)
>
s_tagMap
=
new
Dictionary
<
string
,
(
string
tagOpen
,
string
textBeforeCaret
,
string
textAfterCaret
,
string
tagClose
)
>
{
//
Open Before caret $$ After caret
Close
{
ExceptionElementName
,
new
[]
{
$"<
{
ExceptionElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
null
}
},
{
IncludeElementName
,
new
[]
{
$"<
{
IncludeElementName
}
"
,
$"
{
FileAttributeName
}
=\'"
,
$"\'
{
PathAttributeName
}
=\'[@name=\"\"]\'"
,
"/>"
}
},
{
PermissionElementName
,
new
[]
{
$"<
{
PermissionElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
null
}
},
{
SeeElementName
,
new
[]
{
$"<
{
SeeElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
"/>"
}
},
{
SeeAlsoElementName
,
new
[]
{
$"<
{
SeeAlsoElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
"/>"
}
},
{
ListElementName
,
new
[]
{
$"<
{
ListElementName
}
"
,
$"
{
TypeAttributeName
}
=\""
,
"\""
,
null
}
},
{
ParameterReferenceElementName
,
new
[]
{
$"<
{
ParameterReferenceElementName
}
"
,
$"
{
NameAttributeName
}
=\""
,
"\""
,
"/>"
}
},
{
TypeParameterReferenceElementName
,
new
[]
{
$"<
{
TypeParameterReferenceElementName
}
"
,
$"
{
NameAttributeName
}
=\""
,
"\""
,
"/>"
}
},
{
CompletionListElementName
,
new
[]
{
$"<
{
CompletionListElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
"/>"
}
},
//
tagOpen textBeforeCaret $$ textAfterCaret tag
Close
{
ExceptionElementName
,
(
$"<
{
ExceptionElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
null
)
},
{
IncludeElementName
,
(
$"<
{
IncludeElementName
}
"
,
$"
{
FileAttributeName
}
=\'"
,
$"\'
{
PathAttributeName
}
=\'[@name=\"\"]\'"
,
"/>"
)
},
{
PermissionElementName
,
(
$"<
{
PermissionElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
null
)
},
{
SeeElementName
,
(
$"<
{
SeeElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
"/>"
)
},
{
SeeAlsoElementName
,
(
$"<
{
SeeAlsoElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
"/>"
)
},
{
ListElementName
,
(
$"<
{
ListElementName
}
"
,
$"
{
TypeAttributeName
}
=\""
,
"\""
,
null
)
},
{
ParameterReferenceElementName
,
(
$"<
{
ParameterReferenceElementName
}
"
,
$"
{
NameAttributeName
}
=\""
,
"\""
,
"/>"
)
},
{
TypeParameterReferenceElementName
,
(
$"<
{
TypeParameterReferenceElementName
}
"
,
$"
{
NameAttributeName
}
=\""
,
"\""
,
"/>"
)
},
{
CompletionListElementName
,
(
$"<
{
CompletionListElementName
}
"
,
$"
{
CrefAttributeName
}
=\""
,
"\""
,
"/>"
)
},
};
private
static
readonly
string
[][]
s_attributeMap
=
...
...
@@ -80,20 +80,18 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
protected
abstract
IEnumerable
<
string
>
GetExistingTopLevelAttributeValues
(
TSyntax
syntax
,
string
tagName
,
string
attributeName
);
private
bool
HasExistingTopLevelElement
(
TSyntax
syntax
,
string
name
)
{
return
GetExistingTopLevelElementNames
(
syntax
).
Contains
(
name
);
}
private
bool
HasExistingTopLevelElement
(
TSyntax
syntax
,
string
name
)
=>
GetExistingTopLevelElementNames
(
syntax
).
Contains
(
name
);
private
CompletionItem
GetItem
(
string
name
)
{
if
(
s_tagMap
.
TryGetValue
(
name
,
out
var
values
))
{
return
CreateCompletionItem
(
name
,
beforeCaretText
:
values
[
0
]
+
values
[
1
]
,
afterCaretText
:
values
[
2
]
+
values
[
3
]
,
beforeCaretTextOnSpace
:
values
[
0
]
,
afterCaretTextOnSpace
:
values
[
3
]
);
beforeCaretText
:
values
.
tagOpen
+
values
.
textBeforeCaret
,
afterCaretText
:
values
.
textAfterCaret
+
values
.
tagClose
,
beforeCaretTextOnSpace
:
values
.
tagOpen
,
afterCaretTextOnSpace
:
values
.
tagClose
);
}
return
CreateCompletionItem
(
name
);
...
...
src/Features/VisualBasic/Portable/Completion/CompletionProviders/XmlDocCommentCompletionProvider.vb
浏览文件 @
3df54594
...
...
@@ -13,9 +13,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Inherits
AbstractDocCommentCompletionProvider
(
Of
DocumentationCommentTriviaSyntax
)
Friend
Overrides
Function
IsInsertionTrigger
(
text
As
SourceText
,
characterPosition
As
Integer
,
options
As
OptionSet
)
As
Boolean
Return
text
(
characterPosition
)
=
"<"
c
OrElse
text
(
characterPosition
)
=
"
""
"
c
OrElse
(
text
(
characterPosition
)
=
"/"
c
AndAlso
characterPosition
>
0
AndAlso
text
(
characterPosition
-
1
)
=
"<"
c
)
OrElse
IsTriggerAfterSpaceOrStartOfWordCharacter
(
text
,
characterPosition
,
options
)
Dim
isStartOfTag
=
text
(
characterPosition
)
=
"<"
c
Dim
isClosingTag
=
(
text
(
characterPosition
)
=
"/"
c
AndAlso
characterPosition
>
0
AndAlso
text
(
characterPosition
-
1
)
=
"<"
c
)
Dim
isDoubleQuote
=
text
(
characterPosition
)
=
"
""
"
c
Return
isStartOfTag
OrElse
isClosingTag
OrElse
isDoubleQuote
OrElse
IsTriggerAfterSpaceOrStartOfWordCharacter
(
text
,
characterPosition
,
options
)
End
Function
Public
Function
GetPreviousTokenIfTouchingText
(
token
As
SyntaxToken
,
position
As
Integer
)
As
SyntaxToken
...
...
@@ -88,7 +91,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
End
If
End
If
If
trigger
.
Kind
=
CompletionTriggerKind
.
Insertion
AndAlso
Not
trigger
.
Character
=
"
""
"
c
AndAlso
Not
trigger
.
Character
=
"<"
c
Then
If
trigger
.
Kind
=
CompletionTriggerKind
.
Insertion
AndAlso
Not
trigger
.
Character
=
"
""
"
c
AndAlso
Not
trigger
.
Character
=
"<"
c
Then
' With the use of IsTriggerAfterSpaceOrStartOfWordCharacter, the code below is much
' too aggressive at suggesting tags, so exit early before degrading the experience
Return
items
End
If
...
...
@@ -277,6 +284,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Private
Function
GetAttributeValue
(
attribute
As
XmlNodeSyntax
)
As
String
If
TypeOf
attribute
Is
XmlAttributeSyntax
Then
' Decode any XML enities and concatentate the results
Return
DirectCast
(
DirectCast
(
attribute
,
XmlAttributeSyntax
).
Value
,
XmlStringSyntax
).
TextTokens
.
GetValueText
()
End
If
...
...
src/Workspaces/CSharp/Portable/Extensions/SyntaxTokenExtensions.cs
浏览文件 @
3df54594
...
...
@@ -43,11 +43,6 @@ public static bool IsKind(this SyntaxToken token, params SyntaxKind[] kinds)
return
kinds
.
Contains
(
token
.
Kind
());
}
public
static
bool
IsParentKind
(
this
SyntaxToken
token
,
SyntaxKind
kind
)
{
return
token
.
Parent
!=
null
&&
token
.
Parent
.
IsKind
(
kind
);
}
public
static
bool
IsLiteral
(
this
SyntaxToken
token
)
{
switch
(
token
.
Kind
())
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录