Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
e41acb7f
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,发现更多精彩内容 >>
提交
e41acb7f
编写于
5月 27, 2018
作者:
B
Benjamin Pasero
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into ben/editor
上级
1349f0a0
4eaf5834
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
180 addition
and
70 deletion
+180
-70
extensions/search-rg/src/ripgrepFileSearch.ts
extensions/search-rg/src/ripgrepFileSearch.ts
+14
-7
extensions/search-rg/src/ripgrepTextSearch.ts
extensions/search-rg/src/ripgrepTextSearch.ts
+5
-7
src/vs/workbench/api/node/extHostSearch.ts
src/vs/workbench/api/node/extHostSearch.ts
+8
-5
src/vs/workbench/parts/preferences/browser/settingsEditor2.ts
...vs/workbench/parts/preferences/browser/settingsEditor2.ts
+25
-7
src/vs/workbench/parts/preferences/browser/settingsTree.ts
src/vs/workbench/parts/preferences/browser/settingsTree.ts
+13
-4
src/vs/workbench/parts/search/electron-browser/search.contribution.ts
...ench/parts/search/electron-browser/search.contribution.ts
+1
-1
src/vs/workbench/test/electron-browser/api/extHostSearch.test.ts
...workbench/test/electron-browser/api/extHostSearch.test.ts
+114
-39
未找到文件。
extensions/search-rg/src/ripgrepFileSearch.ts
浏览文件 @
e41acb7f
...
@@ -4,14 +4,13 @@
...
@@ -4,14 +4,13 @@
*--------------------------------------------------------------------------------------------*/
*--------------------------------------------------------------------------------------------*/
import
*
as
cp
from
'
child_process
'
;
import
*
as
cp
from
'
child_process
'
;
import
*
as
path
from
'
path
'
;
import
{
Readable
}
from
'
stream
'
;
import
{
Readable
}
from
'
stream
'
;
import
{
NodeStringDecoder
,
StringDecoder
}
from
'
string_decoder
'
;
import
{
NodeStringDecoder
,
StringDecoder
}
from
'
string_decoder
'
;
import
*
as
vscode
from
'
vscode
'
;
import
*
as
vscode
from
'
vscode
'
;
import
{
rgPath
}
from
'
vscode-ripgrep
'
;
import
{
rgPath
}
from
'
vscode-ripgrep
'
;
import
{
normalizeNFC
,
normalizeNFD
}
from
'
./normalization
'
;
import
{
normalizeNFC
,
normalizeNFD
}
from
'
./normalization
'
;
import
{
rgErrorMsgForDisplay
}
from
'
./ripgrepTextSearch
'
;
import
{
anchorGlob
}
from
'
./ripgrepHelpers
'
;
import
{
anchorGlob
}
from
'
./ripgrepHelpers
'
;
import
{
rgErrorMsgForDisplay
}
from
'
./ripgrepTextSearch
'
;
const
isMac
=
process
.
platform
===
'
darwin
'
;
const
isMac
=
process
.
platform
===
'
darwin
'
;
...
@@ -19,12 +18,16 @@ const isMac = process.platform === 'darwin';
...
@@ -19,12 +18,16 @@ const isMac = process.platform === 'darwin';
const
rgDiskPath
=
rgPath
.
replace
(
/
\b
node_modules
\.
asar
\b
/
,
'
node_modules.asar.unpacked
'
);
const
rgDiskPath
=
rgPath
.
replace
(
/
\b
node_modules
\.
asar
\b
/
,
'
node_modules.asar.unpacked
'
);
export
class
RipgrepFileSearchEngine
{
export
class
RipgrepFileSearchEngine
{
private
isDone
=
false
;
private
rgProc
:
cp
.
ChildProcess
;
private
rgProc
:
cp
.
ChildProcess
;
private
killRgProcFn
:
(
code
?:
number
)
=>
void
;
private
killRgProcFn
:
(
code
?:
number
)
=>
void
;
constructor
(
private
outputChannel
:
vscode
.
OutputChannel
)
{
constructor
(
private
outputChannel
:
vscode
.
OutputChannel
)
{
this
.
killRgProcFn
=
()
=>
this
.
rgProc
&&
this
.
rgProc
.
kill
();
this
.
killRgProcFn
=
()
=>
this
.
rgProc
&&
this
.
rgProc
.
kill
();
process
.
once
(
'
exit
'
,
this
.
killRgProcFn
);
}
private
dispose
()
{
process
.
removeListener
(
'
exit
'
,
this
.
killRgProcFn
);
}
}
provideFileSearchResults
(
options
:
vscode
.
SearchOptions
,
progress
:
vscode
.
Progress
<
string
>
,
token
:
vscode
.
CancellationToken
):
Thenable
<
void
>
{
provideFileSearchResults
(
options
:
vscode
.
SearchOptions
,
progress
:
vscode
.
Progress
<
string
>
,
token
:
vscode
.
CancellationToken
):
Thenable
<
void
>
{
...
@@ -38,7 +41,7 @@ export class RipgrepFileSearchEngine {
...
@@ -38,7 +41,7 @@ export class RipgrepFileSearchEngine {
return
new
Promise
((
resolve
,
reject
)
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
let
isDone
=
false
;
let
isDone
=
false
;
const
cancel
=
()
=>
{
const
cancel
=
()
=>
{
this
.
isDone
=
true
;
isDone
=
true
;
this
.
rgProc
.
kill
();
this
.
rgProc
.
kill
();
};
};
token
.
onCancellationRequested
(
cancel
);
token
.
onCancellationRequested
(
cancel
);
...
@@ -53,7 +56,7 @@ export class RipgrepFileSearchEngine {
...
@@ -53,7 +56,7 @@ export class RipgrepFileSearchEngine {
this
.
outputChannel
.
appendLine
(
`rg
${
escapedArgs
}
\n - cwd:
${
cwd
}
\n`
);
this
.
outputChannel
.
appendLine
(
`rg
${
escapedArgs
}
\n - cwd:
${
cwd
}
\n`
);
this
.
rgProc
=
cp
.
spawn
(
rgDiskPath
,
rgArgs
,
{
cwd
});
this
.
rgProc
=
cp
.
spawn
(
rgDiskPath
,
rgArgs
,
{
cwd
});
process
.
once
(
'
exit
'
,
this
.
killRgProcFn
);
this
.
rgProc
.
on
(
'
error
'
,
e
=>
{
this
.
rgProc
.
on
(
'
error
'
,
e
=>
{
console
.
log
(
e
);
console
.
log
(
e
);
reject
(
e
);
reject
(
e
);
...
@@ -90,7 +93,6 @@ export class RipgrepFileSearchEngine {
...
@@ -90,7 +93,6 @@ export class RipgrepFileSearchEngine {
});
});
if
(
last
)
{
if
(
last
)
{
process
.
removeListener
(
'
exit
'
,
this
.
killRgProcFn
);
if
(
isDone
)
{
if
(
isDone
)
{
resolve
();
resolve
();
}
else
{
}
else
{
...
@@ -104,7 +106,12 @@ export class RipgrepFileSearchEngine {
...
@@ -104,7 +106,12 @@ export class RipgrepFileSearchEngine {
}
}
}
}
});
});
});
}).
then
(
()
=>
this
.
dispose
(),
err
=>
{
this
.
dispose
();
return
Promise
.
reject
(
err
);
});
}
}
private
collectStdout
(
cmd
:
cp
.
ChildProcess
,
cb
:
(
err
:
Error
,
stdout
?:
string
,
last
?:
boolean
)
=>
void
):
void
{
private
collectStdout
(
cmd
:
cp
.
ChildProcess
,
cb
:
(
err
:
Error
,
stdout
?:
string
,
last
?:
boolean
)
=>
void
):
void
{
...
...
extensions/search-rg/src/ripgrepTextSearch.ts
浏览文件 @
e41acb7f
...
@@ -5,17 +5,15 @@
...
@@ -5,17 +5,15 @@
'
use strict
'
;
'
use strict
'
;
import
*
as
vscode
from
'
vscode
'
;
import
{
EventEmitter
}
from
'
events
'
;
import
*
as
path
from
'
path
'
;
import
{
StringDecoder
,
NodeStringDecoder
}
from
'
string_decoder
'
;
import
*
as
cp
from
'
child_process
'
;
import
*
as
cp
from
'
child_process
'
;
import
{
EventEmitter
}
from
'
events
'
;
import
{
NodeStringDecoder
,
StringDecoder
}
from
'
string_decoder
'
;
import
*
as
vscode
from
'
vscode
'
;
import
{
rgPath
}
from
'
vscode-ripgrep
'
;
import
{
rgPath
}
from
'
vscode-ripgrep
'
;
import
{
start
}
from
'
repl
'
;
import
{
anchorGlob
}
from
'
./ripgrepHelpers
'
;
import
{
anchorGlob
}
from
'
./ripgrepHelpers
'
;
// If vscode-ripgrep is in an .asar file, then the binary is unpacked.
// If vscode-ripgrep is in an .asar file, then the binary is unpacked.
const
rgDiskPath
=
rgPath
.
replace
(
/
\b
node_modules
\.
asar
\b
/
,
'
node_modules.asar.unpacked
'
);
const
rgDiskPath
=
rgPath
.
replace
(
/
\b
node_modules
\.
asar
\b
/
,
'
node_modules.asar.unpacked
'
);
...
...
src/vs/workbench/api/node/extHostSearch.ts
浏览文件 @
e41acb7f
...
@@ -401,13 +401,15 @@ class TextSearchEngine {
...
@@ -401,13 +401,15 @@ class TextSearchEngine {
return
;
return
;
}
}
this
.
resultCount
++
;
this
.
collector
.
add
(
match
,
folderIdx
);
if
(
this
.
resultCount
>=
this
.
config
.
maxResults
)
{
if
(
this
.
resultCount
>=
this
.
config
.
maxResults
)
{
this
.
isLimitHit
=
true
;
this
.
isLimitHit
=
true
;
this
.
cancel
();
this
.
cancel
();
}
}
if
(
!
this
.
isLimitHit
)
{
this
.
resultCount
++
;
this
.
collector
.
add
(
match
,
folderIdx
);
}
};
};
// For each root folder
// For each root folder
...
@@ -492,7 +494,8 @@ class TextSearchEngine {
...
@@ -492,7 +494,8 @@ class TextSearchEngine {
includes
,
includes
,
useIgnoreFiles
:
!
this
.
config
.
disregardIgnoreFiles
,
useIgnoreFiles
:
!
this
.
config
.
disregardIgnoreFiles
,
followSymlinks
:
!
this
.
config
.
ignoreSymlinks
,
followSymlinks
:
!
this
.
config
.
ignoreSymlinks
,
encoding
:
this
.
config
.
fileEncoding
encoding
:
this
.
config
.
fileEncoding
,
maxFileSize
:
this
.
config
.
maxFileSize
};
};
}
}
}
}
...
@@ -589,7 +592,7 @@ class FileSearchEngine {
...
@@ -589,7 +592,7 @@ class FileSearchEngine {
PPromise
.
join
(
folderQueries
.
map
(
fq
=>
{
PPromise
.
join
(
folderQueries
.
map
(
fq
=>
{
return
this
.
searchInFolder
(
fq
).
then
(
null
,
null
,
onResult
);
return
this
.
searchInFolder
(
fq
).
then
(
null
,
null
,
onResult
);
})).
then
(()
=>
{
})).
then
(()
=>
{
resolve
({
isLimitHit
:
false
});
resolve
({
isLimitHit
:
this
.
isLimitHit
});
},
(
errs
:
Error
[])
=>
{
},
(
errs
:
Error
[])
=>
{
const
errMsg
=
errs
const
errMsg
=
errs
.
map
(
err
=>
toErrorMessage
(
err
))
.
map
(
err
=>
toErrorMessage
(
err
))
...
...
src/vs/workbench/parts/preferences/browser/settingsEditor2.ts
浏览文件 @
e41acb7f
...
@@ -80,7 +80,7 @@ export class SettingsEditor2 extends BaseEditor {
...
@@ -80,7 +80,7 @@ export class SettingsEditor2 extends BaseEditor {
this
.
remoteSearchThrottle
=
new
ThrottledDelayer
(
200
);
this
.
remoteSearchThrottle
=
new
ThrottledDelayer
(
200
);
this
.
viewState
=
{
settingsTarget
:
ConfigurationTarget
.
USER
};
this
.
viewState
=
{
settingsTarget
:
ConfigurationTarget
.
USER
};
this
.
_register
(
configurationService
.
onDidChangeConfiguration
(()
=>
this
.
settingsTree
.
refresh
()));
this
.
_register
(
configurationService
.
onDidChangeConfiguration
(()
=>
this
.
refreshTreeAndMaintainFocus
()));
}
}
createEditor
(
parent
:
HTMLElement
):
void
{
createEditor
(
parent
:
HTMLElement
):
void
{
...
@@ -193,6 +193,7 @@ export class SettingsEditor2 extends BaseEditor {
...
@@ -193,6 +193,7 @@ export class SettingsEditor2 extends BaseEditor {
this
.
treeDataSource
=
this
.
instantiationService
.
createInstance
(
SettingsDataSource
,
this
.
viewState
);
this
.
treeDataSource
=
this
.
instantiationService
.
createInstance
(
SettingsDataSource
,
this
.
viewState
);
const
renderer
=
this
.
instantiationService
.
createInstance
(
SettingsRenderer
,
this
.
settingsTreeContainer
);
const
renderer
=
this
.
instantiationService
.
createInstance
(
SettingsRenderer
,
this
.
settingsTreeContainer
);
this
.
_register
(
renderer
.
onDidChangeSetting
(
e
=>
this
.
onDidChangeSetting
(
e
.
key
,
e
.
value
)));
this
.
_register
(
renderer
.
onDidChangeSetting
(
e
=>
this
.
onDidChangeSetting
(
e
.
key
,
e
.
value
)));
this
.
_register
(
renderer
.
onDidOpenSettings
(()
=>
this
.
openSettingsFile
()));
const
treeClass
=
'
settings-editor-tree
'
;
const
treeClass
=
'
settings-editor-tree
'
;
this
.
settingsTree
=
this
.
instantiationService
.
createInstance
(
WorkbenchTree
,
this
.
settingsTreeContainer
,
this
.
settingsTree
=
this
.
instantiationService
.
createInstance
(
WorkbenchTree
,
this
.
settingsTreeContainer
,
...
@@ -268,7 +269,7 @@ export class SettingsEditor2 extends BaseEditor {
...
@@ -268,7 +269,7 @@ export class SettingsEditor2 extends BaseEditor {
private
onShowConfiguredOnlyClicked
():
void
{
private
onShowConfiguredOnlyClicked
():
void
{
this
.
viewState
.
showConfiguredOnly
=
this
.
showConfiguredSettingsOnlyCheckbox
.
checked
;
this
.
viewState
.
showConfiguredOnly
=
this
.
showConfiguredSettingsOnlyCheckbox
.
checked
;
this
.
refreshTree
();
this
.
refreshTree
AndMaintainFocus
();
// TODO@roblou - This is slow
// TODO@roblou - This is slow
if
(
this
.
viewState
.
showConfiguredOnly
)
{
if
(
this
.
viewState
.
showConfiguredOnly
)
{
...
@@ -294,8 +295,7 @@ export class SettingsEditor2 extends BaseEditor {
...
@@ -294,8 +295,7 @@ export class SettingsEditor2 extends BaseEditor {
// ConfigurationService displays the error if this fails.
// ConfigurationService displays the error if this fails.
// Force a render afterwards because onDidConfigurationUpdate doesn't fire if the update doesn't result in an effective setting value change
// Force a render afterwards because onDidConfigurationUpdate doesn't fire if the update doesn't result in an effective setting value change
this
.
configurationService
.
updateValue
(
key
,
value
,
<
ConfigurationTarget
>
this
.
settingsTargetsWidget
.
settingsTarget
)
this
.
configurationService
.
updateValue
(
key
,
value
,
<
ConfigurationTarget
>
this
.
settingsTargetsWidget
.
settingsTarget
)
.
then
(()
=>
this
.
refreshTree
())
.
then
(()
=>
this
.
refreshTreeAndMaintainFocus
());
.
then
(()
=>
this
.
settingsTree
.
domFocus
());
const
reportModifiedProps
=
{
const
reportModifiedProps
=
{
key
,
key
,
...
@@ -391,8 +391,26 @@ export class SettingsEditor2 extends BaseEditor {
...
@@ -391,8 +391,26 @@ export class SettingsEditor2 extends BaseEditor {
return
TPromise
.
as
(
null
);
return
TPromise
.
as
(
null
);
}
}
private
refreshTree
():
TPromise
<
any
>
{
private
refreshTreeAndMaintainFocus
():
TPromise
<
any
>
{
return
this
.
settingsTree
.
refresh
();
// Sort of a hack to maintain focus on the focused control across a refresh
const
focusedRowItem
=
DOM
.
findParentWithClass
(
<
HTMLElement
>
document
.
activeElement
,
'
setting-item
'
);
const
focusedRowId
=
focusedRowItem
&&
focusedRowItem
.
id
;
const
selection
=
focusedRowId
&&
document
.
activeElement
.
tagName
.
toLowerCase
()
===
'
input
'
?
(
<
HTMLInputElement
>
document
.
activeElement
).
selectionStart
:
null
;
return
this
.
settingsTree
.
refresh
().
then
(()
=>
{
if
(
focusedRowId
)
{
const
rowSelector
=
`.setting-item#
${
focusedRowId
}
`
;
const
inputElementToFocus
:
HTMLElement
=
this
.
settingsTreeContainer
.
querySelector
(
`
${
rowSelector
}
input,
${
rowSelector
}
select,
${
rowSelector
}
a`
);
if
(
inputElementToFocus
)
{
inputElementToFocus
.
focus
();
if
(
typeof
selection
===
'
number
'
)
{
(
<
HTMLInputElement
>
inputElementToFocus
).
setSelectionRange
(
selection
,
selection
);
}
}
}
});
}
}
private
onSearchInputChanged
():
void
{
private
onSearchInputChanged
():
void
{
...
@@ -486,7 +504,7 @@ export class SettingsEditor2 extends BaseEditor {
...
@@ -486,7 +504,7 @@ export class SettingsEditor2 extends BaseEditor {
}
}
this
.
searchResultModel
.
setResult
(
type
,
result
);
this
.
searchResultModel
.
setResult
(
type
,
result
);
return
this
.
refreshTree
();
return
this
.
refreshTree
AndMaintainFocus
();
});
});
}
}
...
...
src/vs/workbench/parts/preferences/browser/settingsTree.ts
浏览文件 @
e41acb7f
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
*--------------------------------------------------------------------------------------------*/
import
*
as
DOM
from
'
vs/base/browser/dom
'
;
import
*
as
DOM
from
'
vs/base/browser/dom
'
;
import
{
StandardKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
IMouseEvent
}
from
'
vs/base/browser/mouseEvent
'
;
import
{
IMouseEvent
}
from
'
vs/base/browser/mouseEvent
'
;
import
{
Button
}
from
'
vs/base/browser/ui/button/button
'
;
import
{
Button
}
from
'
vs/base/browser/ui/button/button
'
;
import
{
InputBox
}
from
'
vs/base/browser/ui/inputbox/inputBox
'
;
import
{
InputBox
}
from
'
vs/base/browser/ui/inputbox/inputBox
'
;
...
@@ -11,6 +12,7 @@ import { renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel';
...
@@ -11,6 +12,7 @@ import { renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel';
import
{
SelectBox
}
from
'
vs/base/browser/ui/selectBox/selectBox
'
;
import
{
SelectBox
}
from
'
vs/base/browser/ui/selectBox/selectBox
'
;
import
{
Color
}
from
'
vs/base/common/color
'
;
import
{
Color
}
from
'
vs/base/common/color
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
KeyCode
}
from
'
vs/base/common/keyCodes
'
;
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
*
as
objects
from
'
vs/base/common/objects
'
;
import
*
as
objects
from
'
vs/base/common/objects
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
URI
from
'
vs/base/common/uri
'
;
...
@@ -119,7 +121,7 @@ export class SettingsDataSource implements IDataSource {
...
@@ -119,7 +121,7 @@ export class SettingsDataSource implements IDataSource {
return
<
ISettingElement
>
{
return
<
ISettingElement
>
{
type
:
TreeItemType
.
setting
,
type
:
TreeItemType
.
setting
,
parent
:
group
,
parent
:
group
,
id
:
`
${
group
.
id
}
_
${
setting
.
key
}
`
,
id
:
`
${
group
.
id
}
_
${
setting
.
key
.
replace
(
/
\.
/g
,
'
_
'
)
}
`
,
setting
,
setting
,
displayLabel
:
displayKeyFormat
.
label
,
displayLabel
:
displayKeyFormat
.
label
,
...
@@ -294,7 +296,7 @@ export class SettingsRenderer implements IRenderer {
...
@@ -294,7 +296,7 @@ export class SettingsRenderer implements IRenderer {
private
measureSettingElementHeight
(
tree
:
ITree
,
element
:
ISettingElement
):
number
{
private
measureSettingElementHeight
(
tree
:
ITree
,
element
:
ISettingElement
):
number
{
const
measureHelper
=
DOM
.
append
(
this
.
measureContainer
,
$
(
'
.setting-measure-helper
'
));
const
measureHelper
=
DOM
.
append
(
this
.
measureContainer
,
$
(
'
.setting-measure-helper
'
));
const
template
=
this
.
renderSettingTemplate
(
measureHelper
);
const
template
=
this
.
renderSettingTemplate
(
tree
,
measureHelper
);
this
.
renderSettingElement
(
tree
,
element
,
template
,
true
);
this
.
renderSettingElement
(
tree
,
element
,
template
,
true
);
const
height
=
measureHelper
.
offsetHeight
;
const
height
=
measureHelper
.
offsetHeight
;
...
@@ -320,7 +322,7 @@ export class SettingsRenderer implements IRenderer {
...
@@ -320,7 +322,7 @@ export class SettingsRenderer implements IRenderer {
}
}
if
(
templateId
===
SETTINGS_ELEMENT_TEMPLATE_ID
)
{
if
(
templateId
===
SETTINGS_ELEMENT_TEMPLATE_ID
)
{
return
this
.
renderSettingTemplate
(
container
);
return
this
.
renderSettingTemplate
(
tree
,
container
);
}
}
return
null
;
return
null
;
...
@@ -341,7 +343,7 @@ export class SettingsRenderer implements IRenderer {
...
@@ -341,7 +343,7 @@ export class SettingsRenderer implements IRenderer {
return
template
;
return
template
;
}
}
private
renderSettingTemplate
(
container
:
HTMLElement
):
ISettingItemTemplate
{
private
renderSettingTemplate
(
tree
:
ITree
,
container
:
HTMLElement
):
ISettingItemTemplate
{
DOM
.
addClass
(
container
,
'
setting-item
'
);
DOM
.
addClass
(
container
,
'
setting-item
'
);
const
leftElement
=
DOM
.
append
(
container
,
$
(
'
.setting-item-left
'
));
const
leftElement
=
DOM
.
append
(
container
,
$
(
'
.setting-item-left
'
));
...
@@ -375,6 +377,13 @@ export class SettingsRenderer implements IRenderer {
...
@@ -375,6 +377,13 @@ export class SettingsRenderer implements IRenderer {
// Prevent clicks from being handled by list
// Prevent clicks from being handled by list
toDispose
.
push
(
DOM
.
addDisposableListener
(
valueElement
,
'
mousedown
'
,
(
e
:
IMouseEvent
)
=>
e
.
stopPropagation
()));
toDispose
.
push
(
DOM
.
addDisposableListener
(
valueElement
,
'
mousedown
'
,
(
e
:
IMouseEvent
)
=>
e
.
stopPropagation
()));
toDispose
.
push
(
DOM
.
addStandardDisposableListener
(
valueElement
,
'
keydown
'
,
(
e
:
StandardKeyboardEvent
)
=>
{
if
(
e
.
keyCode
===
KeyCode
.
Escape
)
{
tree
.
domFocus
();
e
.
browserEvent
.
stopPropagation
();
}
}));
return
template
;
return
template
;
}
}
...
...
src/vs/workbench/parts/search/electron-browser/search.contribution.ts
浏览文件 @
e41acb7f
...
@@ -607,7 +607,7 @@ configurationRegistry.registerConfiguration({
...
@@ -607,7 +607,7 @@ configurationRegistry.registerConfiguration({
},
},
'
search.enableSearchProviders
'
:
{
'
search.enableSearchProviders
'
:
{
type
:
'
boolean
'
,
type
:
'
boolean
'
,
default
:
tru
e
,
default
:
fals
e
,
description
:
nls
.
localize
(
'
search.enableSearchProviders
'
,
"
(Experimental) Controls whether search provider extensions should be enabled.
"
)
description
:
nls
.
localize
(
'
search.enableSearchProviders
'
,
"
(Experimental) Controls whether search provider extensions should be enabled.
"
)
}
}
}
}
...
...
src/vs/workbench/test/electron-browser/api/extHostSearch.test.ts
浏览文件 @
e41acb7f
...
@@ -6,18 +6,18 @@
...
@@ -6,18 +6,18 @@
import
*
as
assert
from
'
assert
'
;
import
*
as
assert
from
'
assert
'
;
import
*
as
path
from
'
path
'
;
import
*
as
path
from
'
path
'
;
import
*
as
extfs
from
'
vs/base/node/extfs
'
;
import
{
isPromiseCanceledError
}
from
'
vs/base/common/errors
'
;
import
{
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
joinPath
}
from
'
vs/base/common/resources
'
;
import
URI
,
{
UriComponents
}
from
'
vs/base/common/uri
'
;
import
URI
,
{
UriComponents
}
from
'
vs/base/common/uri
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IRawFileMatch2
,
IRawSearchQuery
,
QueryType
,
ISearchQuery
,
IPatternInfo
,
IFileMatch
}
from
'
vs/platform/search/common/search
'
;
import
*
as
extfs
from
'
vs/base/node/extfs
'
;
import
{
IFileMatch
,
IPatternInfo
,
IRawFileMatch2
,
IRawSearchQuery
,
ISearchCompleteStats
,
ISearchQuery
,
QueryType
}
from
'
vs/platform/search/common/search
'
;
import
{
MainContext
,
MainThreadSearchShape
}
from
'
vs/workbench/api/node/extHost.protocol
'
;
import
{
MainContext
,
MainThreadSearchShape
}
from
'
vs/workbench/api/node/extHost.protocol
'
;
import
{
ExtHostSearch
}
from
'
vs/workbench/api/node/extHostSearch
'
;
import
{
ExtHostSearch
}
from
'
vs/workbench/api/node/extHostSearch
'
;
import
{
Range
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
{
TestRPCProtocol
}
from
'
vs/workbench/test/electron-browser/api/testRPCProtocol
'
;
import
{
TestRPCProtocol
}
from
'
vs/workbench/test/electron-browser/api/testRPCProtocol
'
;
import
*
as
vscode
from
'
vscode
'
;
import
*
as
vscode
from
'
vscode
'
;
import
{
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
isPromiseCanceledError
}
from
'
vs/base/common/errors
'
;
import
{
Range
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
{
joinPath
}
from
'
vs/base/common/resources
'
;
let
rpcProtocol
:
TestRPCProtocol
;
let
rpcProtocol
:
TestRPCProtocol
;
let
extHostSearch
:
ExtHostSearch
;
let
extHostSearch
:
ExtHostSearch
;
...
@@ -59,7 +59,8 @@ suite('ExtHostSearch', () => {
...
@@ -59,7 +59,8 @@ suite('ExtHostSearch', () => {
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
}
}
async
function
runFileSearch
(
query
:
IRawSearchQuery
,
cancel
=
false
):
TPromise
<
URI
[]
>
{
async
function
runFileSearch
(
query
:
IRawSearchQuery
,
cancel
=
false
):
TPromise
<
{
results
:
URI
[];
stats
:
ISearchCompleteStats
}
>
{
let
stats
:
ISearchCompleteStats
;
try
{
try
{
const
p
=
extHostSearch
.
$provideFileSearchResults
(
mockMainThreadSearch
.
lastHandle
,
0
,
query
);
const
p
=
extHostSearch
.
$provideFileSearchResults
(
mockMainThreadSearch
.
lastHandle
,
0
,
query
);
if
(
cancel
)
{
if
(
cancel
)
{
...
@@ -67,7 +68,7 @@ suite('ExtHostSearch', () => {
...
@@ -67,7 +68,7 @@ suite('ExtHostSearch', () => {
p
.
cancel
();
p
.
cancel
();
}
}
await
p
;
stats
=
await
p
;
}
catch
(
err
)
{
}
catch
(
err
)
{
if
(
!
isPromiseCanceledError
(
err
))
{
if
(
!
isPromiseCanceledError
(
err
))
{
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
...
@@ -76,10 +77,14 @@ suite('ExtHostSearch', () => {
...
@@ -76,10 +77,14 @@ suite('ExtHostSearch', () => {
}
}
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
return
(
<
UriComponents
[]
>
mockMainThreadSearch
.
results
).
map
(
r
=>
URI
.
revive
(
r
));
return
{
results
:
(
<
UriComponents
[]
>
mockMainThreadSearch
.
results
).
map
(
r
=>
URI
.
revive
(
r
)),
stats
};
}
}
async
function
runTextSearch
(
pattern
:
IPatternInfo
,
query
:
IRawSearchQuery
,
cancel
=
false
):
TPromise
<
IFileMatch
[]
>
{
async
function
runTextSearch
(
pattern
:
IPatternInfo
,
query
:
IRawSearchQuery
,
cancel
=
false
):
TPromise
<
{
results
:
IFileMatch
[],
stats
:
ISearchCompleteStats
}
>
{
let
stats
:
ISearchCompleteStats
;
try
{
try
{
const
p
=
extHostSearch
.
$provideTextSearchResults
(
mockMainThreadSearch
.
lastHandle
,
0
,
pattern
,
query
);
const
p
=
extHostSearch
.
$provideTextSearchResults
(
mockMainThreadSearch
.
lastHandle
,
0
,
pattern
,
query
);
if
(
cancel
)
{
if
(
cancel
)
{
...
@@ -87,7 +92,7 @@ suite('ExtHostSearch', () => {
...
@@ -87,7 +92,7 @@ suite('ExtHostSearch', () => {
p
.
cancel
();
p
.
cancel
();
}
}
await
p
;
stats
=
await
p
;
}
catch
(
err
)
{
}
catch
(
err
)
{
if
(
!
isPromiseCanceledError
(
err
))
{
if
(
!
isPromiseCanceledError
(
err
))
{
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
...
@@ -96,12 +101,14 @@ suite('ExtHostSearch', () => {
...
@@ -96,12 +101,14 @@ suite('ExtHostSearch', () => {
}
}
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
return
(
<
IRawFileMatch2
[]
>
mockMainThreadSearch
.
results
).
map
(
r
=>
({
const
results
=
(
<
IRawFileMatch2
[]
>
mockMainThreadSearch
.
results
).
map
(
r
=>
({
...
r
,
...
r
,
...{
...{
resource
:
URI
.
revive
(
r
.
resource
)
resource
:
URI
.
revive
(
r
.
resource
)
}
}
}));
}));
return
{
results
,
stats
};
}
}
setup
(()
=>
{
setup
(()
=>
{
...
@@ -153,7 +160,8 @@ suite('ExtHostSearch', () => {
...
@@ -153,7 +160,8 @@ suite('ExtHostSearch', () => {
}
}
});
});
const
results
=
await
runFileSearch
(
getSimpleQuery
());
const
{
results
,
stats
}
=
await
runFileSearch
(
getSimpleQuery
());
assert
(
!
stats
.
limitHit
);
assert
(
!
results
.
length
);
assert
(
!
results
.
length
);
});
});
...
@@ -171,18 +179,12 @@ suite('ExtHostSearch', () => {
...
@@ -171,18 +179,12 @@ suite('ExtHostSearch', () => {
}
}
});
});
const
results
=
await
runFileSearch
(
getSimpleQuery
());
const
{
results
,
stats
}
=
await
runFileSearch
(
getSimpleQuery
());
assert
(
!
stats
.
limitHit
);
assert
.
equal
(
results
.
length
,
3
);
assert
.
equal
(
results
.
length
,
3
);
compareURIs
(
results
,
reportedResults
);
compareURIs
(
results
,
reportedResults
);
});
});
// Sibling clauses
// Extra files
// Max result count
// Absolute/relative logic
// Includes/excludes passed to provider correctly
// Provider misbehaves
test
(
'
Search canceled
'
,
async
()
=>
{
test
(
'
Search canceled
'
,
async
()
=>
{
let
cancelRequested
=
false
;
let
cancelRequested
=
false
;
await
registerTestSearchProvider
({
await
registerTestSearchProvider
({
...
@@ -198,7 +200,7 @@ suite('ExtHostSearch', () => {
...
@@ -198,7 +200,7 @@ suite('ExtHostSearch', () => {
}
}
});
});
const
results
=
await
runFileSearch
(
getSimpleQuery
(),
true
);
const
{
results
}
=
await
runFileSearch
(
getSimpleQuery
(),
true
);
assert
(
cancelRequested
);
assert
(
cancelRequested
);
assert
(
!
results
.
length
);
assert
(
!
results
.
length
);
});
});
...
@@ -376,7 +378,7 @@ suite('ExtHostSearch', () => {
...
@@ -376,7 +378,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runFileSearch
(
query
);
const
{
results
}
=
await
runFileSearch
(
query
);
compareURIs
(
compareURIs
(
results
,
results
,
[
[
...
@@ -436,7 +438,7 @@ suite('ExtHostSearch', () => {
...
@@ -436,7 +438,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runFileSearch
(
query
);
const
{
results
}
=
await
runFileSearch
(
query
);
compareURIs
(
compareURIs
(
results
,
results
,
[
[
...
@@ -479,7 +481,8 @@ suite('ExtHostSearch', () => {
...
@@ -479,7 +481,8 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runFileSearch
(
query
);
const
{
results
,
stats
}
=
await
runFileSearch
(
query
);
assert
(
stats
.
limitHit
,
'
Expected to return limitHit
'
);
assert
.
equal
(
results
.
length
,
1
);
assert
.
equal
(
results
.
length
,
1
);
compareURIs
(
results
,
reportedResults
.
slice
(
0
,
1
));
compareURIs
(
results
,
reportedResults
.
slice
(
0
,
1
));
assert
(
wasCanceled
,
'
Expected to be canceled when hitting limit
'
);
assert
(
wasCanceled
,
'
Expected to be canceled when hitting limit
'
);
...
@@ -515,12 +518,49 @@ suite('ExtHostSearch', () => {
...
@@ -515,12 +518,49 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runFileSearch
(
query
);
const
{
results
,
stats
}
=
await
runFileSearch
(
query
);
assert
(
stats
.
limitHit
,
'
Expected to return limitHit
'
);
assert
.
equal
(
results
.
length
,
2
);
assert
.
equal
(
results
.
length
,
2
);
compareURIs
(
results
,
reportedResults
.
slice
(
0
,
2
));
compareURIs
(
results
,
reportedResults
.
slice
(
0
,
2
));
assert
(
wasCanceled
,
'
Expected to be canceled when hitting limit
'
);
assert
(
wasCanceled
,
'
Expected to be canceled when hitting limit
'
);
});
});
test
(
'
provider returns maxResults exactly
'
,
async
()
=>
{
const
reportedResults
=
[
joinPath
(
rootFolderA
,
'
file1.ts
'
),
joinPath
(
rootFolderA
,
'
file2.ts
'
),
];
let
wasCanceled
=
false
;
await
registerTestSearchProvider
({
provideFileSearchResults
(
options
:
vscode
.
FileSearchOptions
,
progress
:
vscode
.
Progress
<
string
>
,
token
:
vscode
.
CancellationToken
):
Thenable
<
void
>
{
reportedResults
.
forEach
(
r
=>
progress
.
report
(
path
.
basename
(
r
.
fsPath
)));
token
.
onCancellationRequested
(()
=>
wasCanceled
=
true
);
return
TPromise
.
wrap
(
null
);
}
});
const
query
:
ISearchQuery
=
{
type
:
QueryType
.
File
,
filePattern
:
''
,
maxResults
:
2
,
folderQueries
:
[
{
folder
:
rootFolderA
}
]
};
const
{
results
,
stats
}
=
await
runFileSearch
(
query
);
assert
(
!
stats
.
limitHit
,
'
Expected not to return limitHit
'
);
assert
.
equal
(
results
.
length
,
2
);
compareURIs
(
results
,
reportedResults
);
assert
(
!
wasCanceled
,
'
Expected not to be canceled when just reaching limit
'
);
});
test
(
'
multiroot max results
'
,
async
()
=>
{
test
(
'
multiroot max results
'
,
async
()
=>
{
let
cancels
=
0
;
let
cancels
=
0
;
await
registerTestSearchProvider
({
await
registerTestSearchProvider
({
...
@@ -557,7 +597,7 @@ suite('ExtHostSearch', () => {
...
@@ -557,7 +597,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runFileSearch
(
query
);
const
{
results
}
=
await
runFileSearch
(
query
);
assert
.
equal
(
results
.
length
,
2
);
// Don't care which 2 we got
assert
.
equal
(
results
.
length
,
2
);
// Don't care which 2 we got
assert
.
equal
(
cancels
,
2
,
'
Expected all invocations to be canceled when hitting limit
'
);
assert
.
equal
(
cancels
,
2
,
'
Expected all invocations to be canceled when hitting limit
'
);
});
});
...
@@ -588,7 +628,7 @@ suite('ExtHostSearch', () => {
...
@@ -588,7 +628,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runFileSearch
(
query
);
const
{
results
}
=
await
runFileSearch
(
query
);
assert
.
equal
(
results
.
length
,
1
);
assert
.
equal
(
results
.
length
,
1
);
compareURIs
(
results
,
reportedResults
.
slice
(
2
));
compareURIs
(
results
,
reportedResults
.
slice
(
2
));
});
});
...
@@ -618,7 +658,7 @@ suite('ExtHostSearch', () => {
...
@@ -618,7 +658,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runFileSearch
(
query
);
const
{
results
}
=
await
runFileSearch
(
query
);
compareURIs
(
results
,
reportedResults
);
compareURIs
(
results
,
reportedResults
);
});
});
...
@@ -639,7 +679,7 @@ suite('ExtHostSearch', () => {
...
@@ -639,7 +679,7 @@ suite('ExtHostSearch', () => {
// });
// });
// const queriedFilePath = queriedFile.fsPath;
// const queriedFilePath = queriedFile.fsPath;
// const
results
= await runFileSearch(getSimpleQuery(queriedFilePath));
// const
{ results }
= await runFileSearch(getSimpleQuery(queriedFilePath));
// assert.equal(results.length, 1);
// assert.equal(results.length, 1);
// compareURIs(results, [queriedFile]);
// compareURIs(results, [queriedFile]);
// });
// });
...
@@ -722,7 +762,8 @@ suite('ExtHostSearch', () => {
...
@@ -722,7 +762,8 @@ suite('ExtHostSearch', () => {
}
}
});
});
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
getSimpleQuery
());
const
{
results
,
stats
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
getSimpleQuery
());
assert
(
!
stats
.
limitHit
);
assert
(
!
results
.
length
);
assert
(
!
results
.
length
);
});
});
...
@@ -739,7 +780,8 @@ suite('ExtHostSearch', () => {
...
@@ -739,7 +780,8 @@ suite('ExtHostSearch', () => {
}
}
});
});
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
getSimpleQuery
());
const
{
results
,
stats
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
getSimpleQuery
());
assert
(
!
stats
.
limitHit
);
assertResults
(
results
,
providedResults
);
assertResults
(
results
,
providedResults
);
});
});
...
@@ -903,7 +945,7 @@ suite('ExtHostSearch', () => {
...
@@ -903,7 +945,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
const
{
results
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assertResults
(
results
,
providedResults
.
slice
(
1
));
assertResults
(
results
,
providedResults
.
slice
(
1
));
});
});
...
@@ -975,7 +1017,7 @@ suite('ExtHostSearch', () => {
...
@@ -975,7 +1017,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
const
{
results
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assertResults
(
results
,
[
assertResults
(
results
,
[
makeTextResult
(
'
folder/fileA.scss
'
),
makeTextResult
(
'
folder/fileA.scss
'
),
makeTextResult
(
'
folder/file2.css
'
),
makeTextResult
(
'
folder/file2.css
'
),
...
@@ -1009,7 +1051,7 @@ suite('ExtHostSearch', () => {
...
@@ -1009,7 +1051,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
const
{
results
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assertResults
(
results
,
providedResults
.
slice
(
1
));
assertResults
(
results
,
providedResults
.
slice
(
1
));
});
});
...
@@ -1038,7 +1080,8 @@ suite('ExtHostSearch', () => {
...
@@ -1038,7 +1080,8 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
const
{
results
,
stats
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assert
(
stats
.
limitHit
,
'
Expected to return limitHit
'
);
assertResults
(
results
,
providedResults
.
slice
(
0
,
1
));
assertResults
(
results
,
providedResults
.
slice
(
0
,
1
));
assert
(
wasCanceled
,
'
Expected to be canceled
'
);
assert
(
wasCanceled
,
'
Expected to be canceled
'
);
});
});
...
@@ -1069,11 +1112,43 @@ suite('ExtHostSearch', () => {
...
@@ -1069,11 +1112,43 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
const
{
results
,
stats
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assert
(
stats
.
limitHit
,
'
Expected to return limitHit
'
);
assertResults
(
results
,
providedResults
.
slice
(
0
,
2
));
assertResults
(
results
,
providedResults
.
slice
(
0
,
2
));
assert
(
wasCanceled
,
'
Expected to be canceled
'
);
assert
(
wasCanceled
,
'
Expected to be canceled
'
);
});
});
test
(
'
provider returns maxResults exactly
'
,
async
()
=>
{
const
providedResults
:
vscode
.
TextSearchResult
[]
=
[
makeTextResult
(
'
file1.ts
'
),
makeTextResult
(
'
file2.ts
'
)
];
let
wasCanceled
=
false
;
await
registerTestSearchProvider
({
provideTextSearchResults
(
query
:
vscode
.
TextSearchQuery
,
options
:
vscode
.
TextSearchOptions
,
progress
:
vscode
.
Progress
<
vscode
.
TextSearchResult
>
,
token
:
vscode
.
CancellationToken
):
Thenable
<
void
>
{
token
.
onCancellationRequested
(()
=>
wasCanceled
=
true
);
providedResults
.
forEach
(
r
=>
progress
.
report
(
r
));
return
TPromise
.
wrap
(
null
);
}
});
const
query
:
ISearchQuery
=
{
type
:
QueryType
.
Text
,
maxResults
:
2
,
folderQueries
:
[
{
folder
:
rootFolderA
}
]
};
const
{
results
,
stats
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assert
(
!
stats
.
limitHit
,
'
Expected not to return limitHit
'
);
assertResults
(
results
,
providedResults
);
assert
(
!
wasCanceled
,
'
Expected not to be canceled
'
);
});
test
(
'
multiroot max results
'
,
async
()
=>
{
test
(
'
multiroot max results
'
,
async
()
=>
{
let
cancels
=
0
;
let
cancels
=
0
;
await
registerTestSearchProvider
({
await
registerTestSearchProvider
({
...
@@ -1101,7 +1176,7 @@ suite('ExtHostSearch', () => {
...
@@ -1101,7 +1176,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
const
{
results
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assert
.
equal
(
results
.
length
,
2
);
assert
.
equal
(
results
.
length
,
2
);
assert
.
equal
(
cancels
,
2
);
assert
.
equal
(
cancels
,
2
);
});
});
...
@@ -1128,7 +1203,7 @@ suite('ExtHostSearch', () => {
...
@@ -1128,7 +1203,7 @@ suite('ExtHostSearch', () => {
]
]
};
};
const
results
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
const
{
results
}
=
await
runTextSearch
(
getPattern
(
'
foo
'
),
query
);
assertResults
(
results
,
providedResults
,
fancySchemeFolderA
);
assertResults
(
results
,
providedResults
,
fancySchemeFolderA
);
});
});
});
});
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录