Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
db334b22
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
db334b22
编写于
1月 13, 2017
作者:
I
isidor
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
debug: inline values use map, set. Polish
上级
07b83624
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
176 addition
and
61 deletion
+176
-61
src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts
...h/parts/debug/electron-browser/debugEditorContribution.ts
+9
-10
src/vs/workbench/parts/debug/electron-browser/debugInlineValues.ts
...rkbench/parts/debug/electron-browser/debugInlineValues.ts
+140
-0
src/vs/workbench/parts/debug/test/electron-browser/debugInlineValues.test.ts
...rts/debug/test/electron-browser/debugInlineValues.test.ts
+27
-51
未找到文件。
src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts
浏览文件 @
db334b22
...
...
@@ -14,10 +14,9 @@ import { visit } from 'vs/base/common/json';
import
{
IAction
,
Action
}
from
'
vs/base/common/actions
'
;
import
{
KeyCode
}
from
'
vs/base/common/keyCodes
'
;
import
{
IKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
ICodeEditor
,
IEditorMouseEvent
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
editorContribution
}
from
'
vs/editor/browser/editorBrowserExtensions
'
;
import
{
I
Range
,
I
ModelDecorationOptions
,
MouseTargetType
,
IModelDeltaDecoration
,
TrackedRangeStickiness
,
IPosition
}
from
'
vs/editor/common/editorCommon
'
;
import
{
IModelDecorationOptions
,
MouseTargetType
,
IModelDeltaDecoration
,
TrackedRangeStickiness
,
IPosition
}
from
'
vs/editor/common/editorCommon
'
;
import
{
ICodeEditorService
}
from
'
vs/editor/common/services/codeEditorService
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
...
...
@@ -32,7 +31,7 @@ import { RemoveBreakpointAction, EditConditionalBreakpointAction, EnableBreakpoi
import
{
IDebugEditorContribution
,
IDebugService
,
State
,
IBreakpoint
,
EDITOR_CONTRIBUTION_ID
,
CONTEXT_BREAKPOINT_WIDGET_VISIBLE
,
IStackFrame
,
IDebugConfiguration
}
from
'
vs/workbench/parts/debug/common/debug
'
;
import
{
BreakpointWidget
}
from
'
vs/workbench/parts/debug/browser/breakpointWidget
'
;
import
{
FloatingClickWidget
}
from
'
vs/workbench/parts/preferences/browser/preferencesWidgets
'
;
import
{
getNameValueMapFromScopeChildren
,
getDecorators
,
getEditorWordRangeMap
}
from
'
vs/workbench/parts/debug/electron-browser/debugInlineDecorator
s
'
;
import
{
toNameValueMap
,
getDecorations
,
getWordToLineNumbersMap
}
from
'
vs/workbench/parts/debug/electron-browser/debugInlineValue
s
'
;
const
HOVER_DELAY
=
300
;
const
LAUNCH_JSON_REGEX
=
/launch
\.
json$/
;
...
...
@@ -52,7 +51,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
private
breakpointWidget
:
BreakpointWidget
;
private
breakpointWidgetVisible
:
IContextKey
<
boolean
>
;
private
removeDecorationsTimeoutId
=
0
;
private
editorModelWordRangeMap
:
IStringDictionary
<
IRange
[]
>
;
private
wordToLineNumbersMap
:
Map
<
string
,
number
[]
>
;
private
configurationWidget
:
FloatingClickWidget
;
...
...
@@ -226,14 +225,14 @@ export class DebugEditorContribution implements IDebugEditorContribution {
if
(
!
stackFrame
)
{
this
.
removeDecorationsTimeoutId
=
setTimeout
(()
=>
{
this
.
editor
.
removeDecorations
(
INLINE_DECORATOR_KEY
);
this
.
editorModelWordRange
Map
=
null
;
this
.
wordToLineNumbers
Map
=
null
;
},
REMOVE_DECORATORS_DEBOUNCE_INTERVAL
);
return
;
}
// URI has changed, invalidate the editorWordRangeMap so its re-computed for the current model
if
(
stackFrame
.
source
.
uri
.
toString
()
!==
this
.
editor
.
getModel
().
uri
.
toString
())
{
this
.
editorModelWordRange
Map
=
null
;
this
.
wordToLineNumbers
Map
=
null
;
}
stackFrame
.
getScopes
()
...
...
@@ -243,13 +242,13 @@ export class DebugEditorContribution implements IDebugEditorContribution {
const
editorModel
=
this
.
editor
.
getModel
();
// Compute name-value map for all variables in scope chain
const
expressions
=
[].
concat
.
apply
([],
children
);
const
nameValueMap
=
getNameValueMapFromScopeChildren
(
expressions
);
const
nameValueMap
=
toNameValueMap
(
expressions
);
// Build wordRangeMap if not already computed for the editor model
if
(
!
this
.
editorModelWordRange
Map
)
{
this
.
editorModelWordRangeMap
=
getEditorWordRange
Map
(
editorModel
);
if
(
!
this
.
wordToLineNumbers
Map
)
{
this
.
wordToLineNumbersMap
=
getWordToLineNumbers
Map
(
editorModel
);
}
// Compute decorators from nameValueMap and wordRangeMap and apply to editor
const
decorators
=
getDecorat
ors
(
nameValueMap
,
this
.
editorModelWordRangeMap
,
editorModel
.
getLinesContent
()
);
const
decorators
=
getDecorat
ions
(
nameValueMap
,
this
.
wordToLineNumbersMap
);
this
.
editor
.
setDecorations
(
INLINE_DECORATOR_KEY
,
decorators
);
});
}
...
...
src/vs/workbench/parts/debug/electron-browser/debugInline
Decorator
s.ts
→
src/vs/workbench/parts/debug/electron-browser/debugInline
Value
s.ts
浏览文件 @
db334b22
...
...
@@ -2,10 +2,8 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
IDecorationOptions
,
IRange
,
IModel
}
from
'
vs/editor/common/editorCommon
'
;
import
{
IDecorationOptions
,
IModel
}
from
'
vs/editor/common/editorCommon
'
;
import
{
StandardTokenType
}
from
'
vs/editor/common/modes
'
;
import
{
IExpression
}
from
'
vs/workbench/parts/debug/common/debug
'
;
...
...
@@ -13,23 +11,22 @@ export const MAX_INLINE_VALUE_LENGTH = 50; // Max string length of each inline '
export
const
MAX_INLINE_DECORATOR_LENGTH
=
150
;
// Max string length of each inline decorator when debugging. If exceeded ... is added
export
const
MAX_NUM_INLINE_VALUES
=
100
;
// JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons
export
const
MAX_TOKENIZATION_LINE_LEN
=
500
;
// If line is too long, then inline values for the line are skipped
export
const
ELLIPSES
=
'
…
'
;
// LanguageConfigurationRegistry.getWordDefinition() return regexes that allow spaces and punctuation characters for languages like python
// Using that approach is not viable so we are using a simple regex to look for word tokens.
export
const
WORD_REGEXP
=
/
[\$\_
A-Za-z
][\$\_
A-Za-z0-9
]
*/g
;
export
function
getNameValueMapFromScopeChildren
(
expressions
:
IExpression
[]):
IStringDictionary
<
string
>
{
const
nameValueMap
:
IStringDictionary
<
string
>
=
Object
.
create
(
null
);
export
function
toNameValueMap
(
expressions
:
IExpression
[]):
Map
<
string
,
string
>
{
const
result
=
new
Map
<
string
,
string
>
(
);
let
valueCount
=
0
;
for
(
let
expr
of
expressions
)
{
// Put ellipses in value if its too long. Preserve last char e.g "longstr…" or {a:true, b:true, …}
let
value
=
expr
.
value
;
if
(
value
&&
value
.
length
>
MAX_INLINE_VALUE_LENGTH
)
{
value
=
value
.
substr
(
0
,
MAX_INLINE_VALUE_LENGTH
-
ELLIPSES
.
length
)
+
ELLIPSES
+
value
[
value
.
length
-
1
];
value
=
value
.
substr
(
0
,
MAX_INLINE_VALUE_LENGTH
)
+
'
…
'
+
value
[
value
.
length
-
1
];
}
nameValueMap
[
expr
.
name
]
=
value
;
result
.
set
(
expr
.
name
,
value
)
;
// Limit the size of map. Too large can have a perf impact
if
(
++
valueCount
>=
MAX_NUM_INLINE_VALUES
)
{
...
...
@@ -37,60 +34,53 @@ export function getNameValueMapFromScopeChildren(expressions: IExpression[]): IS
}
}
return
nameValueMap
;
return
result
;
}
export
function
getDecorators
(
nameValueMap
:
IStringDictionary
<
string
>
,
wordRangeMap
:
IStringDictionary
<
IRange
[]
>
,
linesContent
:
string
[]):
IDecorationOptions
[]
{
const
linesNames
:
IStringDictionary
<
IStringDictionary
<
boolean
>>
=
Object
.
create
(
null
);
const
names
=
Object
.
keys
(
nameValueMap
);
const
decorators
:
IDecorationOptions
[]
=
[];
export
function
getDecorations
(
nameValueMap
:
Map
<
string
,
string
>
,
wordToLineNumbersMap
:
Map
<
string
,
number
[]
>
):
IDecorationOptions
[]
{
const
lineToNamesMap
:
Map
<
number
,
string
[]
>
=
new
Map
<
number
,
string
[]
>
();
const
decorations
:
IDecorationOptions
[]
=
[];
// Compute unique set of names on each line
for
(
let
name
of
names
)
{
const
ranges
=
wordRangeMap
[
name
];
if
(
ranges
)
{
for
(
let
range
of
ranges
)
{
const
lineNum
=
range
.
startLineNumber
;
if
(
!
linesNames
[
lineNum
])
{
linesNames
[
lineNum
]
=
Object
.
create
(
null
);
nameValueMap
.
forEach
((
value
,
name
)
=>
{
if
(
wordToLineNumbersMap
.
has
(
name
))
{
for
(
let
lineNumber
of
wordToLineNumbersMap
.
get
(
name
))
{
if
(
!
lineToNamesMap
.
has
(
lineNumber
))
{
lineToNamesMap
.
set
(
lineNumber
,
[]);
}
linesNames
[
lineNum
][
name
]
=
true
;
lineToNamesMap
.
get
(
lineNumber
).
push
(
name
);
}
}
}
}
);
// Compute decorators for each line
const
lineNums
=
Object
.
keys
(
linesNames
);
for
(
let
lineNum
of
lineNums
)
{
const
uniqueNames
=
Object
.
keys
(
linesNames
[
lineNum
]);
const
decorator
=
getDecoratorFromNames
(
parseInt
(
lineNum
),
uniqueNames
,
nameValueMap
,
linesContent
);
decorators
.
push
(
decorator
);
}
lineToNamesMap
.
forEach
((
names
,
line
)
=>
{
// Wrap with 1em unicode space for readability
const
contentText
=
'
\
u2003
'
+
names
.
map
(
name
=>
`
${
name
}
=
${
nameValueMap
.
get
(
name
)}
`
).
join
(
'
,
'
)
+
'
\
u2003
'
;
decorations
.
push
(
createDecoration
(
line
,
contentText
));
});
return
decorat
or
s
;
return
decorat
ion
s
;
}
export
function
getDecoratorFromNames
(
lineNumber
:
number
,
names
:
string
[],
nameValueMap
:
IStringDictionary
<
string
>
,
linesContent
:
string
[]
):
IDecorationOptions
{
function
createDecoration
(
lineNumber
:
number
,
contentText
:
string
):
IDecorationOptions
{
const
margin
=
'
10px
'
;
const
backgroundColor
=
'
rgba(255,200,0,0.2)
'
;
const
lightForegroundColor
=
'
rgba(0,0,0,0.5)
'
;
const
darkForegroundColor
=
'
rgba(255,255,255,0.5)
'
;
const
lineLength
=
linesContent
[
lineNumber
-
1
].
length
;
// Wrap with 1em unicode space for readability
let
contentText
=
'
\
u2003
'
+
names
.
map
(
n
=>
`
${
n
}
=
${
nameValueMap
[
n
]}
`
).
join
(
'
,
'
)
+
'
\
u2003
'
;
const
backgroundColor
=
'
rgba(255, 200, 0, 0.2)
'
;
const
lightForegroundColor
=
'
rgba(0, 0, 0, 0.5)
'
;
const
darkForegroundColor
=
'
rgba(255, 255, 255, 0.5)
'
;
// If decoratorText is too long, trim and add ellipses. This could happen for minified files with everything on a single line
if
(
contentText
.
length
>
MAX_INLINE_DECORATOR_LENGTH
)
{
contentText
=
contentText
.
substr
(
0
,
MAX_INLINE_DECORATOR_LENGTH
-
ELLIPSES
.
length
)
+
ELLIPSES
;
contentText
=
contentText
.
substr
(
0
,
MAX_INLINE_DECORATOR_LENGTH
)
+
'
...
'
;
}
const
decorator
:
IDecorationOptions
=
{
return
{
range
:
{
startLineNumber
:
lineNumber
,
endLineNumber
:
lineNumber
,
startColumn
:
lineLength
,
endColumn
:
lineLength
+
1
startColumn
:
Number
.
MAX_VALUE
,
endColumn
:
Number
.
MAX_VALUE
},
renderOptions
:
{
dark
:
{
...
...
@@ -111,56 +101,40 @@ export function getDecoratorFromNames(lineNumber: number, names: string[], nameV
}
}
};
return
decorator
;
}
export
function
getEditorWordRangeMap
(
editorModel
:
IModel
):
IStringDictionary
<
IRange
[]
>
{
const
wordRangeMap
:
IStringDictionary
<
IRange
[]
>
=
Object
.
create
(
null
);
const
linesContent
=
editorModel
.
getLinesContent
();
export
function
getWordToLineNumbersMap
(
model
:
IModel
):
Map
<
string
,
number
[]
>
{
const
result
=
new
Map
<
string
,
number
[]
>
();
// For every word in every line, map its ranges for fast lookup
for
(
let
i
=
0
,
len
=
linesContent
.
length
;
i
<
len
;
++
i
)
{
const
lineContent
=
linesContent
[
i
]
;
for
(
let
lineNumber
=
1
,
len
=
model
.
getLineCount
();
lineNumber
<=
len
;
++
lineNumber
)
{
const
lineContent
=
model
.
getLineContent
(
lineNumber
)
;
// If line is too long then skip the line
if
(
lineContent
.
length
>
MAX_TOKENIZATION_LINE_LEN
)
{
continue
;
}
const
lineTokens
=
editorModel
.
getLineTokens
(
i
+
1
);
// lineNumbers are 1 based
for
(
let
j
=
0
,
len
=
lineTokens
.
getTokenCount
();
j
<
len
;
++
j
)
{
let
startOffset
=
lineTokens
.
getTokenStartOffset
(
j
);
let
endOffset
=
lineTokens
.
getTokenEndOffset
(
j
);
const
tokenStr
=
lineContent
.
substring
(
startOffset
,
endOffset
);
const
lineTokens
=
model
.
getLineTokens
(
lineNumber
);
for
(
let
token
=
lineTokens
.
firstToken
();
!!
token
;
token
=
token
.
next
())
{
const
tokenStr
=
lineContent
.
substring
(
token
.
startOffset
,
token
.
endOffset
);
// Token is a word and not a comment
if
(
lineTokens
.
getStandardTokenType
(
j
)
===
StandardTokenType
.
Other
)
{
if
(
token
.
tokenType
===
StandardTokenType
.
Other
)
{
WORD_REGEXP
.
lastIndex
=
0
;
// We assume tokens will usually map 1:1 to words if they match
const
wordMatch
=
WORD_REGEXP
.
exec
(
tokenStr
);
if
(
wordMatch
)
{
const
word
=
wordMatch
[
0
];
startOffset
+=
wordMatch
.
index
;
endOffset
=
startOffset
+
word
.
length
;
const
range
:
IRange
=
{
startColumn
:
startOffset
+
1
,
// Line and columns are 1 based
endColumn
:
endOffset
+
1
,
startLineNumber
:
i
+
1
,
endLineNumber
:
i
+
1
};
if
(
!
wordRangeMap
[
word
])
{
wordRangeMap
[
word
]
=
[];
if
(
!
result
.
has
(
word
))
{
result
.
set
(
word
,
[]);
}
wordRangeMap
[
word
].
push
(
range
);
result
.
get
(
word
).
push
(
lineNumber
);
}
}
}
}
return
wordRangeMap
;
return
result
;
}
src/vs/workbench/parts/debug/test/electron-browser/debugInline
Decorator
s.test.ts
→
src/vs/workbench/parts/debug/test/electron-browser/debugInline
Value
s.test.ts
浏览文件 @
db334b22
...
...
@@ -6,23 +6,24 @@
import
*
as
assert
from
'
assert
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
Model
as
EditorModel
}
from
'
vs/editor/common/model/model
'
;
import
{
I
Range
,
I
Model
}
from
'
vs/editor/common/editorCommon
'
;
import
{
IModel
}
from
'
vs/editor/common/editorCommon
'
;
import
{
StandardTokenType
}
from
'
vs/editor/common/modes
'
;
import
{
LineTokens
}
from
'
vs/editor/common/core/lineTokens
'
;
import
{
IExpression
}
from
'
vs/workbench/parts/debug/common/debug
'
;
import
*
as
inline
Decorators
from
'
vs/workbench/parts/debug/electron-browser/debugInlineDecorator
s
'
;
import
*
as
inline
Values
from
'
vs/workbench/parts/debug/electron-browser/debugInlineValue
s
'
;
// Test data
const
testLine
=
'
function doit(everything, is, awesome, awesome, when, youre, part, of, a, team){}
'
;
const
testNameValueMap
=
{
everything
:
'
{emmet: true, batman: true, legoUniverse: true}
'
,
is
:
'
15
'
,
awesome
:
'
"aweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeesome…"
'
,
when
:
'
true
'
,
youre
:
'
"Yes I mean you"
'
,
part
:
'
"𝄞 ♪ ♫"
'
};
const
testNameValueMap
=
new
Map
<
string
,
string
>
();
setup
(()
=>
{
testNameValueMap
.
set
(
'
everything
'
,
'
{emmet: true, batman: true, legoUniverse: true}
'
);
testNameValueMap
.
set
(
'
is
'
,
'
15
'
);
testNameValueMap
.
set
(
'
awesome
'
,
'
"aweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeesome…"
'
);
testNameValueMap
.
set
(
'
when
'
,
'
true
'
);
testNameValueMap
.
set
(
'
youre
'
,
'
"Yes I mean you"
'
);
testNameValueMap
.
set
(
'
part
'
,
'
"𝄞 ♪ ♫"
'
);
});
suite
(
'
Debug - Inline Value Decorators
'
,
()
=>
{
test
(
'
getNameValueMapFromScopeChildren trims long values
'
,
()
=>
{
...
...
@@ -31,7 +32,7 @@ suite('Debug - Inline Value Decorators', () => {
createExpression
(
'
blah
'
,
createLongString
())
];
const
nameValueMap
=
inline
Decorators
.
getNameValueMapFromScopeChildren
(
expressions
);
const
nameValueMap
=
inline
Values
.
toNameValueMap
(
expressions
);
// Ensure blah is capped and ellipses added
assert
.
deepEqual
(
nameValueMap
,
{
...
...
@@ -54,7 +55,7 @@ suite('Debug - Inline Value Decorators', () => {
const
val
=
`val
${
i
}
.
${
j
}
`
;
expressions
[
j
]
=
createExpression
(
name
,
val
);
if
((
i
*
expressions
.
length
+
j
)
<
inline
Decorator
s
.
MAX_NUM_INLINE_VALUES
)
{
if
((
i
*
expressions
.
length
+
j
)
<
inline
Value
s
.
MAX_NUM_INLINE_VALUES
)
{
expectedNameValueMap
[
name
]
=
val
;
}
}
...
...
@@ -63,32 +64,16 @@ suite('Debug - Inline Value Decorators', () => {
}
const
expressions
=
[].
concat
.
apply
([],
scopeChildren
);
const
nameValueMap
=
inline
Decorators
.
getNameValueMapFromScopeChildren
(
expressions
);
const
nameValueMap
=
inline
Values
.
toNameValueMap
(
expressions
);
assert
.
deepEqual
(
nameValueMap
,
expectedNameValueMap
);
});
test
(
'
getDecoratorFromNames caps long decorator afterText
'
,
()
=>
{
const
names
=
Object
.
keys
(
testNameValueMap
);
const
lineNumber
=
1
;
const
decorator
=
inlineDecorators
.
getDecoratorFromNames
(
lineNumber
,
names
,
testNameValueMap
,
[
testLine
]);
const
expectedDecoratorText
=
'
everything = {emmet: true, batman: true, legoUniverse: true}, is = 15, awesome = "aweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeesome…", when = true, youre = "Yes…
'
;
assert
.
equal
(
decorator
.
renderOptions
.
dark
.
after
.
contentText
,
decorator
.
renderOptions
.
light
.
after
.
contentText
);
assert
.
equal
(
decorator
.
renderOptions
.
dark
.
after
.
contentText
,
expectedDecoratorText
);
assert
.
deepEqual
(
decorator
.
range
,
{
startLineNumber
:
lineNumber
,
endLineNumber
:
lineNumber
,
startColumn
:
testLine
.
length
,
endColumn
:
testLine
.
length
+
1
});
});
test
(
'
getDecorators returns correct decorator afterText
'
,
()
=>
{
const
lineContent
=
'
console.log(everything, part, part);
'
;
// part shouldn't be duplicated
const
lineNumber
=
1
;
const
word
RangeMap
=
updateWordRangeMap
(
Object
.
create
(
null
),
lineNumber
,
lineContent
);
const
decorators
=
inline
Decorators
.
getDecorators
(
testNameValueMap
,
wordRangeMap
,
[
lineContent
]
);
const
word
ToLinesMap
=
getWordToLineMap
(
lineNumber
,
lineContent
);
const
decorators
=
inline
Values
.
getDecorations
(
testNameValueMap
,
wordToLinesMap
);
const
expectedDecoratorText
=
'
everything = {emmet: true, batman: true, legoUniverse: true}, part = "𝄞 ♪ ♫"
'
;
assert
.
equal
(
decorators
[
0
].
renderOptions
.
dark
.
after
.
contentText
,
expectedDecoratorText
);
});
...
...
@@ -98,7 +83,7 @@ suite('Debug - Inline Value Decorators', () => {
const
editorModel
=
EditorModel
.
createFromString
(
`/** Copyright comment */\n \n
${
testLine
}
\n// Test comment\n
${
createLongString
()}
\n`
);
mockEditorModelLineTokens
(
editorModel
);
const
wordRangeMap
=
inline
Decorators
.
getEditorWordRange
Map
(
editorModel
);
const
wordRangeMap
=
inline
Values
.
getWordToLineNumbers
Map
(
editorModel
);
const
words
=
Object
.
keys
(
wordRangeMap
);
assert
.
deepEqual
(
words
,
expectedWords
);
});
...
...
@@ -125,8 +110,9 @@ function createLongString(): string {
}
// Simple word range creator that maches wordRegex throughout string
function
updateWordRangeMap
(
wordRangeMap
:
IStringDictionary
<
IRange
[]
>
,
lineNumber
:
number
,
lineContent
:
string
):
IStringDictionary
<
IRange
[]
>
{
const
wordRegexp
=
inlineDecorators
.
WORD_REGEXP
;
function
getWordToLineMap
(
lineNumber
:
number
,
lineContent
:
string
):
Map
<
string
,
number
[]
>
{
const
result
=
new
Map
<
string
,
number
[]
>
();
const
wordRegexp
=
inlineValues
.
WORD_REGEXP
;
wordRegexp
.
lastIndex
=
0
;
// Reset matching
while
(
true
)
{
...
...
@@ -134,26 +120,16 @@ function updateWordRangeMap(wordRangeMap: IStringDictionary<IRange[]>, lineNumbe
if
(
!
wordMatch
)
{
break
;
}
const
word
=
wordMatch
[
0
];
const
startOffset
=
wordMatch
.
index
;
const
endOffset
=
startOffset
+
word
.
length
;
const
range
:
IRange
=
{
startColumn
:
startOffset
+
1
,
endColumn
:
endOffset
+
1
,
startLineNumber
:
lineNumber
,
endLineNumber
:
lineNumber
};
if
(
!
wordRangeMap
[
word
])
{
wordRangeMap
[
word
]
=
[];
if
(
!
result
.
has
(
word
))
{
result
.
set
(
word
,
[]);
}
wordRangeMap
[
word
].
push
(
range
);
result
.
get
(
word
).
push
(
lineNumber
);
}
return
wordRangeMap
;
return
result
;
}
interface
MockToken
{
...
...
@@ -182,7 +158,7 @@ function mockLineTokens(lineContent: string): LineTokens {
});
}
else
{
const
wordRegexp
=
inline
Decorator
s
.
WORD_REGEXP
;
const
wordRegexp
=
inline
Value
s
.
WORD_REGEXP
;
wordRegexp
.
lastIndex
=
0
;
while
(
true
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录