Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
db55807b
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,发现更多精彩内容 >>
提交
db55807b
编写于
3月 02, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Support fix-all for resolving conflict markers.
上级
146b3d74
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
323 addition
and
70 deletion
+323
-70
src/EditorFeatures/CSharpTest/ConflictMarkerResolution/ConflictMarkerResolutionTests.cs
...ConflictMarkerResolution/ConflictMarkerResolutionTests.cs
+142
-0
src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs
...MarkerResolution/AbstractConflictMarkerCodeFixProvider.cs
+145
-55
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.FixAllProvider.cs
...eFixes/SyntaxEditorBasedCodeFixProvider.FixAllProvider.cs
+6
-6
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.cs
...kspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.cs
+30
-9
未找到文件。
src/EditorFeatures/CSharpTest/ConflictMarkerResolution/ConflictMarkerResolutionTests.cs
浏览文件 @
db55807b
...
...
@@ -8,6 +8,7 @@
using
Microsoft.CodeAnalysis.Diagnostics
;
using
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics
;
using
Microsoft.CodeAnalysis.Test.Utilities
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
namespace
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConflictMarkerResolution
...
...
@@ -448,6 +449,147 @@ static void Main2(string[] args)
}
}
}"
,
index
:
2
);
}
[
WorkItem
(
21107
,
"https://github.com/dotnet/roslyn/issues/21107"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsResolveConflictMarker
)]
public
async
Task
TestFixAll1
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
namespace N
{
{|FixAllInDocument:<<<<<<<|} This is mine!
class Program
{
}
=======
class Program2
{
}
>>>>>>> This is theirs!
<<<<<<< This is mine!
class Program3
{
}
=======
class Program4
{
}
>>>>>>> This is theirs!
}"
,
@"
using System;
namespace N
{
class Program
{
}
class Program3
{
}
}"
,
index
:
0
);
}
[
WorkItem
(
21107
,
"https://github.com/dotnet/roslyn/issues/21107"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsResolveConflictMarker
)]
public
async
Task
TestFixAll2
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
namespace N
{
{|FixAllInDocument:<<<<<<<|} This is mine!
class Program
{
}
=======
class Program2
{
}
>>>>>>> This is theirs!
<<<<<<< This is mine!
class Program3
{
}
=======
class Program4
{
}
>>>>>>> This is theirs!
}"
,
@"
using System;
namespace N
{
class Program2
{
}
class Program4
{
}
}"
,
index
:
1
);
}
[
WorkItem
(
21107
,
"https://github.com/dotnet/roslyn/issues/21107"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsResolveConflictMarker
)]
public
async
Task
TestFixAll3
()
{
await
TestInRegularAndScript1Async
(
@"
using System;
namespace N
{
{|FixAllInDocument:<<<<<<<|} This is mine!
class Program
{
}
=======
class Program2
{
}
>>>>>>> This is theirs!
<<<<<<< This is mine!
class Program3
{
}
=======
class Program4
{
}
>>>>>>> This is theirs!
}"
,
@"
using System;
namespace N
{
class Program
{
}
class Program2
{
}
class Program3
{
}
class Program4
{
}
}"
,
index
:
2
);
}
}
...
...
src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs
浏览文件 @
db55807b
...
...
@@ -6,18 +6,26 @@
using
System
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.CodeFixes
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Text
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.ConflictMarkerResolution
{
internal
abstract
class
AbstractResolveConflictMarkerCodeFixProvider
:
CodeFixProvider
internal
abstract
class
AbstractResolveConflictMarkerCodeFixProvider
:
SyntaxEditorBased
CodeFixProvider
{
private
const
string
TakeTopEquivalenceKey
=
nameof
(
TakeTopEquivalenceKey
);
private
const
string
TakeBottomEquivalenceKey
=
nameof
(
TakeBottomEquivalenceKey
);
private
const
string
TakeBothEquivalenceKey
=
nameof
(
TakeBothEquivalenceKey
);
private
static
readonly
int
s_mergeConflictLength
=
"<<<<<<<"
.
Length
;
private
readonly
ISyntaxKinds
_syntaxKinds
;
...
...
@@ -29,15 +37,10 @@ internal abstract class AbstractResolveConflictMarkerCodeFixProvider : CodeFixPr
_syntaxKinds
=
syntaxKinds
;
}
public
override
FixAllProvider
?
GetFixAllProvider
()
{
// Fix All is not currently supported for this code fix
// https://github.com/dotnet/roslyn/issues/34461
return
null
;
}
public
override
ImmutableArray
<
string
>
FixableDiagnosticIds
{
get
;
}
internal
override
CodeFixCategory
CodeFixCategory
=>
CodeFixCategory
.
Compile
;
public
override
async
Task
RegisterCodeFixesAsync
(
CodeFixContext
context
)
{
var
cancellationToken
=
context
.
CancellationToken
;
...
...
@@ -46,17 +49,25 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var
text
=
await
document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
startTrivia
=
root
.
FindTrivia
(
context
.
Span
.
Start
);
if
(!
IsConflictMarker
(
text
,
startTrivia
,
'<'
))
{
return
;
}
var
conflictTrivia
=
TryGetConflictTrivia
(
text
,
startTrivia
);
if
(
conflictTrivia
==
null
)
return
;
var
(
equalsTrivia
,
endTrivia
)
=
conflictTrivia
.
Value
;
RegisterCodeFixes
(
context
,
startTrivia
,
equalsTrivia
,
endTrivia
);
}
private
(
SyntaxTrivia
equalsTrivia
,
SyntaxTrivia
endTrivia
)?
TryGetConflictTrivia
(
SourceText
text
,
SyntaxTrivia
startTrivia
)
{
var
token
=
startTrivia
.
Token
;
while
(
true
)
{
var
index
=
GetEqualsConflictMarkerIndex
(
text
,
token
);
var
index
=
GetEqualsConflictMarkerIndex
(
text
,
token
,
afterPosition
:
startTrivia
.
SpanStart
);
if
(
index
>=
0
)
{
var
leadingTrivia
=
token
.
LeadingTrivia
;
...
...
@@ -74,8 +85,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
_syntaxKinds
.
DisabledTextTrivia
==
disabledTrivia
.
RawKind
&&
IsConflictMarker
(
text
,
endTrivia
,
'>'
))
{
RegisterCodeFixes
(
context
,
startTrivia
,
equalsTrivia
,
endTrivia
);
return
;
return
(
equalsTrivia
,
endTrivia
);
}
}
...
...
@@ -90,8 +100,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
if
(
_syntaxKinds
.
EndOfLineTrivia
==
endOfLineTrivia
.
RawKind
&&
IsConflictMarker
(
text
,
endTrivia
,
'>'
))
{
RegisterCodeFixes
(
context
,
startTrivia
,
equalsTrivia
,
endTrivia
);
return
;
return
(
equalsTrivia
,
endTrivia
);
}
}
}
...
...
@@ -99,7 +108,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
token
=
token
.
GetNextToken
(
includeZeroWidth
:
true
);
if
(
token
.
RawKind
==
0
)
{
return
;
return
default
;
}
}
}
...
...
@@ -125,77 +134,99 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
context
.
RegisterCodeFix
(
new
MyCodeAction
(
takeTopText
,
c
=>
TakeTopAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
c
)),
c
=>
TakeTopAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
c
),
TakeTopEquivalenceKey
),
context
.
Diagnostics
);
context
.
RegisterCodeFix
(
new
MyCodeAction
(
takeBottomText
,
c
=>
TakeBottomAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
c
)),
c
=>
TakeBottomAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
c
),
TakeBottomEquivalenceKey
),
context
.
Diagnostics
);
context
.
RegisterCodeFix
(
new
MyCodeAction
(
FeaturesResources
.
Take_both
,
c
=>
TakeBothAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
c
)),
c
=>
TakeBothAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
c
),
TakeBothEquivalenceKey
),
context
.
Diagnostics
);
}
private
async
Task
<
Document
>
TakeTop
Async
(
private
async
Task
<
Document
>
AddEdits
Async
(
Document
document
,
int
startPos
,
int
equalsPos
,
int
endPos
,
Action
<
SourceText
,
ArrayBuilder
<
TextChange
>,
int
,
int
,
int
>
addEdits
,
CancellationToken
cancellationToken
)
{
var
text
=
await
document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
bottomEnd
=
GetEndIncludingLineBreak
(
text
,
endPos
);
var
newText
=
text
.
Replace
(
TextSpan
.
FromBounds
(
equalsPos
,
bottomEnd
),
""
);
var
startEnd
=
GetEndIncludingLineBreak
(
text
,
startPos
);
var
finaltext
=
newText
.
Replace
(
TextSpan
.
FromBounds
(
startPos
,
startEnd
),
""
);
using
var
_
=
ArrayBuilder
<
TextChange
>.
GetInstance
(
out
var
edits
);
addEdits
(
text
,
edits
,
startPos
,
equalsPos
,
endPos
);
return
document
.
WithText
(
finaltext
);
var
finalText
=
text
.
WithChanges
(
edits
);
return
document
.
WithText
(
finalText
);
}
private
async
Task
<
Document
>
TakeBottomAsync
(
Document
document
,
int
startPos
,
int
equalsPos
,
int
endPo
s
,
CancellationToken
cancellationToken
)
private
static
void
AddTopEdits
(
SourceText
text
,
ArrayBuilder
<
TextChange
>
edit
s
,
int
startPos
,
int
equalsPos
,
int
endPos
)
{
var
text
=
await
document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
// Delete the line containing <<<<<<<
var
startEnd
=
GetEndIncludingLineBreak
(
text
,
startPos
);
edits
.
Add
(
new
TextChange
(
TextSpan
.
FromBounds
(
startPos
,
startEnd
),
""
));
// Remove the chunk of text (inclusive) from ======= through >>>>>>>
var
bottomEnd
=
GetEndIncludingLineBreak
(
text
,
endPos
);
var
newText
=
text
.
Replace
(
TextSpan
.
FromBounds
(
endPos
,
bottomEnd
),
""
);
edits
.
Add
(
new
TextChange
(
TextSpan
.
FromBounds
(
equalsPos
,
bottomEnd
),
""
));
}
private
static
void
AddBottomEdits
(
SourceText
text
,
ArrayBuilder
<
TextChange
>
edits
,
int
startPos
,
int
equalsPos
,
int
endPos
)
{
// Remove the chunk of text (inclusive) from <<<<<<< through =======
var
equalsEnd
=
GetEndIncludingLineBreak
(
text
,
equalsPos
);
var
finaltext
=
newText
.
Replace
(
TextSpan
.
FromBounds
(
startPos
,
equalsEnd
),
""
);
edits
.
Add
(
new
TextChange
(
TextSpan
.
FromBounds
(
startPos
,
equalsEnd
),
""
)
);
return
document
.
WithText
(
finaltext
);
// Delete the line containing >>>>>>>
var
bottomEnd
=
GetEndIncludingLineBreak
(
text
,
endPos
);
edits
.
Add
(
new
TextChange
(
TextSpan
.
FromBounds
(
endPos
,
bottomEnd
),
""
));
}
private
async
Task
<
Document
>
TakeBothAsync
(
Document
document
,
int
startPos
,
int
equalsPos
,
int
endPo
s
,
CancellationToken
cancellationToken
)
private
static
void
AddBothEdits
(
SourceText
text
,
ArrayBuilder
<
TextChange
>
edit
s
,
int
startPos
,
int
equalsPos
,
int
endPos
)
{
var
text
=
await
document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
// Delete the line containing <<<<<<<
var
startEnd
=
GetEndIncludingLineBreak
(
text
,
startPos
);
edits
.
Add
(
new
TextChange
(
TextSpan
.
FromBounds
(
startPos
,
startEnd
),
""
));
// Delete the line containing =======
var
equalsEnd
=
GetEndIncludingLineBreak
(
text
,
equalsPos
);
edits
.
Add
(
new
TextChange
(
TextSpan
.
FromBounds
(
equalsPos
,
equalsEnd
),
""
));
// Delete the line containing >>>>>>>
var
bottomEnd
=
GetEndIncludingLineBreak
(
text
,
endPos
);
var
newText
=
text
.
Replace
(
TextSpan
.
FromBounds
(
endPos
,
bottomEnd
),
""
);
edits
.
Add
(
new
TextChange
(
TextSpan
.
FromBounds
(
endPos
,
bottomEnd
),
""
));
}
var
equalsEnd
=
GetEndIncludingLineBreak
(
text
,
equalsPos
);
newText
=
newText
.
Replace
(
TextSpan
.
FromBounds
(
equalsPos
,
equalsEnd
),
""
);
private
Task
<
Document
>
TakeTopAsync
(
Document
document
,
int
startPos
,
int
equalsPos
,
int
endPos
,
CancellationToken
cancellationToken
)
=>
AddEditsAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
AddTopEdits
,
cancellationToken
);
var
startEnd
=
GetEndIncludingLineBreak
(
text
,
startPos
);
var
finaltext
=
newText
.
Replace
(
TextSpan
.
FromBounds
(
startPos
,
startEnd
),
""
);
private
Task
<
Document
>
TakeBottomAsync
(
Document
document
,
int
startPos
,
int
equalsPos
,
int
endPos
,
CancellationToken
cancellationToken
)
=>
AddEditsAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
AddBottomEdits
,
cancellationToken
);
return
document
.
WithText
(
finaltext
);
}
private
Task
<
Document
>
TakeBothAsync
(
Document
document
,
int
startPos
,
int
equalsPos
,
int
endPos
,
CancellationToken
cancellationToken
)
=>
AddEditsAsync
(
document
,
startPos
,
equalsPos
,
endPos
,
AddBothEdits
,
cancellationToken
);
private
int
GetEndIncludingLineBreak
(
SourceText
text
,
int
position
)
private
static
int
GetEndIncludingLineBreak
(
SourceText
text
,
int
position
)
=>
text
.
Lines
.
GetLineFromPosition
(
position
).
SpanIncludingLineBreak
.
End
;
private
int
GetEqualsConflictMarkerIndex
(
SourceText
text
,
SyntaxToken
token
)
private
int
GetEqualsConflictMarkerIndex
(
SourceText
text
,
SyntaxToken
token
,
int
afterPosition
)
{
if
(
token
.
HasLeadingTrivia
)
{
var
i
=
0
;
foreach
(
var
trivia
in
token
.
LeadingTrivia
)
{
if
(
IsConflictMarker
(
text
,
trivia
,
'='
))
if
(
trivia
.
SpanStart
>=
afterPosition
&&
IsConflictMarker
(
text
,
trivia
,
'='
))
{
return
i
;
}
...
...
@@ -207,11 +238,6 @@ private int GetEqualsConflictMarkerIndex(SourceText text, SyntaxToken token)
return
-
1
;
}
private
SyntaxTrivia
GetEqualsConflictMarker
(
SyntaxToken
token
)
{
throw
new
NotImplementedException
();
}
private
bool
IsConflictMarker
(
SourceText
text
,
SyntaxTrivia
trivia
,
char
ch
)
{
return
...
...
@@ -220,10 +246,74 @@ private bool IsConflictMarker(SourceText text, SyntaxTrivia trivia, char ch)
text
[
trivia
.
SpanStart
]
==
ch
;
}
protected
override
async
Task
FixAllAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
SyntaxEditor
editor
,
string
equivalenceKey
,
CancellationToken
cancellationToken
)
{
Debug
.
Assert
(
equivalenceKey
==
TakeTopEquivalenceKey
||
equivalenceKey
==
TakeBottomEquivalenceKey
||
equivalenceKey
==
TakeBothEquivalenceKey
);
// Process diagnostics in order so we produce edits in the right order.
var
orderedDiagnostics
=
diagnostics
.
OrderBy
(
(
d1
,
d2
)
=>
d1
.
Location
.
SourceSpan
.
Start
-
d2
.
Location
.
SourceSpan
.
Start
).
ToImmutableArray
();
var
text
=
await
document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
tree
=
await
document
.
GetRequiredSyntaxTreeAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
root
=
await
document
.
GetRequiredSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
using
var
_
=
ArrayBuilder
<
TextChange
>.
GetInstance
(
out
var
edits
);
foreach
(
var
diagnostic
in
diagnostics
)
{
var
startTrivia
=
root
.
FindTrivia
(
diagnostic
.
Location
.
SourceSpan
.
Start
);
// We'll be called on all the conflict marker diagnostics (i.e. for <<<<<<< =======
// and >>>>>>>). We only care about the <<<<<<< ones as that controls which chunks
// we'll be processing.
if
(!
IsConflictMarker
(
text
,
startTrivia
,
'<'
))
continue
;
var
conflictTrivia
=
TryGetConflictTrivia
(
text
,
startTrivia
);
if
(
conflictTrivia
==
null
)
continue
;
var
startPos
=
startTrivia
.
SpanStart
;
var
equalsPos
=
conflictTrivia
.
Value
.
equalsTrivia
.
SpanStart
;
var
endPos
=
conflictTrivia
.
Value
.
endTrivia
.
SpanStart
;
switch
(
equivalenceKey
)
{
case
TakeTopEquivalenceKey
:
AddTopEdits
(
text
,
edits
,
startPos
,
equalsPos
,
endPos
);
continue
;
case
TakeBottomEquivalenceKey
:
AddBottomEdits
(
text
,
edits
,
startPos
,
equalsPos
,
endPos
);
continue
;
case
TakeBothEquivalenceKey
:
AddBothEdits
(
text
,
edits
,
startPos
,
equalsPos
,
endPos
);
continue
;
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
equivalenceKey
);
}
}
var
finalText
=
text
.
WithChanges
(
edits
);
var
finalTree
=
tree
.
WithChangedText
(
finalText
);
var
finalRoot
=
finalTree
.
GetRoot
(
cancellationToken
);
editor
.
ReplaceNode
(
root
,
finalRoot
);
}
private
class
MyCodeAction
:
CodeAction
.
DocumentChangeAction
{
public
MyCodeAction
(
string
title
,
Func
<
CancellationToken
,
Task
<
Document
>>
createChangedDocument
)
:
base
(
title
,
createChangedDocument
)
public
MyCodeAction
(
string
title
,
Func
<
CancellationToken
,
Task
<
Document
>>
createChangedDocument
,
string
equivalenceKey
)
:
base
(
title
,
createChangedDocument
,
equivalenceKey
)
{
}
}
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.FixAllProvider.cs
浏览文件 @
db55807b
...
...
@@ -2,15 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.CodeStyle
;
using
Microsoft.CodeAnalysis.GeneratedCodeRecognition
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
namespace
Microsoft.CodeAnalysis.CodeFixes
{
...
...
@@ -81,13 +77,16 @@ public sealed override async Task<CodeAction> GetFixAsync(FixAllContext fixAllCo
private
async
Task
<
Document
>
FixDocumentAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
FixAllContext
fixAllContext
)
{
var
cancellationToken
=
fixAllContext
.
CancellationToken
;
var
equivalenceKey
=
fixAllContext
.
CodeActionEquivalenceKey
;
// Ensure that diagnostics for this document are always in document location
// order. This provides a consistent and deterministic order for fixers
// that want to update a document.
// Also ensure that we do not pass in duplicates by invoking Distinct.
// See https://github.com/dotnet/roslyn/issues/31381, that seems to be causing duplicate diagnostics.
var
filteredDiagnostics
=
diagnostics
.
Distinct
()
.
WhereAsArray
(
d
=>
_codeFixProvider
.
IncludeDiagnosticDuringFixAll
(
d
,
fixAllContext
.
Document
,
fixAllContext
.
CodeActionEquivalenceKey
,
fixAllContext
.
C
ancellationToken
))
.
WhereAsArray
(
d
=>
_codeFixProvider
.
IncludeDiagnosticDuringFixAll
(
d
,
fixAllContext
.
Document
,
equivalenceKey
,
c
ancellationToken
))
.
Sort
((
d1
,
d2
)
=>
d1
.
Location
.
SourceSpan
.
Start
-
d2
.
Location
.
SourceSpan
.
Start
);
// PERF: Do not invoke FixAllAsync on the code fix provider if there are no diagnostics to be fixed.
...
...
@@ -96,7 +95,8 @@ public sealed override async Task<CodeAction> GetFixAsync(FixAllContext fixAllCo
return
document
;
}
return
await
_codeFixProvider
.
FixAllAsync
(
document
,
filteredDiagnostics
,
fixAllContext
.
CancellationToken
).
ConfigureAwait
(
false
);
return
await
_codeFixProvider
.
FixAllAsync
(
document
,
filteredDiagnostics
,
equivalenceKey
,
cancellationToken
).
ConfigureAwait
(
false
);
}
}
}
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.cs
浏览文件 @
db55807b
...
...
@@ -22,17 +22,15 @@ protected SyntaxEditorBasedCodeFixProvider(bool supportsFixAll = true)
public
sealed
override
FixAllProvider
GetFixAllProvider
()
=>
_supportsFixAll
?
new
SyntaxEditorBasedFixAllProvider
(
this
)
:
null
;
protected
Task
<
Document
>
FixAsync
(
Document
document
,
Diagnostic
diagnostic
,
CancellationToken
cancellationToken
)
{
return
FixAllAsync
(
document
,
ImmutableArray
.
Create
(
diagnostic
),
cancellationToken
);
}
protected
Task
<
Document
>
FixAsync
(
Document
document
,
Diagnostic
diagnostic
,
CancellationToken
cancellationToken
)
=>
FixAllAsync
(
document
,
ImmutableArray
.
Create
(
diagnostic
),
equivalenceKey
:
""
,
cancellationToken
);
private
Task
<
Document
>
FixAllAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
CancellationToken
cancellationToken
)
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
string
equivalenceKey
,
CancellationToken
cancellationToken
)
{
return
FixAllWithEditorAsync
(
document
,
editor
=>
FixAllAsync
(
document
,
diagnostics
,
editor
,
cancellationToken
),
editor
=>
FixAllAsync
(
document
,
diagnostics
,
editor
,
equivalenceKey
,
cancellationToken
),
cancellationToken
);
}
...
...
@@ -52,8 +50,31 @@ public sealed override FixAllProvider GetFixAllProvider()
internal
abstract
CodeFixCategory
CodeFixCategory
{
get
;
}
protected
abstract
Task
FixAllAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
SyntaxEditor
editor
,
CancellationToken
cancellationToken
);
/// <summary>
/// Method to override in subclasses to actually implement fix-all behavior for the provided
/// <paramref name="document"/> given the selected set of <paramref name="diagnostics"/>.
/// <para/>
/// This method should be overridden when the subclass does not care about the fix-all
/// equivalence-key when determining what to do.
/// <para/>
/// One of <see cref="FixAllAsync(Document, ImmutableArray{Diagnostic}, SyntaxEditor, CancellationToken)"/> or
/// <see cref="FixAllAsync(Document, ImmutableArray{Diagnostic}, SyntaxEditor, string, CancellationToken)"/> must be overridden.
/// </summary>
protected
virtual
Task
FixAllAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
SyntaxEditor
editor
,
CancellationToken
cancellationToken
)
=>
Task
.
CompletedTask
;
/// <summary>
/// Method to override in subclasses to actually implement fix-all behavior for the provided
/// <paramref name="document"/> given the selected set of <paramref name="diagnostics"/>.
/// <para/>
/// This method should be overridden when the subclass does care about the fix-all
/// equivalence-key when determining what to do.
/// <para/>
/// One of <see cref="FixAllAsync(Document, ImmutableArray{Diagnostic}, SyntaxEditor, CancellationToken)"/> or
/// <see cref="FixAllAsync(Document, ImmutableArray{Diagnostic}, SyntaxEditor, string, CancellationToken)"/> must be overridden.
/// </summary>
protected
virtual
Task
FixAllAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
SyntaxEditor
editor
,
string
equivalenceKey
,
CancellationToken
cancellationToken
)
=>
FixAllAsync
(
document
,
diagnostics
,
editor
,
cancellationToken
);
/// <summary>
/// Whether or not this diagnostic should be included when performing a FixAll. This is
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录