Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
9c3880c5
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,发现更多精彩内容 >>
提交
9c3880c5
编写于
5月 09, 2017
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
validate editor selections
上级
ff8b85ff
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
119 addition
and
30 deletion
+119
-30
src/vs/editor/common/core/range.ts
src/vs/editor/common/core/range.ts
+4
-0
src/vs/editor/contrib/snippet/browser/editorSnippets.ts
src/vs/editor/contrib/snippet/browser/editorSnippets.ts
+52
-15
src/vs/editor/contrib/snippet/common/snippetParser.ts
src/vs/editor/contrib/snippet/common/snippetParser.ts
+1
-1
src/vs/editor/contrib/snippet/test/browser/editorSnippets.test.ts
...ditor/contrib/snippet/test/browser/editorSnippets.test.ts
+48
-1
src/vs/editor/contrib/snippet/test/common/snippetParser.test.ts
.../editor/contrib/snippet/test/common/snippetParser.test.ts
+13
-13
src/vs/monaco.d.ts
src/vs/monaco.d.ts
+1
-0
未找到文件。
src/vs/editor/common/core/range.ts
浏览文件 @
9c3880c5
...
...
@@ -290,6 +290,10 @@ export class Range {
// ---
public
static
fromPositions
(
start
:
IPosition
,
end
:
IPosition
=
start
):
Range
{
return
new
Range
(
start
.
lineNumber
,
start
.
column
,
end
.
lineNumber
,
end
.
column
);
}
/**
* Create a `Range` from an `IRange`.
*/
...
...
src/vs/editor/contrib/snippet/browser/editorSnippets.ts
浏览文件 @
9c3880c5
...
...
@@ -20,14 +20,16 @@ class OneSnippet {
private
readonly
_snippet
:
TextmateSnippet
;
private
readonly
_offset
:
number
;
private
_snippetDecoration
:
string
;
private
_placeholderDecorations
:
Map
<
Placeholder
,
string
>
;
private
_placeholderGroups
:
Placeholder
[][];
private
_placeholderGroupsIdx
:
number
;
private
static
readonly
_decor
ations
=
{
private
static
readonly
_decor
=
{
active
:
<
IModelDecorationOptions
>
{
stickiness
:
TrackedRangeStickiness
.
AlwaysGrowsWhenTypingAtEdges
},
activeFinal
:
<
IModelDecorationOptions
>
{
stickiness
:
TrackedRangeStickiness
.
NeverGrowsWhenTypingAtEdges
},
inActive
:
<
IModelDecorationOptions
>
{
stickiness
:
TrackedRangeStickiness
.
NeverGrowsWhenTypingAtEdges
},
inactive
:
<
IModelDecorationOptions
>
{
stickiness
:
TrackedRangeStickiness
.
NeverGrowsWhenTypingAtEdges
},
snippet
:
<
IModelDecorationOptions
>
{
stickiness
:
TrackedRangeStickiness
.
AlwaysGrowsWhenTypingAtEdges
},
};
constructor
(
editor
:
ICommonCodeEditor
,
snippet
:
TextmateSnippet
,
offset
:
number
)
{
...
...
@@ -52,22 +54,25 @@ class OneSnippet {
this
.
_placeholderDecorations
=
new
Map
<
Placeholder
,
string
>
();
const
model
=
this
.
_editor
.
getModel
();
// create a decoration (tracked range) for each placeholder
this
.
_editor
.
changeDecorations
(
accessor
=>
{
let
lastRange
:
Range
;
// create one decoration for the whole snippets
const
range
=
Range
.
fromPositions
(
model
.
getPositionAt
(
this
.
_offset
),
model
.
getPositionAt
(
this
.
_offset
+
this
.
_snippet
.
text
.
length
)
);
this
.
_snippetDecoration
=
accessor
.
addDecoration
(
range
,
OneSnippet
.
_decor
.
snippet
);
// create a decoration for each placeholder
for
(
const
placeholder
of
this
.
_snippet
.
getPlaceholders
())
{
const
placeholderOffset
=
this
.
_snippet
.
offset
(
placeholder
);
const
placeholderLen
=
this
.
_snippet
.
len
(
placeholder
);
const
start
=
model
.
getPositionAt
(
this
.
_offset
+
placeholderOffset
);
const
end
=
model
.
getPositionAt
(
this
.
_offset
+
placeholderOffset
+
placeholderLen
);
const
range
=
new
Range
(
start
.
lineNumber
,
start
.
column
,
end
.
lineNumber
,
end
.
column
);
const
handle
=
accessor
.
addDecoration
(
range
,
OneSnippet
.
_decor
ations
.
inA
ctive
);
const
range
=
Range
.
fromPositions
(
model
.
getPositionAt
(
this
.
_offset
+
placeholderOffset
),
model
.
getPositionAt
(
this
.
_offset
+
placeholderOffset
+
placeholderLen
)
);
const
handle
=
accessor
.
addDecoration
(
range
,
OneSnippet
.
_decor
.
ina
ctive
);
this
.
_placeholderDecorations
.
set
(
placeholder
,
handle
);
lastRange
=
range
;
}
});
...
...
@@ -107,7 +112,7 @@ class OneSnippet {
if
(
prevGroupsIdx
!==
-
1
)
{
for
(
const
placeholder
of
this
.
_placeholderGroups
[
prevGroupsIdx
])
{
const
id
=
this
.
_placeholderDecorations
.
get
(
placeholder
);
accessor
.
changeDecorationOptions
(
id
,
OneSnippet
.
_decor
ations
.
inA
ctive
);
accessor
.
changeDecorationOptions
(
id
,
OneSnippet
.
_decor
.
ina
ctive
);
}
}
...
...
@@ -120,7 +125,7 @@ class OneSnippet {
const
range
=
this
.
_editor
.
getModel
().
getDecorationRange
(
id
);
selections
.
push
(
new
Selection
(
range
.
startLineNumber
,
range
.
startColumn
,
range
.
endLineNumber
,
range
.
endColumn
));
accessor
.
changeDecorationOptions
(
id
,
placeholder
.
isFinalTabstop
?
OneSnippet
.
_decor
ations
.
activeFinal
:
OneSnippet
.
_decorations
.
active
);
accessor
.
changeDecorationOptions
(
id
,
placeholder
.
isFinalTabstop
?
OneSnippet
.
_decor
.
activeFinal
:
OneSnippet
.
_decor
.
active
);
}
return
selections
;
});
...
...
@@ -133,6 +138,10 @@ class OneSnippet {
return
this
.
_placeholderGroups
[
this
.
_placeholderGroupsIdx
][
0
].
isFinalTabstop
;
}
}
get
range
()
{
return
this
.
_snippetDecoration
!==
undefined
&&
this
.
_editor
.
getModel
().
getDecorationRange
(
this
.
_snippetDecoration
);
}
}
export
class
SnippetSession
{
...
...
@@ -170,10 +179,10 @@ export class SnippetSession {
const
snippet
=
SnippetParser
.
parse
(
adjustedTemplate
);
const
offset
=
model
.
getOffsetAt
(
start
)
+
delta
;
edits
.
push
(
EditOperation
.
replaceMove
(
selection
,
snippet
.
value
));
edits
.
push
(
EditOperation
.
replaceMove
(
selection
,
snippet
.
text
));
this
.
_snippets
.
push
(
new
OneSnippet
(
editor
,
snippet
,
offset
));
delta
+=
snippet
.
value
.
length
-
model
.
getValueLengthInRange
(
selection
);
delta
+=
snippet
.
text
.
length
-
model
.
getValueLengthInRange
(
selection
);
}
// make insert edit and start with first selections
...
...
@@ -211,4 +220,32 @@ export class SnippetSession {
get
isAtFinalPlaceholder
()
{
return
this
.
_snippets
[
0
].
isAtFinalPlaceholder
;
}
validateSelections
():
boolean
{
const
selections
=
this
.
_editor
.
getSelections
();
if
(
selections
.
length
<
this
.
_snippets
.
length
)
{
return
false
;
}
for
(
const
selection
of
selections
)
{
let
found
=
false
;
for
(
const
{
range
}
of
this
.
_snippets
)
{
if
(
!
range
)
{
// too early, not yet initialized
return
true
;
}
if
(
range
.
containsRange
(
selection
))
{
found
=
true
;
break
;
}
}
if
(
!
found
)
{
return
false
;
}
}
return
true
;
}
}
src/vs/editor/contrib/snippet/common/snippetParser.ts
浏览文件 @
9c3880c5
...
...
@@ -271,7 +271,7 @@ export class TextmateSnippet {
return
ret
;
}
get
value
()
{
get
text
()
{
return
Marker
.
toString
(
this
.
marker
);
}
...
...
src/vs/editor/contrib/snippet/test/browser/editorSnippets.test.ts
浏览文件 @
9c3880c5
...
...
@@ -12,7 +12,7 @@ import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import
{
mockCodeEditor
}
from
'
vs/editor/test/common/mocks/mockCodeEditor
'
;
import
{
Model
}
from
"
vs/editor/common/model/model
"
;
suite
(
'
Snippet
Insert
ion
'
,
function
()
{
suite
(
'
Snippet
Sess
ion
'
,
function
()
{
let
editor
:
ICommonCodeEditor
;
let
model
:
Model
;
...
...
@@ -234,5 +234,52 @@ suite('SnippetInsertion', function () {
assertSelections
(
editor
,
new
Selection
(
1
,
4
,
1
,
4
),
new
Selection
(
2
,
8
,
2
,
8
));
});
test
(
'
snippets, overwriting nested placeholder
'
,
function
()
{
const
session
=
new
SnippetSession
(
editor
,
'
log(${1:"$2"});$0
'
);
assertSelections
(
editor
,
new
Selection
(
1
,
5
,
1
,
7
),
new
Selection
(
2
,
9
,
2
,
11
));
editor
.
trigger
(
'
test
'
,
'
type
'
,
{
text
:
'
XXX
'
});
assert
.
equal
(
model
.
getValue
(),
'
log(XXX);function foo() {
\n
log(XXX);console.log(a);
\n
}
'
);
session
.
next
();
assert
.
equal
(
session
.
isAtFinalPlaceholder
,
false
);
// assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
session
.
next
();
assert
.
equal
(
session
.
isAtFinalPlaceholder
,
true
);
assertSelections
(
editor
,
new
Selection
(
1
,
10
,
1
,
10
),
new
Selection
(
2
,
14
,
2
,
14
));
});
test
(
'
snippets, selections and snippet ranges
'
,
function
()
{
const
session
=
new
SnippetSession
(
editor
,
'
${1:foo}farboo${2:bar}$0
'
);
assert
.
equal
(
model
.
getValue
(),
'
foofarboobarfunction foo() {
\n
foofarboobarconsole.log(a);
\n
}
'
);
assertSelections
(
editor
,
new
Selection
(
1
,
1
,
1
,
4
),
new
Selection
(
2
,
5
,
2
,
8
));
assert
.
equal
(
session
.
validateSelections
(),
true
);
editor
.
setSelections
([
new
Selection
(
1
,
1
,
1
,
1
)]);
assert
.
equal
(
session
.
validateSelections
(),
false
);
editor
.
setSelections
([
new
Selection
(
1
,
6
,
1
,
6
),
new
Selection
(
2
,
10
,
2
,
10
)]);
assert
.
equal
(
session
.
validateSelections
(),
true
);
editor
.
setSelections
([
new
Selection
(
1
,
6
,
1
,
6
),
new
Selection
(
2
,
10
,
2
,
10
),
new
Selection
(
1
,
1
,
1
,
1
)]);
assert
.
equal
(
session
.
validateSelections
(),
true
);
editor
.
setSelections
([
new
Selection
(
1
,
6
,
1
,
6
),
new
Selection
(
2
,
10
,
2
,
10
),
new
Selection
(
2
,
20
,
2
,
21
)]);
assert
.
equal
(
session
.
validateSelections
(),
false
);
// reset selection to placeholder
session
.
next
();
assert
.
equal
(
session
.
validateSelections
(),
true
);
assertSelections
(
editor
,
new
Selection
(
1
,
10
,
1
,
13
),
new
Selection
(
2
,
14
,
2
,
17
));
// reset selection to placeholder
session
.
next
();
assert
.
equal
(
session
.
validateSelections
(),
true
);
assert
.
equal
(
session
.
isAtFinalPlaceholder
,
true
);
assertSelections
(
editor
,
new
Selection
(
1
,
13
,
1
,
13
),
new
Selection
(
2
,
17
,
2
,
17
));
});
});
src/vs/editor/contrib/snippet/test/common/snippetParser.test.ts
浏览文件 @
9c3880c5
...
...
@@ -351,30 +351,30 @@ suite('SnippetParser', () => {
test
(
'
TextmateSnippet#withIndentation
'
,
()
=>
{
let
snippet
=
SnippetParser
.
parse
(
'
foo
\n
bar
'
);
assert
.
equal
(
snippet
.
value
,
'
foo
\n
bar
'
);
assert
.
equal
(
snippet
.
text
,
'
foo
\n
bar
'
);
let
snippet1
=
snippet
.
withIndentation
(
s
=>
s
.
replace
(
/ /
,
'
\t
'
));
let
snippet2
=
snippet
.
withIndentation
(
s
=>
s
.
replace
(
/ /
,
'
'
));
assert
.
equal
(
snippet
.
value
,
'
foo
\n
bar
'
);
assert
.
equal
(
snippet1
.
value
,
'
foo
\n\t
bar
'
);
assert
.
equal
(
snippet2
.
value
,
'
foo
\n
bar
'
);
assert
.
equal
(
snippet
.
text
,
'
foo
\n
bar
'
);
assert
.
equal
(
snippet1
.
text
,
'
foo
\n\t
bar
'
);
assert
.
equal
(
snippet2
.
text
,
'
foo
\n
bar
'
);
snippet
=
SnippetParser
.
parse
(
'
foo
\n
bar
'
);
assert
.
equal
(
snippet
.
value
,
'
foo
\n
bar
'
);
assert
.
equal
(
snippet
.
text
,
'
foo
\n
bar
'
);
let
newSnippet
=
snippet
.
withIndentation
(
s
=>
s
.
replace
(
/ /
,
'
\t
'
));
assert
.
equal
(
snippet
.
value
,
'
foo
\n
bar
'
);
assert
.
equal
(
newSnippet
.
value
,
'
foo
\n\t
bar
'
);
assert
.
equal
(
snippet
.
text
,
'
foo
\n
bar
'
);
assert
.
equal
(
newSnippet
.
text
,
'
foo
\n\t
bar
'
);
snippet
=
SnippetParser
.
parse
(
'
foo
\r\n
bar
\r\n
far
'
);
assert
.
equal
(
snippet
.
value
,
'
foo
\r\n
bar
\r\n
far
'
);
assert
.
equal
(
snippet
.
text
,
'
foo
\r\n
bar
\r\n
far
'
);
newSnippet
=
snippet
.
withIndentation
(
s
=>
s
.
replace
(
/ /
,
'
\t
'
));
assert
.
equal
(
snippet
.
value
,
'
foo
\r\n
bar
\r\n
far
'
);
assert
.
equal
(
newSnippet
.
value
,
'
foo
\r\n\t
bar
\r\n\t
far
'
);
assert
.
equal
(
snippet
.
text
,
'
foo
\r\n
bar
\r\n
far
'
);
assert
.
equal
(
newSnippet
.
text
,
'
foo
\r\n\t
bar
\r\n\t
far
'
);
snippet
=
SnippetParser
.
parse
(
'
foo${1:bar
\r
far
\r
boo}
'
);
assert
.
equal
(
snippet
.
value
,
'
foobar
\r
far
\r
boo
'
);
assert
.
equal
(
snippet
.
text
,
'
foobar
\r
far
\r
boo
'
);
newSnippet
=
snippet
.
withIndentation
(
s
=>
s
.
replace
(
/ /
,
'
\t
'
));
assert
.
equal
(
snippet
.
value
,
'
foobar
\r
far
\r
boo
'
);
assert
.
equal
(
newSnippet
.
value
,
'
foobar
\r\t
far
\r\t
boo
'
);
assert
.
equal
(
snippet
.
text
,
'
foobar
\r
far
\r
boo
'
);
assert
.
equal
(
newSnippet
.
text
,
'
foobar
\r\t
far
\r\t
boo
'
);
});
});
src/vs/monaco.d.ts
浏览文件 @
9c3880c5
...
...
@@ -624,6 +624,7 @@ declare module monaco {
* Create a new empty range using this range's start position.
*/
static
collapseToStart
(
range
:
IRange
):
Range
;
static
fromPositions
(
start
:
IPosition
,
end
?:
IPosition
):
Range
;
/**
* Create a `Range` from an `IRange`.
*/
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录