Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
4e3b4b63
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
4e3b4b63
编写于
9月 10, 2019
作者:
I
Isidor Nikolic
提交者:
GitHub
9月 10, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #80422 from dgozman/fix-79196
Separate REPL evaluation from it's result; fixes #79196
上级
81671f3f
3bcaff85
变更
9
显示空白变更内容
内联
并排
Showing
9 changed file
with
205 addition
and
146 deletion
+205
-146
src/vs/workbench/contrib/debug/browser/baseDebugView.ts
src/vs/workbench/contrib/debug/browser/baseDebugView.ts
+3
-3
src/vs/workbench/contrib/debug/browser/debugSession.ts
src/vs/workbench/contrib/debug/browser/debugSession.ts
+3
-1
src/vs/workbench/contrib/debug/browser/media/repl.css
src/vs/workbench/contrib/debug/browser/media/repl.css
+7
-4
src/vs/workbench/contrib/debug/browser/repl.ts
src/vs/workbench/contrib/debug/browser/repl.ts
+51
-30
src/vs/workbench/contrib/debug/common/debug.ts
src/vs/workbench/contrib/debug/common/debug.ts
+4
-4
src/vs/workbench/contrib/debug/common/debugModel.ts
src/vs/workbench/contrib/debug/common/debugModel.ts
+34
-90
src/vs/workbench/contrib/debug/common/replModel.ts
src/vs/workbench/contrib/debug/common/replModel.ts
+97
-6
src/vs/workbench/contrib/debug/test/browser/debugModel.test.ts
...s/workbench/contrib/debug/test/browser/debugModel.test.ts
+3
-5
test/smoke/src/areas/debug/debugSmoke.ts
test/smoke/src/areas/debug/debugSmoke.ts
+3
-3
未找到文件。
src/vs/workbench/contrib/debug/browser/baseDebugView.ts
浏览文件 @
4e3b4b63
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
{
IExpression
,
IDebugService
}
from
'
vs/workbench/contrib/debug/common/debug
'
;
import
{
IExpression
,
IDebugService
,
IExpressionContainer
}
from
'
vs/workbench/contrib/debug/common/debug
'
;
import
{
Expression
,
Variable
,
ExpressionContainer
}
from
'
vs/workbench/contrib/debug/common/debugModel
'
;
import
{
IContextViewService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
IInputValidationOptions
,
InputBox
}
from
'
vs/base/browser/ui/inputbox/inputBox
'
;
...
...
@@ -50,7 +50,7 @@ export function replaceWhitespace(value: string): string {
return
value
.
replace
(
/
[\n\r\t]
/g
,
char
=>
map
[
char
]);
}
export
function
renderExpressionValue
(
expressionOrValue
:
IExpression
|
string
,
container
:
HTMLElement
,
options
:
IRenderValueOptions
):
void
{
export
function
renderExpressionValue
(
expressionOrValue
:
IExpression
Container
|
string
,
container
:
HTMLElement
,
options
:
IRenderValueOptions
):
void
{
let
value
=
typeof
expressionOrValue
===
'
string
'
?
expressionOrValue
:
expressionOrValue
.
value
;
// remove stale classes
...
...
src/vs/workbench/contrib/debug/browser/debugSession.ts
浏览文件 @
4e3b4b63
...
...
@@ -921,7 +921,9 @@ export class DebugSession implements IDebugSession {
}
async
addReplExpression
(
stackFrame
:
IStackFrame
|
undefined
,
name
:
string
):
Promise
<
void
>
{
await
this
.
repl
.
addReplExpression
(
stackFrame
,
name
);
const
expressionEvaluated
=
this
.
repl
.
addReplExpression
(
stackFrame
,
name
);
this
.
_onDidChangeREPLElements
.
fire
();
await
expressionEvaluated
;
this
.
_onDidChangeREPLElements
.
fire
();
// Evaluate all watch expressions and fetch variables again since repl evaluation might have changed some.
variableSetEmitter
.
fire
();
...
...
src/vs/workbench/contrib/debug/browser/media/repl.css
浏览文件 @
4e3b4b63
...
...
@@ -48,11 +48,13 @@
cursor
:
text
;
}
.repl
.repl-tree
.output.expression
>
.value
{
.repl
.repl-tree
.output.expression
>
.value
,
.repl
.repl-tree
.evaluation-result.expression
>
.value
{
margin-left
:
0px
;
}
.repl
.repl-tree
.output.expression
>
.annotation
{
.repl
.repl-tree
.output.expression
>
.annotation
,
.repl
.repl-tree
.evaluation-result.expression
>
.annotation
{
font-size
:
inherit
;
padding-left
:
6px
;
}
...
...
@@ -67,7 +69,7 @@
}
/* Only show 'stale expansion' info when the element gets expanded. */
.repl
.repl-tree
.
input-output-pair
>
.outpu
t
>
.annotation
::before
{
.repl
.repl-tree
.
evaluation-resul
t
>
.annotation
::before
{
content
:
''
;
}
...
...
@@ -134,7 +136,8 @@
.monaco-workbench
.repl
.repl-tree
.output.expression
.code-underline
{
text-decoration
:
underline
;
}
/* Links */
.monaco-workbench
.repl
.repl-tree
.output.expression
a
{
.monaco-workbench
.repl
.repl-tree
.output.expression
a
,
.monaco-workbench
.repl
.repl-tree
.evaluation-result.expression
a
{
text-decoration
:
underline
;
cursor
:
pointer
;
}
src/vs/workbench/contrib/debug/browser/repl.ts
浏览文件 @
4e3b4b63
...
...
@@ -44,7 +44,8 @@ import { CompletionContext, CompletionList, CompletionProviderRegistry } from 'v
import
{
first
}
from
'
vs/base/common/arrays
'
;
import
{
IPanelService
}
from
'
vs/workbench/services/panel/common/panelService
'
;
import
{
IAccessibilityProvider
}
from
'
vs/base/browser/ui/list/listWidget
'
;
import
{
Variable
,
Expression
,
SimpleReplElement
,
RawObjectReplElement
}
from
'
vs/workbench/contrib/debug/common/debugModel
'
;
import
{
Variable
}
from
'
vs/workbench/contrib/debug/common/debugModel
'
;
import
{
SimpleReplElement
,
RawObjectReplElement
,
ReplEvaluationInput
,
ReplEvaluationResult
}
from
'
vs/workbench/contrib/debug/common/replModel
'
;
import
{
IListVirtualDelegate
}
from
'
vs/base/browser/ui/list/list
'
;
import
{
ITreeRenderer
,
ITreeNode
,
ITreeContextMenuEvent
,
IAsyncDataSource
}
from
'
vs/base/browser/ui/tree/tree
'
;
import
{
IEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
...
...
@@ -412,7 +413,8 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
[
this
.
instantiationService
.
createInstance
(
VariablesRenderer
),
this
.
instantiationService
.
createInstance
(
ReplSimpleElementsRenderer
),
new
ReplExpressionsRenderer
(),
new
ReplEvaluationInputsRenderer
(),
new
ReplEvaluationResultsRenderer
(),
new
ReplRawObjectsRenderer
()
],
// https://github.com/microsoft/TypeScript/issues/32526
...
...
@@ -568,12 +570,13 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
// Repl tree
interface
IExpressionTemplateData
{
input
:
HTMLElement
;
output
:
HTMLElement
;
interface
IReplEvaluationInputTemplateData
{
label
:
HighlightedLabel
;
}
interface
IReplEvaluationResultTemplateData
{
value
:
HTMLElement
;
annotation
:
HTMLElement
;
label
:
HighlightedLabel
;
}
interface
ISimpleReplElementTemplateData
{
...
...
@@ -593,27 +596,46 @@ interface IRawObjectReplTemplateData {
label
:
HighlightedLabel
;
}
class
ReplE
xpressionsRenderer
implements
ITreeRenderer
<
Expression
,
FuzzyScore
,
IExpression
TemplateData
>
{
static
readonly
ID
=
'
expressionRepl
'
;
class
ReplE
valuationInputsRenderer
implements
ITreeRenderer
<
ReplEvaluationInput
,
FuzzyScore
,
IReplEvaluationInput
TemplateData
>
{
static
readonly
ID
=
'
replEvaluationInput
'
;
get
templateId
():
string
{
return
ReplE
xpression
sRenderer
.
ID
;
return
ReplE
valuationInput
sRenderer
.
ID
;
}
renderTemplate
(
container
:
HTMLElement
):
IExpressionTemplateData
{
dom
.
addClass
(
container
,
'
input-output-pair
'
);
const
input
=
dom
.
append
(
container
,
$
(
'
.input.expression
'
));
renderTemplate
(
container
:
HTMLElement
):
IReplEvaluationInputTemplateData
{
const
input
=
dom
.
append
(
container
,
$
(
'
.expression
'
));
const
label
=
new
HighlightedLabel
(
input
,
false
);
const
output
=
dom
.
append
(
container
,
$
(
'
.output.expression
'
));
return
{
label
};
}
renderElement
(
element
:
ITreeNode
<
ReplEvaluationInput
,
FuzzyScore
>
,
index
:
number
,
templateData
:
IReplEvaluationInputTemplateData
):
void
{
const
evaluation
=
element
.
element
;
templateData
.
label
.
set
(
evaluation
.
value
,
createMatches
(
element
.
filterData
));
}
disposeTemplate
(
templateData
:
IReplEvaluationInputTemplateData
):
void
{
// noop
}
}
class
ReplEvaluationResultsRenderer
implements
ITreeRenderer
<
ReplEvaluationResult
,
FuzzyScore
,
IReplEvaluationResultTemplateData
>
{
static
readonly
ID
=
'
replEvaluationResult
'
;
get
templateId
():
string
{
return
ReplEvaluationResultsRenderer
.
ID
;
}
renderTemplate
(
container
:
HTMLElement
):
IReplEvaluationResultTemplateData
{
const
output
=
dom
.
append
(
container
,
$
(
'
.evaluation-result.expression
'
));
const
value
=
dom
.
append
(
output
,
$
(
'
span.value
'
));
const
annotation
=
dom
.
append
(
output
,
$
(
'
span
'
));
return
{
input
,
label
,
output
,
value
,
annotation
};
return
{
value
,
annotation
};
}
renderElement
(
element
:
ITreeNode
<
Expression
,
FuzzyScore
>
,
index
:
number
,
templateData
:
IExpression
TemplateData
):
void
{
renderElement
(
element
:
ITreeNode
<
ReplEvaluationResult
,
FuzzyScore
>
,
index
:
number
,
templateData
:
IReplEvaluationResult
TemplateData
):
void
{
const
expression
=
element
.
element
;
templateData
.
label
.
set
(
expression
.
name
,
createMatches
(
element
.
filterData
));
renderExpressionValue
(
expression
,
templateData
.
value
,
{
preserveWhitespace
:
!
expression
.
hasChildren
,
showHover
:
false
,
...
...
@@ -625,7 +647,7 @@ class ReplExpressionsRenderer implements ITreeRenderer<Expression, FuzzyScore, I
}
}
disposeTemplate
(
templateData
:
I
Expression
TemplateData
):
void
{
disposeTemplate
(
templateData
:
I
ReplEvaluationResult
TemplateData
):
void
{
// noop
}
}
...
...
@@ -757,24 +779,23 @@ class ReplDelegate implements IListVirtualDelegate<IReplElement> {
const
rowHeight
=
Math
.
ceil
(
1.4
*
fontSize
);
const
wordWrap
=
config
.
console
.
wordWrap
;
if
(
!
wordWrap
)
{
return
element
instanceof
Expression
?
2
*
rowHeight
:
rowHeight
;
return
rowHeight
;
}
// In order to keep scroll position we need to give a good approximation to the tree
// For every 150 characters increase the number of lines needed
if
(
element
instanceof
Expression
)
{
let
{
name
,
value
}
=
element
;
let
nameRows
=
countNumberOfLines
(
name
)
+
Math
.
floor
(
name
.
length
/
150
);
if
(
element
instanceof
ReplEvaluationResult
)
{
let
value
=
element
.
value
;
if
(
element
.
hasChildren
)
{
return
(
nameRows
+
1
)
*
rowHeight
;
return
rowHeight
;
}
let
valueRows
=
value
?
(
countNumberOfLines
(
value
)
+
Math
.
floor
(
value
.
length
/
150
))
:
0
;
return
rowHeight
*
(
nameRows
+
valueRows
)
;
return
rowHeight
*
valueRows
;
}
if
(
element
instanceof
SimpleReplElement
)
{
if
(
element
instanceof
SimpleReplElement
||
element
instanceof
ReplEvaluationInput
)
{
let
value
=
element
.
value
;
let
valueRows
=
countNumberOfLines
(
value
)
+
Math
.
floor
(
value
.
length
/
150
);
...
...
@@ -788,8 +809,11 @@ class ReplDelegate implements IListVirtualDelegate<IReplElement> {
if
(
element
instanceof
Variable
&&
element
.
name
)
{
return
VariablesRenderer
.
ID
;
}
if
(
element
instanceof
Expression
)
{
return
ReplExpressionsRenderer
.
ID
;
if
(
element
instanceof
ReplEvaluationResult
)
{
return
ReplEvaluationResultsRenderer
.
ID
;
}
if
(
element
instanceof
ReplEvaluationInput
)
{
return
ReplEvaluationInputsRenderer
.
ID
;
}
if
(
element
instanceof
SimpleReplElement
||
(
element
instanceof
Variable
&&
!
element
.
name
))
{
// Variable with no name is a top level variable which should be rendered like a repl element #17404
...
...
@@ -836,10 +860,7 @@ class ReplAccessibilityProvider implements IAccessibilityProvider<IReplElement>
if
(
element
instanceof
Variable
)
{
return
nls
.
localize
(
'
replVariableAriaLabel
'
,
"
Variable {0} has value {1}, read eval print loop, debug
"
,
element
.
name
,
element
.
value
);
}
if
(
element
instanceof
Expression
)
{
return
nls
.
localize
(
'
replExpressionAriaLabel
'
,
"
Expression {0} has value {1}, read eval print loop, debug
"
,
element
.
name
,
element
.
value
);
}
if
(
element
instanceof
SimpleReplElement
)
{
if
(
element
instanceof
SimpleReplElement
||
element
instanceof
ReplEvaluationInput
||
element
instanceof
ReplEvaluationResult
)
{
return
nls
.
localize
(
'
replValueOutputAriaLabel
'
,
"
{0}, read eval print loop, debug
"
,
element
.
value
);
}
if
(
element
instanceof
RawObjectReplElement
)
{
...
...
src/vs/workbench/contrib/debug/common/debug.ts
浏览文件 @
4e3b4b63
...
...
@@ -104,13 +104,13 @@ export interface IExpressionContainer extends ITreeElement {
readonly
hasChildren
:
boolean
;
getChildren
():
Promise
<
IExpression
[]
>
;
readonly
reference
?:
number
;
readonly
value
:
string
;
readonly
type
?:
string
;
valueChanged
?:
boolean
;
}
export
interface
IExpression
extends
I
ReplElement
,
I
ExpressionContainer
{
export
interface
IExpression
extends
IExpressionContainer
{
name
:
string
;
readonly
value
:
string
;
valueChanged
?:
boolean
;
readonly
type
?:
string
;
}
export
interface
IDebugger
{
...
...
src/vs/workbench/contrib/debug/common/debugModel.ts
浏览文件 @
4e3b4b63
...
...
@@ -10,13 +10,12 @@ import * as lifecycle from 'vs/base/common/lifecycle';
import
{
Event
,
Emitter
}
from
'
vs/base/common/event
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
import
{
RunOnceScheduler
}
from
'
vs/base/common/async
'
;
import
severity
from
'
vs/base/common/severity
'
;
import
{
isObject
,
isString
,
isUndefinedOrNull
}
from
'
vs/base/common/types
'
;
import
{
isString
,
isUndefinedOrNull
}
from
'
vs/base/common/types
'
;
import
{
distinct
,
lastIndex
}
from
'
vs/base/common/arrays
'
;
import
{
Range
,
IRange
}
from
'
vs/editor/common/core/range
'
;
import
{
ITreeElement
,
IExpression
,
IExpressionContainer
,
IDebugSession
,
IStackFrame
,
IExceptionBreakpoint
,
IBreakpoint
,
IFunctionBreakpoint
,
IDebugModel
,
IReplElementSource
,
IThread
,
IRawModelUpdate
,
IScope
,
IRawStoppedDetails
,
IEnablement
,
IBreakpointData
,
IExceptionInfo
,
I
ReplElement
,
I
BreakpointsChangeEvent
,
IBreakpointUpdateData
,
IBaseBreakpoint
,
State
,
IDataBreakpoint
ITreeElement
,
IExpression
,
IExpressionContainer
,
IDebugSession
,
IStackFrame
,
IExceptionBreakpoint
,
IBreakpoint
,
IFunctionBreakpoint
,
IDebugModel
,
IThread
,
IRawModelUpdate
,
IScope
,
IRawStoppedDetails
,
IEnablement
,
IBreakpointData
,
IExceptionInfo
,
IBreakpointsChangeEvent
,
IBreakpointUpdateData
,
IBaseBreakpoint
,
State
,
IDataBreakpoint
}
from
'
vs/workbench/contrib/debug/common/debug
'
;
import
{
Source
,
UNKNOWN_SOURCE_LABEL
}
from
'
vs/workbench/contrib/debug/common/debugSource
'
;
import
{
commonSuffixLength
}
from
'
vs/base/common/strings
'
;
...
...
@@ -25,75 +24,13 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import
{
ITextFileService
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
ITextEditor
}
from
'
vs/workbench/common/editor
'
;
export
class
SimpleReplElement
implements
IReplElement
{
constructor
(
private
id
:
string
,
public
value
:
string
,
public
severity
:
severity
,
public
sourceData
?:
IReplElementSource
,
)
{
}
toString
():
string
{
return
this
.
value
;
}
getId
():
string
{
return
this
.
id
;
}
}
export
class
RawObjectReplElement
implements
IExpression
{
private
static
readonly
MAX_CHILDREN
=
1000
;
// upper bound of children per value
constructor
(
private
id
:
string
,
public
name
:
string
,
public
valueObj
:
any
,
public
sourceData
?:
IReplElementSource
,
public
annotation
?:
string
)
{
}
getId
():
string
{
return
this
.
id
;
}
get
value
():
string
{
if
(
this
.
valueObj
===
null
)
{
return
'
null
'
;
}
else
if
(
Array
.
isArray
(
this
.
valueObj
))
{
return
`Array[
${
this
.
valueObj
.
length
}
]`
;
}
else
if
(
isObject
(
this
.
valueObj
))
{
return
'
Object
'
;
}
else
if
(
isString
(
this
.
valueObj
))
{
return
`"
${
this
.
valueObj
}
"`
;
}
return
String
(
this
.
valueObj
)
||
''
;
}
get
hasChildren
():
boolean
{
return
(
Array
.
isArray
(
this
.
valueObj
)
&&
this
.
valueObj
.
length
>
0
)
||
(
isObject
(
this
.
valueObj
)
&&
Object
.
getOwnPropertyNames
(
this
.
valueObj
).
length
>
0
);
}
getChildren
():
Promise
<
IExpression
[]
>
{
let
result
:
IExpression
[]
=
[];
if
(
Array
.
isArray
(
this
.
valueObj
))
{
result
=
(
<
any
[]
>
this
.
valueObj
).
slice
(
0
,
RawObjectReplElement
.
MAX_CHILDREN
)
.
map
((
v
,
index
)
=>
new
RawObjectReplElement
(
`
${
this
.
id
}
:
${
index
}
`
,
String
(
index
),
v
));
}
else
if
(
isObject
(
this
.
valueObj
))
{
result
=
Object
.
getOwnPropertyNames
(
this
.
valueObj
).
slice
(
0
,
RawObjectReplElement
.
MAX_CHILDREN
)
.
map
((
key
,
index
)
=>
new
RawObjectReplElement
(
`
${
this
.
id
}
:
${
index
}
`
,
key
,
this
.
valueObj
[
key
]));
}
return
Promise
.
resolve
(
result
);
}
toString
():
string
{
return
`
${
this
.
name
}
\n
${
this
.
value
}
`
;
}
}
export
class
ExpressionContainer
implements
IExpressionContainer
{
public
static
allValues
=
new
Map
<
string
,
string
>
();
// Use chunks to support variable paging #9537
private
static
readonly
BASE_CHUNK_SIZE
=
100
;
public
type
:
string
|
undefined
;
public
valueChanged
=
false
;
private
_value
:
string
=
''
;
protected
children
?:
Promise
<
IExpression
[]
>
;
...
...
@@ -195,49 +132,56 @@ export class ExpressionContainer implements IExpressionContainer {
toString
():
string
{
return
this
.
value
;
}
}
export
class
Expression
extends
ExpressionContainer
implements
IExpression
{
static
DEFAULT_VALUE
=
nls
.
localize
(
'
notAvailable
'
,
"
not available
"
);
public
available
:
boolean
;
public
type
:
string
|
undefined
;
constructor
(
public
name
:
string
,
id
=
generateUuid
())
{
super
(
undefined
,
0
,
id
);
this
.
available
=
false
;
// name is not set if the expression is just being added
// in that case do not set default value to prevent flashing #14499
if
(
name
)
{
this
.
value
=
Expression
.
DEFAULT_VALUE
;
}
}
async
evaluateExpression
(
expression
:
string
,
session
:
IDebugSession
|
undefined
,
stackFrame
:
IStackFrame
|
undefined
,
context
:
string
):
Promise
<
boolean
>
{
async
evaluate
(
session
:
IDebugSession
|
undefined
,
stackFrame
:
IStackFrame
|
undefined
,
context
:
string
):
Promise
<
void
>
{
if
(
!
session
||
(
!
stackFrame
&&
context
!==
'
repl
'
))
{
this
.
value
=
context
===
'
repl
'
?
nls
.
localize
(
'
startDebugFirst
'
,
"
Please start a debug session to evaluate expressions
"
)
:
Expression
.
DEFAULT_VALUE
;
this
.
available
=
false
;
this
.
reference
=
0
;
return
Promise
.
resolve
(
undefined
);
return
false
;
}
this
.
session
=
session
;
try
{
const
response
=
await
session
.
evaluate
(
this
.
name
,
stackFrame
?
stackFrame
.
frameId
:
undefined
,
context
);
this
.
available
=
!!
(
response
&&
response
.
body
);
const
response
=
await
session
.
evaluate
(
expression
,
stackFrame
?
stackFrame
.
frameId
:
undefined
,
context
);
if
(
response
&&
response
.
body
)
{
this
.
value
=
response
.
body
.
result
||
''
;
this
.
reference
=
response
.
body
.
variablesReference
;
this
.
namedVariables
=
response
.
body
.
namedVariables
;
this
.
indexedVariables
=
response
.
body
.
indexedVariables
;
this
.
type
=
response
.
body
.
type
||
this
.
type
;
return
true
;
}
return
false
;
}
catch
(
e
)
{
this
.
value
=
e
.
message
||
''
;
this
.
available
=
false
;
this
.
reference
=
0
;
return
false
;
}
}
}
export
class
Expression
extends
ExpressionContainer
implements
IExpression
{
static
DEFAULT_VALUE
=
nls
.
localize
(
'
notAvailable
'
,
"
not available
"
);
public
available
:
boolean
;
constructor
(
public
name
:
string
,
id
=
generateUuid
())
{
super
(
undefined
,
0
,
id
);
this
.
available
=
false
;
// name is not set if the expression is just being added
// in that case do not set default value to prevent flashing #14499
if
(
name
)
{
this
.
value
=
Expression
.
DEFAULT_VALUE
;
}
}
async
evaluate
(
session
:
IDebugSession
|
undefined
,
stackFrame
:
IStackFrame
|
undefined
,
context
:
string
):
Promise
<
void
>
{
this
.
available
=
await
this
.
evaluateExpression
(
this
.
name
,
session
,
stackFrame
,
context
);
}
toString
():
string
{
...
...
src/vs/workbench/contrib/debug/common/replModel.ts
浏览文件 @
4e3b4b63
...
...
@@ -6,15 +6,105 @@
import
*
as
nls
from
'
vs/nls
'
;
import
severity
from
'
vs/base/common/severity
'
;
import
{
IReplElement
,
IStackFrame
,
IExpression
,
IReplElementSource
,
IDebugSession
}
from
'
vs/workbench/contrib/debug/common/debug
'
;
import
{
Expression
,
SimpleReplElement
,
RawObjectReplElement
}
from
'
vs/workbench/contrib/debug/common/debugModel
'
;
import
{
isUndefinedOrNull
,
isObject
}
from
'
vs/base/common/types
'
;
import
{
Expression
Container
}
from
'
vs/workbench/contrib/debug/common/debugModel
'
;
import
{
is
String
,
is
UndefinedOrNull
,
isObject
}
from
'
vs/base/common/types
'
;
import
{
basenameOrAuthority
}
from
'
vs/base/common/resources
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
endsWith
}
from
'
vs/base/common/strings
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
const
MAX_REPL_LENGTH
=
10000
;
let
topReplElementCounter
=
0
;
export
class
SimpleReplElement
implements
IReplElement
{
constructor
(
private
id
:
string
,
public
value
:
string
,
public
severity
:
severity
,
public
sourceData
?:
IReplElementSource
,
)
{
}
toString
():
string
{
return
this
.
value
;
}
getId
():
string
{
return
this
.
id
;
}
}
export
class
RawObjectReplElement
implements
IExpression
{
private
static
readonly
MAX_CHILDREN
=
1000
;
// upper bound of children per value
constructor
(
private
id
:
string
,
public
name
:
string
,
public
valueObj
:
any
,
public
sourceData
?:
IReplElementSource
,
public
annotation
?:
string
)
{
}
getId
():
string
{
return
this
.
id
;
}
get
value
():
string
{
if
(
this
.
valueObj
===
null
)
{
return
'
null
'
;
}
else
if
(
Array
.
isArray
(
this
.
valueObj
))
{
return
`Array[
${
this
.
valueObj
.
length
}
]`
;
}
else
if
(
isObject
(
this
.
valueObj
))
{
return
'
Object
'
;
}
else
if
(
isString
(
this
.
valueObj
))
{
return
`"
${
this
.
valueObj
}
"`
;
}
return
String
(
this
.
valueObj
)
||
''
;
}
get
hasChildren
():
boolean
{
return
(
Array
.
isArray
(
this
.
valueObj
)
&&
this
.
valueObj
.
length
>
0
)
||
(
isObject
(
this
.
valueObj
)
&&
Object
.
getOwnPropertyNames
(
this
.
valueObj
).
length
>
0
);
}
getChildren
():
Promise
<
IExpression
[]
>
{
let
result
:
IExpression
[]
=
[];
if
(
Array
.
isArray
(
this
.
valueObj
))
{
result
=
(
<
any
[]
>
this
.
valueObj
).
slice
(
0
,
RawObjectReplElement
.
MAX_CHILDREN
)
.
map
((
v
,
index
)
=>
new
RawObjectReplElement
(
`
${
this
.
id
}
:
${
index
}
`
,
String
(
index
),
v
));
}
else
if
(
isObject
(
this
.
valueObj
))
{
result
=
Object
.
getOwnPropertyNames
(
this
.
valueObj
).
slice
(
0
,
RawObjectReplElement
.
MAX_CHILDREN
)
.
map
((
key
,
index
)
=>
new
RawObjectReplElement
(
`
${
this
.
id
}
:
${
index
}
`
,
key
,
this
.
valueObj
[
key
]));
}
return
Promise
.
resolve
(
result
);
}
toString
():
string
{
return
`
${
this
.
name
}
\n
${
this
.
value
}
`
;
}
}
export
class
ReplEvaluationInput
implements
IReplElement
{
private
id
:
string
;
constructor
(
public
value
:
string
)
{
this
.
id
=
generateUuid
();
}
toString
():
string
{
return
this
.
value
;
}
getId
():
string
{
return
this
.
id
;
}
}
export
class
ReplEvaluationResult
extends
ExpressionContainer
implements
IReplElement
{
constructor
()
{
super
(
undefined
,
0
,
generateUuid
());
}
toString
():
string
{
return
`
${
this
.
value
}
`
;
}
}
export
class
ReplModel
{
private
replElements
:
IReplElement
[]
=
[];
...
...
@@ -24,10 +114,11 @@ export class ReplModel {
return
this
.
replElements
;
}
addReplExpression
(
stackFrame
:
IStackFrame
|
undefined
,
name
:
string
):
Promise
<
void
>
{
const
expression
=
new
Expression
(
name
);
this
.
addReplElement
(
expression
);
return
expression
.
evaluate
(
this
.
session
,
stackFrame
,
'
repl
'
);
async
addReplExpression
(
stackFrame
:
IStackFrame
|
undefined
,
name
:
string
):
Promise
<
void
>
{
this
.
addReplElement
(
new
ReplEvaluationInput
(
name
));
const
result
=
new
ReplEvaluationResult
();
await
result
.
evaluateExpression
(
name
,
this
.
session
,
stackFrame
,
'
repl
'
);
this
.
addReplElement
(
result
);
}
appendToRepl
(
data
:
string
|
IExpression
,
sev
:
severity
,
source
?:
IReplElementSource
):
void
{
...
...
src/vs/workbench/contrib/debug/test/browser/debugModel.test.ts
浏览文件 @
4e3b4b63
...
...
@@ -6,12 +6,12 @@
import
*
as
assert
from
'
assert
'
;
import
{
URI
as
uri
}
from
'
vs/base/common/uri
'
;
import
severity
from
'
vs/base/common/severity
'
;
import
{
SimpleReplElement
,
DebugModel
,
Expression
,
RawObjectReplElement
,
StackFrame
,
Thread
}
from
'
vs/workbench/contrib/debug/common/debugModel
'
;
import
{
DebugModel
,
Expression
,
StackFrame
,
Thread
}
from
'
vs/workbench/contrib/debug/common/debugModel
'
;
import
*
as
sinon
from
'
sinon
'
;
import
{
MockRawSession
}
from
'
vs/workbench/contrib/debug/test/common/mockDebug
'
;
import
{
Source
}
from
'
vs/workbench/contrib/debug/common/debugSource
'
;
import
{
DebugSession
}
from
'
vs/workbench/contrib/debug/browser/debugSession
'
;
import
{
ReplModel
}
from
'
vs/workbench/contrib/debug/common/replModel
'
;
import
{
SimpleReplElement
,
RawObjectReplElement
,
ReplEvaluationInput
,
ReplModel
}
from
'
vs/workbench/contrib/debug/common/replModel
'
;
import
{
IBreakpointUpdateData
}
from
'
vs/workbench/contrib/debug/common/debug
'
;
import
{
NullOpenerService
}
from
'
vs/platform/opener/common/opener
'
;
...
...
@@ -348,9 +348,7 @@ suite('Debug - Model', () => {
assert
.
equal
(
replModel
.
getReplElements
().
length
,
3
);
replModel
.
getReplElements
().
forEach
(
re
=>
{
assert
.
equal
((
<
Expression
>
re
).
available
,
false
);
assert
.
equal
((
<
Expression
>
re
).
name
,
'
myVariable
'
);
assert
.
equal
((
<
Expression
>
re
).
reference
,
0
);
assert
.
equal
((
<
ReplEvaluationInput
>
re
).
value
,
'
myVariable
'
);
});
replModel
.
removeReplExpressions
();
...
...
test/smoke/src/areas/debug/debugSmoke.ts
浏览文件 @
4e3b4b63
...
...
@@ -28,7 +28,7 @@ const STACK_FRAME = `${VIEWLET} .monaco-list-row .stack-frame`;
const
SPECIFIC_STACK_FRAME
=
filename
=>
`
${
STACK_FRAME
}
.file[title*="
${
filename
}
"]`
;
const
VARIABLE
=
`
${
VIEWLET
}
.debug-variables .monaco-list-row .expression`
;
const
CONSOLE_OUTPUT
=
`.repl .output.expression .value`
;
const
CONSOLE_
INPUT_OUTPUT
=
`.repl .input-output-pair .outpu
t.expression .value`
;
const
CONSOLE_
EVALUATION_RESULT
=
`.repl .evaluation-resul
t.expression .value`
;
const
REPL_FOCUSED
=
'
.repl-input-wrapper .monaco-editor textarea
'
;
...
...
@@ -132,8 +132,8 @@ export class Debug extends Viewlet {
// Wait for the keys to be picked up by the editor model such that repl evalutes what just got typed
await
this
.
editor
.
waitForEditorContents
(
'
debug:replinput
'
,
s
=>
s
.
indexOf
(
text
)
>=
0
);
await
this
.
code
.
dispatchKeybinding
(
'
enter
'
);
await
this
.
code
.
waitForElement
(
CONSOLE_INPUT_OUTPUT
);
await
this
.
waitForOutput
(
output
=>
accept
(
output
[
output
.
length
-
1
]
||
''
));
await
this
.
code
.
waitForElement
s
(
CONSOLE_EVALUATION_RESULT
,
false
,
elements
=>
!!
elements
.
length
&&
accept
(
elements
[
elements
.
length
-
1
].
textContent
));
}
// Different node versions give different number of variables. As a workaround be more relaxed when checking for variable count
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录