Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
abe27026
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
abe27026
编写于
5月 19, 2016
作者:
B
Benjamin Pasero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dispose inputs when closing them
上级
1d451bc0
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
255 addition
and
108 deletion
+255
-108
src/vs/workbench/browser/parts/editor/editorActions.ts
src/vs/workbench/browser/parts/editor/editorActions.ts
+2
-2
src/vs/workbench/browser/parts/editor/editorPart.ts
src/vs/workbench/browser/parts/editor/editorPart.ts
+52
-66
src/vs/workbench/common/editor.ts
src/vs/workbench/common/editor.ts
+15
-13
src/vs/workbench/common/editor/diffEditorInput.ts
src/vs/workbench/common/editor/diffEditorInput.ts
+0
-4
src/vs/workbench/common/editor/editorStacksModel.ts
src/vs/workbench/common/editor/editorStacksModel.ts
+65
-19
src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts
.../workbench/parts/files/browser/editors/fileEditorInput.ts
+9
-0
src/vs/workbench/test/common/editor/editorInput.test.ts
src/vs/workbench/test/common/editor/editorInput.test.ts
+1
-1
src/vs/workbench/test/common/editor/editorStacksModel.test.ts
...vs/workbench/test/common/editor/editorStacksModel.test.ts
+111
-3
未找到文件。
src/vs/workbench/browser/parts/editor/editorActions.ts
浏览文件 @
abe27026
...
...
@@ -422,7 +422,7 @@ export class CloseEditorAction extends Action {
// Get Top Editor at Position
let
visibleEditors
=
this
.
editorService
.
getVisibleEditors
();
if
(
visibleEditors
[
position
])
{
input
=
visibleEditors
[
position
].
input
;
input
=
<
EditorInput
>
visibleEditors
[
position
].
input
;
}
}
...
...
@@ -555,7 +555,7 @@ export class CloseOtherEditorsInGroupAction extends Action {
const
active
=
this
.
editorService
.
getActiveEditor
();
if
(
active
)
{
position
=
typeof
position
===
'
number
'
?
position
:
active
.
position
;
input
=
input
?
input
:
active
.
input
;
input
=
input
?
input
:
<
EditorInput
>
active
.
input
;
}
if
(
typeof
position
===
'
number
'
&&
input
)
{
...
...
src/vs/workbench/browser/parts/editor/editorPart.ts
浏览文件 @
abe27026
...
...
@@ -38,7 +38,7 @@ import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollect
import
{
IMessageService
,
IMessageWithAction
,
Severity
}
from
'
vs/platform/message/common/message
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
IProgressService
}
from
'
vs/platform/progress/common/progress
'
;
import
{
EditorStacksModel
,
EditorGroup
}
from
'
vs/workbench/common/editor/editorStacksModel
'
;
import
{
EditorStacksModel
,
EditorGroup
,
IEditorIdentifier
}
from
'
vs/workbench/common/editor/editorStacksModel
'
;
class
ProgressMonitor
{
...
...
@@ -72,11 +72,10 @@ export class EditorPart extends Part implements IEditorPart {
private
dimension
:
Dimension
;
private
sideBySideControl
:
ISideBySideEditorControl
;
private
memento
:
any
;
private
stacks
Model
:
EditorStacksModel
;
private
stacks
:
EditorStacksModel
;
// The following data structures are partitioned into array of Position as provided by Services.POSITION array
private
visibleInputs
:
EditorInput
[];
private
visibleInputListeners
:
Function
[];
private
visibleEditors
:
BaseEditor
[];
private
visibleEditorListeners
:
Function
[][];
private
instantiatedEditors
:
BaseEditor
[][];
...
...
@@ -85,7 +84,7 @@ export class EditorPart extends Part implements IEditorPart {
private
mapEditorCreationPromiseToEditor
:
{
[
editorId
:
string
]:
TPromise
<
BaseEditor
>
;
}[];
private
editorOpenToken
:
number
[];
private
editorSetInputErrorCounter
:
number
[];
private
pendingEditorInputsToClose
:
{
input
:
EditorInput
;
position
:
Position
}
[];
private
pendingEditorInputsToClose
:
IEditorIdentifier
[];
private
pendingEditorInputCloseTimeout
:
number
;
constructor
(
...
...
@@ -100,7 +99,6 @@ export class EditorPart extends Part implements IEditorPart {
super
(
id
);
this
.
visibleInputs
=
[];
this
.
visibleInputListeners
=
[];
this
.
visibleEditors
=
[];
this
.
editorOpenToken
=
arrays
.
fill
(
POSITIONS
.
length
,
()
=>
0
);
...
...
@@ -116,13 +114,16 @@ export class EditorPart extends Part implements IEditorPart {
this
.
pendingEditorInputsToClose
=
[];
this
.
pendingEditorInputCloseTimeout
=
null
;
this
.
stacks
Model
=
this
.
instantiationService
.
createInstance
(
EditorStacksModel
);
this
.
stacks
=
this
.
instantiationService
.
createInstance
(
EditorStacksModel
);
this
.
registerListeners
();
}
private
registerListeners
():
void
{
this
.
toUnbind
.
push
(
this
.
eventService
.
addListener
(
WorkbenchEventType
.
EDITOR_INPUT_STATE_CHANGED
,
(
event
:
EditorInputEvent
)
=>
this
.
onEditorInputStateChanged
(
event
)));
const
unbind
=
this
.
stacks
.
onEditorDisposed
(
editor
=>
this
.
onEditorDisposed
(
editor
));
this
.
toUnbind
.
push
(()
=>
unbind
.
dispose
());
}
private
onEditorInputStateChanged
(
event
:
EditorInputEvent
):
void
{
...
...
@@ -131,6 +132,11 @@ export class EditorPart extends Part implements IEditorPart {
}
}
private
onEditorDisposed
(
identifier
:
IEditorIdentifier
):
void
{
this
.
pendingEditorInputsToClose
.
push
(
identifier
);
this
.
startDelayedCloseEditorsFromInputDispose
();
}
public
openEditor
(
input
:
EditorInput
,
options
?:
EditorOptions
,
sideBySide
?:
boolean
):
TPromise
<
BaseEditor
>
;
public
openEditor
(
input
:
EditorInput
,
options
?:
EditorOptions
,
position
?:
Position
,
widthRatios
?:
number
[]):
TPromise
<
BaseEditor
>
;
public
openEditor
(
input
:
EditorInput
,
options
?:
EditorOptions
,
arg3
?:
any
,
widthRatios
?:
number
[]):
TPromise
<
BaseEditor
>
{
...
...
@@ -162,12 +168,6 @@ export class EditorPart extends Part implements IEditorPart {
// Remember as visible input for this position
this
.
visibleInputs
[
position
]
=
input
;
// Dispose previous input listener if any
if
(
this
.
visibleInputListeners
[
position
])
{
this
.
visibleInputListeners
[
position
]();
this
.
visibleInputListeners
[
position
]
=
null
;
}
// Open: input is provided
return
this
.
doOpenEditor
(
input
,
options
,
position
,
widthRatios
);
}
...
...
@@ -190,18 +190,6 @@ export class EditorPart extends Part implements IEditorPart {
options
=
this
.
findSideOptions
(
input
,
options
,
position
);
}
// Close editor when input provided and input gets disposed
this
.
visibleInputListeners
[
position
]
=
input
.
addListener
(
EventType
.
DISPOSE
,
()
=>
{
// Keep the inputs to close. We use this to support multiple inputs closing
// right after each other and this helps avoid layout issues with the delayed
// timeout based closing below
if
(
input
===
this
.
visibleInputs
[
position
])
{
this
.
pendingEditorInputsToClose
.
push
({
input
,
position
});
this
.
startDelayedCloseEditorsFromInputDispose
();
}
});
// Progress Monitor & Ref Counting
this
.
editorOpenToken
[
position
]
++
;
const
editorOpenToken
=
this
.
editorOpenToken
[
position
];
...
...
@@ -523,12 +511,6 @@ export class EditorPart extends Part implements IEditorPart {
// Update visible inputs for position
this
.
visibleInputs
[
position
]
=
null
;
// Dispose previous input listener if any
if
(
this
.
visibleInputListeners
[
position
])
{
this
.
visibleInputListeners
[
position
]();
this
.
visibleInputListeners
[
position
]
=
null
;
}
// Reset counter
this
.
editorSetInputErrorCounter
[
position
]
=
0
;
...
...
@@ -564,7 +546,7 @@ export class EditorPart extends Part implements IEditorPart {
// Update stacks model
const
group
=
this
.
groupAt
(
position
);
this
.
modifyGroups
(()
=>
this
.
stacks
Model
.
closeGroup
(
group
));
this
.
modifyGroups
(()
=>
this
.
stacks
.
closeGroup
(
group
));
// Emit Input-Changed Event
this
.
emit
(
WorkbenchEventType
.
EDITOR_INPUT_CHANGED
,
new
EditorEvent
(
null
,
null
,
null
,
null
,
position
));
...
...
@@ -712,7 +694,7 @@ export class EditorPart extends Part implements IEditorPart {
}
public
getStacksModel
():
EditorStacksModel
{
return
this
.
stacks
Model
;
return
this
.
stacks
;
}
public
getActiveEditorInput
():
EditorInput
{
...
...
@@ -743,14 +725,13 @@ export class EditorPart extends Part implements IEditorPart {
}
// Update stacks model
this
.
modifyGroups
(()
=>
this
.
stacks
Model
.
moveGroup
(
this
.
groupAt
(
from
),
to
));
this
.
modifyGroups
(()
=>
this
.
stacks
.
moveGroup
(
this
.
groupAt
(
from
),
to
));
// Move widgets
this
.
sideBySideControl
.
move
(
from
,
to
);
// Move data structures
arrays
.
move
(
this
.
visibleInputs
,
from
,
to
);
arrays
.
move
(
this
.
visibleInputListeners
,
from
,
to
);
arrays
.
move
(
this
.
visibleEditors
,
from
,
to
);
arrays
.
move
(
this
.
visibleEditorListeners
,
from
,
to
);
arrays
.
move
(
this
.
editorOpenToken
,
from
,
to
);
...
...
@@ -843,7 +824,7 @@ export class EditorPart extends Part implements IEditorPart {
// Update stacks model
let
activePosition
=
this
.
sideBySideControl
.
getActivePosition
();
if
(
typeof
activePosition
===
'
number
'
)
{
this
.
stacks
Model
.
setActive
(
this
.
groupAt
(
activePosition
));
this
.
stacks
.
setActive
(
this
.
groupAt
(
activePosition
));
}
// Emit as editor input change event so that clients get aware of new active editor
...
...
@@ -873,7 +854,7 @@ export class EditorPart extends Part implements IEditorPart {
}
public
restoreEditors
():
TPromise
<
BaseEditor
[]
>
{
const
editors
=
this
.
stacks
Model
.
groups
.
map
((
group
,
index
)
=>
{
const
editors
=
this
.
stacks
.
groups
.
map
((
group
,
index
)
=>
{
return
{
input
:
group
.
activeEditor
,
position
:
index
...
...
@@ -888,8 +869,8 @@ export class EditorPart extends Part implements IEditorPart {
let
widthRatios
=
editorState
.
widthRatio
;
let
activePosition
:
Position
;
if
(
this
.
stacks
Model
.
groups
.
length
)
{
activePosition
=
this
.
stacks
Model
.
positionOfGroup
(
this
.
stacksModel
.
activeGroup
);
if
(
this
.
stacks
.
groups
.
length
)
{
activePosition
=
this
.
stacks
.
positionOfGroup
(
this
.
stacks
.
activeGroup
);
}
return
this
.
doOpenEditors
(
editors
,
activePosition
,
widthRatios
);
...
...
@@ -960,7 +941,7 @@ export class EditorPart extends Part implements IEditorPart {
}
public
groupAt
(
position
:
Position
):
EditorGroup
{
return
this
.
stacks
Model
.
groups
[
position
];
return
this
.
stacks
.
groups
[
position
];
}
public
activateGroup
(
position
:
Position
):
void
{
...
...
@@ -968,7 +949,7 @@ export class EditorPart extends Part implements IEditorPart {
if
(
editor
)
{
// Update stacks model
this
.
stacks
Model
.
setActive
(
this
.
groupAt
(
position
));
this
.
stacks
.
setActive
(
this
.
groupAt
(
position
));
// Update UI
this
.
sideBySideControl
.
setActive
(
editor
);
...
...
@@ -1105,16 +1086,6 @@ export class EditorPart extends Part implements IEditorPart {
}
}
// Input listeners
for
(
let
i
=
0
;
i
<
this
.
visibleInputListeners
.
length
;
i
++
)
{
let
listener
=
this
.
visibleInputListeners
[
i
];
if
(
listener
)
{
listener
();
}
this
.
visibleInputListeners
=
[];
}
// Pass to active editors
this
.
visibleEditors
.
forEach
((
editor
)
=>
{
if
(
editor
)
{
...
...
@@ -1245,11 +1216,27 @@ export class EditorPart extends Part implements IEditorPart {
if
(
this
.
pendingEditorInputCloseTimeout
===
null
)
{
this
.
pendingEditorInputCloseTimeout
=
setTimeout
(()
=>
{
// Close all
TPromise
.
join
(
this
.
pendingEditorInputsToClose
.
sort
((
c1
,
c2
)
=>
c2
.
position
-
c1
.
position
)
// reduce layout work by starting right first
.
map
(
c
=>
this
.
closeEditor
(
c
.
position
,
c
.
input
)))
// close input at position
.
done
(
null
,
errors
.
onUnexpectedError
);
// Split between active and inactive editors
const
activeEditors
:
IEditorIdentifier
[]
=
[];
const
inactiveEditors
:
IEditorIdentifier
[]
=
[];
this
.
pendingEditorInputsToClose
.
forEach
(
identifier
=>
{
if
(
identifier
.
group
.
isActive
(
identifier
.
editor
))
{
activeEditors
.
push
(
identifier
);
}
else
{
inactiveEditors
.
push
(
identifier
);
}
});
// Close all inactive first
TPromise
.
join
(
inactiveEditors
.
map
(
inactive
=>
this
.
closeEditor
(
this
.
stacks
.
positionOfGroup
(
inactive
.
group
),
inactive
.
editor
))).
done
(()
=>
{
// Close active ones second
TPromise
.
join
(
activeEditors
.
sort
((
a1
,
a2
)
=>
this
.
stacks
.
positionOfGroup
(
a2
.
group
)
-
this
.
stacks
.
positionOfGroup
(
a1
.
group
))
// reduce layout work by starting right first
.
map
(
active
=>
this
.
closeEditor
(
this
.
stacks
.
positionOfGroup
(
active
.
group
),
active
.
editor
))
).
done
(
null
,
errors
.
onUnexpectedError
);
},
errors
.
onUnexpectedError
);
// Reset
this
.
pendingEditorInputCloseTimeout
=
null
;
...
...
@@ -1279,7 +1266,6 @@ export class EditorPart extends Part implements IEditorPart {
let
to
=
<
Position
>
arg2
;
this
.
doRochade
(
this
.
visibleInputs
,
from
,
to
,
null
);
this
.
doRochade
(
this
.
visibleInputListeners
,
from
,
to
,
null
);
this
.
doRochade
(
this
.
visibleEditors
,
from
,
to
,
null
);
this
.
doRochade
(
this
.
editorOpenToken
,
from
,
to
,
null
);
this
.
doRochade
(
this
.
mapEditorInstantiationPromiseToEditor
,
from
,
to
,
Object
.
create
(
null
));
...
...
@@ -1306,18 +1292,18 @@ export class EditorPart extends Part implements IEditorPart {
this
.
modifyGroups
(()
=>
{
for
(
let
i
=
0
;
i
<
position
;
i
++
)
{
if
(
!
this
.
hasGroup
(
i
))
{
this
.
stacks
Model
.
openGroup
(
''
,
false
,
i
);
this
.
stacks
.
openGroup
(
''
,
false
,
i
);
}
}
group
=
this
.
stacks
Model
.
openGroup
(
''
,
activate
,
position
);
group
=
this
.
stacks
.
openGroup
(
''
,
activate
,
position
);
});
}
else
{
this
.
renameGroups
();
// ensure group labels are proper
}
if
(
activate
)
{
this
.
stacks
Model
.
setActive
(
group
);
this
.
stacks
.
setActive
(
group
);
}
return
group
;
...
...
@@ -1333,25 +1319,25 @@ export class EditorPart extends Part implements IEditorPart {
}
private
renameGroups
():
void
{
const
groups
=
this
.
stacks
Model
.
groups
;
const
groups
=
this
.
stacks
.
groups
;
if
(
groups
.
length
>
0
)
{
// LEFT | CENTER | RIGHT
if
(
groups
.
length
>
2
)
{
this
.
stacks
Model
.
renameGroup
(
this
.
groupAt
(
Position
.
LEFT
),
EditorPart
.
GROUP_LEFT_LABEL
);
this
.
stacks
Model
.
renameGroup
(
this
.
groupAt
(
Position
.
CENTER
),
EditorPart
.
GROUP_CENTER_LABEL
);
this
.
stacks
Model
.
renameGroup
(
this
.
groupAt
(
Position
.
RIGHT
),
EditorPart
.
GROUP_RIGHT_LABEL
);
this
.
stacks
.
renameGroup
(
this
.
groupAt
(
Position
.
LEFT
),
EditorPart
.
GROUP_LEFT_LABEL
);
this
.
stacks
.
renameGroup
(
this
.
groupAt
(
Position
.
CENTER
),
EditorPart
.
GROUP_CENTER_LABEL
);
this
.
stacks
.
renameGroup
(
this
.
groupAt
(
Position
.
RIGHT
),
EditorPart
.
GROUP_RIGHT_LABEL
);
}
// LEFT | RIGHT
else
if
(
groups
.
length
>
1
)
{
this
.
stacks
Model
.
renameGroup
(
this
.
groupAt
(
Position
.
LEFT
),
EditorPart
.
GROUP_LEFT_LABEL
);
this
.
stacks
Model
.
renameGroup
(
this
.
groupAt
(
Position
.
CENTER
),
EditorPart
.
GROUP_RIGHT_LABEL
);
this
.
stacks
.
renameGroup
(
this
.
groupAt
(
Position
.
LEFT
),
EditorPart
.
GROUP_LEFT_LABEL
);
this
.
stacks
.
renameGroup
(
this
.
groupAt
(
Position
.
CENTER
),
EditorPart
.
GROUP_RIGHT_LABEL
);
}
// LEFT
else
{
this
.
stacks
Model
.
renameGroup
(
this
.
groupAt
(
Position
.
LEFT
),
EditorPart
.
GROUP_LEFT_LABEL
);
this
.
stacks
.
renameGroup
(
this
.
groupAt
(
Position
.
LEFT
),
EditorPart
.
GROUP_LEFT_LABEL
);
}
}
}
...
...
src/vs/workbench/common/editor.ts
浏览文件 @
abe27026
...
...
@@ -53,6 +53,12 @@ export enum ConfirmResult {
export
abstract
class
EditorInput
extends
EventEmitter
implements
IEditorInput
{
private
disposed
:
boolean
;
constructor
()
{
super
();
this
.
disposed
=
false
;
}
/**
* Returns the unique id of this input.
*/
...
...
@@ -96,13 +102,6 @@ export abstract class EditorInput extends EventEmitter implements IEditorInput {
return
null
;
}
/**
* Returns true if this input is identical to the otherInput.
*/
public
matches
(
otherInput
:
any
):
boolean
{
return
this
===
otherInput
;
}
/**
* Returns a type of EditorModel that represents the resolved input. Subclasses should
* override to provide a meaningful model. The optional second argument allows to specify
...
...
@@ -140,9 +139,17 @@ export abstract class EditorInput extends EventEmitter implements IEditorInput {
}
/**
* Called when th
e editor is closed
. Subclasses can free resources as needed.
* Called when th
is input is no longer opened in any editor
. Subclasses can free resources as needed.
*/
public
close
():
void
{
this
.
dispose
();
}
/**
* Returns true if this input is identical to the otherInput.
*/
public
matches
(
otherInput
:
any
):
boolean
{
return
this
===
otherInput
;
}
/**
...
...
@@ -280,11 +287,6 @@ export abstract class BaseDiffEditorInput extends EditorInput {
public
revert
():
TPromise
<
boolean
>
{
return
this
.
_modifiedInput
.
revert
();
}
public
close
():
void
{
this
.
_originalInput
.
close
();
this
.
_modifiedInput
.
close
();
}
}
/**
...
...
src/vs/workbench/common/editor/diffEditorInput.ts
浏览文件 @
abe27026
...
...
@@ -197,10 +197,6 @@ export class DiffEditorInput extends BaseDiffEditorInput {
this
.
cachedModel
=
null
;
}
// Delegate to Inputs
this
.
originalInput
.
dispose
();
this
.
modifiedInput
.
dispose
();
super
.
dispose
();
}
}
...
...
src/vs/workbench/common/editor/editorStacksModel.ts
浏览文件 @
abe27026
...
...
@@ -14,7 +14,8 @@ import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/c
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IEditorRegistry
,
Extensions
}
from
'
vs/workbench/browser/parts/editor/baseEditor
'
;
import
{
Registry
}
from
'
vs/platform/platform
'
;
import
{
Position
,
Direction
,
IEditorInput
}
from
'
vs/platform/editor/common/editor
'
;
import
{
Position
,
Direction
}
from
'
vs/platform/editor/common/editor
'
;
import
{
DiffEditorInput
}
from
'
vs/workbench/common/editor/diffEditorInput
'
;
export
interface
IEditorGroup
{
...
...
@@ -72,7 +73,7 @@ export interface IEditorStacksModel {
export
interface
IEditorIdentifier
{
group
:
IEditorGroup
;
editor
:
I
EditorInput
;
editor
:
EditorInput
;
}
export
type
GroupIdentifier
=
number
;
...
...
@@ -118,6 +119,7 @@ export class EditorGroup implements IEditorGroup {
private
_onEditorActivated
:
Emitter
<
EditorInput
>
;
private
_onEditorOpened
:
Emitter
<
EditorInput
>
;
private
_onEditorClosed
:
Emitter
<
IGroupEvent
>
;
private
_onEditorDisposed
:
Emitter
<
EditorInput
>
;
private
_onEditorMoved
:
Emitter
<
EditorInput
>
;
private
_onEditorPinned
:
Emitter
<
EditorInput
>
;
private
_onEditorUnpinned
:
Emitter
<
EditorInput
>
;
...
...
@@ -142,12 +144,13 @@ export class EditorGroup implements IEditorGroup {
this
.
_onEditorActivated
=
new
Emitter
<
EditorInput
>
();
this
.
_onEditorOpened
=
new
Emitter
<
EditorInput
>
();
this
.
_onEditorClosed
=
new
Emitter
<
IGroupEvent
>
();
this
.
_onEditorDisposed
=
new
Emitter
<
EditorInput
>
();
this
.
_onEditorMoved
=
new
Emitter
<
EditorInput
>
();
this
.
_onEditorPinned
=
new
Emitter
<
EditorInput
>
();
this
.
_onEditorUnpinned
=
new
Emitter
<
EditorInput
>
();
this
.
_onEditorChanged
=
new
Emitter
<
EditorInput
>
();
this
.
toDispose
.
push
(
this
.
_onEditorActivated
,
this
.
_onEditorOpened
,
this
.
_onEditorClosed
,
this
.
_onEditorMoved
,
this
.
_onEditorPinned
,
this
.
_onEditorUnpinned
,
this
.
_onEditorChanged
);
this
.
toDispose
.
push
(
this
.
_onEditorActivated
,
this
.
_onEditorOpened
,
this
.
_onEditorClosed
,
this
.
_onEditor
Disposed
,
this
.
_onEditor
Moved
,
this
.
_onEditorPinned
,
this
.
_onEditorUnpinned
,
this
.
_onEditorChanged
);
}
public
get
id
():
GroupIdentifier
{
...
...
@@ -178,6 +181,10 @@ export class EditorGroup implements IEditorGroup {
return
this
.
_onEditorClosed
.
event
;
}
public
get
onEditorDisposed
():
Event
<
EditorInput
>
{
return
this
.
_onEditorDisposed
.
event
;
}
public
get
onEditorMoved
():
Event
<
EditorInput
>
{
return
this
.
_onEditorMoved
.
event
;
}
...
...
@@ -270,6 +277,21 @@ export class EditorGroup implements IEditorGroup {
this
.
preview
=
editor
;
}
// Re-emit disposal of editor input as our own event
const
l1
=
editor
.
addOneTimeDisposableListener
(
'
dispose
'
,
()
=>
{
if
(
this
.
indexOf
(
editor
)
>=
0
)
{
this
.
_onEditorDisposed
.
fire
(
editor
);
}
});
// Clean up dispose listeners once the editor gets closed
const
l2
=
this
.
onEditorClosed
(
event
=>
{
if
(
event
.
editor
.
matches
(
editor
))
{
l1
.
dispose
();
l2
.
dispose
();
}
});
// Event
this
.
fireEvent
(
this
.
_onEditorOpened
,
editor
);
...
...
@@ -326,9 +348,6 @@ export class EditorGroup implements IEditorGroup {
pinned
=
false
;
}
// Close it
editor
.
close
();
// Remove from arrays
this
.
splice
(
index
,
true
);
...
...
@@ -587,6 +606,7 @@ export class EditorStacksModel implements IEditorStacksModel {
private
_onGroupActivated
:
Emitter
<
EditorGroup
>
;
private
_onGroupRenamed
:
Emitter
<
EditorGroup
>
;
private
_onModelChanged
:
Emitter
<
EditorGroup
>
;
private
_onEditorDisposed
:
Emitter
<
IEditorIdentifier
>
;
constructor
(
@
IStorageService
private
storageService
:
IStorageService
,
...
...
@@ -607,8 +627,9 @@ export class EditorStacksModel implements IEditorStacksModel {
this
.
_onGroupMoved
=
new
Emitter
<
EditorGroup
>
();
this
.
_onGroupRenamed
=
new
Emitter
<
EditorGroup
>
();
this
.
_onModelChanged
=
new
Emitter
<
EditorGroup
>
();
this
.
_onEditorDisposed
=
new
Emitter
<
IEditorIdentifier
>
();
this
.
toDispose
.
push
(
this
.
_onGroupOpened
,
this
.
_onGroupClosed
,
this
.
_onGroupActivated
,
this
.
_onGroupMoved
,
this
.
_onGroupRenamed
,
this
.
_onModelChanged
);
this
.
toDispose
.
push
(
this
.
_onGroupOpened
,
this
.
_onGroupClosed
,
this
.
_onGroupActivated
,
this
.
_onGroupMoved
,
this
.
_onGroupRenamed
,
this
.
_onModelChanged
,
this
.
_onEditorDisposed
);
this
.
registerListeners
();
}
...
...
@@ -641,6 +662,10 @@ export class EditorStacksModel implements IEditorStacksModel {
return
this
.
_onModelChanged
.
event
;
}
public
get
onEditorDisposed
():
Event
<
IEditorIdentifier
>
{
return
this
.
_onEditorDisposed
.
event
;
}
public
get
groups
():
EditorGroup
[]
{
this
.
ensureLoaded
();
...
...
@@ -786,6 +811,8 @@ export class EditorStacksModel implements IEditorStacksModel {
return
this
.
_groups
.
indexOf
(
group
);
}
public
positionOfGroup
(
group
:
IEditorGroup
);
public
positionOfGroup
(
group
:
EditorGroup
);
public
positionOfGroup
(
group
:
EditorGroup
):
Position
{
return
this
.
indexOf
(
group
);
}
...
...
@@ -988,9 +1015,10 @@ export class EditorStacksModel implements IEditorStacksModel {
// Funnel editor changes in the group through our event aggregator
const
l1
=
group
.
onEditorChanged
(
e
=>
this
.
_onModelChanged
.
fire
(
group
));
const
l2
=
group
.
onEditorClosed
(
e
=>
this
.
onEditorClosed
(
e
));
const
l3
=
this
.
onGroupClosed
(
g
=>
{
const
l3
=
group
.
onEditorDisposed
(
editor
=>
this
.
_onEditorDisposed
.
fire
({
editor
,
group
}));
const
l4
=
this
.
onGroupClosed
(
g
=>
{
if
(
g
===
group
)
{
dispose
(
l1
,
l2
,
l3
);
dispose
(
l1
,
l2
,
l3
,
l4
);
}
});
...
...
@@ -1009,23 +1037,41 @@ export class EditorStacksModel implements IEditorStacksModel {
}
private
onEditorClosed
(
event
:
IGroupEvent
):
void
{
if
(
!
event
.
pinned
)
{
return
;
// we only care about pinned editors
const
editor
=
event
.
editor
;
// Close the editor when it is no longer open in any group
if
(
!
this
.
isOpen
(
editor
))
{
editor
.
close
();
// Also take care of diff editor inputs that wrap around 2 editors
if
(
editor
instanceof
DiffEditorInput
)
{
[
editor
.
getOriginalInput
(),
editor
.
getModifiedInput
()].
forEach
(
editor
=>
{
if
(
!
this
.
isOpen
(
editor
))
{
editor
.
close
();
}
});
}
}
const
editor
=
event
.
editor
;
const
registry
=
Registry
.
as
<
IEditorRegistry
>
(
Extensions
.
Editors
);
// Track closing of pinned editor to support to reopen closed editors
if
(
event
.
pinned
)
{
const
registry
=
Registry
.
as
<
IEditorRegistry
>
(
Extensions
.
Editors
);
const
factory
=
registry
.
getEditorInputFactory
(
editor
.
getId
());
if
(
factory
)
{
let
value
=
factory
.
serialize
(
editor
);
if
(
typeof
value
===
'
string
'
)
{
this
.
recentlyClosedEditors
.
push
({
id
:
editor
.
getId
(),
value
});
this
.
recentlyClosedEditors
=
this
.
recentlyClosedEditors
.
slice
(
0
,
10
);
// upper bound of recently closed
const
factory
=
registry
.
getEditorInputFactory
(
editor
.
getId
());
if
(
factory
)
{
let
value
=
factory
.
serialize
(
editor
);
if
(
typeof
value
===
'
string
'
)
{
this
.
recentlyClosedEditors
.
push
({
id
:
editor
.
getId
(),
value
});
this
.
recentlyClosedEditors
=
this
.
recentlyClosedEditors
.
slice
(
0
,
10
);
// upper bound of recently closed
}
}
}
}
private
isOpen
(
editor
:
EditorInput
):
boolean
{
return
this
.
_groups
.
some
(
g
=>
g
.
indexOf
(
editor
)
>=
0
);
}
private
onShutdown
():
void
{
this
.
save
();
...
...
src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts
浏览文件 @
abe27026
...
...
@@ -275,6 +275,15 @@ export class FileEditorInput extends CommonFileEditorInput {
});
}
public
close
():
void
{
let
inputs
:
FileEditorInput
[]
=
[
this
,
...
FileEditorInput
.
getAll
(
this
.
resource
)];
inputs
.
forEach
(
input
=>
{
if
(
!
input
.
isDisposed
())
{
input
.
dispose
(
true
);
}
});
}
private
indexOfClient
():
number
{
if
(
!
types
.
isUndefinedOrNull
(
FileEditorInput
.
FILE_EDITOR_MODEL_CLIENTS
[
this
.
resource
.
toString
()]))
{
for
(
let
i
=
0
;
i
<
FileEditorInput
.
FILE_EDITOR_MODEL_CLIENTS
[
this
.
resource
.
toString
()].
length
;
i
++
)
{
...
...
src/vs/workbench/test/common/editor/editorInput.test.ts
浏览文件 @
abe27026
...
...
@@ -67,7 +67,7 @@ suite('Workbench - EditorInput', () => {
assert
(
!
diffInput
.
matches
(
null
));
diffInput
.
dispose
();
assert
.
equal
(
counter
,
2
);
assert
.
equal
(
counter
,
0
);
});
test
(
'
DiffEditorInput disposes when input inside disposes
'
,
function
()
{
...
...
src/vs/workbench/test/common/editor/editorStacksModel.test.ts
浏览文件 @
abe27026
...
...
@@ -6,7 +6,7 @@
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
EditorStacksModel
,
IEditor
StacksModel
,
IEditorGroup
,
EditorGroup
,
setOpenEditorDirection
}
from
'
vs/workbench/common/editor/editorStacksModel
'
;
import
{
EditorStacksModel
,
IEditor
Identifier
,
IEditorGroup
,
EditorGroup
,
setOpenEditorDirection
}
from
'
vs/workbench/common/editor/editorStacksModel
'
;
import
{
EditorInput
}
from
'
vs/workbench/common/editor
'
;
import
{
TestStorageService
,
TestLifecycleService
,
TestContextService
,
TestWorkspace
,
TestConfiguration
}
from
'
vs/workbench/test/common/servicesTestUtils
'
;
import
{
InstantiationService
}
from
'
vs/platform/instantiation/common/instantiationService
'
;
...
...
@@ -18,6 +18,7 @@ import {IEditorRegistry, Extensions as EditorExtensions, IEditorInputFactory} fr
import
{
Registry
}
from
'
vs/platform/platform
'
;
import
{
Position
,
Direction
}
from
'
vs/platform/editor/common/editor
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
DiffEditorInput
}
from
'
vs/workbench/common/editor/diffEditorInput
'
;
function
create
():
EditorStacksModel
{
let
services
=
new
ServiceCollection
();
...
...
@@ -36,6 +37,7 @@ interface ModelEvents {
closed
:
IEditorGroup
[];
moved
:
IEditorGroup
[];
renamed
:
IEditorGroup
[];
disposed
:
IEditorIdentifier
[];
}
interface
GroupEvents
{
...
...
@@ -47,13 +49,14 @@ interface GroupEvents {
moved
:
EditorInput
[];
}
function
modelListener
(
model
:
I
EditorStacksModel
):
ModelEvents
{
function
modelListener
(
model
:
EditorStacksModel
):
ModelEvents
{
const
modelEvents
=
{
opened
:
[],
activated
:
[],
closed
:
[],
moved
:
[],
renamed
:
[]
renamed
:
[],
disposed
:
[]
};
model
.
onGroupOpened
(
g
=>
modelEvents
.
opened
.
push
(
g
));
...
...
@@ -61,6 +64,7 @@ function modelListener(model: IEditorStacksModel): ModelEvents {
model
.
onGroupClosed
(
g
=>
modelEvents
.
closed
.
push
(
g
));
model
.
onGroupMoved
(
g
=>
modelEvents
.
moved
.
push
(
g
));
model
.
onGroupRenamed
(
g
=>
modelEvents
.
renamed
.
push
(
g
));
model
.
onEditorDisposed
(
e
=>
modelEvents
.
disposed
.
push
(
e
));
return
modelEvents
;
}
...
...
@@ -1395,4 +1399,108 @@ suite('Editor Stacks Model', () => {
assert
.
equal
(
previous
.
group
,
group1
);
assert
.
equal
(
previous
.
editor
,
input3
);
});
test
(
'
Stack - Multiple Editors - Editor Dispose
'
,
function
()
{
const
model
=
create
();
const
events
=
modelListener
(
model
);
const
group1
=
model
.
openGroup
(
'
group1
'
);
const
group2
=
model
.
openGroup
(
'
group2
'
);
const
input1
=
input
();
const
input2
=
input
();
const
input3
=
input
();
group1
.
openEditor
(
input1
,
{
pinned
:
true
,
active
:
true
});
group1
.
openEditor
(
input2
,
{
pinned
:
true
,
active
:
true
});
group1
.
openEditor
(
input3
,
{
pinned
:
true
,
active
:
true
});
group2
.
openEditor
(
input1
,
{
pinned
:
true
,
active
:
true
});
group2
.
openEditor
(
input2
,
{
pinned
:
true
,
active
:
true
});
input1
.
dispose
();
assert
.
equal
(
events
.
disposed
.
length
,
2
);
assert
.
ok
(
events
.
disposed
[
0
].
editor
.
matches
(
input1
));
assert
.
ok
(
events
.
disposed
[
1
].
editor
.
matches
(
input1
));
input3
.
dispose
();
assert
.
equal
(
events
.
disposed
.
length
,
3
);
assert
.
ok
(
events
.
disposed
[
2
].
editor
.
matches
(
input3
));
const
input4
=
input
();
const
input5
=
input
();
group1
.
openEditor
(
input4
,
{
pinned
:
false
,
active
:
true
});
group1
.
openEditor
(
input5
,
{
pinned
:
false
,
active
:
true
});
input4
.
dispose
();
assert
.
equal
(
events
.
disposed
.
length
,
3
);
model
.
closeGroup
(
group2
);
input2
.
dispose
();
assert
.
equal
(
events
.
disposed
.
length
,
4
);
});
test
(
'
Stack - Multiple Editors - Editor Disposed on Close
'
,
function
()
{
const
model
=
create
();
const
group1
=
model
.
openGroup
(
'
group1
'
);
const
group2
=
model
.
openGroup
(
'
group2
'
);
const
input1
=
input
();
const
input2
=
input
();
const
input3
=
input
();
const
input4
=
input
();
group1
.
openEditor
(
input1
,
{
pinned
:
true
,
active
:
true
});
group1
.
openEditor
(
input2
,
{
pinned
:
true
,
active
:
true
});
group1
.
openEditor
(
input3
,
{
pinned
:
true
,
active
:
true
});
group1
.
openEditor
(
input4
,
{
pinned
:
true
,
active
:
true
});
group1
.
closeEditor
(
input3
);
assert
.
equal
(
input3
.
isDisposed
(),
true
);
group2
.
openEditor
(
input2
,
{
pinned
:
true
,
active
:
true
});
group2
.
openEditor
(
input3
,
{
pinned
:
true
,
active
:
true
});
group2
.
openEditor
(
input4
,
{
pinned
:
true
,
active
:
true
});
group1
.
closeEditor
(
input2
);
assert
.
equal
(
input2
.
isDisposed
(),
false
);
group2
.
closeEditor
(
input2
);
assert
.
equal
(
input2
.
isDisposed
(),
true
);
group1
.
closeAllEditors
();
assert
.
equal
(
input4
.
isDisposed
(),
false
);
model
.
closeGroups
();
assert
.
equal
(
input4
.
isDisposed
(),
true
);
});
test
(
'
Stack - Multiple Editors - Editor Disposed on Close (Diff Editor)
'
,
function
()
{
const
model
=
create
();
const
group1
=
model
.
openGroup
(
'
group1
'
);
const
input1
=
input
();
const
input2
=
input
();
const
diffInput
=
new
DiffEditorInput
(
'
name
'
,
'
description
'
,
input1
,
input2
);
group1
.
openEditor
(
diffInput
,
{
pinned
:
true
,
active
:
true
});
group1
.
openEditor
(
input1
,
{
pinned
:
true
,
active
:
true
});
group1
.
closeEditor
(
diffInput
);
assert
.
equal
(
diffInput
.
isDisposed
(),
true
);
assert
.
equal
(
input2
.
isDisposed
(),
true
);
assert
.
equal
(
input1
.
isDisposed
(),
false
);
});
});
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录