Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
eb257f59
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,体验更适合开发者的 AI 搜索 >>
提交
eb257f59
编写于
3月 04, 2016
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
improve extension recommendations
related to #3633
上级
7c803f78
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
52 addition
and
147 deletion
+52
-147
src/vs/base/browser/ui/list/listView.ts
src/vs/base/browser/ui/list/listView.ts
+1
-1
src/vs/base/common/objects.ts
src/vs/base/common/objects.ts
+2
-2
src/vs/workbench/parts/extensions/common/extensions.ts
src/vs/workbench/parts/extensions/common/extensions.ts
+1
-2
src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts
...parts/extensions/electron-browser/extensionTipsService.ts
+36
-131
src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts
...ch/parts/extensions/electron-browser/extensionsActions.ts
+1
-1
src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts
.../parts/extensions/electron-browser/extensionsQuickOpen.ts
+10
-9
src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts
...tensions/electron-browser/extensionsWorkbenchExtension.ts
+1
-1
未找到文件。
src/vs/base/browser/ui/list/listView.ts
浏览文件 @
eb257f59
...
@@ -80,7 +80,7 @@ export class ListView<T> implements IScrollable, IDisposable {
...
@@ -80,7 +80,7 @@ export class ListView<T> implements IScrollable, IDisposable {
this
.
items
=
[];
this
.
items
=
[];
this
.
itemId
=
0
;
this
.
itemId
=
0
;
this
.
rangeMap
=
new
RangeMap
();
this
.
rangeMap
=
new
RangeMap
();
this
.
renderers
=
toObject
(
renderers
,
r
=>
r
.
templateId
);
this
.
renderers
=
toObject
<
IRenderer
<
T
,
any
>
,
IRenderer
<
T
,
any
>>
(
renderers
,
r
=>
r
.
templateId
);
this
.
cache
=
new
RowCache
(
this
.
renderers
);
this
.
cache
=
new
RowCache
(
this
.
renderers
);
this
.
renderTop
=
0
;
this
.
renderTop
=
0
;
...
...
src/vs/base/common/objects.ts
浏览文件 @
eb257f59
...
@@ -157,8 +157,8 @@ export function assign(destination: any, ...sources: any[]): any {
...
@@ -157,8 +157,8 @@ export function assign(destination: any, ...sources: any[]): any {
return
destination
;
return
destination
;
}
}
export
function
toObject
<
T
>
(
arr
:
T
[],
hash
:
(
T
)
=>
string
):
{
[
key
:
string
]:
T
}
{
export
function
toObject
<
T
,
R
>
(
arr
:
T
[],
keyMap
:
(
T
)
=>
string
,
valueMap
:
(
T
)
=>
R
=
x
=>
x
):
{
[
key
:
string
]:
R
}
{
return
arr
.
reduce
((
o
,
d
)
=>
assign
(
o
,
{
[
hash
(
d
)]:
d
}),
Object
.
create
(
null
));
return
arr
.
reduce
((
o
,
d
)
=>
assign
(
o
,
{
[
keyMap
(
d
)]:
valueMap
(
d
)
}),
Object
.
create
(
null
));
}
}
/**
/**
...
...
src/vs/workbench/parts/extensions/common/extensions.ts
浏览文件 @
eb257f59
...
@@ -66,6 +66,5 @@ export var IExtensionTipsService = createDecorator<IExtensionTipsService>('exten
...
@@ -66,6 +66,5 @@ export var IExtensionTipsService = createDecorator<IExtensionTipsService>('exten
export
interface
IExtensionTipsService
{
export
interface
IExtensionTipsService
{
serviceId
:
ServiceIdentifier
<
any
>
;
serviceId
:
ServiceIdentifier
<
any
>
;
tips
:
IExtension
[];
getRecommendations
():
TPromise
<
IExtension
[]
>
;
onDidChangeTips
:
Event
<
IExtension
[]
>
;
}
}
\ No newline at end of file
src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts
浏览文件 @
eb257f59
...
@@ -6,177 +6,82 @@
...
@@ -6,177 +6,82 @@
import
'
vs/text!vs/workbench/parts/extensions/electron-browser/extensionTips.json
'
;
import
'
vs/text!vs/workbench/parts/extensions/electron-browser/extensionTips.json
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
{
toObject
}
from
'
vs/base/common/objects
'
;
import
{
toObject
}
from
'
vs/base/common/objects
'
;
import
{
values
,
forEach
}
from
'
vs/base/common/collections
'
;
import
{
IDisposable
,
disposeAll
}
from
'
vs/base/common/lifecycle
'
;
import
{
IDisposable
,
disposeAll
}
from
'
vs/base/common/lifecycle
'
;
import
{
TPromise
as
Promise
}
from
'
vs/base/common/winjs.base
'
;
import
{
TPromise
as
Promise
}
from
'
vs/base/common/winjs.base
'
;
import
{
match
}
from
'
vs/base/common/glob
'
;
import
{
match
}
from
'
vs/base/common/glob
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
IGalleryService
,
IExtensionTipsService
,
IExtension
}
from
'
vs/workbench/parts/extensions/common/extensions
'
;
import
{
IExtensionsService
,
IGalleryService
,
IExtensionTipsService
,
IExtension
}
from
'
vs/workbench/parts/extensions/common/extensions
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
EventType
}
from
'
vs/editor/common/editorCommon
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
interface
ExtensionMap
{
interface
ExtensionRecommendations
{
[
id
:
string
]:
IExtension
;
}
interface
ExtensionData
{
[
id
:
string
]:
string
;
[
id
:
string
]:
string
;
}
}
enum
ExtensionTipReasons
{
// FileExists = 1
FileOpened
=
2
,
FileEdited
=
3
}
class
ExtensionTip
{
private
resources
:
{
[
uri
:
string
]:
ExtensionTipReasons
}
=
Object
.
create
(
null
);
private
touched
=
Date
.
now
();
private
_score
=
-
1
;
constructor
(
public
extension
:
IExtension
)
{
//
}
resource
(
uri
:
URI
,
reason
:
ExtensionTipReasons
):
boolean
{
if
(
reason
!==
this
.
resources
[
uri
.
toString
()])
{
this
.
touched
=
Date
.
now
();
this
.
resources
[
uri
.
toString
()]
=
Math
.
max
((
this
.
resources
[
uri
.
toString
()]
||
0
),
reason
);
this
.
_score
=
-
1
;
return
true
;
}
}
get
score
()
{
if
(
this
.
_score
===
-
1
)
{
forEach
(
this
.
resources
,
entry
=>
this
.
_score
+=
entry
.
value
);
}
return
this
.
_score
;
}
compareTo
(
tip
:
ExtensionTip
):
number
{
if
(
this
===
tip
)
{
return
0
;
}
let
result
=
tip
.
touched
-
this
.
touched
;
if
(
result
===
0
)
{
result
=
tip
.
score
-
this
.
score
;
}
return
result
;
}
}
export
class
ExtensionTipsService
implements
IExtensionTipsService
{
export
class
ExtensionTipsService
implements
IExtensionTipsService
{
serviceId
:
any
;
serviceId
:
any
;
private
recommendations
:
{
[
id
:
string
]:
boolean
;
};
private
_onDidChangeTips
:
Emitter
<
IExtension
[]
>
=
new
Emitter
<
IExtension
[]
>
();
private
_tips
:
{
[
id
:
string
]:
ExtensionTip
}
=
Object
.
create
(
null
);
private
disposables
:
IDisposable
[]
=
[];
private
disposables
:
IDisposable
[]
=
[];
private
availableExtensions
:
Promise
<
ExtensionMap
>
;
private
availableRecommendations
:
Promise
<
ExtensionRecommendations
>
;
private
extensionData
:
Promise
<
ExtensionData
>
;
constructor
(
constructor
(
@
IExtensionsService
private
extensionService
:
IExtensionsService
,
@
IGalleryService
private
galleryService
:
IGalleryService
,
@
IGalleryService
private
galleryService
:
IGalleryService
,
@
IModelService
private
modelService
:
IModelService
@
IModelService
private
modelService
:
IModelService
,
@
IStorageService
private
storageService
:
IStorageService
)
{
)
{
this
.
init
();
}
dispose
()
{
this
.
disposables
=
disposeAll
(
this
.
disposables
);
}
get
onDidChangeTips
():
Event
<
IExtension
[]
>
{
return
this
.
_onDidChangeTips
.
event
;
}
get
tips
():
IExtension
[]
{
let
tips
=
values
(
this
.
_tips
);
tips
.
sort
((
a
,
b
)
=>
a
.
compareTo
(
b
));
return
tips
.
map
(
tip
=>
tip
.
extension
);
}
// --- internals
private
init
():
void
{
if
(
!
this
.
galleryService
.
isEnabled
())
{
if
(
!
this
.
galleryService
.
isEnabled
())
{
return
;
return
;
}
}
this
.
extensionData
=
new
Promise
((
resolve
,
reject
)
=>
{
this
.
recommendations
=
toObject
(
JSON
.
parse
(
storageService
.
get
(
'
extensionsAssistant/recommendations
'
,
StorageScope
.
GLOBAL
,
'
[]
'
)),
id
=>
id
,
()
=>
true
);
this
.
availableRecommendations
=
new
Promise
((
resolve
,
reject
)
=>
{
require
([
'
vs/text!vs/workbench/parts/extensions/electron-browser/extensionTips.json
'
],
require
([
'
vs/text!vs/workbench/parts/extensions/electron-browser/extensionTips.json
'
],
data
=>
resolve
(
JSON
.
parse
(
data
)),
data
=>
resolve
(
JSON
.
parse
(
data
)),
reject
);
()
=>
({})
);
});
});
this
.
availableExtensions
=
this
.
getAvailableExtensions
();
// we listen for editor models being added and changed
// when a model is added it gives 2 points, a change gives 3 points
// such that files you type have bigger impact on the suggest
// order than those you only look at
const
modelListener
:
{
[
uri
:
string
]:
IDisposable
}
=
Object
.
create
(
null
);
this
.
disposables
.
push
({
dispose
()
{
disposeAll
(
values
(
modelListener
));
}
});
this
.
disposables
.
push
(
this
.
modelService
.
onModelAdded
(
model
=>
{
this
.
disposables
.
push
(
this
.
modelService
.
onModelAdded
(
model
=>
{
const
uri
=
model
.
getAssociatedResource
();
this
.
suggest
(
model
.
getAssociatedResource
());
this
.
suggestByResource
(
uri
,
ExtensionTipReasons
.
FileOpened
);
modelListener
[
uri
.
toString
()]
=
model
.
addListener2
(
EventType
.
ModelContentChanged2
,
()
=>
this
.
suggestByResource
(
uri
,
ExtensionTipReasons
.
FileEdited
));
}));
this
.
disposables
.
push
(
this
.
modelService
.
onModelRemoved
(
model
=>
{
const
subscription
=
modelListener
[
model
.
getAssociatedResource
().
toString
()];
if
(
subscription
)
{
subscription
.
dispose
();
delete
modelListener
[
model
.
getAssociatedResource
().
toString
()];
}
}));
}));
for
(
let
model
of
this
.
modelService
.
getModels
())
{
for
(
let
model
of
this
.
modelService
.
getModels
())
{
this
.
suggest
ByResource
(
model
.
getAssociatedResource
(),
ExtensionTipReasons
.
FileOpened
);
this
.
suggest
(
model
.
getAssociatedResource
()
);
}
}
}
}
private
getAvailableExtensions
():
Promise
<
ExtensionMap
>
{
getRecommendations
():
Promise
<
IExtension
[]
>
{
return
this
.
galleryService
.
query
()
return
this
.
galleryService
.
query
()
.
then
(
null
,
()
=>
[])
.
then
(
null
,
()
=>
[])
.
then
(
extensions
=>
toObject
(
extensions
,
ext
=>
`
${
ext
.
publisher
}
.
${
ext
.
name
}
`
));
.
then
(
available
=>
toObject
(
available
,
ext
=>
`
${
ext
.
publisher
}
.
${
ext
.
name
}
`
))
.
then
(
available
=>
{
return
Object
.
keys
(
this
.
recommendations
)
.
map
(
id
=>
available
[
id
])
.
filter
(
i
=>
!!
i
);
});
}
}
// --- suggest logic
private
suggest
(
uri
:
URI
):
Promise
<
any
>
{
private
suggestByResource
(
uri
:
URI
,
reason
:
ExtensionTipReasons
):
Promise
<
any
>
{
if
(
!
uri
)
{
if
(
!
uri
)
{
return
;
return
;
}
}
Promise
.
join
<
any
>
([
this
.
availableExtensions
,
this
.
extensionData
]).
then
(
all
=>
{
this
.
availableRecommendations
.
done
(
availableRecommendations
=>
{
let
extensions
=
<
ExtensionMap
>
all
[
0
];
const
ids
=
Object
.
keys
(
availableRecommendations
);
let
data
=
<
ExtensionData
>
all
[
1
];
const
recommendations
=
ids
.
filter
(
id
=>
match
(
availableRecommendations
[
id
],
uri
.
fsPath
));
let
change
=
false
;
recommendations
.
forEach
(
r
=>
this
.
recommendations
[
r
]
=
true
);
forEach
(
data
,
entry
=>
{
let
extension
=
extensions
[
entry
.
key
];
this
.
storageService
.
store
(
if
(
extension
&&
match
(
entry
.
value
,
uri
.
fsPath
))
{
'
extensionsAssistant/recommendations
'
,
let
value
=
this
.
_tips
[
entry
.
key
];
JSON
.
stringify
(
Object
.
keys
(
this
.
recommendations
)),
if
(
!
value
)
{
StorageScope
.
GLOBAL
value
=
this
.
_tips
[
entry
.
key
]
=
new
ExtensionTip
(
extension
);
);
}
if
(
value
.
resource
(
uri
,
reason
))
{
change
=
true
;
}
}
});
if
(
change
)
{
this
.
_onDidChangeTips
.
fire
(
this
.
tips
);
}
},
()
=>
{
// ignore
});
});
}
}
dispose
()
{
this
.
disposables
=
disposeAll
(
this
.
disposables
);
}
}
}
src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts
浏览文件 @
eb257f59
...
@@ -98,7 +98,7 @@ export class ListSuggestedExtensionsAction extends Action {
...
@@ -98,7 +98,7 @@ export class ListSuggestedExtensionsAction extends Action {
}
}
public
run
():
Promise
{
public
run
():
Promise
{
return
this
.
quickOpenService
.
show
(
'
ext
tips
'
);
return
this
.
quickOpenService
.
show
(
'
ext
recommend
'
);
}
}
protected
isEnabled
():
boolean
{
protected
isEnabled
():
boolean
{
...
...
src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts
浏览文件 @
eb257f59
...
@@ -579,14 +579,15 @@ class SuggestedExtensionsModel implements IModel<IExtensionEntry> {
...
@@ -579,14 +579,15 @@ class SuggestedExtensionsModel implements IModel<IExtensionEntry> {
highlights
,
highlights
,
state
:
ExtensionState
.
Uninstalled
state
:
ExtensionState
.
Uninstalled
};
};
});
})
.
sort
(
extensionEntryCompare
);
}
}
}
}
export
class
SuggestedExtensionHandler
extends
QuickOpenHandler
{
export
class
SuggestedExtensionHandler
extends
QuickOpenHandler
{
private
model
:
SuggestedExtensionsModel
;
private
model
Promise
:
TPromise
<
SuggestedExtensionsModel
>
;
constructor
(
constructor
(
@
IExtensionTipsService
private
extensionTipsService
:
IExtensionTipsService
,
@
IExtensionTipsService
private
extensionTipsService
:
IExtensionTipsService
,
...
@@ -598,20 +599,20 @@ export class SuggestedExtensionHandler extends QuickOpenHandler {
...
@@ -598,20 +599,20 @@ export class SuggestedExtensionHandler extends QuickOpenHandler {
}
}
getResults
(
input
:
string
):
TPromise
<
IModel
<
IExtensionEntry
>>
{
getResults
(
input
:
string
):
TPromise
<
IModel
<
IExtensionEntry
>>
{
return
this
.
extensionsService
.
getInstalled
().
then
(
localExtensions
=>
{
if
(
!
this
.
modelPromise
)
{
const
model
=
this
.
instantiationService
.
createInstance
(
this
.
telemetryService
.
publicLog
(
'
extensionRecommendations:open
'
);
SuggestedExtensionsModel
,
this
.
modelPromise
=
TPromise
.
join
<
any
>
([
this
.
extensionTipsService
.
getRecommendations
(),
this
.
extensionsService
.
getInstalled
()])
this
.
extensionTipsService
.
tips
,
.
then
(
result
=>
this
.
instantiationService
.
createInstance
(
SuggestedExtensionsModel
,
result
[
0
],
result
[
1
]));
localExtensions
}
);
return
this
.
modelPromise
.
then
(
model
=>
{
model
.
input
=
input
;
model
.
input
=
input
;
return
model
;
return
model
;
});
});
}
}
onClose
(
canceled
:
boolean
):
void
{
onClose
(
canceled
:
boolean
):
void
{
this
.
model
=
null
;
this
.
model
Promise
=
null
;
}
}
getEmptyLabel
(
input
:
string
):
string
{
getEmptyLabel
(
input
:
string
):
string
{
...
...
src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts
浏览文件 @
eb257f59
...
@@ -91,7 +91,7 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution {
...
@@ -91,7 +91,7 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution {
new
QuickOpenHandlerDescriptor
(
new
QuickOpenHandlerDescriptor
(
'
vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen
'
,
'
vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen
'
,
'
SuggestedExtensionHandler
'
,
'
SuggestedExtensionHandler
'
,
'
ext
tips
'
,
'
ext
recommend
'
,
nls
.
localize
(
'
suggestedExtensionsCommands
'
,
"
Show Extension Recommendations
"
)
nls
.
localize
(
'
suggestedExtensionsCommands
'
,
"
Show Extension Recommendations
"
)
)
)
);
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录