Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
d4a81920
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,发现更多精彩内容 >>
提交
d4a81920
编写于
2月 05, 2016
作者:
A
Artur Spychaj
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor send to interactive
Base selection on the currently opened Document
上级
ab1b4fcf
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
164 addition
and
102 deletion
+164
-102
src/Interactive/EditorFeatures/CSharp/Interactive/CSharpSendToInteractiveSubmissionProvider.cs
.../Interactive/CSharpSendToInteractiveSubmissionProvider.cs
+44
-44
src/Interactive/EditorFeatures/Core/Extensibility/Interactive/InteractiveCommandHandler.cs
...re/Extensibility/Interactive/InteractiveCommandHandler.cs
+5
-1
src/Interactive/EditorFeatures/Core/Extensibility/Interactive/ResetInteractive.cs
...atures/Core/Extensibility/Interactive/ResetInteractive.cs
+8
-2
src/Interactive/EditorFeatures/Core/Extensibility/Interactive/SendToInteractiveSubmissionProvider.cs
...bility/Interactive/SendToInteractiveSubmissionProvider.cs
+27
-35
src/Interactive/EditorFeatures/Core/InteractiveEditorFeaturesResources.Designer.cs
...tures/Core/InteractiveEditorFeaturesResources.Designer.cs
+2
-2
src/Interactive/EditorFeatures/Core/InteractiveEditorFeaturesResources.resx
...itorFeatures/Core/InteractiveEditorFeaturesResources.resx
+2
-2
src/Interactive/EditorFeatures/VisualBasic/Interactive/VisualBasicSendToInteractiveSubmissionProvider.vb
...ractive/VisualBasicSendToInteractiveSubmissionProvider.vb
+2
-2
src/VisualStudio/CSharp/Test/Interactive/Commands/InteractiveCommandHandlerTests.cs
...st/Interactive/Commands/InteractiveCommandHandlerTests.cs
+32
-4
src/VisualStudio/CSharp/Test/Interactive/Commands/ResetInteractiveTests.cs
...CSharp/Test/Interactive/Commands/ResetInteractiveTests.cs
+25
-6
src/VisualStudio/CSharp/Test/Interactive/Commands/TestResetInteractive.cs
.../CSharp/Test/Interactive/Commands/TestResetInteractive.cs
+8
-2
src/VisualStudio/InteractiveServices/Interactive/VsResetInteractive.cs
...dio/InteractiveServices/Interactive/VsResetInteractive.cs
+9
-2
未找到文件。
src/Interactive/EditorFeatures/CSharp/Interactive/CSharpSendToInteractiveSubmissionProvider.cs
浏览文件 @
d4a81920
...
...
@@ -14,42 +14,50 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.Interactive
{
[
Export
(
typeof
(
ISendToInteractiveSubmissionProvider
))]
internal
sealed
class
CSharpSendToInteractiveSubmissionProvider
:
SendToInteractiveSubmissionProvider
:
Abstract
SendToInteractiveSubmissionProvider
{
protected
override
bool
CanParseSubmission
(
string
code
)
{
SourceText
sourceCode
=
SourceText
.
From
(
code
);
ParseOptions
options
=
CSharpParseOptions
.
Default
.
WithKind
(
SourceCodeKind
.
Script
);
SyntaxTree
tree
=
SyntaxFactory
.
ParseSyntaxTree
(
sourceCode
,
options
);
if
(
tree
==
null
)
{
return
false
;
}
return
tree
.
HasCompilationUnitRoot
&&
!
tree
.
GetDiagnostics
().
Any
();
SyntaxTree
tree
=
SyntaxFactory
.
ParseSyntaxTree
(
code
,
options
);
return
tree
.
HasCompilationUnitRoot
&&
!
tree
.
GetDiagnostics
().
Any
(
diagnostic
=>
diagnostic
.
Severity
==
DiagnosticSeverity
.
Error
);
}
protected
override
IEnumerable
<
TextSpan
>
GetExecutableSyntaxTreeNodeSelection
(
TextSpan
selectionSpan
,
S
ourceText
source
,
SyntaxNode
root
,
SemanticModel
model
)
protected
override
IEnumerable
<
TextSpan
>
GetExecutableSyntaxTreeNodeSelection
(
TextSpan
selectionSpan
,
S
yntaxNode
root
)
{
SyntaxNode
expandedNode
=
Get
ExecutableSyntaxTreeNode
(
selectionSpan
,
source
,
root
,
model
);
SyntaxNode
expandedNode
=
Get
SyntaxNodeForSubmission
(
selectionSpan
,
root
);
return
expandedNode
!=
null
?
new
TextSpan
[]
{
expandedNode
.
Span
}
:
Array
.
Empty
<
TextSpan
>();
}
private
SyntaxNode
GetExecutableSyntaxTreeNode
(
TextSpan
selectionSpan
,
SourceText
source
,
SyntaxNode
root
,
SemanticModel
model
)
/// <summary>
/// Finds a <see cref="SyntaxNode"/> that should be submitted to REPL.
/// </summary>
/// <param name="selectionSpan">Selection that user has originally made.</param>
/// <param name="root">Root of the syntax tree.</param>
private
SyntaxNode
GetSyntaxNodeForSubmission
(
TextSpan
selectionSpan
,
SyntaxNode
root
)
{
Tuple
<
SyntaxToken
,
SyntaxToken
>
tokens
=
GetSelectedTokens
(
selectionSpan
,
root
);
var
startToken
=
tokens
.
Item1
;
var
endToken
=
tokens
.
Item2
;
SyntaxToken
startToken
,
endToken
;
GetSelectedTokens
(
selectionSpan
,
root
,
out
startToken
,
out
endToken
);
// Ensure that the first token comes before the last token.
// Otherwise selection did not contain any tokens.
if
(
startToken
!=
endToken
&&
startToken
.
Span
.
End
>
endToken
.
SpanStart
)
{
return
null
;
}
// If a selection falls within a single executable statement then execute that statement.
var
startNode
=
GetGlobalExecutableStatement
(
startToken
);
var
endNode
=
GetGlobalExecutableStatement
(
endToken
);
if
(
startToken
==
endToken
)
{
return
GetSyntaxNodeForSubmission
(
startToken
.
Parent
);
}
var
startNode
=
GetSyntaxNodeForSubmission
(
startToken
.
Parent
);
var
endNode
=
GetSyntaxNodeForSubmission
(
endToken
.
Parent
);
// If there is no SyntaxNode worth sending to the REPL return null.
if
(
startNode
==
null
||
endNode
==
null
)
{
return
null
;
...
...
@@ -67,16 +75,14 @@ private SyntaxNode GetExecutableSyntaxTreeNode(TextSpan selectionSpan, SourceTex
// Selection spans multiple statements.
// In this case find common parent and find a span of statements within that parent.
var
commonNode
=
root
.
FindNode
(
TextSpan
.
FromBounds
(
startNode
.
Span
.
Start
,
endNode
.
Span
.
End
));
return
commonNode
;
return
GetSyntaxNodeForSubmission
(
startNode
.
GetCommonRoot
(
endNode
));
}
private
static
SyntaxNode
GetGlobalExecutableStatement
(
SyntaxToken
token
)
{
return
GetGlobalExecutableStatement
(
token
.
Parent
);
}
private
static
SyntaxNode
GetGlobalExecutableStatement
(
SyntaxNode
node
)
/// <summary>
/// Finds a <see cref="SyntaxNode"/> that should be submitted to REPL.
/// </summary>
/// <param name="node">The currently selected node.</param>
private
static
SyntaxNode
GetSyntaxNodeForSubmission
(
SyntaxNode
node
)
{
SyntaxNode
candidate
=
node
.
GetAncestorOrThis
<
StatementSyntax
>();
if
(
candidate
!=
null
)
...
...
@@ -85,7 +91,7 @@ private static SyntaxNode GetGlobalExecutableStatement(SyntaxNode node)
}
candidate
=
node
.
GetAncestorsOrThis
<
SyntaxNode
>()
.
Where
(
n
=>
IsGlobalExecutableStatement
(
n
)
).
FirstOrDefault
();
.
Where
(
IsSubmissionNode
).
FirstOrDefault
();
if
(
candidate
!=
null
)
{
return
candidate
;
...
...
@@ -94,7 +100,8 @@ private static SyntaxNode GetGlobalExecutableStatement(SyntaxNode node)
return
null
;
}
private
static
bool
IsGlobalExecutableStatement
(
SyntaxNode
node
)
/// <summary>Returns <c>true</c> if <c>node</c> could be treated as a REPL submission.</summary>
private
static
bool
IsSubmissionNode
(
SyntaxNode
node
)
{
var
kind
=
node
.
Kind
();
return
SyntaxFacts
.
IsTypeDeclaration
(
kind
)
...
...
@@ -102,23 +109,16 @@ private static bool IsGlobalExecutableStatement(SyntaxNode node)
||
node
.
IsKind
(
SyntaxKind
.
UsingDirective
);
}
private
Tuple
<
SyntaxToken
,
SyntaxToken
>
GetSelectedTokens
(
TextSpan
selectionSpan
,
SyntaxNode
root
)
private
void
GetSelectedTokens
(
TextSpan
selectionSpan
,
SyntaxNode
root
,
out
SyntaxToken
startToken
,
out
SyntaxToken
endToken
)
{
if
(
selectionSpan
.
Length
==
0
)
{
var
selectedToken
=
root
.
FindTokenOnLeftOfPosition
(
selectionSpan
.
End
);
return
Tuple
.
Create
(
selectedToken
,
selectedToken
);
}
else
{
// For a selection find the first and the last token of the selection.
// Ensure that the first token comes before the last token.
return
Tuple
.
Create
(
root
.
FindTokenOnRightOfPosition
(
selectionSpan
.
Start
),
root
.
FindTokenOnLeftOfPosition
(
selectionSpan
.
End
));
}
endToken
=
root
.
FindTokenOnLeftOfPosition
(
selectionSpan
.
End
);
startToken
=
selectionSpan
.
Length
==
0
?
endToken
:
root
.
FindTokenOnRightOfPosition
(
selectionSpan
.
Start
);
}
}
}
src/Interactive/EditorFeatures/Core/Extensibility/Interactive/InteractiveCommandHandler.cs
浏览文件 @
d4a81920
...
...
@@ -62,7 +62,11 @@ void ICommandHandler<ExecuteInInteractiveCommandArgs>.ExecuteCommand(ExecuteInIn
allowCancel
:
true
,
action
:
context
=>
{
window
.
SubmitAsync
(
new
[]
{
GetSelectedText
(
args
,
context
.
CancellationToken
)
});
string
submission
=
GetSelectedText
(
args
,
context
.
CancellationToken
);
if
(!
String
.
IsNullOrWhiteSpace
(
submission
))
{
window
.
SubmitAsync
(
new
string
[]
{
submission
});
}
});
}
...
...
src/Interactive/EditorFeatures/Core/Extensibility/Interactive/ResetInteractive.cs
浏览文件 @
d4a81920
...
...
@@ -9,6 +9,8 @@
using
Microsoft.VisualStudio.InteractiveWindow
;
using
System.Collections.Immutable
;
using
Microsoft.CodeAnalysis.Editor
;
using
Microsoft.VisualStudio.Text.Editor
;
using
Microsoft.VisualStudio.Text.Editor.OptionsExtensionMethods
;
namespace
Microsoft.VisualStudio.LanguageServices.Interactive
{
...
...
@@ -22,10 +24,13 @@ internal abstract class ResetInteractive
private
readonly
Func
<
string
,
string
>
_createImport
;
private
readonly
IEditorOptionsFactoryService
_editorOptionsFactoryService
;
internal
event
EventHandler
ExecutionCompleted
;
internal
ResetInteractive
(
Func
<
string
,
string
>
createReference
,
Func
<
string
,
string
>
createImport
)
internal
ResetInteractive
(
IEditorOptionsFactoryService
editorOptionsFactoryService
,
Func
<
string
,
string
>
createReference
,
Func
<
string
,
string
>
createImport
)
{
_editorOptionsFactoryService
=
editorOptionsFactoryService
;
_createReference
=
createReference
;
_createImport
=
createImport
;
}
...
...
@@ -104,8 +109,9 @@ internal Task Execute(IInteractiveWindow interactiveWindow, string title)
await
interactiveEvaluator
.
SetPathsAsync
(
referenceSearchPaths
,
sourceSearchPaths
,
projectDirectory
).
ConfigureAwait
(
true
);
}
var
editorOptions
=
_editorOptionsFactoryService
.
GetOptions
(
interactiveWindow
.
CurrentLanguageBuffer
);
var
importReferencesCommand
=
referencePaths
.
Select
(
_createReference
);
var
importNamespacesCommand
=
namespacesToImport
.
Select
(
_createImport
).
Join
(
"\r\n"
);
var
importNamespacesCommand
=
namespacesToImport
.
Select
(
_createImport
).
Join
(
editorOptions
.
GetNewLineCharacter
()
);
await
interactiveWindow
.
SubmitAsync
(
importReferencesCommand
.
Concat
(
new
[]
{
importNamespacesCommand
...
...
src/Interactive/EditorFeatures/Core/Extensibility/Interactive/SendToInteractiveSubmissionProvider.cs
浏览文件 @
d4a81920
...
...
@@ -16,79 +16,71 @@ namespace Microsoft.CodeAnalysis.Editor.Interactive
/// <summary>
/// Implementers of this interface are responsible for retrieving source code that
/// should be sent to the REPL given the user's selection.
///
///
/// If the user does not make a selection then a line should be selected.
/// If the user selects code that fails to be parsed then the selection gets expanded
/// to a syntax node.
/// </summary>
internal
abstract
class
SendToInteractiveSubmissionProvider
:
ISendToInteractiveSubmissionProvider
internal
abstract
class
Abstract
SendToInteractiveSubmissionProvider
:
ISendToInteractiveSubmissionProvider
{
/// <summary>Expands the selection span of an invalid selection to a span that should be sent to REPL.</summary>
protected
abstract
IEnumerable
<
TextSpan
>
GetExecutableSyntaxTreeNodeSelection
(
TextSpan
selectedSpan
,
S
ourceText
source
,
SyntaxNode
node
,
SemanticModel
model
);
protected
abstract
IEnumerable
<
TextSpan
>
GetExecutableSyntaxTreeNodeSelection
(
TextSpan
selectedSpan
,
S
yntaxNode
node
);
/// <summary>Returns whether the submission can be parsed in interactive.</summary>
protected
abstract
bool
CanParseSubmission
(
string
code
);
public
string
GetSelectedText
(
IEditorOptions
editorOptions
,
CommandArgs
args
,
CancellationToken
cancellationToken
)
string
ISendToInteractiveSubmissionProvider
.
GetSelectedText
(
IEditorOptions
editorOptions
,
CommandArgs
args
,
CancellationToken
cancellationToken
)
{
IEnumerable
<
SnapshotSpan
>
selectedSpans
=
args
.
TextView
.
Selection
.
IsEmpty
?
GetExpandedLineAsync
(
editorOptions
,
args
,
cancellationToken
).
WaitAndGetResult
(
cancellationToken
)
:
args
.
TextView
.
Selection
.
GetSnapshotSpansOnBuffer
(
args
.
SubjectBuffer
).
Where
(
ss
=>
ss
.
Length
>
0
);
IEnumerable
<
SnapshotSpan
>
selectedSpans
=
args
.
TextView
.
Selection
.
GetSnapshotSpansOnBuffer
(
args
.
SubjectBuffer
).
Where
(
ss
=>
ss
.
Length
>
0
);
// If there is no selection select the current line.
if
(!
selectedSpans
.
Any
())
{
selectedSpans
=
GetSelectedLine
(
args
);
}
return
GetSubmissionFromSelectedSpans
(
editorOptions
,
selectedSpans
);
}
// Send the selection as is if it does not contain any parsing errors.
/// <summary>Returns the span for the selected line. Extends it if it is a part of a multi line statement or declaration.</summary>
private
Task
<
IEnumerable
<
SnapshotSpan
>>
GetExpandedLineAsync
(
IEditorOptions
editorOptions
,
CommandArgs
args
,
CancellationToken
cancellationToken
)
{
IEnumerable
<
SnapshotSpan
>
selectedSpans
=
GetSelectedLine
(
args
.
TextView
);
var
candidateSubmission
=
GetSubmissionFromSelectedSpans
(
editorOptions
,
selectedSpans
);
if
(
CanParseSubmission
(
candidateSubmission
))
{
return
candidateSubmission
;
}
// Otherwise heuristically try to expand it.
return
GetSubmissionFromSelectedSpans
(
editorOptions
,
ExpandSelection
(
selectedSpans
,
args
,
cancellationToken
));
return
CanParseSubmission
(
candidateSubmission
)
?
Task
.
FromResult
(
selectedSpans
)
:
ExpandSelectionAsync
(
selectedSpans
,
args
,
cancellationToken
);
}
/// <summary>Returns the span for the currently selected line.</summary>
private
static
IEnumerable
<
SnapshotSpan
>
GetSelectedLine
(
CommandArgs
args
)
private
static
IEnumerable
<
SnapshotSpan
>
GetSelectedLine
(
ITextView
textView
)
{
SnapshotPoint
?
caret
=
args
.
TextView
.
GetCaretPoint
(
args
.
SubjectBuffer
);
int
caretPosition
=
args
.
TextView
.
Caret
.
Position
.
BufferPosition
.
Position
;
ITextSnapshotLine
containingLine
=
caret
.
Value
.
GetContainingLine
();
return
new
SnapshotSpan
[]
{
new
SnapshotSpan
(
containingLine
.
Start
,
containingLine
.
End
)
};
ITextSnapshotLine
snapshotLine
=
textView
.
Caret
.
Position
.
VirtualBufferPosition
.
Position
.
GetContainingLine
();
SnapshotSpan
span
=
new
SnapshotSpan
(
snapshotLine
.
Start
,
snapshotLine
.
LengthIncludingLineBreak
);
return
new
NormalizedSnapshotSpanCollection
(
span
);
}
private
async
Task
<
IEnumerable
<
SnapshotSpan
>>
GetExecutableSyntaxTreeNodeSelection
(
private
async
Task
<
IEnumerable
<
SnapshotSpan
>>
GetExecutableSyntaxTreeNodeSelection
Async
(
TextSpan
selectionSpan
,
CommandArgs
args
,
ITextSnapshot
snapshot
,
CancellationToken
cancellationToken
)
{
Document
doc
=
args
.
SubjectBuffer
.
GetRelatedDocuments
().
FirstOrDefault
();
var
semanticDocument
=
await
SemanticDocument
.
CreateAsync
(
doc
,
cancellationToken
).
ConfigureAwait
(
false
);
var
text
=
semanticDocument
.
Text
;
Document
doc
=
args
.
SubjectBuffer
.
CurrentSnapshot
.
GetOpenDocumentInCurrentContextWithChanges
();
var
semanticDocument
=
await
SemanticDocument
.
CreateAsync
(
doc
,
cancellationToken
).
ConfigureAwait
(
true
);
var
root
=
semanticDocument
.
Root
;
var
model
=
semanticDocument
.
SemanticModel
;
return
GetExecutableSyntaxTreeNodeSelection
(
selectionSpan
,
text
,
root
,
model
)
return
GetExecutableSyntaxTreeNodeSelection
(
selectionSpan
,
root
)
.
Select
(
span
=>
new
SnapshotSpan
(
snapshot
,
span
.
Start
,
span
.
Length
));
}
private
IEnumerable
<
SnapshotSpan
>
ExpandSelection
(
IEnumerable
<
SnapshotSpan
>
selectedSpans
,
CommandArgs
args
,
CancellationToken
cancellationToken
)
private
async
Task
<
IEnumerable
<
SnapshotSpan
>>
ExpandSelectionAsync
(
IEnumerable
<
SnapshotSpan
>
selectedSpans
,
CommandArgs
args
,
CancellationToken
cancellationToken
)
{
var
selectedSpansStart
=
selectedSpans
.
Min
(
span
=>
span
.
Start
);
var
selectedSpansEnd
=
selectedSpans
.
Max
(
span
=>
span
.
End
);
ITextSnapshot
snapshot
=
args
.
TextView
.
TextSnapshot
;
IEnumerable
<
SnapshotSpan
>
newSpans
=
GetExecutableSyntaxTreeNodeSelection
(
IEnumerable
<
SnapshotSpan
>
newSpans
=
await
GetExecutableSyntaxTreeNodeSelectionAsync
(
TextSpan
.
FromBounds
(
selectedSpansStart
,
selectedSpansEnd
),
args
,
snapshot
,
cancellationToken
).
WaitAndGetResult
(
cancellationToken
);
cancellationToken
).
ConfigureAwait
(
true
);
return
newSpans
.
Any
()
?
newSpans
.
Select
(
n
=>
new
SnapshotSpan
(
snapshot
,
n
.
Span
.
Start
,
n
.
Span
.
Length
))
...
...
src/Interactive/EditorFeatures/Core/InteractiveEditorFeaturesResources.Designer.cs
浏览文件 @
d4a81920
...
...
@@ -70,7 +70,7 @@ internal class InteractiveEditorFeaturesResources {
}
/// <summary>
/// Looks up a localized string similar to Copying selection to
interactive w
indow..
/// Looks up a localized string similar to Copying selection to
Interactive W
indow..
/// </summary>
internal
static
string
CopyToInteractiveDescription
{
get
{
...
...
@@ -79,7 +79,7 @@ internal class InteractiveEditorFeaturesResources {
}
/// <summary>
/// Looks up a localized string similar to Executing selection in
interactive w
indow..
/// Looks up a localized string similar to Executing selection in
Interactive W
indow..
/// </summary>
internal
static
string
ExecuteInInteractiveDescription
{
get
{
...
...
src/Interactive/EditorFeatures/Core/InteractiveEditorFeaturesResources.resx
浏览文件 @
d4a81920
...
...
@@ -121,10 +121,10 @@
<value>
Building Project
</value>
</data>
<data
name=
"CopyToInteractiveDescription"
xml:space=
"preserve"
>
<value>
Copying selection to
interactive w
indow.
</value>
<value>
Copying selection to
Interactive W
indow.
</value>
</data>
<data
name=
"ExecuteInInteractiveDescription"
xml:space=
"preserve"
>
<value>
Executing selection in
interactive w
indow.
</value>
<value>
Executing selection in
Interactive W
indow.
</value>
</data>
<data
name=
"ReferencesCommandDescription"
xml:space=
"preserve"
>
<value>
Print a list of referenced assemblies.
</value>
...
...
src/Interactive/EditorFeatures/VisualBasic/Interactive/VisualBasicSendToInteractiveSubmissionProvider.vb
浏览文件 @
d4a81920
...
...
@@ -8,14 +8,14 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Interactive
<
Export
(
GetType
(
ISendToInteractiveSubmissionProvider
))
>
Friend
NotInheritable
Class
VisualBasicSendToInteractiveSubmissionProvider
Inherits
SendToInteractiveSubmissionProvider
Inherits
Abstract
SendToInteractiveSubmissionProvider
Protected
Overrides
Function
CanParseSubmission
(
code
As
String
)
As
Boolean
' Return True to send the direct selection.
Return
True
End
Function
Protected
Overrides
Function
GetExecutableSyntaxTreeNodeSelection
(
position
As
TextSpan
,
source
As
SourceText
,
node
As
SyntaxNode
,
model
As
SemanticModel
)
As
IEnumerable
(
Of
TextSpan
)
Protected
Overrides
Function
GetExecutableSyntaxTreeNodeSelection
(
position
As
TextSpan
,
node
As
SyntaxNode
)
As
IEnumerable
(
Of
TextSpan
)
Return
Nothing
End
Function
End
Class
...
...
src/VisualStudio/CSharp/Test/Interactive/Commands/InteractiveCommandHandlerTests.cs
浏览文件 @
d4a81920
...
...
@@ -36,6 +36,10 @@ internal class InteractiveCommandHandlerTests
public
void
TestExecuteInInteractiveWithoutSelection
()
{
AssertExecuteInInteractive
(
Caret
,
new
string
[
0
]);
AssertExecuteInInteractive
(
@"var x = 1;
$$
var y = 2;"
,
new
string
[
0
]);
AssertExecuteInInteractive
(
ExampleCode1
+
Caret
,
ExampleCode1
);
AssertExecuteInInteractive
(
ExampleCode1
.
Insert
(
3
,
Caret
),
ExampleCode1
);
AssertExecuteInInteractive
(
ExampleCode2
+
Caret
,
ExampleCode2Line2
);
...
...
@@ -46,6 +50,9 @@ public void TestExecuteInInteractiveWithoutSelection()
[
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Interactive
)]
public
void
TestExecuteInInteractiveWithEmptyBuffer
()
{
AssertExecuteInInteractive
(
@"{|Selection:|}var x = 1;
{|Selection:$$|}var y = 2;"
,
new
string
[
0
]);
AssertExecuteInInteractive
(
$@"
{{|
Selection
:{
ExampleCode1
}
$$
|}}
"
,
ExampleCode1
);
AssertExecuteInInteractive
(
$@"
{{|
Selection
:{
ExampleCode2
}
$$
|}}
"
,
ExampleCode2
);
AssertExecuteInInteractive
(
...
...
@@ -88,6 +95,29 @@ public void TestExecuteInInteractiveWithNonEmptyBuffer()
submissionBuffer
:
"var x = 1;"
);
}
[
WpfFact
]
public
void
TestExecuteInInteractiveWithDefines
()
{
string
exampleWithIfDirective
=
@"#if DEF
public void $$Run()
{
}
#endif"
;
AssertExecuteInInteractive
(
exampleWithIfDirective
,
@"public void Run()"
);
string
exampleWithDefine
=
$@"#define DEF
{
exampleWithIfDirective
}
"
;
AssertExecuteInInteractive
(
exampleWithDefine
,
@"public void Run()
{
}"
);
}
[
WpfFact
]
[
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Interactive
)]
public
void
TestCopyToInteractiveWithoutSelection
()
...
...
@@ -156,12 +186,10 @@ private static void AssertExecuteInInteractive(string code, string[] expectedSub
private
static
void
PrepareSubmissionBuffer
(
string
submissionBuffer
,
InteractiveWindowCommandHandlerTestState
workspace
)
{
if
(
string
.
IsNullOrEmpty
(
submissionBuffer
))
if
(
!
string
.
IsNullOrEmpty
(
submissionBuffer
))
{
return
;
workspace
.
WindowCurrentLanguageBuffer
.
Insert
(
0
,
submissionBuffer
)
;
}
workspace
.
WindowCurrentLanguageBuffer
.
Insert
(
0
,
submissionBuffer
);
}
}
}
src/VisualStudio/CSharp/Test/Interactive/Commands/ResetInteractiveTests.cs
浏览文件 @
d4a81920
...
...
@@ -8,6 +8,8 @@
using
System
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
Microsoft.VisualStudio.Text.Editor
;
using
Microsoft.VisualStudio.Text.Editor.OptionsExtensionMethods
;
namespace
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive.Commands
{
...
...
@@ -37,13 +39,12 @@ public async void TestResetREPLWithProjectContext()
Assert
.
True
(
replReferenceCommands
.
Any
(
rc
=>
rc
.
EndsWith
(
@"ResetInteractiveTestsAssembly.dll"""
)));
Assert
.
True
(
replReferenceCommands
.
Any
(
rc
=>
rc
.
EndsWith
(
@"ResetInteractiveVisualBasicSubproject.dll"""
)));
var
expectedSubmissions
=
new
List
<
string
>();
expectedSubmissions
.
AddRange
(
replReferenceCommands
.
Select
(
r
=>
r
+
"\r\n"
));
expectedSubmissions
.
Add
(
string
.
Join
(
"\r\n"
,
@"using ""ns1"";"
,
@"using ""ns2"";"
)
+
"\r\n"
);
AssertResetInteractive
(
workspace
,
project
,
buildSucceeds
:
true
,
expectedSubmissions
:
expectedSubmissions
);
var
expectedReferences
=
replReferenceCommands
.
ToList
();
var
expectedUsings
=
new
List
<
string
>
{
@"using ""ns1"";"
,
@"using ""ns2"";"
};
AssertResetInteractive
(
workspace
,
project
,
buildSucceeds
:
true
,
expectedReferences
:
expectedReferences
,
expectedUsings
:
expectedUsings
);
// Test that no submissions are executed if the build fails.
AssertResetInteractive
(
workspace
,
project
,
buildSucceeds
:
false
,
expected
Submission
s
:
new
List
<
string
>());
AssertResetInteractive
(
workspace
,
project
,
buildSucceeds
:
false
,
expected
Reference
s
:
new
List
<
string
>());
}
}
...
...
@@ -51,8 +52,12 @@ public async void TestResetREPLWithProjectContext()
TestWorkspace
workspace
,
Project
project
,
bool
buildSucceeds
,
List
<
string
>
expectedSubmissions
)
List
<
string
>
expectedReferences
=
null
,
List
<
string
>
expectedUsings
=
null
)
{
expectedReferences
=
expectedReferences
??
new
List
<
string
>();
expectedUsings
=
expectedUsings
??
new
List
<
string
>();
InteractiveWindowTestHost
testHost
=
new
InteractiveWindowTestHost
();
List
<
string
>
executedSubmissionCalls
=
new
List
<
string
>();
EventHandler
<
string
>
ExecuteSubmission
=
(
_
,
code
)
=>
{
executedSubmissionCalls
.
Add
(
code
);
};
...
...
@@ -60,9 +65,13 @@ public async void TestResetREPLWithProjectContext()
testHost
.
Evaluator
.
OnExecute
+=
ExecuteSubmission
;
IWaitIndicator
waitIndicator
=
workspace
.
GetService
<
IWaitIndicator
>();
IEditorOptionsFactoryService
editorOptionsFactoryService
=
workspace
.
GetService
<
IEditorOptionsFactoryService
>();
var
editorOptions
=
editorOptionsFactoryService
.
GetOptions
(
testHost
.
Window
.
CurrentLanguageBuffer
);
var
newLineCharacter
=
editorOptions
.
GetNewLineCharacter
();
TestResetInteractive
resetInteractive
=
new
TestResetInteractive
(
waitIndicator
,
editorOptionsFactoryService
,
CreateReplReferenceCommand
,
CreateImport
,
buildSucceeds
:
buildSucceeds
)
...
...
@@ -80,6 +89,16 @@ public async void TestResetREPLWithProjectContext()
Assert
.
Equal
(
1
,
resetInteractive
.
BuildProjectCount
);
Assert
.
Equal
(
0
,
resetInteractive
.
CancelBuildProjectCount
);
var
expectedSubmissions
=
new
List
<
string
>();
if
(
expectedReferences
.
Any
())
{
expectedSubmissions
.
AddRange
(
expectedReferences
.
Select
(
r
=>
r
+
newLineCharacter
));
}
if
(
expectedUsings
.
Any
())
{
expectedSubmissions
.
Add
(
string
.
Join
(
newLineCharacter
,
expectedUsings
)
+
newLineCharacter
);
}
AssertEx
.
Equal
(
expectedSubmissions
,
executedSubmissionCalls
);
testHost
.
Evaluator
.
OnExecute
-=
ExecuteSubmission
;
...
...
src/VisualStudio/CSharp/Test/Interactive/Commands/TestResetInteractive.cs
浏览文件 @
d4a81920
...
...
@@ -2,6 +2,7 @@
using
Microsoft.CodeAnalysis.Editor.Host
;
using
Microsoft.VisualStudio.LanguageServices.Interactive
;
using
Microsoft.VisualStudio.Text.Editor
;
using
System
;
using
System.Collections.Immutable
;
using
System.Threading.Tasks
;
...
...
@@ -28,8 +29,13 @@ internal class TestResetInteractive : ResetInteractive
internal
string
ProjectDirectory
{
get
;
set
;
}
public
TestResetInteractive
(
IWaitIndicator
waitIndicator
,
Func
<
string
,
string
>
createReference
,
Func
<
string
,
string
>
createImport
,
bool
buildSucceeds
)
:
base
(
createReference
,
createImport
)
public
TestResetInteractive
(
IWaitIndicator
waitIndicator
,
IEditorOptionsFactoryService
editorOptionsFactoryService
,
Func
<
string
,
string
>
createReference
,
Func
<
string
,
string
>
createImport
,
bool
buildSucceeds
)
:
base
(
editorOptionsFactoryService
,
createReference
,
createImport
)
{
_waitIndicator
=
waitIndicator
;
_buildSucceeds
=
buildSucceeds
;
...
...
src/VisualStudio/InteractiveServices/Interactive/VsResetInteractive.cs
浏览文件 @
d4a81920
...
...
@@ -16,6 +16,7 @@
using
VSLangProj
;
using
Project
=
EnvDTE
.
Project
;
using
System.Collections.Immutable
;
using
Microsoft.VisualStudio.Text.Editor
;
namespace
Microsoft.VisualStudio.LanguageServices.Interactive
{
...
...
@@ -26,8 +27,14 @@ internal sealed class VsResetInteractive : ResetInteractive
private
readonly
IVsMonitorSelection
_monitorSelection
;
private
readonly
IVsSolutionBuildManager
_buildManager
;
internal
VsResetInteractive
(
DTE
dte
,
IComponentModel
componentModel
,
IVsMonitorSelection
monitorSelection
,
IVsSolutionBuildManager
buildManager
,
Func
<
string
,
string
>
createReference
,
Func
<
string
,
string
>
createImport
)
:
base
(
createReference
,
createImport
)
internal
VsResetInteractive
(
DTE
dte
,
IComponentModel
componentModel
,
IVsMonitorSelection
monitorSelection
,
IVsSolutionBuildManager
buildManager
,
Func
<
string
,
string
>
createReference
,
Func
<
string
,
string
>
createImport
)
:
base
(
componentModel
.
GetService
<
IEditorOptionsFactoryService
>(),
createReference
,
createImport
)
{
_dte
=
dte
;
_componentModel
=
componentModel
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录