Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
d81a1bcd
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,发现更多精彩内容 >>
提交
d81a1bcd
编写于
11月 28, 2018
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add internal api for selection ranges provider, #63935
上级
b10fc8fc
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
111 addition
and
52 deletion
+111
-52
src/vs/editor/common/modes.ts
src/vs/editor/common/modes.ts
+13
-0
src/vs/editor/contrib/smartSelect/defaultProvider.ts
src/vs/editor/contrib/smartSelect/defaultProvider.ts
+30
-0
src/vs/editor/contrib/smartSelect/smartSelect.ts
src/vs/editor/contrib/smartSelect/smartSelect.ts
+49
-39
src/vs/editor/contrib/smartSelect/test/tokenSelectionSupport.test.ts
...or/contrib/smartSelect/test/tokenSelectionSupport.test.ts
+12
-13
src/vs/monaco.d.ts
src/vs/monaco.d.ts
+7
-0
未找到文件。
src/vs/editor/common/modes.ts
浏览文件 @
d81a1bcd
...
...
@@ -1031,6 +1031,14 @@ export interface DocumentColorProvider {
*/
provideColorPresentations
(
model
:
model
.
ITextModel
,
colorInfo
:
IColorInformation
,
token
:
CancellationToken
):
ProviderResult
<
IColorPresentation
[]
>
;
}
export
interface
SelectionRangeProvider
{
/**
* Provide ranges that should be selected from the given position.
*/
provideSelectionRanges
(
model
:
model
.
ITextModel
,
position
:
Position
,
token
:
CancellationToken
):
ProviderResult
<
Range
[]
>
;
}
export
interface
FoldingContext
{
}
/**
...
...
@@ -1337,6 +1345,11 @@ export const LinkProviderRegistry = new LanguageFeatureRegistry<LinkProvider>();
*/
export
const
ColorProviderRegistry
=
new
LanguageFeatureRegistry
<
DocumentColorProvider
>
();
/**
* @internal
*/
export
const
SelectionRangeRegistry
=
new
LanguageFeatureRegistry
<
SelectionRangeProvider
>
();
/**
* @internal
*/
...
...
src/vs/editor/contrib/smartSelect/
tokenSelectionSupport
.ts
→
src/vs/editor/contrib/smartSelect/
defaultProvider
.ts
浏览文件 @
d81a1bcd
...
...
@@ -3,52 +3,20 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
SelectionRangeProvider
}
from
'
vs/editor/common/modes
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
build
,
find
}
from
'
./tokenTree
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
build
,
find
}
from
'
vs/editor/contrib/smartSelect/tokenTree
'
;
/**
* Interface used to compute a hierachry of logical ranges.
*/
export
interface
ILogicalSelectionEntry
{
type
?:
string
;
range
:
Range
;
}
export
class
TokenSelectionSupport
{
private
_modelService
:
IModelService
;
constructor
(@
IModelService
modelService
:
IModelService
)
{
this
.
_modelService
=
modelService
;
}
public
getRangesToPositionSync
(
resource
:
URI
,
position
:
Position
):
ILogicalSelectionEntry
[]
{
const
model
=
this
.
_modelService
.
getModel
(
resource
);
let
entries
:
ILogicalSelectionEntry
[]
=
[];
if
(
model
)
{
this
.
_doGetRangesToPosition
(
model
,
position
).
forEach
(
range
=>
{
entries
.
push
({
type
:
void
0
,
range
});
});
}
return
entries
;
}
private
_doGetRangesToPosition
(
model
:
ITextModel
,
position
:
Position
):
Range
[]
{
export
class
DefaultSelectionRangeProvider
implements
SelectionRangeProvider
{
provideSelectionRanges
(
model
:
ITextModel
,
position
:
Position
,
token
:
CancellationToken
):
Range
[]
{
let
tree
=
build
(
model
);
let
lastRange
:
Range
|
undefined
;
let
node
=
find
(
tree
,
position
);
let
ranges
:
Range
[]
=
[];
let
lastRange
:
Range
|
undefined
;
while
(
node
)
{
if
(
!
lastRange
||
!
Range
.
equalsRange
(
lastRange
,
node
.
range
))
{
ranges
.
push
(
node
.
range
);
...
...
@@ -59,5 +27,4 @@ export class TokenSelectionSupport {
ranges
=
ranges
.
reverse
();
return
ranges
;
}
}
src/vs/editor/contrib/smartSelect/smartSelect.ts
浏览文件 @
d81a1bcd
...
...
@@ -3,19 +3,23 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
nls
from
'
vs/nls
'
;
import
*
as
arrays
from
'
vs/base/common/arrays
'
;
import
{
asThenable
,
first
}
from
'
vs/base/common/async
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
KeyCode
,
KeyMod
}
from
'
vs/base/common/keyCodes
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
ICodeEditor
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
EditorAction
,
IActionOptions
,
registerEditorAction
,
registerEditorContribution
,
ServicesAccessor
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
ICursorPositionChangedEvent
}
from
'
vs/editor/common/controller/cursorEvents
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
IEditorContribution
}
from
'
vs/editor/common/editorCommon
'
;
import
{
EditorContextKeys
}
from
'
vs/editor/common/editorContextKeys
'
;
import
{
registerEditorAction
,
ServicesAccessor
,
IActionOptions
,
EditorAction
,
registerEditorContribution
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
TokenSelectionSupport
,
ILogicalSelectionEntry
}
from
'
./tokenSelectionSupport
'
;
import
{
ICursorPositionChangedEvent
}
from
'
vs/editor/common/controller/cursorEvents
'
;
import
{
ICodeEditor
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
KeybindingWeight
}
from
'
vs/platform/keybinding/common/keybindingsRegistry
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
*
as
modes
from
'
vs/editor/common/modes
'
;
import
{
DefaultSelectionRangeProvider
}
from
'
vs/editor/contrib/smartSelect/defaultProvider
'
;
import
*
as
nls
from
'
vs/nls
'
;
import
{
MenuId
}
from
'
vs/platform/actions/common/actions
'
;
import
{
KeybindingWeight
}
from
'
vs/platform/keybinding/common/keybindingsRegistry
'
;
// --- selection state machine
...
...
@@ -42,62 +46,62 @@ class SmartSelectController implements IEditorContribution {
return
editor
.
getContribution
<
SmartSelectController
>
(
SmartSelectController
.
ID
);
}
private
_
tokenSelectionSupport
:
TokenSelectionSupport
;
private
_
editor
:
ICodeEditor
;
private
_state
?:
State
;
private
_ignoreSelection
:
boolean
;
constructor
(
private
editor
:
ICodeEditor
,
@
IInstantiationService
instantiationService
:
IInstantiationService
)
{
this
.
_tokenSelectionSupport
=
instantiationService
.
createInstance
(
TokenSelectionSupport
);
constructor
(
editor
:
ICodeEditor
)
{
this
.
_editor
=
editor
;
this
.
_ignoreSelection
=
false
;
}
public
dispose
():
void
{
dispose
():
void
{
}
public
getId
():
string
{
getId
():
string
{
return
SmartSelectController
.
ID
;
}
public
run
(
forward
:
boolean
):
Promise
<
void
>
{
if
(
!
this
.
editor
.
hasModel
())
{
return
Promise
.
resolve
(
void
0
)
;
run
(
forward
:
boolean
):
Promise
<
void
>
|
void
{
if
(
!
this
.
_
editor
.
hasModel
())
{
return
;
}
const
selection
=
this
.
editor
.
getSelection
();
const
model
=
this
.
editor
.
getModel
();
const
selection
=
this
.
_editor
.
getSelection
();
const
model
=
this
.
_editor
.
getModel
();
if
(
!
modes
.
SelectionRangeRegistry
.
has
(
model
))
{
return
;
}
// forget about current state
if
(
this
.
_state
)
{
if
(
this
.
_state
.
editor
!==
this
.
editor
)
{
if
(
this
.
_state
.
editor
!==
this
.
_
editor
)
{
this
.
_state
=
undefined
;
}
}
let
promise
:
Promise
<
void
>
=
Promise
.
resolve
(
void
0
);
if
(
!
this
.
_state
)
{
promise
=
Promise
.
resolve
(
this
.
_tokenSelectionSupport
.
getRangesToPositionSync
(
model
.
uri
,
selection
.
getStartPosition
())).
then
((
elements
:
ILogicalSelectionEntry
[])
=>
{
if
(
arrays
.
isFalsyOrEmpty
(
elements
))
{
if
(
!
this
.
_state
)
{
promise
=
provideSelectionRanges
(
model
,
selection
.
getStartPosition
(),
CancellationToken
.
None
).
then
(
ranges
=>
{
if
(
!
arrays
.
isNonEmptyArray
(
ranges
))
{
// invalid result
return
;
}
if
(
!
this
.
_editor
.
hasModel
()
||
!
this
.
_editor
.
getSelection
().
equalsSelection
(
selection
))
{
// invalid editor state
return
;
}
let
lastState
:
State
|
undefined
;
elements
.
filter
((
element
)
=>
{
if
(
!
this
.
editor
.
hasModel
())
{
return
false
;
}
ranges
.
filter
(
range
=>
{
// filter ranges inside the selection
const
selection
=
this
.
editor
.
getSelection
();
const
range
=
new
Range
(
element
.
range
.
startLineNumber
,
element
.
range
.
startColumn
,
element
.
range
.
endLineNumber
,
element
.
range
.
endColumn
);
return
range
.
containsPosition
(
selection
.
getStartPosition
())
&&
range
.
containsPosition
(
selection
.
getEndPosition
());
}).
forEach
(
(
element
)
=>
{
}).
forEach
(
range
=>
{
// create ranges
const
range
=
element
.
range
;
const
state
=
new
State
(
this
.
editor
);
const
state
=
new
State
(
this
.
_editor
);
state
.
selection
=
new
Range
(
range
.
startLineNumber
,
range
.
startColumn
,
range
.
endLineNumber
,
range
.
endColumn
);
if
(
lastState
)
{
state
.
next
=
lastState
;
...
...
@@ -107,7 +111,7 @@ class SmartSelectController implements IEditorContribution {
});
// insert current selection
const
editorState
=
new
State
(
this
.
editor
);
const
editorState
=
new
State
(
this
.
_
editor
);
editorState
.
next
=
lastState
;
if
(
lastState
)
{
lastState
.
previous
=
editorState
;
...
...
@@ -115,7 +119,7 @@ class SmartSelectController implements IEditorContribution {
this
.
_state
=
editorState
;
// listen to caret move and forget about state
const
unhook
=
this
.
editor
.
onDidChangeCursorPosition
((
e
:
ICursorPositionChangedEvent
)
=>
{
const
unhook
=
this
.
_
editor
.
onDidChangeCursorPosition
((
e
:
ICursorPositionChangedEvent
)
=>
{
if
(
this
.
_ignoreSelection
)
{
return
;
}
...
...
@@ -139,7 +143,7 @@ class SmartSelectController implements IEditorContribution {
this
.
_ignoreSelection
=
true
;
try
{
if
(
this
.
_state
.
selection
)
{
this
.
editor
.
setSelection
(
this
.
_state
.
selection
);
this
.
_
editor
.
setSelection
(
this
.
_state
.
selection
);
}
}
finally
{
this
.
_ignoreSelection
=
false
;
...
...
@@ -159,12 +163,11 @@ abstract class AbstractSmartSelect extends EditorAction {
this
.
_forward
=
forward
;
}
public
run
(
accessor
:
ServicesAccessor
,
editor
:
ICodeEditor
):
Promise
<
void
>
|
undefined
{
async
run
(
accessor
:
ServicesAccessor
,
editor
:
ICodeEditor
):
Promise
<
void
>
{
let
controller
=
SmartSelectController
.
get
(
editor
);
if
(
controller
)
{
return
controller
.
run
(
this
.
_forward
);
await
controller
.
run
(
this
.
_forward
);
}
return
undefined
;
}
}
...
...
@@ -217,3 +220,10 @@ class ShrinkSelectionAction extends AbstractSmartSelect {
registerEditorContribution
(
SmartSelectController
);
registerEditorAction
(
GrowSelectionAction
);
registerEditorAction
(
ShrinkSelectionAction
);
export
function
provideSelectionRanges
(
model
:
ITextModel
,
position
:
Position
,
token
:
CancellationToken
):
Promise
<
Range
[]
|
undefined
|
null
>
{
const
provider
=
modes
.
SelectionRangeRegistry
.
ordered
(
model
);
return
first
(
provider
.
map
(
pro
=>
()
=>
asThenable
(()
=>
pro
.
provideSelectionRanges
(
model
,
position
,
token
))),
arrays
.
isNonEmptyArray
);
}
modes
.
SelectionRangeRegistry
.
register
(
'
*
'
,
new
DefaultSelectionRangeProvider
());
src/vs/editor/contrib/smartSelect/test/tokenSelectionSupport.test.ts
浏览文件 @
d81a1bcd
...
...
@@ -7,7 +7,6 @@ import { URI } from 'vs/base/common/uri';
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
LanguageIdentifier
}
from
'
vs/editor/common/modes
'
;
import
{
TokenSelectionSupport
}
from
'
vs/editor/contrib/smartSelect/tokenSelectionSupport
'
;
import
{
MockMode
,
StaticLanguageSelector
}
from
'
vs/editor/test/common/mocks/mockMode
'
;
import
{
LanguageConfigurationRegistry
}
from
'
vs/editor/common/modes/languageConfigurationRegistry
'
;
import
{
ModelServiceImpl
}
from
'
vs/editor/common/services/modelServiceImpl
'
;
...
...
@@ -16,6 +15,8 @@ import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/jav
import
{
ITextResourcePropertiesService
}
from
'
vs/editor/common/services/resourceConfiguration
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
isLinux
,
isMacintosh
}
from
'
vs/base/common/platform
'
;
import
{
provideSelectionRanges
}
from
'
vs/editor/contrib/smartSelect/smartSelect
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
class
MockJSMode
extends
MockMode
{
...
...
@@ -39,13 +40,11 @@ class MockJSMode extends MockMode {
suite
(
'
TokenSelectionSupport
'
,
()
=>
{
let
modelService
:
ModelServiceImpl
|
null
=
null
;
let
tokenSelectionSupport
:
TokenSelectionSupport
;
let
mode
:
MockJSMode
|
null
=
null
;
setup
(()
=>
{
const
configurationService
=
new
TestConfigurationService
();
modelService
=
new
ModelServiceImpl
(
null
,
configurationService
,
new
TestTextResourcePropertiesService
(
configurationService
));
tokenSelectionSupport
=
new
TokenSelectionSupport
(
modelService
);
mode
=
new
MockJSMode
();
});
...
...
@@ -54,13 +53,13 @@ suite('TokenSelectionSupport', () => {
mode
.
dispose
();
});
function
assertGetRangesToPosition
(
text
:
string
[],
lineNumber
:
number
,
column
:
number
,
ranges
:
Range
[]):
void
{
async
function
assertGetRangesToPosition
(
text
:
string
[],
lineNumber
:
number
,
column
:
number
,
ranges
:
Range
[]):
Promise
<
void
>
{
let
uri
=
URI
.
file
(
'
test.js
'
);
modelService
.
createModel
(
text
.
join
(
'
\n
'
),
new
StaticLanguageSelector
(
mode
.
getLanguageIdentifier
()),
uri
);
let
model
=
modelService
.
createModel
(
text
.
join
(
'
\n
'
),
new
StaticLanguageSelector
(
mode
.
getLanguageIdentifier
()),
uri
);
let
actual
=
tokenSelectionSupport
.
getRangesToPositionSync
(
uri
,
new
Position
(
lineNumber
,
column
)
);
let
actual
=
await
provideSelectionRanges
(
model
,
new
Position
(
lineNumber
,
column
),
CancellationToken
.
None
);
let
actualStr
=
actual
.
map
(
r
=>
new
Range
(
r
.
range
.
startLineNumber
,
r
.
range
.
startColumn
,
r
.
range
.
endLineNumber
,
r
.
range
.
endColumn
).
toString
());
let
actualStr
=
actual
.
map
(
r
=>
new
Range
(
r
.
startLineNumber
,
r
.
startColumn
,
r
.
endLineNumber
,
r
.
endColumn
).
toString
());
let
desiredStr
=
ranges
.
map
(
r
=>
String
(
r
));
assert
.
deepEqual
(
actualStr
,
desiredStr
);
...
...
@@ -70,7 +69,7 @@ suite('TokenSelectionSupport', () => {
test
(
'
getRangesToPosition #1
'
,
()
=>
{
assertGetRangesToPosition
([
return
assertGetRangesToPosition
([
'
function a(bar, foo){
'
,
'
\t
if (bar) {
'
,
'
\t\t
return (bar + (2 * foo))
'
,
...
...
@@ -93,7 +92,7 @@ suite('TokenSelectionSupport', () => {
test
(
'
getRangesToPosition #56886. Skip empty lines correctly.
'
,
()
=>
{
assertGetRangesToPosition
([
return
assertGetRangesToPosition
([
'
function a(bar, foo){
'
,
'
\t
if (bar) {
'
,
''
,
...
...
@@ -109,7 +108,7 @@ suite('TokenSelectionSupport', () => {
test
(
'
getRangesToPosition #56886. Do not skip lines with only whitespaces.
'
,
()
=>
{
assertGetRangesToPosition
([
return
assertGetRangesToPosition
([
'
function a(bar, foo){
'
,
'
\t
if (bar) {
'
,
'
'
,
...
...
@@ -127,7 +126,7 @@ suite('TokenSelectionSupport', () => {
test
(
'
getRangesToPosition #40658. Cursor at first position inside brackets should select line inside.
'
,
()
=>
{
assertGetRangesToPosition
([
return
assertGetRangesToPosition
([
'
[ ]
'
,
'
{ }
'
,
'
( )
'
...
...
@@ -141,7 +140,7 @@ suite('TokenSelectionSupport', () => {
test
(
'
getRangesToPosition #40658. Cursor in empty brackets should reveal brackets first.
'
,
()
=>
{
assertGetRangesToPosition
([
return
assertGetRangesToPosition
([
'
[]
'
,
'
{ }
'
,
'
( )
'
...
...
@@ -154,7 +153,7 @@ suite('TokenSelectionSupport', () => {
test
(
'
getRangesToPosition #40658. Tokens before bracket will be revealed first.
'
,
()
=>
{
assertGetRangesToPosition
([
return
assertGetRangesToPosition
([
'
[]
'
,
'
{ }
'
,
'
selectthis( )
'
...
...
src/vs/monaco.d.ts
浏览文件 @
d81a1bcd
...
...
@@ -5294,6 +5294,13 @@ declare namespace monaco.languages {
provideColorPresentations
(
model
:
editor
.
ITextModel
,
colorInfo
:
IColorInformation
,
token
:
CancellationToken
):
ProviderResult
<
IColorPresentation
[]
>
;
}
export
interface
SelectionRangeProvider
{
/**
* Provide ranges that should be selected from the given position.
*/
provideSelectionRanges
(
model
:
editor
.
ITextModel
,
position
:
Position
,
token
:
CancellationToken
):
ProviderResult
<
Range
[]
>
;
}
export
interface
FoldingContext
{
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录