Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
1239cebb
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,发现更多精彩内容 >>
提交
1239cebb
编写于
3月 06, 2017
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Merge branch 'joh/editors'
上级
1645d0d1
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
1311 addition
and
998 deletion
+1311
-998
extensions/vscode-api-tests/src/editor.test.ts
extensions/vscode-api-tests/src/editor.test.ts
+62
-1
src/vs/base/common/arrays.ts
src/vs/base/common/arrays.ts
+46
-0
src/vs/base/test/common/arrays.test.ts
src/vs/base/test/common/arrays.test.ts
+34
-0
src/vs/workbench/api/node/extHost.api.impl.ts
src/vs/workbench/api/node/extHost.api.impl.ts
+5
-3
src/vs/workbench/api/node/extHost.contribution.ts
src/vs/workbench/api/node/extHost.contribution.ts
+5
-2
src/vs/workbench/api/node/extHost.protocol.ts
src/vs/workbench/api/node/extHost.protocol.ts
+15
-6
src/vs/workbench/api/node/extHostCommands.ts
src/vs/workbench/api/node/extHostCommands.ts
+3
-3
src/vs/workbench/api/node/extHostDocumentData.ts
src/vs/workbench/api/node/extHostDocumentData.ts
+244
-0
src/vs/workbench/api/node/extHostDocuments.ts
src/vs/workbench/api/node/extHostDocuments.ts
+51
-301
src/vs/workbench/api/node/extHostDocumentsAndEditors.ts
src/vs/workbench/api/node/extHostDocumentsAndEditors.ts
+148
-0
src/vs/workbench/api/node/extHostTextEditor.ts
src/vs/workbench/api/node/extHostTextEditor.ts
+9
-164
src/vs/workbench/api/node/extHostTextEditors.ts
src/vs/workbench/api/node/extHostTextEditors.ts
+105
-0
src/vs/workbench/api/node/mainThreadDocuments.ts
src/vs/workbench/api/node/mainThreadDocuments.ts
+12
-17
src/vs/workbench/api/node/mainThreadDocumentsAndEditors.ts
src/vs/workbench/api/node/mainThreadDocumentsAndEditors.ts
+351
-0
src/vs/workbench/api/node/mainThreadEditor.ts
src/vs/workbench/api/node/mainThreadEditor.ts
+4
-324
src/vs/workbench/api/node/mainThreadEditors.ts
src/vs/workbench/api/node/mainThreadEditors.ts
+32
-141
src/vs/workbench/test/node/api/extHostApiCommands.test.ts
src/vs/workbench/test/node/api/extHostApiCommands.test.ts
+14
-10
src/vs/workbench/test/node/api/extHostDocumentData.test.ts
src/vs/workbench/test/node/api/extHostDocumentData.test.ts
+4
-4
src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts
...ench/test/node/api/extHostDocumentSaveParticipant.test.ts
+14
-11
src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts
...s/workbench/test/node/api/extHostLanguageFeatures.test.ts
+13
-9
src/vs/workbench/test/node/api/extHostTextEditor.test.ts
src/vs/workbench/test/node/api/extHostTextEditor.test.ts
+2
-2
src/vs/workbench/test/node/api/mainThreadDocumentsAndEditors.test.ts
...bench/test/node/api/mainThreadDocumentsAndEditors.test.ts
+138
-0
未找到文件。
extensions/vscode-api-tests/src/editor.test.ts
浏览文件 @
1239cebb
...
...
@@ -6,7 +6,8 @@
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
workspace
,
window
,
Position
,
Range
,
commands
,
TextEditor
,
TextDocument
,
TextEditorCursorStyle
,
TextEditorLineNumbersStyle
,
SnippetString
,
Selection
}
from
'
vscode
'
;
import
{
join
}
from
'
path
'
;
import
{
workspace
,
window
,
Position
,
Range
,
commands
,
TextEditor
,
TextDocument
,
TextEditorCursorStyle
,
TextEditorLineNumbersStyle
,
SnippetString
,
Selection
,
ViewColumn
}
from
'
vscode
'
;
import
{
createRandomFile
,
deleteFile
,
cleanUp
}
from
'
./utils
'
;
suite
(
'
editor tests
'
,
()
=>
{
...
...
@@ -109,6 +110,66 @@ suite('editor tests', () => {
});
});
test
(
'
issue #20867: vscode.window.visibleTextEditors returns closed document 1/2
'
,
()
=>
{
return
withRandomFileEditor
(
'
Hello world!
'
,
editor
=>
{
const
p
=
new
Promise
((
resolve
,
reject
)
=>
{
const
sub
=
workspace
.
onDidCloseTextDocument
(
doc
=>
{
try
{
sub
.
dispose
();
assert
.
ok
(
window
.
activeTextEditor
===
undefined
);
assert
.
equal
(
window
.
visibleTextEditors
.
length
,
0
);
resolve
();
}
catch
(
e
)
{
reject
(
e
);
}
});
});
return
Promise
.
all
([
commands
.
executeCommand
(
'
workbench.action.closeAllEditors
'
),
p
]).
then
(()
=>
undefined
);
});
});
test
(
'
issue #20867: vscode.window.visibleTextEditors returns closed document 2/2
'
,
()
=>
{
const
file10Path
=
join
(
workspace
.
rootPath
||
''
,
'
./10linefile.ts
'
);
const
file30Path
=
join
(
workspace
.
rootPath
||
''
,
'
./30linefile.ts
'
);
return
Promise
.
all
([
workspace
.
openTextDocument
(
file10Path
),
workspace
.
openTextDocument
(
file30Path
)
]).
then
(
docs
=>
{
return
Promise
.
all
([
window
.
showTextDocument
(
docs
[
0
],
ViewColumn
.
One
),
window
.
showTextDocument
(
docs
[
1
],
ViewColumn
.
Two
),
]);
}).
then
(
editors
=>
{
const
p
=
new
Promise
((
resolve
,
reject
)
=>
{
const
sub
=
workspace
.
onDidCloseTextDocument
(
doc
=>
{
try
{
sub
.
dispose
();
assert
.
ok
(
window
.
activeTextEditor
===
editors
[
1
]);
assert
.
ok
(
window
.
visibleTextEditors
[
0
]
===
editors
[
1
]);
assert
.
equal
(
window
.
visibleTextEditors
.
length
,
1
);
resolve
();
}
catch
(
e
)
{
reject
(
e
);
}
});
});
// hide doesn't what it means because it triggers a close event and because it
// detached the editor. For this test that's what we want.
editors
[
0
].
hide
();
return
p
;
});
});
function
executeReplace
(
editor
:
TextEditor
,
range
:
Range
,
text
:
string
,
undoStopBefore
:
boolean
,
undoStopAfter
:
boolean
):
Thenable
<
boolean
>
{
return
editor
.
edit
((
builder
)
=>
{
builder
.
replace
(
range
,
text
);
...
...
src/vs/base/common/arrays.ts
浏览文件 @
1239cebb
...
...
@@ -66,6 +66,52 @@ export function findFirst<T>(array: T[], p: (x: T) => boolean): number {
return
low
;
}
/**
* Takes two *sorted* arrays and computes their delta (removed, added elements).
* Finishes in `Math.min(before.length, after.length)` steps.
* @param before
* @param after
* @param compare
*/
export
function
delta
<
T
>
(
before
:
T
[],
after
:
T
[],
compare
:
(
a
:
T
,
b
:
T
)
=>
number
)
{
const
removed
:
T
[]
=
[];
const
added
:
T
[]
=
[];
let
beforeIdx
=
0
;
let
afterIdx
=
0
;
while
(
true
)
{
if
(
beforeIdx
===
before
.
length
)
{
added
.
push
(...
after
.
slice
(
afterIdx
));
break
;
}
if
(
afterIdx
===
after
.
length
)
{
removed
.
push
(...
before
.
slice
(
beforeIdx
));
break
;
}
const
beforeElement
=
before
[
beforeIdx
];
const
afterElement
=
after
[
afterIdx
];
const
n
=
compare
(
beforeElement
,
afterElement
);
if
(
n
===
0
)
{
// equal
beforeIdx
+=
1
;
afterIdx
+=
1
;
}
else
if
(
n
<
0
)
{
// beforeElement is smaller -> before element removed
removed
.
push
(
beforeElement
);
beforeIdx
+=
1
;
}
else
if
(
n
>
0
)
{
// beforeElement is greater -> after element added
added
.
push
(
afterElement
);
afterIdx
+=
1
;
}
}
return
{
removed
,
added
};
}
/**
* Returns the top N elements from the array.
*
...
...
src/vs/base/test/common/arrays.test.ts
浏览文件 @
1239cebb
...
...
@@ -33,6 +33,40 @@ suite('Arrays', () => {
assert
.
equal
(
array
[
idx
],
1
);
});
test
(
'
delta
'
,
function
()
{
function
compare
(
a
:
number
,
b
:
number
):
number
{
return
a
-
b
;
}
let
d
=
arrays
.
delta
([
1
,
2
,
4
],
[],
compare
);
assert
.
deepEqual
(
d
.
removed
,
[
1
,
2
,
4
]);
assert
.
deepEqual
(
d
.
added
,
[]);
d
=
arrays
.
delta
([],
[
1
,
2
,
4
],
compare
);
assert
.
deepEqual
(
d
.
removed
,
[]);
assert
.
deepEqual
(
d
.
added
,
[
1
,
2
,
4
]);
d
=
arrays
.
delta
([
1
,
2
,
4
],
[
1
,
2
,
4
],
compare
);
assert
.
deepEqual
(
d
.
removed
,
[]);
assert
.
deepEqual
(
d
.
added
,
[]);
d
=
arrays
.
delta
([
1
,
2
,
4
],
[
2
,
3
,
4
,
5
],
compare
);
assert
.
deepEqual
(
d
.
removed
,
[
1
]);
assert
.
deepEqual
(
d
.
added
,
[
3
,
5
]);
d
=
arrays
.
delta
([
2
,
3
,
4
,
5
],
[
1
,
2
,
4
],
compare
);
assert
.
deepEqual
(
d
.
removed
,
[
3
,
5
]);
assert
.
deepEqual
(
d
.
added
,
[
1
]);
d
=
arrays
.
delta
([
1
,
3
,
5
,
7
],
[
5
,
9
,
11
],
compare
);
assert
.
deepEqual
(
d
.
removed
,
[
1
,
3
,
7
]);
assert
.
deepEqual
(
d
.
added
,
[
9
,
11
]);
d
=
arrays
.
delta
([
1
,
3
,
7
],
[
5
,
9
,
11
],
compare
);
assert
.
deepEqual
(
d
.
removed
,
[
1
,
3
,
7
]);
assert
.
deepEqual
(
d
.
added
,
[
5
,
9
,
11
]);
});
test
(
'
binarySearch
'
,
function
()
{
function
compare
(
a
:
number
,
b
:
number
):
number
{
return
a
-
b
;
...
...
src/vs/workbench/api/node/extHost.api.impl.ts
浏览文件 @
1239cebb
...
...
@@ -13,6 +13,7 @@ import * as errors from 'vs/base/common/errors';
import
product
from
'
vs/platform/node/product
'
;
import
pkg
from
'
vs/platform/node/package
'
;
import
{
ExtHostFileSystemEventService
}
from
'
vs/workbench/api/node/extHostFileSystemEventService
'
;
import
{
ExtHostDocumentsAndEditors
}
from
'
vs/workbench/api/node/extHostDocumentsAndEditors
'
;
import
{
ExtHostDocuments
}
from
'
vs/workbench/api/node/extHostDocuments
'
;
import
{
ExtHostDocumentSaveParticipant
}
from
'
vs/workbench/api/node/extHostDocumentSaveParticipant
'
;
import
{
ExtHostConfiguration
}
from
'
vs/workbench/api/node/extHostConfiguration
'
;
...
...
@@ -28,7 +29,7 @@ import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import
{
ExtHostOutputService
}
from
'
vs/workbench/api/node/extHostOutputService
'
;
import
{
ExtHostTerminalService
}
from
'
vs/workbench/api/node/extHostTerminalService
'
;
import
{
ExtHostMessageService
}
from
'
vs/workbench/api/node/extHostMessageService
'
;
import
{
ExtHostEditors
}
from
'
vs/workbench/api/node/extHostEditors
'
;
import
{
ExtHostEditors
}
from
'
vs/workbench/api/node/extHost
Text
Editors
'
;
import
{
ExtHostLanguages
}
from
'
vs/workbench/api/node/extHostLanguages
'
;
import
{
ExtHostLanguageFeatures
}
from
'
vs/workbench/api/node/extHostLanguageFeatures
'
;
import
{
ExtHostApiCommands
}
from
'
vs/workbench/api/node/extHostApiCommands
'
;
...
...
@@ -97,9 +98,10 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ
// Addressable instances
const
col
=
new
InstanceCollection
();
const
extHostHeapService
=
col
.
define
(
ExtHostContext
.
ExtHostHeapService
).
set
<
ExtHostHeapService
>
(
new
ExtHostHeapService
());
const
extHostDocuments
=
col
.
define
(
ExtHostContext
.
ExtHostDocuments
).
set
<
ExtHostDocuments
>
(
new
ExtHostDocuments
(
threadService
));
const
extHostDocumentsAndEditors
=
col
.
define
(
ExtHostContext
.
ExtHostDocumentsAndEditors
).
set
<
ExtHostDocumentsAndEditors
>
(
new
ExtHostDocumentsAndEditors
(
threadService
));
const
extHostDocuments
=
col
.
define
(
ExtHostContext
.
ExtHostDocuments
).
set
<
ExtHostDocuments
>
(
new
ExtHostDocuments
(
threadService
,
extHostDocumentsAndEditors
));
const
extHostDocumentSaveParticipant
=
col
.
define
(
ExtHostContext
.
ExtHostDocumentSaveParticipant
).
set
<
ExtHostDocumentSaveParticipant
>
(
new
ExtHostDocumentSaveParticipant
(
extHostDocuments
,
threadService
.
get
(
MainContext
.
MainThreadWorkspace
)));
const
extHostEditors
=
col
.
define
(
ExtHostContext
.
ExtHostEditors
).
set
<
ExtHostEditors
>
(
new
ExtHostEditors
(
threadService
,
extHostDocuments
));
const
extHostEditors
=
col
.
define
(
ExtHostContext
.
ExtHostEditors
).
set
<
ExtHostEditors
>
(
new
ExtHostEditors
(
threadService
,
extHostDocuments
AndEditors
));
const
extHostCommands
=
col
.
define
(
ExtHostContext
.
ExtHostCommands
).
set
<
ExtHostCommands
>
(
new
ExtHostCommands
(
threadService
,
extHostEditors
,
extHostHeapService
));
const
extHostExplorers
=
col
.
define
(
ExtHostContext
.
ExtHostExplorers
).
set
<
ExtHostTreeExplorers
>
(
new
ExtHostTreeExplorers
(
threadService
,
extHostCommands
));
const
extHostConfiguration
=
col
.
define
(
ExtHostContext
.
ExtHostConfiguration
).
set
<
ExtHostConfiguration
>
(
new
ExtHostConfiguration
(
threadService
.
get
(
MainContext
.
MainThreadConfiguration
),
initData
.
configuration
));
...
...
src/vs/workbench/api/node/extHost.contribution.ts
浏览文件 @
1239cebb
...
...
@@ -36,6 +36,7 @@ import { MainThreadFileSystemEventService } from './mainThreadFileSystemEventSer
import
{
MainThreadSCM
}
from
'
./mainThreadSCM
'
;
// --- other interested parties
import
{
MainThreadDocumentsAndEditors
}
from
'
./mainThreadDocumentsAndEditors
'
;
import
{
JSONValidationExtensionPoint
}
from
'
vs/platform/jsonschemas/common/jsonValidationExtensionPoint
'
;
import
{
LanguageConfigurationFileHandler
}
from
'
vs/editor/node/languageConfigurationExtensionPoint
'
;
import
{
SaveParticipant
}
from
'
./mainThreadSaveParticipant
'
;
...
...
@@ -62,13 +63,15 @@ export class ExtHostContribution implements IWorkbenchContribution {
return
this
.
instantiationService
.
createInstance
(
ctor
);
};
const
documentsAndEditors
=
this
.
instantiationService
.
createInstance
(
MainThreadDocumentsAndEditors
);
// Addressable instances
const
col
=
new
InstanceCollection
();
col
.
define
(
MainContext
.
MainThreadCommands
).
set
(
create
(
MainThreadCommands
));
col
.
define
(
MainContext
.
MainThreadConfiguration
).
set
(
create
(
MainThreadConfiguration
));
col
.
define
(
MainContext
.
MainThreadDiagnostics
).
set
(
create
(
MainThreadDiagnostics
));
col
.
define
(
MainContext
.
MainThreadDocuments
).
set
(
create
(
MainThreadDocument
s
));
col
.
define
(
MainContext
.
MainThreadEditors
).
set
(
create
(
MainThrea
dEditors
));
col
.
define
(
MainContext
.
MainThreadDocuments
).
set
(
this
.
instantiationService
.
createInstance
(
MainThreadDocuments
,
documentsAndEditor
s
));
col
.
define
(
MainContext
.
MainThreadEditors
).
set
(
this
.
instantiationService
.
createInstance
(
MainThreadEditors
,
documentsAn
dEditors
));
col
.
define
(
MainContext
.
MainThreadErrors
).
set
(
create
(
MainThreadErrors
));
col
.
define
(
MainContext
.
MainThreadExplorers
).
set
(
create
(
MainThreadTreeExplorers
));
col
.
define
(
MainContext
.
MainThreadLanguageFeatures
).
set
(
create
(
MainThreadLanguageFeatures
));
...
...
src/vs/workbench/api/node/extHost.protocol.ts
浏览文件 @
1239cebb
...
...
@@ -35,7 +35,7 @@ import { IWorkspaceConfigurationValues } from 'vs/workbench/services/configurati
import
{
IPickOpenEntry
,
IPickOptions
}
from
'
vs/platform/quickOpen/common/quickOpen
'
;
import
{
SaveReason
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IWorkspaceSymbol
}
from
'
vs/workbench/parts/search/common/search
'
;
import
{
IApplyEditsOptions
,
IUndoStopOptions
,
TextEditorRevealType
,
ITextEditorConfigurationUpdate
,
IResolvedTextEditorConfiguration
,
ISelectionChangeEvent
}
from
'
./mainThreadEditor
sTracker
'
;
import
{
IApplyEditsOptions
,
IUndoStopOptions
,
TextEditorRevealType
,
ITextEditorConfigurationUpdate
,
IResolvedTextEditorConfiguration
,
ISelectionChangeEvent
}
from
'
./mainThreadEditor
'
;
import
{
InternalTreeExplorerNodeContent
}
from
'
vs/workbench/parts/explorers/common/treeExplorerViewModel
'
;
...
...
@@ -290,12 +290,10 @@ export interface IModelAddedData {
}
export
abstract
class
ExtHostDocumentsShape
{
$provideTextDocumentContent
(
handle
:
number
,
uri
:
URI
):
TPromise
<
string
>
{
throw
ni
();
}
$acceptModelAdd
(
initData
:
IModelAddedData
):
void
{
throw
ni
();
}
$acceptModelModeChanged
(
strURL
:
string
,
oldModeId
:
string
,
newModeId
:
string
):
void
{
throw
ni
();
}
$acceptModelSaved
(
strURL
:
string
):
void
{
throw
ni
();
}
$acceptModelDirty
(
strURL
:
string
):
void
{
throw
ni
();
}
$acceptModelReverted
(
strURL
:
string
):
void
{
throw
ni
();
}
$acceptModelRemoved
(
strURL
:
string
):
void
{
throw
ni
();
}
$acceptModelChanged
(
strURL
:
string
,
events
:
editorCommon
.
IModelContentChangedEvent2
[],
isDirty
:
boolean
):
void
{
throw
ni
();
}
}
...
...
@@ -314,14 +312,24 @@ export interface ITextEditorPositionData {
[
id
:
string
]:
EditorPosition
;
}
export
abstract
class
ExtHostEditorsShape
{
$acceptTextEditorAdd
(
data
:
ITextEditorAddData
):
void
{
throw
ni
();
}
$acceptOptionsChanged
(
id
:
string
,
opts
:
IResolvedTextEditorConfiguration
):
void
{
throw
ni
();
}
$acceptSelectionsChanged
(
id
:
string
,
event
:
ISelectionChangeEvent
):
void
{
throw
ni
();
}
$acceptActiveEditorAndVisibleEditors
(
id
:
string
,
visibleIds
:
string
[]):
void
{
throw
ni
();
}
$acceptEditorPositionData
(
data
:
ITextEditorPositionData
):
void
{
throw
ni
();
}
$acceptTextEditorRemove
(
id
:
string
):
void
{
throw
ni
();
}
}
export
interface
IDocumentsAndEditorsDelta
{
removedDocuments
?:
string
[];
addedDocuments
?:
IModelAddedData
[];
removedEditors
?:
string
[];
addedEditors
?:
ITextEditorAddData
[];
newActiveEditor
?:
string
;
}
export
abstract
class
ExtHostDocumentsAndEditorsShape
{
$acceptDocumentsAndEditorsDelta
(
delta
:
IDocumentsAndEditorsDelta
):
void
{
throw
ni
();
}
}
export
abstract
class
ExtHostTreeExplorersShape
{
$provideRootNode
(
providerId
:
string
):
TPromise
<
InternalTreeExplorerNodeContent
>
{
throw
ni
();
};
$resolveChildren
(
providerId
:
string
,
node
:
InternalTreeExplorerNodeContent
):
TPromise
<
InternalTreeExplorerNodeContent
[]
>
{
throw
ni
();
}
...
...
@@ -432,6 +440,7 @@ export const ExtHostContext = {
ExtHostCommands
:
createExtId
<
ExtHostCommandsShape
>
(
'
ExtHostCommands
'
,
ExtHostCommandsShape
),
ExtHostConfiguration
:
createExtId
<
ExtHostConfigurationShape
>
(
'
ExtHostConfiguration
'
,
ExtHostConfigurationShape
),
ExtHostDiagnostics
:
createExtId
<
ExtHostDiagnosticsShape
>
(
'
ExtHostDiagnostics
'
,
ExtHostDiagnosticsShape
),
ExtHostDocumentsAndEditors
:
createExtId
<
ExtHostDocumentsAndEditorsShape
>
(
'
ExtHostDocumentsAndEditors
'
,
ExtHostDocumentsAndEditorsShape
),
ExtHostDocuments
:
createExtId
<
ExtHostDocumentsShape
>
(
'
ExtHostDocuments
'
,
ExtHostDocumentsShape
),
ExtHostDocumentSaveParticipant
:
createExtId
<
ExtHostDocumentSaveParticipantShape
>
(
'
ExtHostDocumentSaveParticipant
'
,
ExtHostDocumentSaveParticipantShape
),
ExtHostEditors
:
createExtId
<
ExtHostEditorsShape
>
(
'
ExtHostEditors
'
,
ExtHostEditorsShape
),
...
...
src/vs/workbench/api/node/extHostCommands.ts
浏览文件 @
1239cebb
...
...
@@ -8,7 +8,7 @@ import { IThreadService } from 'vs/workbench/services/thread/common/threadServic
import
{
validateConstraint
}
from
'
vs/base/common/types
'
;
import
{
ICommandHandlerDescription
}
from
'
vs/platform/commands/common/commands
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
ExtHostEditors
}
from
'
vs/workbench/api/node/extHostEditors
'
;
import
{
ExtHostEditors
}
from
'
vs/workbench/api/node/extHost
Text
Editors
'
;
import
*
as
extHostTypes
from
'
vs/workbench/api/node/extHostTypes
'
;
import
*
as
extHostTypeConverter
from
'
vs/workbench/api/node/extHostTypeConverters
'
;
import
{
cloneAndChange
}
from
'
vs/base/common/objects
'
;
...
...
@@ -102,7 +102,7 @@ export class ExtHostCommands extends ExtHostCommandsShape {
return
TPromise
.
wrapError
<
T
>
(
`Contributed command '
${
id
}
' does not exist.`
);
}
let
{
callback
,
thisArg
,
description
}
=
command
;
let
{
callback
,
thisArg
,
description
}
=
command
;
if
(
description
)
{
for
(
let
i
=
0
;
i
<
description
.
args
.
length
;
i
++
)
{
...
...
@@ -140,7 +140,7 @@ export class ExtHostCommands extends ExtHostCommandsShape {
$getContributedCommandHandlerDescriptions
():
TPromise
<
{
[
id
:
string
]:
string
|
ICommandHandlerDescription
}
>
{
const
result
:
{
[
id
:
string
]:
string
|
ICommandHandlerDescription
}
=
Object
.
create
(
null
);
this
.
_commands
.
forEach
((
command
,
id
)
=>
{
let
{
description
}
=
command
;
let
{
description
}
=
command
;
if
(
description
)
{
result
[
id
]
=
description
;
}
...
...
src/vs/workbench/api/node/extHostDocumentData.ts
0 → 100644
浏览文件 @
1239cebb
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
regExpLeadsToEndlessLoop
}
from
'
vs/base/common/strings
'
;
import
{
MirrorModel2
}
from
'
vs/editor/common/model/mirrorModel2
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
{
Range
,
Position
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
*
as
vscode
from
'
vscode
'
;
import
{
getWordAtText
,
ensureValidWordDefinition
}
from
'
vs/editor/common/model/wordHelper
'
;
import
{
MainThreadDocumentsShape
}
from
'
./extHost.protocol
'
;
import
{
ITextSource
}
from
'
vs/editor/common/model/textSource
'
;
const
_modeId2WordDefinition
=
new
Map
<
string
,
RegExp
>
();
export
function
setWordDefinitionFor
(
modeId
:
string
,
wordDefinition
:
RegExp
):
void
{
_modeId2WordDefinition
.
set
(
modeId
,
wordDefinition
);
}
export
function
getWordDefinitionFor
(
modeId
:
string
):
RegExp
{
return
_modeId2WordDefinition
.
get
(
modeId
);
}
export
class
ExtHostDocumentData
extends
MirrorModel2
{
private
_proxy
:
MainThreadDocumentsShape
;
private
_languageId
:
string
;
private
_isDirty
:
boolean
;
private
_textLines
:
vscode
.
TextLine
[];
private
_document
:
vscode
.
TextDocument
;
constructor
(
proxy
:
MainThreadDocumentsShape
,
uri
:
URI
,
lines
:
string
[],
eol
:
string
,
languageId
:
string
,
versionId
:
number
,
isDirty
:
boolean
)
{
super
(
uri
,
lines
,
eol
,
versionId
);
this
.
_proxy
=
proxy
;
this
.
_languageId
=
languageId
;
this
.
_isDirty
=
isDirty
;
this
.
_textLines
=
[];
}
dispose
():
void
{
this
.
_textLines
.
length
=
0
;
this
.
_isDirty
=
false
;
super
.
dispose
();
}
equalLines
({
lines
}:
ITextSource
):
boolean
{
const
len
=
lines
.
length
;
if
(
len
!==
this
.
_lines
.
length
)
{
return
false
;
}
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
if
(
lines
[
i
]
!==
this
.
_lines
[
i
])
{
return
false
;
}
}
return
true
;
}
get
document
():
vscode
.
TextDocument
{
if
(
!
this
.
_document
)
{
const
data
=
this
;
this
.
_document
=
{
get
uri
()
{
return
data
.
_uri
;
},
get
fileName
()
{
return
data
.
_uri
.
fsPath
;
},
get
isUntitled
()
{
return
data
.
_uri
.
scheme
!==
'
file
'
;
},
get
languageId
()
{
return
data
.
_languageId
;
},
get
version
()
{
return
data
.
_versionId
;
},
get
isDirty
()
{
return
data
.
_isDirty
;
},
save
()
{
return
data
.
_proxy
.
$trySaveDocument
(
data
.
_uri
);
},
getText
(
range
?)
{
return
range
?
data
.
_getTextInRange
(
range
)
:
data
.
getText
();
},
get
lineCount
()
{
return
data
.
_lines
.
length
;
},
lineAt
(
lineOrPos
)
{
return
data
.
lineAt
(
lineOrPos
);
},
offsetAt
(
pos
)
{
return
data
.
offsetAt
(
pos
);
},
positionAt
(
offset
)
{
return
data
.
positionAt
(
offset
);
},
validateRange
(
ran
)
{
return
data
.
validateRange
(
ran
);
},
validatePosition
(
pos
)
{
return
data
.
validatePosition
(
pos
);
},
getWordRangeAtPosition
(
pos
,
regexp
?)
{
return
data
.
getWordRangeAtPosition
(
pos
,
regexp
);
}
};
}
return
this
.
_document
;
}
_acceptLanguageId
(
newLanguageId
:
string
):
void
{
this
.
_languageId
=
newLanguageId
;
}
_acceptIsDirty
(
isDirty
:
boolean
):
void
{
this
.
_isDirty
=
isDirty
;
}
private
_getTextInRange
(
_range
:
vscode
.
Range
):
string
{
let
range
=
this
.
validateRange
(
_range
);
if
(
range
.
isEmpty
)
{
return
''
;
}
if
(
range
.
isSingleLine
)
{
return
this
.
_lines
[
range
.
start
.
line
].
substring
(
range
.
start
.
character
,
range
.
end
.
character
);
}
let
lineEnding
=
this
.
_eol
,
startLineIndex
=
range
.
start
.
line
,
endLineIndex
=
range
.
end
.
line
,
resultLines
:
string
[]
=
[];
resultLines
.
push
(
this
.
_lines
[
startLineIndex
].
substring
(
range
.
start
.
character
));
for
(
let
i
=
startLineIndex
+
1
;
i
<
endLineIndex
;
i
++
)
{
resultLines
.
push
(
this
.
_lines
[
i
]);
}
resultLines
.
push
(
this
.
_lines
[
endLineIndex
].
substring
(
0
,
range
.
end
.
character
));
return
resultLines
.
join
(
lineEnding
);
}
lineAt
(
lineOrPosition
:
number
|
vscode
.
Position
):
vscode
.
TextLine
{
let
line
:
number
;
if
(
lineOrPosition
instanceof
Position
)
{
line
=
lineOrPosition
.
line
;
}
else
if
(
typeof
lineOrPosition
===
'
number
'
)
{
line
=
lineOrPosition
;
}
if
(
line
<
0
||
line
>=
this
.
_lines
.
length
)
{
throw
new
Error
(
'
Illegal value for `line`
'
);
}
let
result
=
this
.
_textLines
[
line
];
if
(
!
result
||
result
.
lineNumber
!==
line
||
result
.
text
!==
this
.
_lines
[
line
])
{
const
text
=
this
.
_lines
[
line
];
const
firstNonWhitespaceCharacterIndex
=
/^
(\s
*
)
/
.
exec
(
text
)[
1
].
length
;
const
range
=
new
Range
(
line
,
0
,
line
,
text
.
length
);
const
rangeIncludingLineBreak
=
line
<
this
.
_lines
.
length
-
1
?
new
Range
(
line
,
0
,
line
+
1
,
0
)
:
range
;
result
=
Object
.
freeze
({
lineNumber
:
line
,
range
,
rangeIncludingLineBreak
,
text
,
firstNonWhitespaceCharacterIndex
,
//TODO@api, rename to 'leadingWhitespaceLength'
isEmptyOrWhitespace
:
firstNonWhitespaceCharacterIndex
===
text
.
length
});
this
.
_textLines
[
line
]
=
result
;
}
return
result
;
}
offsetAt
(
position
:
vscode
.
Position
):
number
{
position
=
this
.
validatePosition
(
position
);
this
.
_ensureLineStarts
();
return
this
.
_lineStarts
.
getAccumulatedValue
(
position
.
line
-
1
)
+
position
.
character
;
}
positionAt
(
offset
:
number
):
vscode
.
Position
{
offset
=
Math
.
floor
(
offset
);
offset
=
Math
.
max
(
0
,
offset
);
this
.
_ensureLineStarts
();
let
out
=
this
.
_lineStarts
.
getIndexOf
(
offset
);
let
lineLength
=
this
.
_lines
[
out
.
index
].
length
;
// Ensure we return a valid position
return
new
Position
(
out
.
index
,
Math
.
min
(
out
.
remainder
,
lineLength
));
}
// ---- range math
validateRange
(
range
:
vscode
.
Range
):
vscode
.
Range
{
if
(
!
(
range
instanceof
Range
))
{
throw
new
Error
(
'
Invalid argument
'
);
}
let
start
=
this
.
validatePosition
(
range
.
start
);
let
end
=
this
.
validatePosition
(
range
.
end
);
if
(
start
===
range
.
start
&&
end
===
range
.
end
)
{
return
range
;
}
return
new
Range
(
start
.
line
,
start
.
character
,
end
.
line
,
end
.
character
);
}
validatePosition
(
position
:
vscode
.
Position
):
vscode
.
Position
{
if
(
!
(
position
instanceof
Position
))
{
throw
new
Error
(
'
Invalid argument
'
);
}
let
{
line
,
character
}
=
position
;
let
hasChanged
=
false
;
if
(
line
<
0
)
{
line
=
0
;
character
=
0
;
hasChanged
=
true
;
}
else
if
(
line
>=
this
.
_lines
.
length
)
{
line
=
this
.
_lines
.
length
-
1
;
character
=
this
.
_lines
[
line
].
length
;
hasChanged
=
true
;
}
else
{
let
maxCharacter
=
this
.
_lines
[
line
].
length
;
if
(
character
<
0
)
{
character
=
0
;
hasChanged
=
true
;
}
else
if
(
character
>
maxCharacter
)
{
character
=
maxCharacter
;
hasChanged
=
true
;
}
}
if
(
!
hasChanged
)
{
return
position
;
}
return
new
Position
(
line
,
character
);
}
getWordRangeAtPosition
(
_position
:
vscode
.
Position
,
regexp
?:
RegExp
):
vscode
.
Range
{
let
position
=
this
.
validatePosition
(
_position
);
if
(
!
regexp
||
regExpLeadsToEndlessLoop
(
regexp
))
{
regexp
=
getWordDefinitionFor
(
this
.
_languageId
);
}
let
wordAtText
=
getWordAtText
(
position
.
character
+
1
,
ensureValidWordDefinition
(
regexp
),
this
.
_lines
[
position
.
line
],
0
);
if
(
wordAtText
)
{
return
new
Range
(
position
.
line
,
wordAtText
.
startColumn
-
1
,
position
.
line
,
wordAtText
.
endColumn
-
1
);
}
return
undefined
;
}
}
src/vs/workbench/api/node/extHostDocuments.ts
浏览文件 @
1239cebb
...
...
@@ -5,82 +5,74 @@
'
use strict
'
;
import
{
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
import
{
regExpLeadsToEndlessLoop
}
from
'
vs/base/common/strings
'
;
import
*
as
editorCommon
from
'
vs/editor/common/editorCommon
'
;
import
{
MirrorModel2
}
from
'
vs/editor/common/model/mirrorModel2
'
;
import
{
IThreadService
}
from
'
vs/workbench/services/thread/common/threadService
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
Range
,
Position
,
Disposable
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
Disposable
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
*
as
TypeConverters
from
'
./extHostTypeConverters
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
*
as
vscode
from
'
vscode
'
;
import
{
asWinJsPromise
}
from
'
vs/base/common/async
'
;
import
{
getWordAtText
,
ensureValidWordDefinition
}
from
'
vs/editor/common/model/wordHelper
'
;
import
{
MainContext
,
MainThreadDocumentsShape
,
ExtHostDocumentsShape
,
IModelAddedData
}
from
'
./extHost.protocol
'
;
import
{
ITextSource
,
TextSource
}
from
'
vs/editor/common/model/textSource
'
;
const
_modeId2WordDefinition
=
new
Map
<
string
,
RegExp
>
();
function
setWordDefinitionFor
(
modeId
:
string
,
wordDefinition
:
RegExp
):
void
{
_modeId2WordDefinition
.
set
(
modeId
,
wordDefinition
);
}
function
getWordDefinitionFor
(
modeId
:
string
):
RegExp
{
return
_modeId2WordDefinition
.
get
(
modeId
);
}
import
{
TextSource
}
from
'
vs/editor/common/model/textSource
'
;
import
{
MainContext
,
MainThreadDocumentsShape
,
ExtHostDocumentsShape
}
from
'
./extHost.protocol
'
;
import
{
ExtHostDocumentData
,
setWordDefinitionFor
}
from
'
./extHostDocumentData
'
;
import
{
ExtHostDocumentsAndEditors
}
from
'
./extHostDocumentsAndEditors
'
;
export
class
ExtHostDocuments
extends
ExtHostDocumentsShape
{
private
static
_handlePool
:
number
=
0
;
private
_onDidAddDocumentEventEmitter
:
Emitter
<
vscode
.
TextDocument
>
;
public
onDidAddDocument
:
Event
<
vscode
.
TextDocument
>
;
private
_onDidRemoveDocumentEventEmitter
:
Emitter
<
vscode
.
TextDocument
>
;
public
onDidRemoveDocument
:
Event
<
vscode
.
TextDocument
>
;
private
_onDidAddDocument
=
new
Emitter
<
vscode
.
TextDocument
>
();
private
_onDidRemoveDocument
=
new
Emitter
<
vscode
.
TextDocument
>
();
private
_onDidChangeDocument
=
new
Emitter
<
vscode
.
TextDocumentChangeEvent
>
();
private
_onDidSaveDocument
=
new
Emitter
<
vscode
.
TextDocument
>
();
private
_onDidChangeDocumentEventEmitter
:
Emitter
<
vscode
.
TextDocumentChangeEvent
>
;
public
onDidChangeDocument
:
Event
<
vscode
.
TextDocumentChangeEvent
>
;
readonly
onDidAddDocument
:
Event
<
vscode
.
TextDocument
>
=
this
.
_onDidAddDocument
.
event
;
readonly
onDidRemoveDocument
:
Event
<
vscode
.
TextDocument
>
=
this
.
_onDidRemoveDocument
.
event
;
readonly
onDidChangeDocument
:
Event
<
vscode
.
TextDocumentChangeEvent
>
=
this
.
_onDidChangeDocument
.
event
;
readonly
onDidSaveDocument
:
Event
<
vscode
.
TextDocument
>
=
this
.
_onDidSaveDocument
.
event
;
private
_onDidSaveDocumentEventEmitter
:
Emitter
<
vscode
.
TextDocument
>
;
public
onDidSaveDocument
:
Event
<
vscode
.
TextDocument
>
;
private
_documentData
=
new
Map
<
string
,
ExtHostDocumentData
>
();
private
_toDispose
:
IDisposable
[];
private
_proxy
:
MainThreadDocumentsShape
;
private
_documentsAndEditors
:
ExtHostDocumentsAndEditors
;
private
_documentLoader
=
new
Map
<
string
,
TPromise
<
ExtHostDocumentData
>>
();
private
_documentContentProviders
=
new
Map
<
number
,
vscode
.
TextDocumentContentProvider
>
();
private
_proxy
:
MainThreadDocumentsShape
;
constructor
(
threadService
:
IThreadService
)
{
constructor
(
threadService
:
IThreadService
,
documentsAndEditors
:
ExtHostDocumentsAndEditors
)
{
super
();
this
.
_proxy
=
threadService
.
get
(
MainContext
.
MainThreadDocuments
);
this
.
_documentsAndEditors
=
documentsAndEditors
;
this
.
_onDidAddDocumentEventEmitter
=
new
Emitter
<
vscode
.
TextDocument
>
();
this
.
onDidAddDocument
=
this
.
_onDidAddDocumentEventEmitter
.
event
;
this
.
_onDidRemoveDocumentEventEmitter
=
new
Emitter
<
vscode
.
TextDocument
>
();
this
.
onDidRemoveDocument
=
this
.
_onDidRemoveDocumentEventEmitter
.
event
;
this
.
_onDidChangeDocumentEventEmitter
=
new
Emitter
<
vscode
.
TextDocumentChangeEvent
>
();
this
.
onDidChangeDocument
=
this
.
_onDidChangeDocumentEventEmitter
.
event
;
this
.
_toDispose
=
[
this
.
_documentsAndEditors
.
onDidRemoveDocuments
(
documents
=>
{
for
(
const
data
of
documents
)
{
this
.
_onDidRemoveDocument
.
fire
(
data
.
document
);
}
}),
this
.
_documentsAndEditors
.
onDidAddDocuments
(
documents
=>
{
for
(
const
data
of
documents
)
{
this
.
_onDidAddDocument
.
fire
(
data
.
document
);
}
})
];
}
this
.
_onDidSaveDocumentEventEmitter
=
new
Emitter
<
vscode
.
TextDocument
>
();
this
.
onDidSaveDocument
=
this
.
_onDidSaveDocumentEventEmitter
.
event
;
public
dispose
():
void
{
dispose
(
this
.
_toDispose
)
;
}
public
getAllDocumentData
():
ExtHostDocumentData
[]
{
const
result
:
ExtHostDocumentData
[]
=
[];
this
.
_documentData
.
forEach
(
data
=>
result
.
push
(
data
));
return
result
;
return
this
.
_documentsAndEditors
.
allDocuments
();
}
public
getDocumentData
(
resource
:
vscode
.
Uri
):
ExtHostDocumentData
{
if
(
!
resource
)
{
return
undefined
;
}
const
data
=
this
.
_document
Data
.
ge
t
(
resource
.
toString
());
const
data
=
this
.
_document
sAndEditors
.
getDocumen
t
(
resource
.
toString
());
if
(
data
)
{
return
data
;
}
...
...
@@ -89,7 +81,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
public
ensureDocumentData
(
uri
:
URI
):
TPromise
<
ExtHostDocumentData
>
{
let
cached
=
this
.
_document
Data
.
ge
t
(
uri
.
toString
());
let
cached
=
this
.
_document
sAndEditors
.
getDocumen
t
(
uri
.
toString
());
if
(
cached
)
{
return
TPromise
.
as
(
cached
);
}
...
...
@@ -98,7 +90,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
if
(
!
promise
)
{
promise
=
this
.
_proxy
.
$tryOpenDocument
(
uri
).
then
(()
=>
{
this
.
_documentLoader
.
delete
(
uri
.
toString
());
return
this
.
_document
Data
.
ge
t
(
uri
.
toString
());
return
this
.
_document
sAndEditors
.
getDocumen
t
(
uri
.
toString
());
},
err
=>
{
this
.
_documentLoader
.
delete
(
uri
.
toString
());
return
TPromise
.
wrapError
(
err
);
...
...
@@ -126,10 +118,10 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
let
subscription
:
IDisposable
;
if
(
typeof
provider
.
onDidChange
===
'
function
'
)
{
subscription
=
provider
.
onDidChange
(
uri
=>
{
if
(
this
.
_document
Data
.
has
(
uri
.
toString
()))
{
if
(
this
.
_document
sAndEditors
.
getDocument
(
uri
.
toString
()))
{
this
.
$provideTextDocumentContent
(
handle
,
<
URI
>
uri
).
then
(
value
=>
{
const
document
=
this
.
_document
Data
.
ge
t
(
uri
.
toString
());
const
document
=
this
.
_document
sAndEditors
.
getDocumen
t
(
uri
.
toString
());
if
(
!
document
)
{
// disposed in the meantime
return
;
...
...
@@ -158,7 +150,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
});
}
$provideTextDocumentContent
(
handle
:
number
,
uri
:
URI
):
TPromise
<
string
>
{
public
$provideTextDocumentContent
(
handle
:
number
,
uri
:
URI
):
TPromise
<
string
>
{
const
provider
=
this
.
_documentContentProviders
.
get
(
handle
);
if
(
!
provider
)
{
return
TPromise
.
wrapError
<
string
>
(
`unsupported uri-scheme:
${
uri
.
scheme
}
`
);
...
...
@@ -166,57 +158,37 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
return
asWinJsPromise
(
token
=>
provider
.
provideTextDocumentContent
(
uri
,
token
));
}
public
$acceptModelAdd
(
initData
:
IModelAddedData
):
void
{
let
data
=
new
ExtHostDocumentData
(
this
.
_proxy
,
initData
.
url
,
initData
.
lines
,
initData
.
EOL
,
initData
.
modeId
,
initData
.
versionId
,
initData
.
isDirty
);
let
key
=
data
.
document
.
uri
.
toString
();
if
(
this
.
_documentData
.
has
(
key
))
{
throw
new
Error
(
'
Document `
'
+
key
+
'
` already exists.
'
);
}
this
.
_documentData
.
set
(
key
,
data
);
this
.
_onDidAddDocumentEventEmitter
.
fire
(
data
.
document
);
}
public
$acceptModelModeChanged
(
strURL
:
string
,
oldModeId
:
string
,
newModeId
:
string
):
void
{
let
data
=
this
.
_document
Data
.
ge
t
(
strURL
);
let
data
=
this
.
_document
sAndEditors
.
getDocumen
t
(
strURL
);
// Treat a mode change as a remove + add
this
.
_onDidRemoveDocument
EventEmitter
.
fire
(
data
.
document
);
this
.
_onDidRemoveDocument
.
fire
(
data
.
document
);
data
.
_acceptLanguageId
(
newModeId
);
this
.
_onDidAddDocument
EventEmitter
.
fire
(
data
.
document
);
this
.
_onDidAddDocument
.
fire
(
data
.
document
);
}
public
$acceptModelSaved
(
strURL
:
string
):
void
{
let
data
=
this
.
_document
Data
.
ge
t
(
strURL
);
let
data
=
this
.
_document
sAndEditors
.
getDocumen
t
(
strURL
);
data
.
_acceptIsDirty
(
false
);
this
.
_onDidSaveDocument
EventEmitter
.
fire
(
data
.
document
);
this
.
_onDidSaveDocument
.
fire
(
data
.
document
);
}
public
$acceptModelDirty
(
strURL
:
string
):
void
{
let
document
=
this
.
_document
Data
.
ge
t
(
strURL
);
let
document
=
this
.
_document
sAndEditors
.
getDocumen
t
(
strURL
);
document
.
_acceptIsDirty
(
true
);
}
public
$acceptModelReverted
(
strURL
:
string
):
void
{
let
document
=
this
.
_document
Data
.
ge
t
(
strURL
);
let
document
=
this
.
_document
sAndEditors
.
getDocumen
t
(
strURL
);
document
.
_acceptIsDirty
(
false
);
}
public
$acceptModelRemoved
(
strURL
:
string
):
void
{
if
(
!
this
.
_documentData
.
has
(
strURL
))
{
throw
new
Error
(
'
Document `
'
+
strURL
+
'
` does not exist.
'
);
}
let
data
=
this
.
_documentData
.
get
(
strURL
);
this
.
_documentData
.
delete
(
strURL
);
this
.
_onDidRemoveDocumentEventEmitter
.
fire
(
data
.
document
);
data
.
dispose
();
}
public
$acceptModelChanged
(
strURL
:
string
,
events
:
editorCommon
.
IModelContentChangedEvent2
[],
isDirty
:
boolean
):
void
{
let
data
=
this
.
_document
Data
.
ge
t
(
strURL
);
let
data
=
this
.
_document
sAndEditors
.
getDocumen
t
(
strURL
);
data
.
_acceptIsDirty
(
isDirty
);
data
.
onEvents
(
events
);
this
.
_onDidChangeDocument
EventEmitter
.
fire
({
this
.
_onDidChangeDocument
.
fire
({
document
:
data
.
document
,
contentChanges
:
events
.
map
((
e
)
=>
{
return
{
...
...
@@ -228,229 +200,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
});
}
setWordDefinitionFor
(
modeId
:
string
,
wordDefinition
:
RegExp
):
void
{
public
setWordDefinitionFor
(
modeId
:
string
,
wordDefinition
:
RegExp
):
void
{
setWordDefinitionFor
(
modeId
,
wordDefinition
);
}
}
export
class
ExtHostDocumentData
extends
MirrorModel2
{
private
_proxy
:
MainThreadDocumentsShape
;
private
_languageId
:
string
;
private
_isDirty
:
boolean
;
private
_textLines
:
vscode
.
TextLine
[];
private
_document
:
vscode
.
TextDocument
;
constructor
(
proxy
:
MainThreadDocumentsShape
,
uri
:
URI
,
lines
:
string
[],
eol
:
string
,
languageId
:
string
,
versionId
:
number
,
isDirty
:
boolean
)
{
super
(
uri
,
lines
,
eol
,
versionId
);
this
.
_proxy
=
proxy
;
this
.
_languageId
=
languageId
;
this
.
_isDirty
=
isDirty
;
this
.
_textLines
=
[];
}
dispose
():
void
{
this
.
_textLines
.
length
=
0
;
this
.
_isDirty
=
false
;
super
.
dispose
();
}
equalLines
({
lines
}:
ITextSource
):
boolean
{
const
len
=
lines
.
length
;
if
(
len
!==
this
.
_lines
.
length
)
{
return
false
;
}
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
if
(
lines
[
i
]
!==
this
.
_lines
[
i
])
{
return
false
;
}
}
return
true
;
}
get
document
():
vscode
.
TextDocument
{
if
(
!
this
.
_document
)
{
const
data
=
this
;
this
.
_document
=
{
get
uri
()
{
return
data
.
_uri
;
},
get
fileName
()
{
return
data
.
_uri
.
fsPath
;
},
get
isUntitled
()
{
return
data
.
_uri
.
scheme
!==
'
file
'
;
},
get
languageId
()
{
return
data
.
_languageId
;
},
get
version
()
{
return
data
.
_versionId
;
},
get
isDirty
()
{
return
data
.
_isDirty
;
},
save
()
{
return
data
.
_proxy
.
$trySaveDocument
(
data
.
_uri
);
},
getText
(
range
?)
{
return
range
?
data
.
_getTextInRange
(
range
)
:
data
.
getText
();
},
get
lineCount
()
{
return
data
.
_lines
.
length
;
},
lineAt
(
lineOrPos
)
{
return
data
.
lineAt
(
lineOrPos
);
},
offsetAt
(
pos
)
{
return
data
.
offsetAt
(
pos
);
},
positionAt
(
offset
)
{
return
data
.
positionAt
(
offset
);
},
validateRange
(
ran
)
{
return
data
.
validateRange
(
ran
);
},
validatePosition
(
pos
)
{
return
data
.
validatePosition
(
pos
);
},
getWordRangeAtPosition
(
pos
,
regexp
?)
{
return
data
.
getWordRangeAtPosition
(
pos
,
regexp
);
}
};
}
return
this
.
_document
;
}
_acceptLanguageId
(
newLanguageId
:
string
):
void
{
this
.
_languageId
=
newLanguageId
;
}
_acceptIsDirty
(
isDirty
:
boolean
):
void
{
this
.
_isDirty
=
isDirty
;
}
private
_getTextInRange
(
_range
:
vscode
.
Range
):
string
{
let
range
=
this
.
validateRange
(
_range
);
if
(
range
.
isEmpty
)
{
return
''
;
}
if
(
range
.
isSingleLine
)
{
return
this
.
_lines
[
range
.
start
.
line
].
substring
(
range
.
start
.
character
,
range
.
end
.
character
);
}
let
lineEnding
=
this
.
_eol
,
startLineIndex
=
range
.
start
.
line
,
endLineIndex
=
range
.
end
.
line
,
resultLines
:
string
[]
=
[];
resultLines
.
push
(
this
.
_lines
[
startLineIndex
].
substring
(
range
.
start
.
character
));
for
(
let
i
=
startLineIndex
+
1
;
i
<
endLineIndex
;
i
++
)
{
resultLines
.
push
(
this
.
_lines
[
i
]);
}
resultLines
.
push
(
this
.
_lines
[
endLineIndex
].
substring
(
0
,
range
.
end
.
character
));
return
resultLines
.
join
(
lineEnding
);
}
lineAt
(
lineOrPosition
:
number
|
vscode
.
Position
):
vscode
.
TextLine
{
let
line
:
number
;
if
(
lineOrPosition
instanceof
Position
)
{
line
=
lineOrPosition
.
line
;
}
else
if
(
typeof
lineOrPosition
===
'
number
'
)
{
line
=
lineOrPosition
;
}
if
(
line
<
0
||
line
>=
this
.
_lines
.
length
)
{
throw
new
Error
(
'
Illegal value for `line`
'
);
}
let
result
=
this
.
_textLines
[
line
];
if
(
!
result
||
result
.
lineNumber
!==
line
||
result
.
text
!==
this
.
_lines
[
line
])
{
const
text
=
this
.
_lines
[
line
];
const
firstNonWhitespaceCharacterIndex
=
/^
(\s
*
)
/
.
exec
(
text
)[
1
].
length
;
const
range
=
new
Range
(
line
,
0
,
line
,
text
.
length
);
const
rangeIncludingLineBreak
=
line
<
this
.
_lines
.
length
-
1
?
new
Range
(
line
,
0
,
line
+
1
,
0
)
:
range
;
result
=
Object
.
freeze
({
lineNumber
:
line
,
range
,
rangeIncludingLineBreak
,
text
,
firstNonWhitespaceCharacterIndex
,
//TODO@api, rename to 'leadingWhitespaceLength'
isEmptyOrWhitespace
:
firstNonWhitespaceCharacterIndex
===
text
.
length
});
this
.
_textLines
[
line
]
=
result
;
}
return
result
;
}
offsetAt
(
position
:
vscode
.
Position
):
number
{
position
=
this
.
validatePosition
(
position
);
this
.
_ensureLineStarts
();
return
this
.
_lineStarts
.
getAccumulatedValue
(
position
.
line
-
1
)
+
position
.
character
;
}
positionAt
(
offset
:
number
):
vscode
.
Position
{
offset
=
Math
.
floor
(
offset
);
offset
=
Math
.
max
(
0
,
offset
);
this
.
_ensureLineStarts
();
let
out
=
this
.
_lineStarts
.
getIndexOf
(
offset
);
let
lineLength
=
this
.
_lines
[
out
.
index
].
length
;
// Ensure we return a valid position
return
new
Position
(
out
.
index
,
Math
.
min
(
out
.
remainder
,
lineLength
));
}
// ---- range math
validateRange
(
range
:
vscode
.
Range
):
vscode
.
Range
{
if
(
!
(
range
instanceof
Range
))
{
throw
new
Error
(
'
Invalid argument
'
);
}
let
start
=
this
.
validatePosition
(
range
.
start
);
let
end
=
this
.
validatePosition
(
range
.
end
);
if
(
start
===
range
.
start
&&
end
===
range
.
end
)
{
return
range
;
}
return
new
Range
(
start
.
line
,
start
.
character
,
end
.
line
,
end
.
character
);
}
validatePosition
(
position
:
vscode
.
Position
):
vscode
.
Position
{
if
(
!
(
position
instanceof
Position
))
{
throw
new
Error
(
'
Invalid argument
'
);
}
let
{
line
,
character
}
=
position
;
let
hasChanged
=
false
;
if
(
line
<
0
)
{
line
=
0
;
character
=
0
;
hasChanged
=
true
;
}
else
if
(
line
>=
this
.
_lines
.
length
)
{
line
=
this
.
_lines
.
length
-
1
;
character
=
this
.
_lines
[
line
].
length
;
hasChanged
=
true
;
}
else
{
let
maxCharacter
=
this
.
_lines
[
line
].
length
;
if
(
character
<
0
)
{
character
=
0
;
hasChanged
=
true
;
}
else
if
(
character
>
maxCharacter
)
{
character
=
maxCharacter
;
hasChanged
=
true
;
}
}
if
(
!
hasChanged
)
{
return
position
;
}
return
new
Position
(
line
,
character
);
}
getWordRangeAtPosition
(
_position
:
vscode
.
Position
,
regexp
?:
RegExp
):
vscode
.
Range
{
let
position
=
this
.
validatePosition
(
_position
);
if
(
!
regexp
||
regExpLeadsToEndlessLoop
(
regexp
))
{
regexp
=
getWordDefinitionFor
(
this
.
_languageId
);
}
let
wordAtText
=
getWordAtText
(
position
.
character
+
1
,
ensureValidWordDefinition
(
regexp
),
this
.
_lines
[
position
.
line
],
0
);
if
(
wordAtText
)
{
return
new
Range
(
position
.
line
,
wordAtText
.
startColumn
-
1
,
position
.
line
,
wordAtText
.
endColumn
-
1
);
}
return
undefined
;
}
}
src/vs/workbench/api/node/extHostDocumentsAndEditors.ts
0 → 100644
浏览文件 @
1239cebb
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
MainContext
,
ExtHostDocumentsAndEditorsShape
,
IDocumentsAndEditorsDelta
}
from
'
./extHost.protocol
'
;
import
{
ExtHostDocumentData
}
from
'
./extHostDocumentData
'
;
import
{
ExtHostTextEditor
}
from
'
./extHostTextEditor
'
;
import
{
IThreadService
}
from
'
vs/workbench/services/thread/common/threadService
'
;
import
*
as
assert
from
'
assert
'
;
import
*
as
typeConverters
from
'
./extHostTypeConverters
'
;
export
class
ExtHostDocumentsAndEditors
extends
ExtHostDocumentsAndEditorsShape
{
private
_activeEditorId
:
string
;
private
readonly
_editors
=
new
Map
<
string
,
ExtHostTextEditor
>
();
private
readonly
_documents
=
new
Map
<
string
,
ExtHostDocumentData
>
();
private
readonly
_onDidAddDocuments
=
new
Emitter
<
ExtHostDocumentData
[]
>
();
private
readonly
_onDidRemoveDocuments
=
new
Emitter
<
ExtHostDocumentData
[]
>
();
private
readonly
_onDidChangeVisibleTextEditors
=
new
Emitter
<
ExtHostTextEditor
[]
>
();
private
readonly
_onDidChangeActiveTextEditor
=
new
Emitter
<
ExtHostTextEditor
>
();
readonly
onDidAddDocuments
:
Event
<
ExtHostDocumentData
[]
>
=
this
.
_onDidAddDocuments
.
event
;
readonly
onDidRemoveDocuments
:
Event
<
ExtHostDocumentData
[]
>
=
this
.
_onDidRemoveDocuments
.
event
;
readonly
onDidChangeVisibleTextEditors
:
Event
<
ExtHostTextEditor
[]
>
=
this
.
_onDidChangeVisibleTextEditors
.
event
;
readonly
onDidChangeActiveTextEditor
:
Event
<
ExtHostTextEditor
>
=
this
.
_onDidChangeActiveTextEditor
.
event
;
constructor
(
@
IThreadService
private
_threadService
:
IThreadService
)
{
super
();
}
$acceptDocumentsAndEditorsDelta
(
delta
:
IDocumentsAndEditorsDelta
):
void
{
const
removedDocuments
:
ExtHostDocumentData
[]
=
[];
const
addedDocuments
:
ExtHostDocumentData
[]
=
[];
const
removedEditors
:
ExtHostTextEditor
[]
=
[];
if
(
delta
.
removedDocuments
)
{
for
(
const
id
of
delta
.
removedDocuments
)
{
const
data
=
this
.
_documents
.
get
(
id
);
this
.
_documents
.
delete
(
id
);
removedDocuments
.
push
(
data
);
}
}
if
(
delta
.
addedDocuments
)
{
for
(
const
data
of
delta
.
addedDocuments
)
{
assert
.
ok
(
!
this
.
_documents
.
has
(
data
.
url
.
toString
()),
`document '
${
data
.
url
}
already exists!'`
);
const
documentData
=
new
ExtHostDocumentData
(
this
.
_threadService
.
get
(
MainContext
.
MainThreadDocuments
),
data
.
url
,
data
.
lines
,
data
.
EOL
,
data
.
modeId
,
data
.
versionId
,
data
.
isDirty
);
this
.
_documents
.
set
(
data
.
url
.
toString
(),
documentData
);
addedDocuments
.
push
(
documentData
);
}
}
if
(
delta
.
removedEditors
)
{
for
(
const
id
of
delta
.
removedEditors
)
{
const
editor
=
this
.
_editors
.
get
(
id
);
this
.
_editors
.
delete
(
id
);
removedEditors
.
push
(
editor
);
}
}
if
(
delta
.
addedEditors
)
{
for
(
const
data
of
delta
.
addedEditors
)
{
assert
.
ok
(
this
.
_documents
.
has
(
data
.
document
.
toString
()),
`document '
${
data
.
document
}
' does not exist`
);
assert
.
ok
(
!
this
.
_editors
.
has
(
data
.
id
),
`editor '
${
data
.
id
}
' already exists!`
);
const
documentData
=
this
.
_documents
.
get
(
data
.
document
.
toString
());
const
editor
=
new
ExtHostTextEditor
(
this
.
_threadService
.
get
(
MainContext
.
MainThreadEditors
),
data
.
id
,
documentData
,
data
.
selections
.
map
(
typeConverters
.
toSelection
),
data
.
options
,
typeConverters
.
toViewColumn
(
data
.
editorPosition
)
);
this
.
_editors
.
set
(
data
.
id
,
editor
);
}
}
if
(
delta
.
newActiveEditor
!==
undefined
)
{
assert
.
ok
(
delta
.
newActiveEditor
===
null
||
this
.
_editors
.
has
(
delta
.
newActiveEditor
),
`active editor '
${
delta
.
newActiveEditor
}
' does not exist`
);
this
.
_activeEditorId
=
delta
.
newActiveEditor
;
}
// now that the internal state is complete, fire events
if
(
delta
.
removedDocuments
)
{
this
.
_onDidRemoveDocuments
.
fire
(
removedDocuments
);
}
if
(
delta
.
addedDocuments
)
{
this
.
_onDidAddDocuments
.
fire
(
addedDocuments
);
}
if
(
delta
.
removedEditors
||
delta
.
addedEditors
)
{
this
.
_onDidChangeVisibleTextEditors
.
fire
(
this
.
allEditors
());
}
if
(
delta
.
newActiveEditor
)
{
this
.
_onDidChangeActiveTextEditor
.
fire
(
this
.
activeEditor
());
}
// now that the events are out, dispose removed documents and editors
dispose
(
removedDocuments
);
dispose
(
removedEditors
);
}
getDocument
(
strUrl
:
string
):
ExtHostDocumentData
{
return
this
.
_documents
.
get
(
strUrl
);
}
allDocuments
():
ExtHostDocumentData
[]
{
const
result
:
ExtHostDocumentData
[]
=
[];
this
.
_documents
.
forEach
(
data
=>
result
.
push
(
data
));
return
result
;
}
getEditor
(
id
:
string
):
ExtHostTextEditor
{
return
this
.
_editors
.
get
(
id
);
}
activeEditor
():
ExtHostTextEditor
|
undefined
{
if
(
!
this
.
_activeEditorId
)
{
return
undefined
;
}
else
{
return
this
.
_editors
.
get
(
this
.
_activeEditorId
);
}
}
allEditors
():
ExtHostTextEditor
[]
{
const
result
:
ExtHostTextEditor
[]
=
[];
this
.
_editors
.
forEach
(
data
=>
result
.
push
(
data
));
return
result
;
}
}
src/vs/workbench/api/node/extHost
Editors
.ts
→
src/vs/workbench/api/node/extHost
TextEditor
.ts
浏览文件 @
1239cebb
...
...
@@ -4,174 +4,19 @@
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
{
readonly
,
illegalArgument
}
from
'
vs/base/common/errors
'
;
import
{
equals
as
arrayEquals
}
from
'
vs/base/common/arrays
'
;
import
{
IdGenerator
}
from
'
vs/base/common/idGenerator
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IThreadService
}
from
'
vs/workbench/services/thread/common/threadService
'
;
import
{
ExtHostDocuments
,
ExtHostDocumentData
}
from
'
vs/workbench/api/node/extHostDocuments
'
;
import
{
Selection
,
Range
,
Position
,
EndOfLine
,
TextEditorRevealType
,
TextEditorSelectionChangeKind
,
TextEditorLineNumbersStyle
,
SnippetString
}
from
'
./extHostTypes
'
;
import
{
ExtHostDocumentData
}
from
'
vs/workbench/api/node/extHostDocumentData
'
;
import
{
Selection
,
Range
,
Position
,
EndOfLine
,
TextEditorRevealType
,
TextEditorLineNumbersStyle
,
SnippetString
}
from
'
./extHostTypes
'
;
import
{
ISingleEditOperation
,
TextEditorCursorStyle
,
IRange
}
from
'
vs/editor/common/editorCommon
'
;
import
{
IResolvedTextEditorConfiguration
,
I
SelectionChangeEvent
,
ITextEditorConfigurationUpdate
}
from
'
vs/workbench/api/node/mainThreadEditorsTracke
r
'
;
import
{
IResolvedTextEditorConfiguration
,
I
TextEditorConfigurationUpdate
}
from
'
vs/workbench/api/node/mainThreadEdito
r
'
;
import
*
as
TypeConverters
from
'
./extHostTypeConverters
'
;
import
{
Main
Context
,
MainThreadEditorsShape
,
ExtHostEditorsShape
,
ITextEditorAddData
,
ITextEditorPositionData
}
from
'
./extHost.protocol
'
;
import
{
Main
ThreadEditorsShape
}
from
'
./extHost.protocol
'
;
import
*
as
vscode
from
'
vscode
'
;
export
class
ExtHostEditors
extends
ExtHostEditorsShape
{
public
onDidChangeTextEditorSelection
:
Event
<
vscode
.
TextEditorSelectionChangeEvent
>
;
private
_onDidChangeTextEditorSelection
:
Emitter
<
vscode
.
TextEditorSelectionChangeEvent
>
;
public
onDidChangeTextEditorOptions
:
Event
<
vscode
.
TextEditorOptionsChangeEvent
>
;
private
_onDidChangeTextEditorOptions
:
Emitter
<
vscode
.
TextEditorOptionsChangeEvent
>
;
public
onDidChangeTextEditorViewColumn
:
Event
<
vscode
.
TextEditorViewColumnChangeEvent
>
;
private
_onDidChangeTextEditorViewColumn
:
Emitter
<
vscode
.
TextEditorViewColumnChangeEvent
>
;
private
_editors
:
Map
<
string
,
ExtHostTextEditor
>
;
private
_proxy
:
MainThreadEditorsShape
;
private
_onDidChangeActiveTextEditor
:
Emitter
<
vscode
.
TextEditor
>
;
private
_onDidChangeVisibleTextEditors
:
Emitter
<
vscode
.
TextEditor
[]
>
;
private
_extHostDocuments
:
ExtHostDocuments
;
private
_activeEditorId
:
string
;
private
_visibleEditorIds
:
string
[];
constructor
(
threadService
:
IThreadService
,
extHostDocuments
:
ExtHostDocuments
)
{
super
();
this
.
_onDidChangeTextEditorSelection
=
new
Emitter
<
vscode
.
TextEditorSelectionChangeEvent
>
();
this
.
onDidChangeTextEditorSelection
=
this
.
_onDidChangeTextEditorSelection
.
event
;
this
.
_onDidChangeTextEditorOptions
=
new
Emitter
<
vscode
.
TextEditorOptionsChangeEvent
>
();
this
.
onDidChangeTextEditorOptions
=
this
.
_onDidChangeTextEditorOptions
.
event
;
this
.
_onDidChangeTextEditorViewColumn
=
new
Emitter
<
vscode
.
TextEditorViewColumnChangeEvent
>
();
this
.
onDidChangeTextEditorViewColumn
=
this
.
_onDidChangeTextEditorViewColumn
.
event
;
this
.
_extHostDocuments
=
extHostDocuments
;
this
.
_proxy
=
threadService
.
get
(
MainContext
.
MainThreadEditors
);
this
.
_onDidChangeActiveTextEditor
=
new
Emitter
<
vscode
.
TextEditor
>
();
this
.
_onDidChangeVisibleTextEditors
=
new
Emitter
<
vscode
.
TextEditor
[]
>
();
this
.
_editors
=
new
Map
<
string
,
ExtHostTextEditor
>
();
this
.
_visibleEditorIds
=
[];
}
getActiveTextEditor
():
vscode
.
TextEditor
{
return
this
.
_editors
.
get
(
this
.
_activeEditorId
);
}
getVisibleTextEditors
():
vscode
.
TextEditor
[]
{
return
this
.
_visibleEditorIds
.
map
(
id
=>
this
.
_editors
.
get
(
id
));
}
get
onDidChangeActiveTextEditor
():
Event
<
vscode
.
TextEditor
>
{
return
this
.
_onDidChangeActiveTextEditor
&&
this
.
_onDidChangeActiveTextEditor
.
event
;
}
get
onDidChangeVisibleTextEditors
():
Event
<
vscode
.
TextEditor
[]
>
{
return
this
.
_onDidChangeVisibleTextEditors
&&
this
.
_onDidChangeVisibleTextEditors
.
event
;
}
showTextDocument
(
document
:
vscode
.
TextDocument
,
column
:
vscode
.
ViewColumn
,
preserveFocus
:
boolean
):
TPromise
<
vscode
.
TextEditor
>
{
return
this
.
_proxy
.
$tryShowTextDocument
(
<
URI
>
document
.
uri
,
TypeConverters
.
fromViewColumn
(
column
),
preserveFocus
).
then
(
id
=>
{
let
editor
=
this
.
_editors
.
get
(
id
);
if
(
editor
)
{
return
editor
;
}
else
{
throw
new
Error
(
`Failed to show text document
${
document
.
uri
.
toString
()}
, should show in editor #
${
id
}
`
);
}
});
}
createTextEditorDecorationType
(
options
:
vscode
.
DecorationRenderOptions
):
vscode
.
TextEditorDecorationType
{
return
new
TextEditorDecorationType
(
this
.
_proxy
,
options
);
}
// --- called from main thread
$acceptTextEditorAdd
(
data
:
ITextEditorAddData
):
void
{
let
document
=
this
.
_extHostDocuments
.
getDocumentData
(
data
.
document
);
let
newEditor
=
new
ExtHostTextEditor
(
this
.
_proxy
,
data
.
id
,
document
,
data
.
selections
.
map
(
TypeConverters
.
toSelection
),
data
.
options
,
TypeConverters
.
toViewColumn
(
data
.
editorPosition
));
this
.
_editors
.
set
(
data
.
id
,
newEditor
);
}
$acceptOptionsChanged
(
id
:
string
,
opts
:
IResolvedTextEditorConfiguration
):
void
{
let
editor
=
this
.
_editors
.
get
(
id
);
editor
.
_acceptOptions
(
opts
);
this
.
_onDidChangeTextEditorOptions
.
fire
({
textEditor
:
editor
,
options
:
opts
});
}
$acceptSelectionsChanged
(
id
:
string
,
event
:
ISelectionChangeEvent
):
void
{
const
kind
=
TextEditorSelectionChangeKind
.
fromValue
(
event
.
source
);
const
selections
=
event
.
selections
.
map
(
TypeConverters
.
toSelection
);
const
textEditor
=
this
.
_editors
.
get
(
id
);
textEditor
.
_acceptSelections
(
selections
);
this
.
_onDidChangeTextEditorSelection
.
fire
({
textEditor
,
selections
,
kind
});
}
$acceptActiveEditorAndVisibleEditors
(
id
:
string
,
visibleIds
:
string
[]):
void
{
let
visibleChanged
=
false
;
let
activeChanged
=
false
;
if
(
!
arrayEquals
(
this
.
_visibleEditorIds
,
visibleIds
))
{
this
.
_visibleEditorIds
=
visibleIds
;
visibleChanged
=
true
;
}
if
(
this
.
_activeEditorId
!==
id
)
{
this
.
_activeEditorId
=
id
;
activeChanged
=
true
;
}
if
(
visibleChanged
)
{
this
.
_onDidChangeVisibleTextEditors
.
fire
(
this
.
getVisibleTextEditors
());
}
if
(
activeChanged
)
{
this
.
_onDidChangeActiveTextEditor
.
fire
(
this
.
getActiveTextEditor
());
}
}
$acceptEditorPositionData
(
data
:
ITextEditorPositionData
):
void
{
for
(
let
id
in
data
)
{
let
textEditor
=
this
.
_editors
.
get
(
id
);
let
viewColumn
=
TypeConverters
.
toViewColumn
(
data
[
id
]);
if
(
textEditor
.
viewColumn
!==
viewColumn
)
{
textEditor
.
_acceptViewColumn
(
viewColumn
);
this
.
_onDidChangeTextEditorViewColumn
.
fire
({
textEditor
,
viewColumn
});
}
}
}
$acceptTextEditorRemove
(
id
:
string
):
void
{
// make sure the removed editor is not visible
let
newVisibleEditors
=
this
.
_visibleEditorIds
.
filter
(
visibleEditorId
=>
visibleEditorId
!==
id
);
if
(
this
.
_activeEditorId
===
id
)
{
// removing the current active editor
this
.
$acceptActiveEditorAndVisibleEditors
(
undefined
,
newVisibleEditors
);
}
else
{
this
.
$acceptActiveEditorAndVisibleEditors
(
this
.
_activeEditorId
,
newVisibleEditors
);
}
let
editor
=
this
.
_editors
.
get
(
id
);
editor
.
dispose
();
this
.
_editors
.
delete
(
id
);
}
}
class
TextEditorDecorationType
implements
vscode
.
TextEditorDecorationType
{
export
class
TextEditorDecorationType
implements
vscode
.
TextEditorDecorationType
{
private
static
_Keys
=
new
IdGenerator
(
'
TextEditorDecorationType
'
);
...
...
@@ -467,7 +312,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
}
class
ExtHostTextEditor
implements
vscode
.
TextEditor
{
export
class
ExtHostTextEditor
implements
vscode
.
TextEditor
{
private
_proxy
:
MainThreadEditorsShape
;
private
_id
:
string
;
...
...
@@ -630,7 +475,7 @@ class ExtHostTextEditor implements vscode.TextEditor {
ranges
=
this
.
_selections
.
map
(
TypeConverters
.
fromRange
);
}
else
if
(
where
instanceof
Position
)
{
const
{
lineNumber
,
column
}
=
TypeConverters
.
fromPosition
(
where
);
const
{
lineNumber
,
column
}
=
TypeConverters
.
fromPosition
(
where
);
ranges
=
[{
startLineNumber
:
lineNumber
,
startColumn
:
column
,
endLineNumber
:
lineNumber
,
endColumn
:
column
}];
}
else
if
(
where
instanceof
Range
)
{
...
...
@@ -641,7 +486,7 @@ class ExtHostTextEditor implements vscode.TextEditor {
if
(
posOrRange
instanceof
Range
)
{
ranges
.
push
(
TypeConverters
.
fromRange
(
posOrRange
));
}
else
{
const
{
lineNumber
,
column
}
=
TypeConverters
.
fromPosition
(
posOrRange
);
const
{
lineNumber
,
column
}
=
TypeConverters
.
fromPosition
(
posOrRange
);
ranges
.
push
({
startLineNumber
:
lineNumber
,
startColumn
:
column
,
endLineNumber
:
lineNumber
,
endColumn
:
column
});
}
}
...
...
src/vs/workbench/api/node/extHostTextEditors.ts
0 → 100644
浏览文件 @
1239cebb
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IThreadService
}
from
'
vs/workbench/services/thread/common/threadService
'
;
import
{
TextEditorSelectionChangeKind
}
from
'
./extHostTypes
'
;
import
{
IResolvedTextEditorConfiguration
,
ISelectionChangeEvent
}
from
'
vs/workbench/api/node/mainThreadEditor
'
;
import
*
as
TypeConverters
from
'
./extHostTypeConverters
'
;
import
{
TextEditorDecorationType
}
from
'
./extHostTextEditor
'
;
import
{
ExtHostDocumentsAndEditors
}
from
'
./extHostDocumentsAndEditors
'
;
import
{
MainContext
,
MainThreadEditorsShape
,
ExtHostEditorsShape
,
ITextEditorPositionData
}
from
'
./extHost.protocol
'
;
import
*
as
vscode
from
'
vscode
'
;
export
class
ExtHostEditors
extends
ExtHostEditorsShape
{
private
readonly
_onDidChangeTextEditorSelection
=
new
Emitter
<
vscode
.
TextEditorSelectionChangeEvent
>
();
private
readonly
_onDidChangeTextEditorOptions
=
new
Emitter
<
vscode
.
TextEditorOptionsChangeEvent
>
();
private
readonly
_onDidChangeTextEditorViewColumn
=
new
Emitter
<
vscode
.
TextEditorViewColumnChangeEvent
>
();
private
readonly
_onDidChangeActiveTextEditor
=
new
Emitter
<
vscode
.
TextEditor
>
();
private
readonly
_onDidChangeVisibleTextEditors
=
new
Emitter
<
vscode
.
TextEditor
[]
>
();
readonly
onDidChangeTextEditorSelection
:
Event
<
vscode
.
TextEditorSelectionChangeEvent
>
=
this
.
_onDidChangeTextEditorSelection
.
event
;
readonly
onDidChangeTextEditorOptions
:
Event
<
vscode
.
TextEditorOptionsChangeEvent
>
=
this
.
_onDidChangeTextEditorOptions
.
event
;
readonly
onDidChangeTextEditorViewColumn
:
Event
<
vscode
.
TextEditorViewColumnChangeEvent
>
=
this
.
_onDidChangeTextEditorViewColumn
.
event
;
readonly
onDidChangeActiveTextEditor
:
Event
<
vscode
.
TextEditor
>
=
this
.
_onDidChangeActiveTextEditor
.
event
;
readonly
onDidChangeVisibleTextEditors
:
Event
<
vscode
.
TextEditor
[]
>
=
this
.
_onDidChangeVisibleTextEditors
.
event
;
private
_proxy
:
MainThreadEditorsShape
;
private
_extHostDocumentsAndEditors
:
ExtHostDocumentsAndEditors
;
constructor
(
threadService
:
IThreadService
,
extHostDocumentsAndEditors
:
ExtHostDocumentsAndEditors
,
)
{
super
();
this
.
_proxy
=
threadService
.
get
(
MainContext
.
MainThreadEditors
);
this
.
_extHostDocumentsAndEditors
=
extHostDocumentsAndEditors
;
this
.
_extHostDocumentsAndEditors
.
onDidChangeVisibleTextEditors
(
e
=>
this
.
_onDidChangeVisibleTextEditors
.
fire
(
e
));
this
.
_extHostDocumentsAndEditors
.
onDidChangeActiveTextEditor
(
e
=>
this
.
_onDidChangeActiveTextEditor
.
fire
(
e
));
}
getActiveTextEditor
():
vscode
.
TextEditor
{
return
this
.
_extHostDocumentsAndEditors
.
activeEditor
();
}
getVisibleTextEditors
():
vscode
.
TextEditor
[]
{
return
this
.
_extHostDocumentsAndEditors
.
allEditors
();
}
showTextDocument
(
document
:
vscode
.
TextDocument
,
column
:
vscode
.
ViewColumn
,
preserveFocus
:
boolean
):
TPromise
<
vscode
.
TextEditor
>
{
return
this
.
_proxy
.
$tryShowTextDocument
(
<
URI
>
document
.
uri
,
TypeConverters
.
fromViewColumn
(
column
),
preserveFocus
).
then
(
id
=>
{
let
editor
=
this
.
_extHostDocumentsAndEditors
.
getEditor
(
id
);
if
(
editor
)
{
return
editor
;
}
else
{
throw
new
Error
(
`Failed to show text document
${
document
.
uri
.
toString
()}
, should show in editor #
${
id
}
`
);
}
});
}
createTextEditorDecorationType
(
options
:
vscode
.
DecorationRenderOptions
):
vscode
.
TextEditorDecorationType
{
return
new
TextEditorDecorationType
(
this
.
_proxy
,
options
);
}
// --- called from main thread
$acceptOptionsChanged
(
id
:
string
,
opts
:
IResolvedTextEditorConfiguration
):
void
{
let
editor
=
this
.
_extHostDocumentsAndEditors
.
getEditor
(
id
);
editor
.
_acceptOptions
(
opts
);
this
.
_onDidChangeTextEditorOptions
.
fire
({
textEditor
:
editor
,
options
:
opts
});
}
$acceptSelectionsChanged
(
id
:
string
,
event
:
ISelectionChangeEvent
):
void
{
const
kind
=
TextEditorSelectionChangeKind
.
fromValue
(
event
.
source
);
const
selections
=
event
.
selections
.
map
(
TypeConverters
.
toSelection
);
const
textEditor
=
this
.
_extHostDocumentsAndEditors
.
getEditor
(
id
);
textEditor
.
_acceptSelections
(
selections
);
this
.
_onDidChangeTextEditorSelection
.
fire
({
textEditor
,
selections
,
kind
});
}
$acceptEditorPositionData
(
data
:
ITextEditorPositionData
):
void
{
for
(
let
id
in
data
)
{
let
textEditor
=
this
.
_extHostDocumentsAndEditors
.
getEditor
(
id
);
let
viewColumn
=
TypeConverters
.
toViewColumn
(
data
[
id
]);
if
(
textEditor
.
viewColumn
!==
viewColumn
)
{
textEditor
.
_acceptViewColumn
(
viewColumn
);
this
.
_onDidChangeTextEditorViewColumn
.
fire
({
textEditor
,
viewColumn
});
}
}
}
}
src/vs/workbench/api/node/mainThreadDocuments.ts
浏览文件 @
1239cebb
...
...
@@ -20,8 +20,10 @@ import { ExtHostContext, MainThreadDocumentsShape, ExtHostDocumentsShape } from
import
{
ITextModelResolverService
}
from
'
vs/editor/common/services/resolverService
'
;
import
{
ICodeEditorService
}
from
'
vs/editor/common/services/codeEditorService
'
;
import
{
ITextSource
}
from
'
vs/editor/common/model/textSource
'
;
import
{
MainThreadDocumentsAndEditors
}
from
'
./mainThreadDocumentsAndEditors
'
;
export
class
MainThreadDocuments
extends
MainThreadDocumentsShape
{
private
_modelService
:
IModelService
;
private
_modeService
:
IModeService
;
private
_textModelResolverService
:
ITextModelResolverService
;
...
...
@@ -36,6 +38,7 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
private
_resourceContentProvider
:
{
[
handle
:
number
]:
IDisposable
};
constructor
(
documentsAndEditors
:
MainThreadDocumentsAndEditors
,
@
IThreadService
threadService
:
IThreadService
,
@
IModelService
modelService
:
IModelService
,
@
IModeService
modeService
:
IModeService
,
...
...
@@ -57,8 +60,8 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
this
.
_modelIsSynced
=
{};
this
.
_toDispose
=
[];
modelService
.
onModelAdded
(
this
.
_onModelAdded
,
this
,
this
.
_toDispose
);
modelService
.
onModelRemoved
(
this
.
_onModelRemoved
,
this
,
this
.
_toDispose
);
this
.
_toDispose
.
push
(
documentsAndEditors
.
onDocumentAdd
(
models
=>
models
.
forEach
(
this
.
_onModelAdded
,
this
))
);
this
.
_toDispose
.
push
(
documentsAndEditors
.
onDocumentRemove
(
urls
=>
urls
.
forEach
(
this
.
_onModelRemoved
,
this
))
);
modelService
.
onModelModeChanged
(
this
.
_onModelModeChanged
,
this
,
this
.
_toDispose
);
this
.
_toDispose
.
push
(
textFileService
.
models
.
onModelSaved
(
e
=>
{
...
...
@@ -103,14 +106,6 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
let
modelUrl
=
model
.
uri
;
this
.
_modelIsSynced
[
modelUrl
.
toString
()]
=
true
;
this
.
_modelToDisposeMap
[
modelUrl
.
toString
()]
=
model
.
addBulkListener
((
events
)
=>
this
.
_onModelEvents
(
modelUrl
,
events
));
this
.
_proxy
.
$acceptModelAdd
({
url
:
model
.
uri
,
versionId
:
model
.
getVersionId
(),
lines
:
model
.
getLinesContent
(),
EOL
:
model
.
getEOL
(),
modeId
:
model
.
getLanguageIdentifier
().
language
,
isDirty
:
this
.
_textFileService
.
isDirty
(
modelUrl
)
});
}
private
_onModelModeChanged
(
event
:
{
model
:
editorCommon
.
IModel
;
oldModeId
:
string
;
}):
void
{
...
...
@@ -122,15 +117,14 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
this
.
_proxy
.
$acceptModelModeChanged
(
model
.
uri
.
toString
(),
oldModeId
,
model
.
getLanguageIdentifier
().
language
);
}
private
_onModelRemoved
(
model
:
editorCommon
.
IModel
):
void
{
let
modelUrl
=
model
.
uri
;
if
(
!
this
.
_modelIsSynced
[
modelUrl
.
toString
()
])
{
private
_onModelRemoved
(
model
Url
:
string
):
void
{
if
(
!
this
.
_modelIsSynced
[
modelUrl
])
{
return
;
}
delete
this
.
_modelIsSynced
[
modelUrl
.
toString
()];
this
.
_modelToDisposeMap
[
modelUrl
.
toString
()].
dispose
();
delete
this
.
_modelToDisposeMap
[
modelUrl
.
toString
()];
this
.
_proxy
.
$acceptModelRemoved
(
modelUrl
.
toString
());
delete
this
.
_modelIsSynced
[
modelUrl
];
this
.
_modelToDisposeMap
[
modelUrl
].
dispose
();
delete
this
.
_modelToDisposeMap
[
modelUrl
];
}
private
_onModelEvents
(
modelUrl
:
URI
,
events
:
EmitterEvent
[]):
void
{
...
...
@@ -246,6 +240,7 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
if
(
!
model
)
{
return
;
}
const
raw
:
ITextSource
=
{
lines
:
value
.
lines
,
length
:
value
.
length
,
...
...
src/vs/workbench/api/node/mainThreadDocumentsAndEditors.ts
0 → 100644
浏览文件 @
1239cebb
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
IModel
,
ICommonCodeEditor
,
isCommonCodeEditor
,
isCommonDiffEditor
}
from
'
vs/editor/common/editorCommon
'
;
import
{
compare
}
from
'
vs/base/common/strings
'
;
import
{
delta
}
from
'
vs/base/common/arrays
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
ICodeEditorService
}
from
'
vs/editor/common/services/codeEditorService
'
;
import
Event
,
{
Emitter
,
any
}
from
'
vs/base/common/event
'
;
import
{
ExtHostContext
,
ExtHostDocumentsAndEditorsShape
,
IModelAddedData
,
ITextEditorAddData
,
IDocumentsAndEditorsDelta
}
from
'
./extHost.protocol
'
;
import
{
MainThreadTextEditor
}
from
'
vs/workbench/api/node/mainThreadEditor
'
;
import
{
IThreadService
}
from
'
vs/workbench/services/thread/common/threadService
'
;
import
{
ITextFileService
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
Position
as
EditorPosition
,
IEditor
}
from
'
vs/platform/editor/common/editor
'
;
namespace
cmp
{
export
function
compareModels
(
a
:
IModel
,
b
:
IModel
):
number
{
return
compare
(
a
.
uri
.
toString
(),
b
.
uri
.
toString
());
}
export
function
compareEditors
(
a
:
EditorAndModel
,
b
:
EditorAndModel
):
number
{
let
ret
=
compare
(
a
.
editor
.
getId
(),
b
.
editor
.
getId
());
if
(
ret
===
0
)
{
ret
=
compare
(
a
.
document
.
uri
.
toString
(),
b
.
document
.
uri
.
toString
());
}
return
ret
;
}
}
class
EditorAndModel
{
readonly
id
:
string
;
constructor
(
readonly
editor
:
ICommonCodeEditor
,
readonly
document
:
IModel
,
)
{
this
.
id
=
`
${
editor
.
getId
()}
,
${
document
.
uri
.
toString
()}
`
;
}
}
class
DocumentAndEditorStateDelta
{
readonly
isEmpty
:
boolean
;
constructor
(
readonly
removedDocuments
:
IModel
[],
readonly
addedDocuments
:
IModel
[],
readonly
removedEditors
:
EditorAndModel
[],
readonly
addedEditors
:
EditorAndModel
[],
readonly
oldActiveEditor
:
string
,
readonly
newActiveEditor
:
string
,
)
{
this
.
isEmpty
=
this
.
removedDocuments
.
length
===
0
&&
this
.
addedDocuments
.
length
===
0
&&
this
.
removedEditors
.
length
===
0
&&
this
.
addedEditors
.
length
===
0
&&
oldActiveEditor
===
newActiveEditor
;
}
toString
():
string
{
let
ret
=
'
DocumentAndEditorStateDelta
\n
'
;
ret
+=
`\tRemoved Documents: [
${
this
.
removedDocuments
.
map
(
d
=>
d
.
uri
.
toString
(
true
)).
join
(
'
,
'
)}
]\n`
;
ret
+=
`\tAdded Documents: [
${
this
.
addedDocuments
.
map
(
d
=>
d
.
uri
.
toString
(
true
)).
join
(
'
,
'
)}
]\n`
;
ret
+=
`\tRemoved Editors: [
${
this
.
removedEditors
.
map
(
e
=>
e
.
id
).
join
(
'
,
'
)}
]\n`
;
ret
+=
`\tAdded Editors: [
${
this
.
addedEditors
.
map
(
e
=>
e
.
id
).
join
(
'
,
'
)}
]\n`
;
ret
+=
`\tNew Active Editor:
${
this
.
newActiveEditor
}
\n`
;
return
ret
;
}
}
class
DocumentAndEditorState
{
static
compute
(
before
:
DocumentAndEditorState
,
after
:
DocumentAndEditorState
):
DocumentAndEditorStateDelta
{
if
(
!
before
)
{
return
new
DocumentAndEditorStateDelta
([],
after
.
documents
,
[],
after
.
editors
,
undefined
,
after
.
activeEditor
);
}
const
documentDelta
=
delta
(
before
.
documents
,
after
.
documents
,
cmp
.
compareModels
);
const
editorDelta
=
delta
(
before
.
editors
,
after
.
editors
,
cmp
.
compareEditors
);
const
oldActiveEditor
=
before
.
activeEditor
!==
after
.
activeEditor
?
before
.
activeEditor
:
undefined
;
const
newActiveEditor
=
before
.
activeEditor
!==
after
.
activeEditor
?
after
.
activeEditor
:
undefined
;
return
new
DocumentAndEditorStateDelta
(
documentDelta
.
removed
,
documentDelta
.
added
,
editorDelta
.
removed
,
editorDelta
.
added
,
oldActiveEditor
,
newActiveEditor
);
}
constructor
(
readonly
documents
:
IModel
[],
readonly
editors
:
EditorAndModel
[],
readonly
activeEditor
:
string
,
)
{
this
.
documents
=
documents
.
sort
(
cmp
.
compareModels
);
this
.
editors
=
editors
.
sort
(
cmp
.
compareEditors
);
}
}
class
MainThreadDocumentAndEditorStateComputer
{
private
_toDispose
:
IDisposable
[]
=
[];
private
_toDisposeOnEditorRemove
=
new
Map
<
string
,
IDisposable
>
();
private
_onDidChangeState
=
new
Emitter
<
DocumentAndEditorStateDelta
>
();
private
_currentState
:
DocumentAndEditorState
;
readonly
onDidChangeState
:
Event
<
DocumentAndEditorStateDelta
>
=
this
.
_onDidChangeState
.
event
;
constructor
(
@
IModelService
private
_modelService
:
IModelService
,
@
ICodeEditorService
private
_codeEditorService
:
ICodeEditorService
,
@
IWorkbenchEditorService
private
_workbenchEditorService
:
IWorkbenchEditorService
)
{
this
.
_modelService
.
onModelAdded
(
this
.
_updateState
,
this
,
this
.
_toDispose
);
this
.
_modelService
.
onModelRemoved
(
this
.
_updateState
,
this
,
this
.
_toDispose
);
this
.
_codeEditorService
.
onCodeEditorAdd
(
this
.
_onDidAddEditor
,
this
,
this
.
_toDispose
);
this
.
_codeEditorService
.
onCodeEditorRemove
(
this
.
_onDidRemoveEditor
,
this
,
this
.
_toDispose
);
// this._updateState();
}
dispose
():
void
{
this
.
_toDispose
=
dispose
(
this
.
_toDispose
);
}
private
_onDidAddEditor
(
e
:
ICommonCodeEditor
):
void
{
const
listener
=
any
<
any
>
(
e
.
onDidChangeModel
,
e
.
onDidFocusEditor
,
e
.
onDidBlurEditor
)(
this
.
_updateState
,
this
);
this
.
_toDisposeOnEditorRemove
.
set
(
e
.
getId
(),
listener
);
this
.
_updateState
();
}
private
_onDidRemoveEditor
(
e
:
ICommonCodeEditor
):
void
{
const
sub
=
this
.
_toDisposeOnEditorRemove
.
get
(
e
.
getId
());
if
(
sub
)
{
this
.
_toDisposeOnEditorRemove
.
delete
(
e
.
getId
());
sub
.
dispose
();
this
.
_updateState
();
}
}
private
_updateState
():
void
{
// models: ignore too large models
const
models
=
this
.
_modelService
.
getModels
();
for
(
let
i
=
0
;
i
<
models
.
length
;
i
++
)
{
if
(
models
[
i
].
isTooLargeForHavingARichMode
())
{
models
.
splice
(
i
,
1
);
i
--
;
}
}
// editor: only take those that have a not too large model
const
editors
:
EditorAndModel
[]
=
[];
let
activeEditor
:
string
=
null
;
for
(
const
editor
of
this
.
_codeEditorService
.
listCodeEditors
())
{
const
model
=
editor
.
getModel
();
if
(
model
&&
!
model
.
isTooLargeForHavingARichMode
()
&&
!
model
.
isDisposed
()
// model disposed
&&
Boolean
(
this
.
_modelService
.
getModel
(
model
.
uri
))
// model disposing, the flag didn't flip yet but the model service already removed it
)
{
const
apiEditor
=
new
EditorAndModel
(
editor
,
model
);
editors
.
push
(
apiEditor
);
if
(
editor
.
isFocused
())
{
activeEditor
=
apiEditor
.
id
;
}
}
}
// active editor: if none of the previous editors had focus we try
// to match the action workbench editor with one of editor we have
// just computed
if
(
!
activeEditor
)
{
const
workbenchEditor
=
this
.
_workbenchEditorService
.
getActiveEditor
();
if
(
workbenchEditor
)
{
const
workbenchEditorControl
=
workbenchEditor
.
getControl
();
let
candidate
:
ICommonCodeEditor
;
if
(
isCommonCodeEditor
(
workbenchEditorControl
))
{
candidate
=
workbenchEditorControl
;
}
else
if
(
isCommonDiffEditor
(
workbenchEditorControl
))
{
candidate
=
workbenchEditorControl
.
getModifiedEditor
();
}
if
(
candidate
)
{
for
(
const
{
editor
,
id
}
of
editors
)
{
if
(
candidate
===
editor
)
{
activeEditor
=
id
;
break
;
}
}
}
}
}
// compute new state and compare against old
const
newState
=
new
DocumentAndEditorState
(
models
,
editors
,
activeEditor
);
const
delta
=
DocumentAndEditorState
.
compute
(
this
.
_currentState
,
newState
);
if
(
!
delta
.
isEmpty
)
{
this
.
_currentState
=
newState
;
this
.
_onDidChangeState
.
fire
(
delta
);
}
}
}
export
class
MainThreadDocumentsAndEditors
{
private
_toDispose
:
IDisposable
[];
private
_proxy
:
ExtHostDocumentsAndEditorsShape
;
private
_stateComputer
:
MainThreadDocumentAndEditorStateComputer
;
private
_editors
=
<
{
[
id
:
string
]:
MainThreadTextEditor
}
>
Object
.
create
(
null
);
private
_onTextEditorAdd
=
new
Emitter
<
MainThreadTextEditor
[]
>
();
private
_onTextEditorRemove
=
new
Emitter
<
string
[]
>
();
private
_onDocumentAdd
=
new
Emitter
<
IModel
[]
>
();
private
_onDocumentRemove
=
new
Emitter
<
string
[]
>
();
readonly
onTextEditorAdd
:
Event
<
MainThreadTextEditor
[]
>
=
this
.
_onTextEditorAdd
.
event
;
readonly
onTextEditorRemove
:
Event
<
string
[]
>
=
this
.
_onTextEditorRemove
.
event
;
readonly
onDocumentAdd
:
Event
<
IModel
[]
>
=
this
.
_onDocumentAdd
.
event
;
readonly
onDocumentRemove
:
Event
<
string
[]
>
=
this
.
_onDocumentRemove
.
event
;
constructor
(
@
IModelService
private
_modelService
:
IModelService
,
@
ITextFileService
private
_textFileService
:
ITextFileService
,
@
IWorkbenchEditorService
private
_workbenchEditorService
:
IWorkbenchEditorService
,
@
IThreadService
threadService
:
IThreadService
,
@
ICodeEditorService
codeEditorService
:
ICodeEditorService
,
)
{
this
.
_proxy
=
threadService
.
get
(
ExtHostContext
.
ExtHostDocumentsAndEditors
);
this
.
_stateComputer
=
new
MainThreadDocumentAndEditorStateComputer
(
_modelService
,
codeEditorService
,
_workbenchEditorService
);
this
.
_toDispose
=
[
this
.
_stateComputer
,
this
.
_stateComputer
.
onDidChangeState
(
this
.
_onDelta
,
this
)
];
}
dispose
():
void
{
this
.
_toDispose
=
dispose
(
this
.
_toDispose
);
}
private
_onDelta
(
delta
:
DocumentAndEditorStateDelta
):
void
{
let
removedDocuments
:
string
[];
let
removedEditors
:
string
[]
=
[];
let
addedEditors
:
MainThreadTextEditor
[]
=
[];
// removed models
removedDocuments
=
delta
.
removedDocuments
.
map
(
m
=>
m
.
uri
.
toString
());
// added editors
for
(
const
apiEditor
of
delta
.
addedEditors
)
{
const
mainThreadEditor
=
new
MainThreadTextEditor
(
apiEditor
.
id
,
apiEditor
.
document
,
apiEditor
.
editor
,
{
onGainedFocus
()
{
},
onLostFocus
()
{
}
},
this
.
_modelService
);
this
.
_editors
[
apiEditor
.
id
]
=
mainThreadEditor
;
addedEditors
.
push
(
mainThreadEditor
);
}
// removed editors
for
(
const
{
id
}
of
delta
.
removedEditors
)
{
const
mainThreadEditor
=
this
.
_editors
[
id
];
if
(
mainThreadEditor
)
{
mainThreadEditor
.
dispose
();
delete
this
.
_editors
[
id
];
removedEditors
.
push
(
id
);
}
}
let
extHostDelta
:
IDocumentsAndEditorsDelta
=
Object
.
create
(
null
);
let
empty
=
true
;
if
(
delta
.
newActiveEditor
!==
undefined
)
{
empty
=
false
;
extHostDelta
.
newActiveEditor
=
delta
.
newActiveEditor
;
}
if
(
removedDocuments
.
length
>
0
)
{
empty
=
false
;
extHostDelta
.
removedDocuments
=
removedDocuments
;
}
if
(
removedEditors
.
length
>
0
)
{
empty
=
false
;
extHostDelta
.
removedEditors
=
removedEditors
;
}
if
(
delta
.
addedDocuments
.
length
>
0
)
{
empty
=
false
;
extHostDelta
.
addedDocuments
=
delta
.
addedDocuments
.
map
(
m
=>
this
.
_toModelAddData
(
m
));
}
if
(
delta
.
addedEditors
.
length
>
0
)
{
empty
=
false
;
extHostDelta
.
addedEditors
=
addedEditors
.
map
(
e
=>
this
.
_toTextEditorAddData
(
e
));
}
if
(
!
empty
)
{
// first update ext host
this
.
_proxy
.
$acceptDocumentsAndEditorsDelta
(
extHostDelta
);
// second update dependent state listener
this
.
_onDocumentRemove
.
fire
(
removedDocuments
);
this
.
_onDocumentAdd
.
fire
(
delta
.
addedDocuments
);
this
.
_onTextEditorRemove
.
fire
(
removedEditors
);
this
.
_onTextEditorAdd
.
fire
(
addedEditors
);
}
}
private
_toModelAddData
(
model
:
IModel
):
IModelAddedData
{
return
{
url
:
model
.
uri
,
versionId
:
model
.
getVersionId
(),
lines
:
model
.
getLinesContent
(),
EOL
:
model
.
getEOL
(),
modeId
:
model
.
getLanguageIdentifier
().
language
,
isDirty
:
this
.
_textFileService
.
isDirty
(
model
.
uri
)
};
}
private
_toTextEditorAddData
(
textEditor
:
MainThreadTextEditor
):
ITextEditorAddData
{
return
{
id
:
textEditor
.
getId
(),
document
:
textEditor
.
getModel
().
uri
,
options
:
textEditor
.
getConfiguration
(),
selections
:
textEditor
.
getSelections
(),
editorPosition
:
this
.
_findEditorPosition
(
textEditor
)
};
}
private
_findEditorPosition
(
editor
:
MainThreadTextEditor
):
EditorPosition
{
for
(
let
workbenchEditor
of
this
.
_workbenchEditorService
.
getVisibleEditors
())
{
if
(
editor
.
matches
(
workbenchEditor
))
{
return
workbenchEditor
.
position
;
}
}
return
undefined
;
}
findTextEditorIdFor
(
editor
:
IEditor
):
string
{
for
(
let
id
in
this
.
_editors
)
{
if
(
this
.
_editors
[
id
].
matches
(
editor
))
{
return
id
;
}
}
return
undefined
;
}
getEditor
(
id
:
string
):
MainThreadTextEditor
{
return
this
.
_editors
[
id
];
}
}
src/vs/workbench/api/node/mainThreadEditor
sTracker
.ts
→
src/vs/workbench/api/node/mainThreadEditor.ts
浏览文件 @
1239cebb
...
...
@@ -7,11 +7,8 @@
import
EditorCommon
=
require
(
'
vs/editor/common/editorCommon
'
);
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
IEditor
}
from
'
vs/platform/editor/common/editor
'
;
import
{
ICodeEditorService
}
from
'
vs/editor/common/services/codeEditorService
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
RunOnceScheduler
}
from
'
vs/base/common/async
'
;
import
{
IdGenerator
}
from
'
vs/base/common/idGenerator
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
import
{
SnippetController
}
from
'
vs/editor/contrib/snippet/common/snippetController
'
;
...
...
@@ -131,6 +128,10 @@ export class MainThreadTextEditor {
return
this
.
_model
;
}
public
getCodeEditor
():
EditorCommon
.
ICommonCodeEditor
{
return
this
.
_codeEditor
;
}
public
hasCodeEditor
(
codeEditor
:
EditorCommon
.
ICommonCodeEditor
):
boolean
{
return
(
this
.
_codeEditor
===
codeEditor
);
}
...
...
@@ -413,324 +414,3 @@ export class MainThreadTextEditor {
return
true
;
}
}
/**
* Keeps track of what goes on in the main thread and maps models => text editors
*/
export
class
MainThreadEditorsTracker
{
private
static
_Ids
=
new
IdGenerator
(
''
);
private
_toDispose
:
IDisposable
[];
private
_codeEditorService
:
ICodeEditorService
;
private
_modelService
:
IModelService
;
private
_updateMapping
:
RunOnceScheduler
;
private
_editorModelChangeListeners
:
{
[
editorId
:
string
]:
IDisposable
;
};
private
_model2TextEditors
:
{
[
modelUri
:
string
]:
MainThreadTextEditor
[];
};
private
_focusedTextEditorId
:
string
;
private
_visibleTextEditorIds
:
string
[];
private
_onTextEditorAdd
:
Emitter
<
MainThreadTextEditor
>
;
private
_onTextEditorRemove
:
Emitter
<
MainThreadTextEditor
>
;
private
_onDidChangeFocusedTextEditor
:
Emitter
<
string
>
;
private
_onDidUpdateTextEditors
:
Emitter
<
void
>
;
private
_focusTracker
:
IFocusTracker
;
constructor
(
editorService
:
ICodeEditorService
,
modelService
:
IModelService
)
{
this
.
_codeEditorService
=
editorService
;
this
.
_modelService
=
modelService
;
this
.
_toDispose
=
[];
this
.
_focusedTextEditorId
=
null
;
this
.
_visibleTextEditorIds
=
[];
this
.
_editorModelChangeListeners
=
Object
.
create
(
null
);
this
.
_model2TextEditors
=
Object
.
create
(
null
);
this
.
_onTextEditorAdd
=
new
Emitter
<
MainThreadTextEditor
>
();
this
.
_onTextEditorRemove
=
new
Emitter
<
MainThreadTextEditor
>
();
this
.
_onDidUpdateTextEditors
=
new
Emitter
<
void
>
();
this
.
_onDidChangeFocusedTextEditor
=
new
Emitter
<
string
>
();
this
.
_focusTracker
=
{
onGainedFocus
:
()
=>
this
.
_updateFocusedTextEditor
(),
onLostFocus
:
()
=>
this
.
_updateFocusedTextEditor
()
};
this
.
_modelService
.
onModelAdded
(
this
.
_onModelAdded
,
this
,
this
.
_toDispose
);
this
.
_modelService
.
onModelRemoved
(
this
.
_onModelRemoved
,
this
,
this
.
_toDispose
);
this
.
_codeEditorService
.
onCodeEditorAdd
(
this
.
_onCodeEditorAdd
,
this
,
this
.
_toDispose
);
this
.
_codeEditorService
.
onCodeEditorRemove
(
this
.
_onCodeEditorRemove
,
this
,
this
.
_toDispose
);
this
.
_updateMapping
=
new
RunOnceScheduler
(()
=>
this
.
_doUpdateMapping
(),
0
);
this
.
_toDispose
.
push
(
this
.
_updateMapping
);
}
public
dispose
():
void
{
this
.
_toDispose
=
dispose
(
this
.
_toDispose
);
}
private
_onModelAdded
(
model
:
EditorCommon
.
IModel
):
void
{
this
.
_updateMapping
.
schedule
();
}
private
_onModelRemoved
(
model
:
EditorCommon
.
IModel
):
void
{
this
.
_updateMapping
.
schedule
();
}
private
_onCodeEditorAdd
(
codeEditor
:
EditorCommon
.
ICommonCodeEditor
):
void
{
this
.
_editorModelChangeListeners
[
codeEditor
.
getId
()]
=
codeEditor
.
onDidChangeModel
(
_
=>
this
.
_updateMapping
.
schedule
());
this
.
_updateMapping
.
schedule
();
}
private
_onCodeEditorRemove
(
codeEditor
:
EditorCommon
.
ICommonCodeEditor
):
void
{
this
.
_editorModelChangeListeners
[
codeEditor
.
getId
()].
dispose
();
delete
this
.
_editorModelChangeListeners
[
codeEditor
.
getId
()];
this
.
_updateMapping
.
schedule
();
}
private
_doUpdateMapping
():
void
{
let
allModels
=
this
.
_modelService
.
getModels
();
// Same filter as in extHostDocuments
allModels
=
allModels
.
filter
((
model
)
=>
!
model
.
isTooLargeForHavingARichMode
());
let
allModelsMap
:
{
[
modelUri
:
string
]:
EditorCommon
.
IModel
;
}
=
Object
.
create
(
null
);
allModels
.
forEach
((
model
)
=>
{
allModelsMap
[
model
.
uri
.
toString
()]
=
model
;
});
// Remove text editors for models that no longer exist
Object
.
keys
(
this
.
_model2TextEditors
).
forEach
((
modelUri
)
=>
{
if
(
allModelsMap
[
modelUri
])
{
// model still exists, will be updated below
return
;
}
let
textEditorsToRemove
=
this
.
_model2TextEditors
[
modelUri
];
delete
this
.
_model2TextEditors
[
modelUri
];
for
(
let
i
=
0
;
i
<
textEditorsToRemove
.
length
;
i
++
)
{
this
.
_onTextEditorRemove
.
fire
(
textEditorsToRemove
[
i
]);
textEditorsToRemove
[
i
].
dispose
();
}
});
// Handle all visible models
let
visibleModels
=
this
.
_getVisibleModels
();
Object
.
keys
(
visibleModels
).
forEach
((
modelUri
)
=>
{
let
model
=
visibleModels
[
modelUri
].
model
;
let
codeEditors
=
visibleModels
[
modelUri
].
codeEditors
;
if
(
!
this
.
_model2TextEditors
[
modelUri
])
{
this
.
_model2TextEditors
[
modelUri
]
=
[];
}
let
existingTextEditors
=
this
.
_model2TextEditors
[
modelUri
];
// Remove text editors if more exist
while
(
existingTextEditors
.
length
>
codeEditors
.
length
)
{
let
removedTextEditor
=
existingTextEditors
.
pop
();
this
.
_onTextEditorRemove
.
fire
(
removedTextEditor
);
removedTextEditor
.
dispose
();
}
// Adjust remaining text editors
for
(
let
i
=
0
;
i
<
existingTextEditors
.
length
;
i
++
)
{
existingTextEditors
[
i
].
setCodeEditor
(
codeEditors
[
i
]);
}
// Create new editors as needed
for
(
let
i
=
existingTextEditors
.
length
;
i
<
codeEditors
.
length
;
i
++
)
{
let
newTextEditor
=
new
MainThreadTextEditor
(
MainThreadEditorsTracker
.
_Ids
.
nextId
(),
model
,
codeEditors
[
i
],
this
.
_focusTracker
,
this
.
_modelService
);
existingTextEditors
.
push
(
newTextEditor
);
this
.
_onTextEditorAdd
.
fire
(
newTextEditor
);
}
});
// Handle all not visible models
allModels
.
forEach
((
model
)
=>
{
let
modelUri
=
model
.
uri
.
toString
();
if
(
visibleModels
[
modelUri
])
{
// model is visible, already handled above
return
;
}
if
(
!
this
.
_model2TextEditors
[
modelUri
])
{
this
.
_model2TextEditors
[
modelUri
]
=
[];
}
let
existingTextEditors
=
this
.
_model2TextEditors
[
modelUri
];
// Remove extra text editors
while
(
existingTextEditors
.
length
>
1
)
{
let
removedTextEditor
=
existingTextEditors
.
pop
();
this
.
_onTextEditorRemove
.
fire
(
removedTextEditor
);
removedTextEditor
.
dispose
();
}
// Create new editor if needed or adjust it
if
(
existingTextEditors
.
length
===
0
)
{
let
newTextEditor
=
new
MainThreadTextEditor
(
MainThreadEditorsTracker
.
_Ids
.
nextId
(),
model
,
null
,
this
.
_focusTracker
,
this
.
_modelService
);
existingTextEditors
.
push
(
newTextEditor
);
this
.
_onTextEditorAdd
.
fire
(
newTextEditor
);
}
else
{
existingTextEditors
[
0
].
setCodeEditor
(
null
);
}
});
this
.
_printState
();
this
.
_visibleTextEditorIds
=
this
.
_findVisibleTextEditorIds
();
this
.
_updateFocusedTextEditor
();
// this is a sync event
this
.
_onDidUpdateTextEditors
.
fire
(
undefined
);
}
private
_updateFocusedTextEditor
():
void
{
this
.
_setFocusedTextEditorId
(
this
.
_findFocusedTextEditorId
());
}
private
_findFocusedTextEditorId
():
string
{
let
modelUris
=
Object
.
keys
(
this
.
_model2TextEditors
);
for
(
let
i
=
0
,
len
=
modelUris
.
length
;
i
<
len
;
i
++
)
{
let
editors
=
this
.
_model2TextEditors
[
modelUris
[
i
]];
for
(
let
j
=
0
,
lenJ
=
editors
.
length
;
j
<
lenJ
;
j
++
)
{
if
(
editors
[
j
].
isFocused
())
{
return
editors
[
j
].
getId
();
}
}
}
return
null
;
}
private
_findVisibleTextEditorIds
():
string
[]
{
let
result
:
string
[]
=
[];
let
modelUris
=
Object
.
keys
(
this
.
_model2TextEditors
);
for
(
let
i
=
0
,
len
=
modelUris
.
length
;
i
<
len
;
i
++
)
{
let
editors
=
this
.
_model2TextEditors
[
modelUris
[
i
]];
for
(
let
j
=
0
,
lenJ
=
editors
.
length
;
j
<
lenJ
;
j
++
)
{
if
(
editors
[
j
].
isVisible
())
{
result
.
push
(
editors
[
j
].
getId
());
}
}
}
result
.
sort
();
return
result
;
}
private
_setFocusedTextEditorId
(
focusedTextEditorId
:
string
):
void
{
if
(
this
.
_focusedTextEditorId
===
focusedTextEditorId
)
{
// no change
return
;
}
this
.
_focusedTextEditorId
=
focusedTextEditorId
;
this
.
_printState
();
this
.
_onDidChangeFocusedTextEditor
.
fire
(
this
.
_focusedTextEditorId
);
}
private
_printState
():
void
{
// console.log('----------------------');
// Object.keys(this._model2TextEditors).forEach((modelUri) => {
// let editors = this._model2TextEditors[modelUri];
// console.log(editors.map((e) => {
// return e.getId() + " (" + (e.getId() === this._focusedTextEditorId ? 'FOCUSED, ': '') + modelUri + ")";
// }).join('\n'));
// });
}
private
_getVisibleModels
():
IVisibleModels
{
let
r
:
IVisibleModels
=
{};
let
allCodeEditors
=
this
.
_codeEditorService
.
listCodeEditors
();
// Maintain a certain sorting such that the mapping doesn't change too much all the time
allCodeEditors
.
sort
((
a
,
b
)
=>
strcmp
(
a
.
getId
(),
b
.
getId
()));
allCodeEditors
.
forEach
((
codeEditor
)
=>
{
let
model
=
codeEditor
.
getModel
();
if
(
!
model
||
model
.
isTooLargeForHavingARichMode
()
||
!
this
.
_modelService
.
getModel
(
model
.
uri
))
{
return
;
}
let
modelUri
=
model
.
uri
.
toString
();
r
[
modelUri
]
=
r
[
modelUri
]
||
{
model
:
model
,
codeEditors
:
[]
};
r
[
modelUri
].
codeEditors
.
push
(
codeEditor
);
});
return
r
;
}
public
getFocusedTextEditorId
():
string
{
return
this
.
_focusedTextEditorId
;
}
public
getVisibleTextEditorIds
():
string
[]
{
return
this
.
_visibleTextEditorIds
;
}
public
get
onTextEditorAdd
():
Event
<
MainThreadTextEditor
>
{
return
this
.
_onTextEditorAdd
.
event
;
}
public
get
onTextEditorRemove
():
Event
<
MainThreadTextEditor
>
{
return
this
.
_onTextEditorRemove
.
event
;
}
public
get
onDidUpdateTextEditors
():
Event
<
void
>
{
return
this
.
_onDidUpdateTextEditors
.
event
;
}
public
get
onChangedFocusedTextEditor
():
Event
<
string
>
{
return
this
.
_onDidChangeFocusedTextEditor
.
event
;
}
public
findTextEditorIdFor
(
codeEditor
:
EditorCommon
.
ICommonCodeEditor
):
string
{
let
modelUris
=
Object
.
keys
(
this
.
_model2TextEditors
);
for
(
let
i
=
0
,
len
=
modelUris
.
length
;
i
<
len
;
i
++
)
{
let
editors
=
this
.
_model2TextEditors
[
modelUris
[
i
]];
for
(
let
j
=
0
,
lenJ
=
editors
.
length
;
j
<
lenJ
;
j
++
)
{
if
(
editors
[
j
].
hasCodeEditor
(
codeEditor
))
{
return
editors
[
j
].
getId
();
}
}
}
return
null
;
}
public
registerTextEditorDecorationType
(
key
:
string
,
options
:
EditorCommon
.
IDecorationRenderOptions
):
void
{
this
.
_codeEditorService
.
registerDecorationType
(
key
,
options
);
}
public
removeTextEditorDecorationType
(
key
:
string
):
void
{
this
.
_codeEditorService
.
removeDecorationType
(
key
);
}
}
interface
IVisibleModels
{
[
modelUri
:
string
]:
{
model
:
EditorCommon
.
IModel
;
codeEditors
:
EditorCommon
.
ICommonCodeEditor
[];
};
}
function
strcmp
(
a
:
string
,
b
:
string
):
number
{
if
(
a
<
b
)
{
return
-
1
;
}
if
(
a
>
b
)
{
return
1
;
}
return
0
;
}
src/vs/workbench/api/node/mainThreadEditors.ts
浏览文件 @
1239cebb
...
...
@@ -8,58 +8,47 @@ import URI from 'vs/base/common/uri';
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IThreadService
}
from
'
vs/workbench/services/thread/common/threadService
'
;
import
{
ISingleEditOperation
,
ISelection
,
IRange
,
I
Editor
,
EditorType
,
ICommonCodeEditor
,
ICommonDiffEditor
,
I
DecorationRenderOptions
,
IDecorationOptions
}
from
'
vs/editor/common/editorCommon
'
;
import
{
ISingleEditOperation
,
ISelection
,
IRange
,
IDecorationRenderOptions
,
IDecorationOptions
}
from
'
vs/editor/common/editorCommon
'
;
import
{
ICodeEditorService
}
from
'
vs/editor/common/services/codeEditorService
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IEditorGroupService
}
from
'
vs/workbench/services/group/common/groupService
'
;
import
{
Position
as
EditorPosition
}
from
'
vs/platform/editor/common/editor
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
MainThread
EditorsTracker
,
TextEditorRevealType
,
MainThreadTextEditor
,
IApplyEditsOptions
,
IUndoStopOptions
,
ITextEditorConfigurationUpdate
}
from
'
vs/workbench/api/node/mainThreadEditorsTracker
'
;
import
{
TextEditorRevealType
,
MainThreadTextEditor
,
IApplyEditsOptions
,
IUndoStopOptions
,
ITextEditorConfigurationUpdate
}
from
'
vs/workbench/api/node/mainThreadEditor
'
;
import
{
MainThread
DocumentsAndEditors
}
from
'
./mainThreadDocumentsAndEditors
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
equals
as
arrayEquals
}
from
'
vs/base/common/arrays
'
;
import
{
equals
as
objectEquals
}
from
'
vs/base/common/objects
'
;
import
{
ExtHostContext
,
MainThreadEditorsShape
,
ExtHostEditorsShape
,
ITextEditorPositionData
}
from
'
./extHost.protocol
'
;
export
class
MainThreadEditors
extends
MainThreadEditorsShape
{
private
_proxy
:
ExtHostEditorsShape
;
private
_documentsAndEditors
:
MainThreadDocumentsAndEditors
;
private
_workbenchEditorService
:
IWorkbenchEditorService
;
private
_telemetryService
:
ITelemetryService
;
private
_editorTracker
:
MainThreadEditorsTracker
;
private
_toDispose
:
IDisposable
[];
private
_textEditorsListenersMap
:
{
[
editorId
:
string
]:
IDisposable
[];
};
private
_textEditorsMap
:
{
[
editorId
:
string
]:
MainThreadTextEditor
;
};
private
_activeTextEditor
:
string
;
private
_visibleEditors
:
string
[];
private
_editorPositionData
:
ITextEditorPositionData
;
constructor
(
documentsAndEditors
:
MainThreadDocumentsAndEditors
,
@
ICodeEditorService
private
_codeEditorService
:
ICodeEditorService
,
@
IThreadService
threadService
:
IThreadService
,
@
IWorkbenchEditorService
workbenchEditorService
:
IWorkbenchEditorService
,
@
IEditorGroupService
editorGroupService
:
IEditorGroupService
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
@
ICodeEditorService
editorService
:
ICodeEditorService
,
@
IModelService
modelService
:
IModelService
@
ITelemetryService
telemetryService
:
ITelemetryService
)
{
super
();
this
.
_proxy
=
threadService
.
get
(
ExtHostContext
.
ExtHostEditors
);
this
.
_documentsAndEditors
=
documentsAndEditors
;
this
.
_workbenchEditorService
=
workbenchEditorService
;
this
.
_telemetryService
=
telemetryService
;
this
.
_toDispose
=
[];
this
.
_textEditorsListenersMap
=
Object
.
create
(
null
);
this
.
_textEditorsMap
=
Object
.
create
(
null
);
this
.
_activeTextEditor
=
null
;
this
.
_visibleEditors
=
[];
this
.
_editorPositionData
=
null
;
this
.
_
editorTracker
=
new
MainThreadEditorsTracker
(
editorService
,
modelService
);
this
.
_toDispose
.
push
(
this
.
_editorTracker
);
this
.
_
toDispose
.
push
(
documentsAndEditors
.
onTextEditorAdd
(
editors
=>
editors
.
forEach
(
this
.
_onTextEditorAdd
,
this
))
);
this
.
_toDispose
.
push
(
documentsAndEditors
.
onTextEditorRemove
(
editors
=>
editors
.
forEach
(
this
.
_onTextEditorRemove
,
this
))
);
this
.
_toDispose
.
push
(
this
.
_editorTracker
.
onTextEditorAdd
((
textEditor
)
=>
this
.
_onTextEditorAdd
(
textEditor
)));
this
.
_toDispose
.
push
(
this
.
_editorTracker
.
onTextEditorRemove
((
textEditor
)
=>
this
.
_onTextEditorRemove
(
textEditor
)));
this
.
_toDispose
.
push
(
this
.
_editorTracker
.
onDidUpdateTextEditors
(()
=>
this
.
_updateActiveAndVisibleTextEditors
()));
this
.
_toDispose
.
push
(
this
.
_editorTracker
.
onChangedFocusedTextEditor
((
focusedTextEditorId
)
=>
this
.
_updateActiveAndVisibleTextEditors
()));
this
.
_toDispose
.
push
(
editorGroupService
.
onEditorsChanged
(()
=>
this
.
_updateActiveAndVisibleTextEditors
()));
this
.
_toDispose
.
push
(
editorGroupService
.
onEditorsMoved
(()
=>
this
.
_updateActiveAndVisibleTextEditors
()));
}
...
...
@@ -81,37 +70,17 @@ export class MainThreadEditors extends MainThreadEditorsShape {
toDispose
.
push
(
textEditor
.
onSelectionChanged
((
event
)
=>
{
this
.
_proxy
.
$acceptSelectionsChanged
(
id
,
event
);
}));
this
.
_proxy
.
$acceptTextEditorAdd
({
id
:
id
,
document
:
textEditor
.
getModel
().
uri
,
options
:
textEditor
.
getConfiguration
(),
selections
:
textEditor
.
getSelections
(),
editorPosition
:
this
.
_findEditorPosition
(
textEditor
)
});
this
.
_textEditorsListenersMap
[
id
]
=
toDispose
;
this
.
_textEditorsMap
[
id
]
=
textEditor
;
}
private
_onTextEditorRemove
(
textEditor
:
MainThreadTextEditor
):
void
{
let
id
=
textEditor
.
getId
();
private
_onTextEditorRemove
(
id
:
string
):
void
{
dispose
(
this
.
_textEditorsListenersMap
[
id
]);
delete
this
.
_textEditorsListenersMap
[
id
];
delete
this
.
_textEditorsMap
[
id
];
this
.
_proxy
.
$acceptTextEditorRemove
(
id
);
}
private
_updateActiveAndVisibleTextEditors
():
void
{
// active and visible editors
let
visibleEditors
=
this
.
_editorTracker
.
getVisibleTextEditorIds
();
let
activeEditor
=
this
.
_findActiveTextEditorId
();
if
(
activeEditor
!==
this
.
_activeTextEditor
||
!
arrayEquals
(
this
.
_visibleEditors
,
visibleEditors
,
(
a
,
b
)
=>
a
===
b
))
{
this
.
_activeTextEditor
=
activeEditor
;
this
.
_visibleEditors
=
visibleEditors
;
this
.
_proxy
.
$acceptActiveEditorAndVisibleEditors
(
this
.
_activeTextEditor
,
this
.
_visibleEditors
);
}
// editor columns
let
editorPositionData
=
this
.
_getTextEditorPositionData
();
if
(
!
objectEquals
(
this
.
_editorPositionData
,
editorPositionData
))
{
...
...
@@ -120,55 +89,12 @@ export class MainThreadEditors extends MainThreadEditorsShape {
}
}
private
_findActiveTextEditorId
():
string
{
let
focusedTextEditorId
=
this
.
_editorTracker
.
getFocusedTextEditorId
();
if
(
focusedTextEditorId
)
{
return
focusedTextEditorId
;
}
let
activeEditor
=
this
.
_workbenchEditorService
.
getActiveEditor
();
if
(
!
activeEditor
)
{
return
null
;
}
let
editor
=
<
IEditor
>
activeEditor
.
getControl
();
// Substitute for (editor instanceof ICodeEditor)
if
(
!
editor
||
typeof
editor
.
getEditorType
!==
'
function
'
)
{
// Not a text editor...
return
null
;
}
if
(
editor
.
getEditorType
()
===
EditorType
.
ICodeEditor
)
{
return
this
.
_editorTracker
.
findTextEditorIdFor
(
<
ICommonCodeEditor
>
editor
);
}
// Must be a diff editor => use the modified side
return
this
.
_editorTracker
.
findTextEditorIdFor
((
<
ICommonDiffEditor
>
editor
).
getModifiedEditor
());
}
private
_findEditorPosition
(
editor
:
MainThreadTextEditor
):
EditorPosition
{
for
(
let
workbenchEditor
of
this
.
_workbenchEditorService
.
getVisibleEditors
())
{
if
(
editor
.
matches
(
workbenchEditor
))
{
return
workbenchEditor
.
position
;
}
}
return
undefined
;
}
private
_getTextEditorPositionData
():
ITextEditorPositionData
{
let
result
:
ITextEditorPositionData
=
Object
.
create
(
null
);
for
(
let
workbenchEditor
of
this
.
_workbenchEditorService
.
getVisibleEditors
())
{
let
editor
=
<
IEditor
>
workbenchEditor
.
getControl
();
// Substitute for (editor instanceof ICodeEditor)
if
(
!
editor
||
typeof
editor
.
getEditorType
!==
'
function
'
)
{
// Not a text editor...
continue
;
}
if
(
editor
.
getEditorType
()
===
EditorType
.
ICodeEditor
)
{
let
id
=
this
.
_editorTracker
.
findTextEditorIdFor
(
<
ICommonCodeEditor
>
editor
);
if
(
id
)
{
result
[
id
]
=
workbenchEditor
.
position
;
}
const
id
=
this
.
_documentsAndEditors
.
findTextEditorIdFor
(
workbenchEditor
);
if
(
id
)
{
result
[
id
]
=
workbenchEditor
.
position
;
}
}
return
result
;
...
...
@@ -187,43 +113,7 @@ export class MainThreadEditors extends MainThreadEditorsShape {
if
(
!
editor
)
{
return
undefined
;
}
const
findEditor
=
():
string
=>
{
// find the editor we have just opened and return the
// id we have assigned to it.
for
(
let
id
in
this
.
_textEditorsMap
)
{
if
(
this
.
_textEditorsMap
[
id
].
matches
(
editor
))
{
return
id
;
}
}
return
undefined
;
};
const
syncEditorId
=
findEditor
();
if
(
syncEditorId
)
{
return
TPromise
.
as
(
syncEditorId
);
}
return
new
TPromise
<
void
>
(
resolve
=>
{
// not very nice but the way it is: changes to the editor state aren't
// send to the ext host as they happen but stuff is delayed a little. in
// order to provide the real editor on #openTextEditor we need to sync on
// that update
let
subscription
:
IDisposable
;
let
handle
:
number
;
function
contd
()
{
subscription
.
dispose
();
clearTimeout
(
handle
);
resolve
(
undefined
);
}
subscription
=
this
.
_editorTracker
.
onDidUpdateTextEditors
(()
=>
{
contd
();
});
handle
=
setTimeout
(()
=>
{
contd
();
},
1000
);
}).
then
(
findEditor
);
return
this
.
_documentsAndEditors
.
findTextEditorIdFor
(
editor
);
});
}
...
...
@@ -231,7 +121,7 @@ export class MainThreadEditors extends MainThreadEditorsShape {
// check how often this is used
this
.
_telemetryService
.
publicLog
(
'
api.deprecated
'
,
{
function
:
'
TextEditor.show
'
});
let
mainThreadEditor
=
this
.
_
textEditorsMap
[
id
]
;
let
mainThreadEditor
=
this
.
_
documentsAndEditors
.
getEditor
(
id
)
;
if
(
mainThreadEditor
)
{
let
model
=
mainThreadEditor
.
getModel
();
return
this
.
_workbenchEditorService
.
openEditor
({
...
...
@@ -246,7 +136,7 @@ export class MainThreadEditors extends MainThreadEditorsShape {
// check how often this is used
this
.
_telemetryService
.
publicLog
(
'
api.deprecated
'
,
{
function
:
'
TextEditor.hide
'
});
let
mainThreadEditor
=
this
.
_
textEditorsMap
[
id
]
;
let
mainThreadEditor
=
this
.
_
documentsAndEditors
.
getEditor
(
id
)
;
if
(
mainThreadEditor
)
{
let
editors
=
this
.
_workbenchEditorService
.
getVisibleEditors
();
for
(
let
editor
of
editors
)
{
...
...
@@ -259,56 +149,57 @@ export class MainThreadEditors extends MainThreadEditorsShape {
}
$trySetSelections
(
id
:
string
,
selections
:
ISelection
[]):
TPromise
<
any
>
{
if
(
!
this
.
_
textEditorsMap
[
id
]
)
{
if
(
!
this
.
_
documentsAndEditors
.
getEditor
(
id
)
)
{
return
TPromise
.
wrapError
(
'
TextEditor disposed
'
);
}
this
.
_
textEditorsMap
[
id
]
.
setSelections
(
selections
);
this
.
_
documentsAndEditors
.
getEditor
(
id
)
.
setSelections
(
selections
);
return
TPromise
.
as
(
null
);
}
$trySetDecorations
(
id
:
string
,
key
:
string
,
ranges
:
IDecorationOptions
[]):
TPromise
<
any
>
{
if
(
!
this
.
_
textEditorsMap
[
id
]
)
{
if
(
!
this
.
_
documentsAndEditors
.
getEditor
(
id
)
)
{
return
TPromise
.
wrapError
(
'
TextEditor disposed
'
);
}
this
.
_
textEditorsMap
[
id
]
.
setDecorations
(
key
,
ranges
);
this
.
_
documentsAndEditors
.
getEditor
(
id
)
.
setDecorations
(
key
,
ranges
);
return
TPromise
.
as
(
null
);
}
$tryRevealRange
(
id
:
string
,
range
:
IRange
,
revealType
:
TextEditorRevealType
):
TPromise
<
any
>
{
if
(
!
this
.
_
textEditorsMap
[
id
]
)
{
if
(
!
this
.
_
documentsAndEditors
.
getEditor
(
id
)
)
{
return
TPromise
.
wrapError
(
'
TextEditor disposed
'
);
}
this
.
_
textEditorsMap
[
id
]
.
revealRange
(
range
,
revealType
);
this
.
_
documentsAndEditors
.
getEditor
(
id
)
.
revealRange
(
range
,
revealType
);
return
undefined
;
}
$trySetOptions
(
id
:
string
,
options
:
ITextEditorConfigurationUpdate
):
TPromise
<
any
>
{
if
(
!
this
.
_
textEditorsMap
[
id
]
)
{
if
(
!
this
.
_
documentsAndEditors
.
getEditor
(
id
)
)
{
return
TPromise
.
wrapError
(
'
TextEditor disposed
'
);
}
this
.
_
textEditorsMap
[
id
]
.
setConfiguration
(
options
);
this
.
_
documentsAndEditors
.
getEditor
(
id
)
.
setConfiguration
(
options
);
return
TPromise
.
as
(
null
);
}
$tryApplyEdits
(
id
:
string
,
modelVersionId
:
number
,
edits
:
ISingleEditOperation
[],
opts
:
IApplyEditsOptions
):
TPromise
<
boolean
>
{
if
(
!
this
.
_
textEditorsMap
[
id
]
)
{
if
(
!
this
.
_
documentsAndEditors
.
getEditor
(
id
)
)
{
return
TPromise
.
wrapError
(
'
TextEditor disposed
'
);
}
return
TPromise
.
as
(
this
.
_
textEditorsMap
[
id
]
.
applyEdits
(
modelVersionId
,
edits
,
opts
));
return
TPromise
.
as
(
this
.
_
documentsAndEditors
.
getEditor
(
id
)
.
applyEdits
(
modelVersionId
,
edits
,
opts
));
}
$tryInsertSnippet
(
id
:
string
,
template
:
string
,
ranges
:
IRange
[],
opts
:
IUndoStopOptions
):
TPromise
<
boolean
>
{
if
(
!
this
.
_
textEditorsMap
[
id
]
)
{
if
(
!
this
.
_
documentsAndEditors
.
getEditor
(
id
)
)
{
return
TPromise
.
wrapError
(
'
TextEditor disposed
'
);
}
return
TPromise
.
as
(
this
.
_
textEditorsMap
[
id
]
.
insertSnippet
(
template
,
ranges
,
opts
));
return
TPromise
.
as
(
this
.
_
documentsAndEditors
.
getEditor
(
id
)
.
insertSnippet
(
template
,
ranges
,
opts
));
}
$registerTextEditorDecorationType
(
key
:
string
,
options
:
IDecorationRenderOptions
):
void
{
this
.
_
editorTracker
.
registerTextEdito
rDecorationType
(
key
,
options
);
this
.
_
codeEditorService
.
registe
rDecorationType
(
key
,
options
);
}
$removeTextEditorDecorationType
(
key
:
string
):
void
{
this
.
_editorTracker
.
removeTextEditorDecorationType
(
key
);
this
.
_codeEditorService
.
removeDecorationType
(
key
);
}
}
src/vs/workbench/test/node/api/extHostApiCommands.test.ts
浏览文件 @
1239cebb
...
...
@@ -27,6 +27,7 @@ import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import
{
ExtHostHeapService
}
from
'
vs/workbench/api/node/extHostHeapService
'
;
import
{
MainThreadCommands
}
from
'
vs/workbench/api/node/mainThreadCommands
'
;
import
{
ExtHostDocuments
}
from
'
vs/workbench/api/node/extHostDocuments
'
;
import
{
ExtHostDocumentsAndEditors
}
from
'
vs/workbench/api/node/extHostDocumentsAndEditors
'
;
import
{
MainContext
,
ExtHostContext
}
from
'
vs/workbench/api/node/extHost.protocol
'
;
import
{
ExtHostDiagnostics
}
from
'
vs/workbench/api/node/extHostDiagnostics
'
;
import
*
as
vscode
from
'
vscode
'
;
...
...
@@ -68,7 +69,7 @@ suite('ExtHostLanguageFeatureCommands', function () {
instantiationService
.
stub
(
ICommandService
,
{
_serviceBrand
:
undefined
,
executeCommand
(
id
,
args
):
any
{
let
{
handler
}
=
CommandsRegistry
.
getCommands
()[
id
];
let
{
handler
}
=
CommandsRegistry
.
getCommands
()[
id
];
return
TPromise
.
as
(
instantiationService
.
invokeFunction
(
handler
,
args
));
}
});
...
...
@@ -88,16 +89,19 @@ suite('ExtHostLanguageFeatureCommands', function () {
getCreationOptions
():
any
{
throw
new
Error
();
}
});
const
extHostDocuments
=
new
ExtHostDocuments
(
threadService
);
threadService
.
set
(
ExtHostContext
.
ExtHostDocuments
,
extHostDocuments
);
extHostDocuments
.
$acceptModelAdd
({
isDirty
:
false
,
versionId
:
model
.
getVersionId
(),
modeId
:
model
.
getLanguageIdentifier
().
language
,
url
:
model
.
uri
,
lines
:
model
.
getValue
().
split
(
model
.
getEOL
()),
EOL
:
model
.
getEOL
(),
const
extHostDocumentsAndEditors
=
new
ExtHostDocumentsAndEditors
(
threadService
);
extHostDocumentsAndEditors
.
$acceptDocumentsAndEditorsDelta
({
addedDocuments
:
[{
isDirty
:
false
,
versionId
:
model
.
getVersionId
(),
modeId
:
model
.
getLanguageIdentifier
().
language
,
url
:
model
.
uri
,
lines
:
model
.
getValue
().
split
(
model
.
getEOL
()),
EOL
:
model
.
getEOL
(),
}]
});
const
extHostDocuments
=
new
ExtHostDocuments
(
threadService
,
extHostDocumentsAndEditors
);
threadService
.
set
(
ExtHostContext
.
ExtHostDocuments
,
extHostDocuments
);
const
heapService
=
new
ExtHostHeapService
();
...
...
src/vs/workbench/test/node/api/extHostDocument
s
.test.ts
→
src/vs/workbench/test/node/api/extHostDocument
Data
.test.ts
浏览文件 @
1239cebb
...
...
@@ -7,13 +7,13 @@
import
*
as
assert
from
'
assert
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
{
ExtHostDocumentData
}
from
'
vs/workbench/api/node/extHostDocument
s
'
;
import
{
ExtHostDocumentData
}
from
'
vs/workbench/api/node/extHostDocument
Data
'
;
import
{
Position
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
{
Range
as
CodeEditorRange
}
from
'
vs/editor/common/core/range
'
;
import
*
as
EditorCommon
from
'
vs/editor/common/editorCommon
'
;
suite
(
'
ExtHostDocument
'
,
()
=>
{
suite
(
'
ExtHostDocument
Data
'
,
()
=>
{
let
data
:
ExtHostDocumentData
;
...
...
@@ -87,7 +87,7 @@ suite('ExtHostDocument', () => {
test
(
'
line, issue #5704
'
,
function
()
{
let
line
=
data
.
document
.
lineAt
(
0
);
let
{
range
,
rangeIncludingLineBreak
}
=
line
;
let
{
range
,
rangeIncludingLineBreak
}
=
line
;
assert
.
equal
(
range
.
end
.
line
,
0
);
assert
.
equal
(
range
.
end
.
character
,
16
);
assert
.
equal
(
rangeIncludingLineBreak
.
end
.
line
,
1
);
...
...
@@ -243,7 +243,7 @@ enum AssertDocumentLineMappingDirection {
PositionToOffset
}
suite
(
'
ExtHostDocument updates line mapping
'
,
()
=>
{
suite
(
'
ExtHostDocument
Data
updates line mapping
'
,
()
=>
{
function
positionToStr
(
position
:
{
line
:
number
;
character
:
number
;
}):
string
{
return
'
(
'
+
position
.
line
+
'
,
'
+
position
.
character
+
'
)
'
;
...
...
src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts
浏览文件 @
1239cebb
...
...
@@ -8,6 +8,7 @@ import * as assert from 'assert';
import
URI
from
'
vs/base/common/uri
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
ExtHostDocuments
}
from
'
vs/workbench/api/node/extHostDocuments
'
;
import
{
ExtHostDocumentsAndEditors
}
from
'
vs/workbench/api/node/extHostDocumentsAndEditors
'
;
import
{
TextDocumentSaveReason
,
TextEdit
,
Position
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
{
MainThreadWorkspaceShape
}
from
'
vs/workbench/api/node/extHost.protocol
'
;
import
{
ExtHostDocumentSaveParticipant
}
from
'
vs/workbench/api/node/extHostDocumentSaveParticipant
'
;
...
...
@@ -23,16 +24,18 @@ suite('ExtHostDocumentSaveParticipant', () => {
let
documents
:
ExtHostDocuments
;
setup
(()
=>
{
documents
=
new
ExtHostDocuments
(
OneGetThreadService
(
null
));
documents
.
$acceptModelAdd
({
isDirty
:
false
,
modeId
:
'
foo
'
,
url
:
resource
,
versionId
:
1
,
lines
:
[
'
foo
'
],
EOL
:
'
\n
'
,
});
const
documentsAndEditors
=
new
ExtHostDocumentsAndEditors
(
OneGetThreadService
(
null
));
documentsAndEditors
.
$acceptDocumentsAndEditorsDelta
({
addedDocuments
:
[{
isDirty
:
false
,
modeId
:
'
foo
'
,
url
:
resource
,
versionId
:
1
,
lines
:
[
'
foo
'
],
EOL
:
'
\n
'
,
}]
});
documents
=
new
ExtHostDocuments
(
OneGetThreadService
(
null
),
documentsAndEditors
);
});
test
(
'
no listeners, no problem
'
,
()
=>
{
...
...
@@ -305,7 +308,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
const
participant
=
new
ExtHostDocumentSaveParticipant
(
documents
,
new
class
extends
MainThreadWorkspaceShape
{
$applyWorkspaceEdit
(
_edits
:
IResourceEdit
[])
{
for
(
const
{
resource
,
newText
,
range
}
of
_edits
)
{
for
(
const
{
resource
,
newText
,
range
}
of
_edits
)
{
documents
.
$acceptModelChanged
(
resource
.
toString
(),
[{
range
,
text
:
newText
,
...
...
src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts
浏览文件 @
1239cebb
...
...
@@ -24,6 +24,7 @@ import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import
{
MainThreadCommands
}
from
'
vs/workbench/api/node/mainThreadCommands
'
;
import
{
IHeapService
}
from
'
vs/workbench/api/node/mainThreadHeapService
'
;
import
{
ExtHostDocuments
}
from
'
vs/workbench/api/node/extHostDocuments
'
;
import
{
ExtHostDocumentsAndEditors
}
from
'
vs/workbench/api/node/extHostDocumentsAndEditors
'
;
import
{
getDocumentSymbols
}
from
'
vs/editor/contrib/quickOpen/common/quickOpen
'
;
import
{
DocumentSymbolProviderRegistry
,
DocumentHighlightKind
}
from
'
vs/editor/common/modes
'
;
import
{
getCodeLensData
}
from
'
vs/editor/contrib/codelens/common/codelens
'
;
...
...
@@ -80,16 +81,19 @@ suite('ExtHostLanguageFeatures', function () {
originalErrorHandler
=
errorHandler
.
getUnexpectedErrorHandler
();
setUnexpectedErrorHandler
(()
=>
{
});
const
extHostDocuments
=
new
ExtHostDocuments
(
threadService
);
threadService
.
set
(
ExtHostContext
.
ExtHostDocuments
,
extHostDocuments
);
extHostDocuments
.
$acceptModelAdd
({
isDirty
:
false
,
versionId
:
model
.
getVersionId
(),
modeId
:
model
.
getLanguageIdentifier
().
language
,
url
:
model
.
uri
,
lines
:
model
.
getValue
().
split
(
model
.
getEOL
()),
EOL
:
model
.
getEOL
(),
const
extHostDocumentsAndEditors
=
new
ExtHostDocumentsAndEditors
(
threadService
);
extHostDocumentsAndEditors
.
$acceptDocumentsAndEditorsDelta
({
addedDocuments
:
[{
isDirty
:
false
,
versionId
:
model
.
getVersionId
(),
modeId
:
model
.
getLanguageIdentifier
().
language
,
url
:
model
.
uri
,
lines
:
model
.
getValue
().
split
(
model
.
getEOL
()),
EOL
:
model
.
getEOL
(),
}]
});
const
extHostDocuments
=
new
ExtHostDocuments
(
threadService
,
extHostDocumentsAndEditors
);
threadService
.
set
(
ExtHostContext
.
ExtHostDocuments
,
extHostDocuments
);
const
heapService
=
new
ExtHostHeapService
();
...
...
src/vs/workbench/test/node/api/extHost
Editors
.test.ts
→
src/vs/workbench/test/node/api/extHost
TextEditor
.test.ts
浏览文件 @
1239cebb
...
...
@@ -8,9 +8,9 @@ import * as assert from 'assert';
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
TextEditorLineNumbersStyle
}
from
'
vs/workbench/api/node/extHostTypes
'
;
import
{
TextEditorCursorStyle
}
from
'
vs/editor/common/editorCommon
'
;
import
{
IResolvedTextEditorConfiguration
,
ITextEditorConfigurationUpdate
}
from
'
vs/workbench/api/node/mainThreadEditor
sTracker
'
;
import
{
IResolvedTextEditorConfiguration
,
ITextEditorConfigurationUpdate
}
from
'
vs/workbench/api/node/mainThreadEditor
'
;
import
{
MainThreadEditorsShape
}
from
'
vs/workbench/api/node/extHost.protocol
'
;
import
{
ExtHostTextEditorOptions
}
from
'
vs/workbench/api/node/extHost
Editors
'
;
import
{
ExtHostTextEditorOptions
}
from
'
vs/workbench/api/node/extHost
TextEditor
'
;
suite
(
'
ExtHostTextEditorOptions
'
,
()
=>
{
...
...
src/vs/workbench/test/node/api/mainThreadDocumentsAndEditors.test.ts
0 → 100644
浏览文件 @
1239cebb
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
MainThreadDocumentsAndEditors
}
from
'
vs/workbench/api/node/mainThreadDocumentsAndEditors
'
;
import
{
OneGetThreadService
}
from
'
./testThreadService
'
;
import
{
TestConfigurationService
}
from
'
vs/platform/configuration/test/common/testConfigurationService
'
;
import
{
ModelServiceImpl
}
from
'
vs/editor/common/services/modelServiceImpl
'
;
import
{
MockCodeEditorService
}
from
'
vs/editor/test/common/mocks/mockCodeEditorService
'
;
import
{
ITextFileService
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
ExtHostDocumentsAndEditorsShape
,
IDocumentsAndEditorsDelta
}
from
'
vs/workbench/api/node/extHost.protocol
'
;
import
{
mockCodeEditor
}
from
'
vs/editor/test/common/mocks/mockCodeEditor
'
;
suite
(
'
MainThreadDocumentsAndEditors
'
,
()
=>
{
let
modelService
:
ModelServiceImpl
;
let
codeEditorService
:
MockCodeEditorService
;
let
textFileService
:
ITextFileService
;
let
workbenchEditorService
:
IWorkbenchEditorService
;
let
documentAndEditor
:
MainThreadDocumentsAndEditors
;
let
deltas
:
IDocumentsAndEditorsDelta
[]
=
[];
setup
(()
=>
{
deltas
.
length
=
0
;
modelService
=
new
ModelServiceImpl
(
null
,
new
TestConfigurationService
());
codeEditorService
=
new
MockCodeEditorService
();
textFileService
=
<
ITextFileService
>
{
isDirty
()
{
return
false
;
}
};
workbenchEditorService
=
<
IWorkbenchEditorService
>
{
getVisibleEditors
()
{
return
[];
},
getActiveEditor
()
{
return
undefined
;
}
};
documentAndEditor
=
new
MainThreadDocumentsAndEditors
(
modelService
,
textFileService
,
workbenchEditorService
,
OneGetThreadService
(
new
class
extends
ExtHostDocumentsAndEditorsShape
{
$acceptDocumentsAndEditorsDelta
(
delta
)
{
deltas
.
push
(
delta
);
}
}),
codeEditorService
);
});
test
(
'
Model#add
'
,
()
=>
{
modelService
.
createModel
(
'
farboo
'
,
null
,
null
);
assert
.
equal
(
deltas
.
length
,
1
);
const
[
delta
]
=
deltas
;
assert
.
equal
(
delta
.
addedDocuments
.
length
,
1
);
assert
.
equal
(
delta
.
removedDocuments
,
undefined
);
assert
.
equal
(
delta
.
addedEditors
,
undefined
);
assert
.
equal
(
delta
.
removedEditors
,
undefined
);
assert
.
equal
(
delta
.
newActiveEditor
,
null
);
});
test
(
'
ignore huge model
'
,
()
=>
{
const
data
=
new
Array
(
2
+
(
5
*
1024
*
1024
)).
join
(
'
!
'
);
const
model
=
modelService
.
createModel
(
data
,
null
,
null
);
assert
.
ok
(
model
.
isTooLargeForHavingARichMode
());
assert
.
equal
(
deltas
.
length
,
1
);
const
[
delta
]
=
deltas
;
assert
.
equal
(
delta
.
newActiveEditor
,
null
);
assert
.
equal
(
delta
.
addedDocuments
,
undefined
);
assert
.
equal
(
delta
.
removedDocuments
,
undefined
);
assert
.
equal
(
delta
.
addedEditors
,
undefined
);
assert
.
equal
(
delta
.
removedEditors
,
undefined
);
});
test
(
'
ignore huge model from editor
'
,
()
=>
{
const
data
=
new
Array
(
2
+
(
5
*
1024
*
1024
)).
join
(
'
!
'
);
const
model
=
modelService
.
createModel
(
data
,
null
,
null
);
const
editor
=
mockCodeEditor
(
null
,
{
model
});
assert
.
equal
(
deltas
.
length
,
1
);
deltas
.
length
=
0
;
codeEditorService
.
addCodeEditor
(
editor
);
assert
.
equal
(
deltas
.
length
,
0
);
});
test
(
'
ignore editor w/o model
'
,
()
=>
{
const
editor
=
mockCodeEditor
([],
{});
editor
.
setModel
(
null
);
codeEditorService
.
addCodeEditor
(
editor
);
assert
.
equal
(
deltas
.
length
,
1
);
const
[
delta
]
=
deltas
;
assert
.
equal
(
delta
.
newActiveEditor
,
null
);
assert
.
equal
(
delta
.
addedDocuments
,
undefined
);
assert
.
equal
(
delta
.
removedDocuments
,
undefined
);
assert
.
equal
(
delta
.
addedEditors
,
undefined
);
assert
.
equal
(
delta
.
removedEditors
,
undefined
);
});
test
(
'
editor with model
'
,
()
=>
{
const
model
=
modelService
.
createModel
(
'
farboo
'
,
null
,
null
);
codeEditorService
.
addCodeEditor
(
mockCodeEditor
(
null
,
{
model
}));
assert
.
equal
(
deltas
.
length
,
2
);
const
[
first
,
second
]
=
deltas
;
assert
.
equal
(
first
.
addedDocuments
.
length
,
1
);
assert
.
equal
(
first
.
newActiveEditor
,
null
);
assert
.
equal
(
first
.
removedDocuments
,
undefined
);
assert
.
equal
(
first
.
addedEditors
,
undefined
);
assert
.
equal
(
first
.
removedEditors
,
undefined
);
assert
.
equal
(
second
.
addedEditors
.
length
,
1
);
assert
.
equal
(
second
.
addedDocuments
,
undefined
);
assert
.
equal
(
second
.
removedDocuments
,
undefined
);
assert
.
equal
(
second
.
removedEditors
,
undefined
);
assert
.
equal
(
typeof
second
.
newActiveEditor
,
'
string
'
);
});
test
(
'
editor with dispos-ed/-ing model
'
,
()
=>
{
modelService
.
createModel
(
'
foobar
'
,
null
,
null
);
const
model
=
modelService
.
createModel
(
'
farboo
'
,
null
,
null
);
const
editor
=
mockCodeEditor
(
null
,
{
model
});
codeEditorService
.
addCodeEditor
(
editor
);
// ignore things until now
deltas
.
length
=
0
;
modelService
.
destroyModel
(
model
.
uri
);
assert
.
equal
(
deltas
.
length
,
1
);
const
[
first
]
=
deltas
;
assert
.
equal
(
first
.
newActiveEditor
,
null
);
assert
.
equal
(
first
.
removedEditors
.
length
,
1
);
assert
.
equal
(
first
.
removedDocuments
.
length
,
1
);
assert
.
equal
(
first
.
addedDocuments
,
undefined
);
assert
.
equal
(
first
.
addedEditors
,
undefined
);
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录