Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
43abcc20
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,发现更多精彩内容 >>
提交
43abcc20
编写于
6月 09, 2017
作者:
D
Dirk Baeumer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixes #28379: Run Task should be sorted using MRU list
上级
17773665
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
376 addition
and
29 deletion
+376
-29
src/vs/base/common/linkedMap.ts
src/vs/base/common/linkedMap.ts
+306
-0
src/vs/workbench/parts/tasks/browser/quickOpen.ts
src/vs/workbench/parts/tasks/browser/quickOpen.ts
+29
-27
src/vs/workbench/parts/tasks/common/taskService.ts
src/vs/workbench/parts/tasks/common/taskService.ts
+2
-0
src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts
...rkbench/parts/tasks/electron-browser/task.contribution.ts
+39
-2
未找到文件。
src/vs/base/common/linkedMap.ts
0 → 100644
浏览文件 @
43abcc20
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
interface
Item
<
K
,
V
>
{
previous
:
Item
<
K
,
V
>
|
undefined
;
next
:
Item
<
K
,
V
>
|
undefined
;
key
:
K
;
value
:
V
;
}
export
namespace
Touch
{
export
const
None
:
0
=
0
;
export
const
First
:
1
=
1
;
export
const
Last
:
2
=
2
;
}
export
type
Touch
=
0
|
1
|
2
;
export
class
LinkedMap
<
K
,
V
>
{
private
_map
:
Map
<
K
,
Item
<
K
,
V
>>
;
private
_head
:
Item
<
K
,
V
>
|
undefined
;
private
_tail
:
Item
<
K
,
V
>
|
undefined
;
private
_size
:
number
;
constructor
()
{
this
.
_map
=
new
Map
<
K
,
Item
<
K
,
V
>>
();
this
.
_head
=
undefined
;
this
.
_tail
=
undefined
;
this
.
_size
=
0
;
}
public
clear
():
void
{
this
.
_map
.
clear
();
this
.
_head
=
undefined
;
this
.
_tail
=
undefined
;
this
.
_size
=
0
;
}
public
isEmpty
():
boolean
{
return
!
this
.
_head
&&
!
this
.
_tail
;
}
public
get
size
():
number
{
return
this
.
_size
;
}
public
has
(
key
:
K
):
boolean
{
return
this
.
_map
.
has
(
key
);
}
public
get
(
key
:
K
):
V
|
undefined
{
const
item
=
this
.
_map
.
get
(
key
);
if
(
!
item
)
{
return
undefined
;
}
return
item
.
value
;
}
public
set
(
key
:
K
,
value
:
V
,
touch
:
Touch
=
Touch
.
None
):
void
{
let
item
=
this
.
_map
.
get
(
key
);
if
(
item
)
{
item
.
value
=
value
;
if
(
touch
!==
Touch
.
None
)
{
this
.
touch
(
item
,
touch
);
}
}
else
{
item
=
{
key
,
value
,
next
:
undefined
,
previous
:
undefined
};
switch
(
touch
)
{
case
Touch
.
None
:
this
.
addItemLast
(
item
);
break
;
case
Touch
.
First
:
this
.
addItemFirst
(
item
);
break
;
case
Touch
.
Last
:
this
.
addItemLast
(
item
);
break
;
default
:
this
.
addItemLast
(
item
);
break
;
}
this
.
_map
.
set
(
key
,
item
);
this
.
_size
++
;
}
}
public
delete
(
key
:
K
):
boolean
{
const
item
=
this
.
_map
.
get
(
key
);
if
(
!
item
)
{
return
false
;
}
this
.
_map
.
delete
(
key
);
this
.
removeItem
(
item
);
this
.
_size
--
;
return
true
;
}
public
shift
():
V
|
undefined
{
if
(
!
this
.
_head
&&
!
this
.
_tail
)
{
return
undefined
;
}
if
(
!
this
.
_head
||
!
this
.
_tail
)
{
throw
new
Error
(
'
Invalid list
'
);
}
const
item
=
this
.
_head
;
this
.
_map
.
delete
(
item
.
key
);
this
.
removeItem
(
item
);
this
.
_size
--
;
return
item
.
value
;
}
public
forEach
(
callbackfn
:
(
value
:
V
,
key
:
K
,
map
:
LinkedMap
<
K
,
V
>
)
=>
void
,
thisArg
?:
any
):
void
{
let
current
=
this
.
_head
;
while
(
current
)
{
if
(
thisArg
)
{
callbackfn
.
bind
(
thisArg
)(
current
.
value
,
current
.
key
,
this
);
}
else
{
callbackfn
(
current
.
value
,
current
.
key
,
this
);
}
current
=
current
.
next
;
}
}
public
forEachReverse
(
callbackfn
:
(
value
:
V
,
key
:
K
,
map
:
LinkedMap
<
K
,
V
>
)
=>
void
,
thisArg
?:
any
):
void
{
let
current
=
this
.
_tail
;
while
(
current
)
{
if
(
thisArg
)
{
callbackfn
.
bind
(
thisArg
)(
current
.
value
,
current
.
key
,
this
);
}
else
{
callbackfn
(
current
.
value
,
current
.
key
,
this
);
}
current
=
current
.
previous
;
}
}
public
values
():
V
[]
{
let
result
:
V
[]
=
[];
let
current
=
this
.
_head
;
while
(
current
)
{
result
.
push
(
current
.
value
);
current
=
current
.
next
;
}
return
result
;
}
public
keys
():
K
[]
{
let
result
:
K
[]
=
[];
let
current
=
this
.
_head
;
while
(
current
)
{
result
.
push
(
current
.
key
);
current
=
current
.
next
;
}
return
result
;
}
/* VS Code / Monaco editor runs on es5 which has no Symbol.iterator
public keys(): IterableIterator<K> {
let current = this._head;
let iterator: IterableIterator<K> = {
[Symbol.iterator]() {
return iterator;
},
next():IteratorResult<K> {
if (current) {
let result = { value: current.key, done: false };
current = current.next;
return result;
} else {
return { value: undefined, done: true };
}
}
};
return iterator;
}
public values(): IterableIterator<V> {
let current = this._head;
let iterator: IterableIterator<V> = {
[Symbol.iterator]() {
return iterator;
},
next():IteratorResult<V> {
if (current) {
let result = { value: current.value, done: false };
current = current.next;
return result;
} else {
return { value: undefined, done: true };
}
}
};
return iterator;
}
*/
private
addItemFirst
(
item
:
Item
<
K
,
V
>
):
void
{
// First time Insert
if
(
!
this
.
_head
&&
!
this
.
_tail
)
{
this
.
_tail
=
item
;
}
else
if
(
!
this
.
_head
)
{
throw
new
Error
(
'
Invalid list
'
);
}
else
{
item
.
next
=
this
.
_head
;
this
.
_head
.
previous
=
item
;
}
this
.
_head
=
item
;
}
private
addItemLast
(
item
:
Item
<
K
,
V
>
):
void
{
// First time Insert
if
(
!
this
.
_head
&&
!
this
.
_tail
)
{
this
.
_head
=
item
;
}
else
if
(
!
this
.
_tail
)
{
throw
new
Error
(
'
Invalid list
'
);
}
else
{
item
.
previous
=
this
.
_tail
;
this
.
_tail
.
next
=
item
;
}
this
.
_tail
=
item
;
}
private
removeItem
(
item
:
Item
<
K
,
V
>
):
void
{
if
(
item
===
this
.
_head
&&
item
===
this
.
_tail
)
{
this
.
_head
=
undefined
;
this
.
_tail
=
undefined
;
}
else
if
(
item
===
this
.
_head
)
{
this
.
_head
=
item
.
next
;
}
else
if
(
item
===
this
.
_tail
)
{
this
.
_tail
=
item
.
previous
;
}
else
{
const
next
=
item
.
next
;
const
previous
=
item
.
previous
;
if
(
!
next
||
!
previous
)
{
throw
new
Error
(
'
Invalid list
'
);
}
next
.
previous
=
previous
;
previous
.
next
=
next
;
}
}
private
touch
(
item
:
Item
<
K
,
V
>
,
touch
:
Touch
):
void
{
if
(
!
this
.
_head
||
!
this
.
_tail
)
{
throw
new
Error
(
'
Invalid list
'
);
}
if
((
touch
!==
Touch
.
First
&&
touch
!==
Touch
.
Last
))
{
return
;
}
if
(
touch
===
Touch
.
First
)
{
if
(
item
===
this
.
_head
)
{
return
;
}
const
next
=
item
.
next
;
const
previous
=
item
.
previous
;
// Unlink the item
if
(
item
===
this
.
_tail
)
{
// previous must be defined since item was not head but is tail
// So there are more than on item in the map
previous
!
.
next
=
undefined
;
this
.
_tail
=
previous
;
}
else
{
// Both next and previous are not undefined since item was neither head nor tail.
next
!
.
previous
=
previous
;
previous
!
.
next
=
next
;
}
// Insert the node at head
item
.
previous
=
undefined
;
item
.
next
=
this
.
_head
;
this
.
_head
.
previous
=
item
;
this
.
_head
=
item
;
}
else
if
(
touch
===
Touch
.
Last
)
{
if
(
item
===
this
.
_tail
)
{
return
;
}
const
next
=
item
.
next
;
const
previous
=
item
.
previous
;
// Unlink the item.
if
(
item
===
this
.
_head
)
{
// next must be defined since item was not tail but is head
// So there are more than on item in the map
next
!
.
previous
=
undefined
;
this
.
_head
=
next
;
}
else
{
// Both next and previous are not undefined since item was neither head nor tail.
next
!
.
previous
=
previous
;
previous
!
.
next
=
next
;
}
item
.
next
=
undefined
;
item
.
previous
=
this
.
_tail
;
this
.
_tail
.
next
=
item
;
this
.
_tail
=
item
;
}
}
}
\ No newline at end of file
src/vs/workbench/parts/tasks/browser/quickOpen.ts
浏览文件 @
43abcc20
...
...
@@ -8,6 +8,8 @@ import nls = require('vs/nls');
import
Filters
=
require
(
'
vs/base/common/filters
'
);
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
Action
,
IAction
}
from
'
vs/base/common/actions
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
Quickopen
=
require
(
'
vs/workbench/browser/quickopen
'
);
import
QuickOpen
=
require
(
'
vs/base/parts/quickopen/common/quickOpen
'
);
import
Model
=
require
(
'
vs/base/parts/quickopen/browser/quickOpenModel
'
);
...
...
@@ -49,7 +51,7 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler {
constructor
(
protected
quickOpenService
:
IQuickOpenService
,
protected
taskService
:
ITaskService
,
protected
taskService
:
ITaskService
)
{
super
();
...
...
@@ -71,39 +73,39 @@ export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler {
if
(
tasks
.
length
===
0
)
{
return
new
Model
.
QuickOpenModel
(
entries
);
}
tasks
=
tasks
.
sort
((
a
,
b
)
=>
{
let
aKind
=
a
.
_source
.
kind
;
let
bKind
=
b
.
_source
.
kind
;
if
(
aKind
===
bKind
)
{
if
(
aKind
===
TaskSourceKind
.
Extension
)
{
let
compare
=
a
.
_source
.
label
.
localeCompare
(
b
.
_source
.
label
);
if
(
compare
!==
0
)
{
return
compare
;
}
}
return
a
.
_label
.
localeCompare
(
b
.
_label
);
}
if
(
aKind
===
TaskSourceKind
.
Workspace
)
{
return
-
1
;
}
else
{
return
+
1
;
let
recentlyUsedTasks
=
this
.
taskService
.
getRecentlyUsedTasks
();
let
recent
:
Task
[]
=
[];
let
others
:
Task
[]
=
[];
let
taskMap
:
IStringDictionary
<
Task
>
=
Object
.
create
(
null
);
tasks
.
forEach
(
task
=>
taskMap
[
task
.
identifier
]
=
task
);
recentlyUsedTasks
.
keys
().
forEach
(
key
=>
{
let
task
=
taskMap
[
key
];
if
(
task
)
{
recent
.
push
(
task
);
}
});
let
firstWorkspace
:
boolean
=
true
;
let
firstExtension
:
boolean
=
true
;
let
hadWorkspace
:
boolean
=
false
;
for
(
let
task
of
tasks
)
{
if
(
!
recentlyUsedTasks
.
has
(
task
.
identifier
))
{
others
.
push
(
task
);
}
}
others
=
others
.
sort
((
a
,
b
)
=>
a
.
_source
.
label
.
localeCompare
(
b
.
_source
.
label
));
let
sortedTasks
=
recent
.
concat
(
others
);
let
recentlyUsed
:
boolean
=
recentlyUsedTasks
.
has
(
tasks
[
0
].
identifier
);
let
otherTasks
:
boolean
=
!
recentlyUsedTasks
.
has
(
tasks
[
tasks
.
length
-
1
].
identifier
);
let
hasRecentlyUsed
:
boolean
=
false
;
for
(
let
task
of
sortedTasks
)
{
let
highlights
=
Filters
.
matchesContiguousSubString
(
input
,
task
.
_label
);
if
(
!
highlights
)
{
continue
;
}
if
(
task
.
_source
.
kind
===
TaskSourceKind
.
Workspace
&&
firstWorkspace
)
{
firstWorkspace
=
false
;
ha
dWorkspace
=
true
;
entries
.
push
(
new
TaskGroupEntry
(
this
.
createEntry
(
this
.
taskService
,
task
,
highlights
),
nls
.
localize
(
'
configured
'
,
'
Configured Tasks
'
),
false
));
}
else
if
(
task
.
_source
.
kind
===
TaskSourceKind
.
Extension
&&
firstExtension
)
{
firstExtension
=
false
;
entries
.
push
(
new
TaskGroupEntry
(
this
.
createEntry
(
this
.
taskService
,
task
,
highlights
),
nls
.
localize
(
'
detected
'
,
'
Detected Tasks
'
),
hadWorkspace
));
if
(
recentlyUsed
)
{
recentlyUsed
=
false
;
ha
sRecentlyUsed
=
true
;
entries
.
push
(
new
TaskGroupEntry
(
this
.
createEntry
(
this
.
taskService
,
task
,
highlights
),
nls
.
localize
(
'
recentlyUsed
'
,
'
recently used
'
),
false
));
}
else
if
(
!
recentlyUsedTasks
.
has
(
task
.
identifier
)
&&
otherTasks
)
{
otherTasks
=
false
;
entries
.
push
(
new
TaskGroupEntry
(
this
.
createEntry
(
this
.
taskService
,
task
,
highlights
),
nls
.
localize
(
'
other tasks
'
,
'
other tasks
'
),
hasRecentlyUsed
));
}
else
{
entries
.
push
(
this
.
createEntry
(
this
.
taskService
,
task
,
highlights
));
}
...
...
src/vs/workbench/parts/tasks/common/taskService.ts
浏览文件 @
43abcc20
...
...
@@ -8,6 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import
{
Action
}
from
'
vs/base/common/actions
'
;
import
{
IEventEmitter
}
from
'
vs/base/common/eventEmitter
'
;
import
{
TerminateResponse
}
from
'
vs/base/common/processes
'
;
import
{
LinkedMap
}
from
'
vs/base/common/linkedMap
'
;
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
Task
,
TaskSet
}
from
'
vs/workbench/parts/tasks/common/tasks
'
;
import
{
ITaskSummary
,
TaskEvent
,
TaskType
}
from
'
vs/workbench/parts/tasks/common/taskSystem
'
;
...
...
@@ -43,6 +44,7 @@ export interface ITaskService extends IEventEmitter {
terminateAll
():
TPromise
<
TerminateResponse
>
;
tasks
():
TPromise
<
Task
[]
>
;
getTasksForGroup
(
group
:
string
):
TPromise
<
Task
[]
>
;
getRecentlyUsedTasks
():
LinkedMap
<
string
,
string
>
;
customize
(
task
:
Task
,
openConfig
?:
boolean
):
TPromise
<
void
>
;
...
...
src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts
浏览文件 @
43abcc20
...
...
@@ -29,6 +29,7 @@ import { TerminateResponse, TerminateResponseCode } from 'vs/base/common/process
import
*
as
strings
from
'
vs/base/common/strings
'
;
import
{
ValidationStatus
,
ValidationState
}
from
'
vs/base/common/parsers
'
;
import
*
as
UUID
from
'
vs/base/common/uuid
'
;
import
{
LinkedMap
,
Touch
}
from
'
vs/base/common/linkedMap
'
;
import
{
Registry
}
from
'
vs/platform/platform
'
;
import
{
ILifecycleService
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
...
...
@@ -45,7 +46,7 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import
{
KeybindingsRegistry
}
from
'
vs/platform/keybinding/common/keybindingsRegistry
'
;
import
{
ServicesAccessor
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
ProblemMatcherRegistry
}
from
'
vs/platform/markers/common/problemMatcher
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
IModeService
}
from
'
vs/editor/common/services/modeService
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
...
...
@@ -516,6 +517,7 @@ interface WorkspaceConfigurationResult {
class
TaskService
extends
EventEmitter
implements
ITaskService
{
// private static autoDetectTelemetryName: string = 'taskServer.autoDetect';
private
static
RecentlyUsedTasks_Key
=
'
workbench.tasks.recentlyUsedTasks
'
;
public
_serviceBrand
:
any
;
public
static
SERVICE_ID
:
string
=
'
taskService
'
;
...
...
@@ -544,6 +546,7 @@ class TaskService extends EventEmitter implements ITaskService {
private
_taskSystem
:
ITaskSystem
;
private
_taskSystemListeners
:
IDisposable
[];
private
_recentlyUsedTasks
:
LinkedMap
<
string
,
string
>
;
private
_outputChannel
:
IOutputChannel
;
...
...
@@ -559,7 +562,8 @@ class TaskService extends EventEmitter implements ITaskService {
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
IConfigurationResolverService
private
configurationResolverService
:
IConfigurationResolverService
,
@
ITerminalService
private
terminalService
:
ITerminalService
,
@
IWorkbenchEditorService
private
workbenchEditorService
:
IWorkbenchEditorService
@
IWorkbenchEditorService
private
workbenchEditorService
:
IWorkbenchEditorService
,
@
IStorageService
private
storageService
:
IStorageService
)
{
super
();
...
...
@@ -689,6 +693,37 @@ class TaskService extends EventEmitter implements ITaskService {
return
TPromise
.
as
(
this
.
_taskSystem
.
getActiveTasks
());
}
public
getRecentlyUsedTasks
():
LinkedMap
<
string
,
string
>
{
if
(
this
.
_recentlyUsedTasks
)
{
return
this
.
_recentlyUsedTasks
;
}
this
.
_recentlyUsedTasks
=
new
LinkedMap
<
string
,
string
>
();
let
storageValue
=
this
.
storageService
.
get
(
TaskService
.
RecentlyUsedTasks_Key
,
StorageScope
.
WORKSPACE
);
if
(
storageValue
)
{
try
{
let
values
:
string
[]
=
JSON
.
parse
(
storageValue
);
if
(
Array
.
isArray
(
values
))
{
for
(
let
value
of
values
)
{
this
.
_recentlyUsedTasks
.
set
(
value
,
value
);
}
}
}
catch
(
error
)
{
// Ignore. We use the empty result
}
}
return
this
.
_recentlyUsedTasks
;
}
private
saveRecentlyUsedTasks
():
void
{
if
(
!
this
.
_recentlyUsedTasks
)
{
return
;
}
let
values
=
this
.
_recentlyUsedTasks
.
values
();
if
(
values
.
length
>
30
)
{
values
=
values
.
slice
(
0
,
30
);
}
this
.
storageService
.
store
(
TaskService
.
RecentlyUsedTasks_Key
,
JSON
.
stringify
(
values
),
StorageScope
.
WORKSPACE
);
}
public
build
():
TPromise
<
ITaskSummary
>
{
return
this
.
getTaskSets
().
then
((
values
)
=>
{
...
...
@@ -896,6 +931,7 @@ class TaskService extends EventEmitter implements ITaskService {
throw
new
TaskError
(
Severity
.
Warning
,
nls
.
localize
(
'
TaskSystem.active
'
,
'
There is already a task running. Terminate it first before executing another task.
'
),
TaskErrors
.
RunningTask
);
}
}
this
.
getRecentlyUsedTasks
().
set
(
task
.
identifier
,
task
.
identifier
,
Touch
.
First
);
return
executeResult
.
promise
;
});
});
...
...
@@ -1248,6 +1284,7 @@ class TaskService extends EventEmitter implements ITaskService {
}
public
beforeShutdown
():
boolean
|
TPromise
<
boolean
>
{
this
.
saveRecentlyUsedTasks
();
if
(
this
.
_taskSystem
&&
this
.
_taskSystem
.
isActiveSync
())
{
if
(
this
.
_taskSystem
.
canAutoTerminate
()
||
this
.
messageService
.
confirm
({
message
:
nls
.
localize
(
'
TaskSystem.runningTask
'
,
'
There is a task running. Do you want to terminate it?
'
),
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录