Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
0b21524f
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,发现更多精彩内容 >>
提交
0b21524f
编写于
2月 13, 2019
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
prep for #41882
上级
0e93f650
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
225 addition
and
195 deletion
+225
-195
src/vs/editor/contrib/format/format.ts
src/vs/editor/contrib/format/format.ts
+104
-27
src/vs/editor/contrib/format/formatActions.ts
src/vs/editor/contrib/format/formatActions.ts
+98
-158
src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts
...rkbench/api/electron-browser/mainThreadSaveParticipant.ts
+5
-3
src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts
...test/electron-browser/api/extHostLanguageFeatures.test.ts
+18
-7
未找到文件。
src/vs/editor/contrib/format/format.ts
浏览文件 @
0b21524f
...
@@ -8,12 +8,14 @@ import { URI } from 'vs/base/common/uri';
...
@@ -8,12 +8,14 @@ import { URI } from 'vs/base/common/uri';
import
{
isNonEmptyArray
}
from
'
vs/base/common/arrays
'
;
import
{
isNonEmptyArray
}
from
'
vs/base/common/arrays
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
register
DefaultLanguageCommand
,
register
LanguageCommand
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
registerLanguageCommand
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
DocumentFormattingEditProviderRegistry
,
DocumentRangeFormattingEditProviderRegistry
,
OnTypeFormattingEditProviderRegistry
,
FormattingOptions
,
TextEdit
}
from
'
vs/editor/common/modes
'
;
import
{
DocumentFormattingEditProviderRegistry
,
DocumentRangeFormattingEditProviderRegistry
,
OnTypeFormattingEditProviderRegistry
,
FormattingOptions
,
TextEdit
}
from
'
vs/editor/common/modes
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
first
}
from
'
vs/base/common/async
'
;
import
{
first
}
from
'
vs/base/common/async
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
IEditorWorkerService
}
from
'
vs/editor/common/services/editorWorkerService
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
export
class
NoProviderError
extends
Error
{
export
class
NoProviderError
extends
Error
{
...
@@ -32,44 +34,114 @@ export class NoProviderError extends Error {
...
@@ -32,44 +34,114 @@ export class NoProviderError extends Error {
}
}
}
}
export
function
getDocumentRangeFormattingEdits
(
model
:
ITextModel
,
range
:
Range
,
options
:
FormattingOptions
,
token
:
CancellationToken
):
Promise
<
TextEdit
[]
|
undefined
|
null
>
{
export
function
getDocumentRangeFormattingEdits
(
telemetryService
:
ITelemetryService
,
const
providers
=
DocumentRangeFormattingEditProviderRegistry
.
ordered
(
model
);
workerService
:
IEditorWorkerService
,
model
:
ITextModel
,
if
(
providers
.
length
===
0
)
{
range
:
Range
,
options
:
FormattingOptions
,
token
:
CancellationToken
):
Promise
<
TextEdit
[]
|
undefined
|
null
>
{
const
allProvider
=
DocumentRangeFormattingEditProviderRegistry
.
ordered
(
model
);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
telemetryService
.
publicLog
(
'
formatterInfo
'
,
{
type
:
'
range
'
,
language
:
model
.
getLanguageIdentifier
().
language
,
count
:
allProvider
.
length
,
});
if
(
allProvider
.
length
===
0
)
{
return
Promise
.
reject
(
new
NoProviderError
());
return
Promise
.
reject
(
new
NoProviderError
());
}
}
return
first
(
providers
.
map
(
provider
=>
()
=>
{
return
first
(
allProvider
.
map
(
provider
=>
()
=>
{
return
Promise
.
resolve
(
provider
.
provideDocumentRangeFormattingEdits
(
model
,
range
,
options
,
token
))
return
Promise
.
resolve
(
provider
.
provideDocumentRangeFormattingEdits
(
model
,
range
,
options
,
token
)).
catch
(
onUnexpectedExternalError
);
.
then
(
undefined
,
onUnexpectedExternalError
);
}),
isNonEmptyArray
).
then
(
edits
=>
{
}),
isNonEmptyArray
);
// break edits into smaller edits
return
workerService
.
computeMoreMinimalEdits
(
model
.
uri
,
edits
);
});
}
}
export
function
getDocumentFormattingEdits
(
model
:
ITextModel
,
options
:
FormattingOptions
,
token
:
CancellationToken
):
Promise
<
TextEdit
[]
|
null
|
undefined
>
{
export
function
getDocumentFormattingEdits
(
telemetryService
:
ITelemetryService
,
workerService
:
IEditorWorkerService
,
model
:
ITextModel
,
options
:
FormattingOptions
,
token
:
CancellationToken
):
Promise
<
TextEdit
[]
|
null
|
undefined
>
{
const
providers
=
DocumentFormattingEditProviderRegistry
.
ordered
(
model
);
const
providers
=
DocumentFormattingEditProviderRegistry
.
ordered
(
model
);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
telemetryService
.
publicLog
(
'
formatterInfo
'
,
{
type
:
'
document
'
,
language
:
model
.
getLanguageIdentifier
().
language
,
count
:
providers
.
length
,
});
// try range formatters when no document formatter is registered
// try range formatters when no document formatter is registered
if
(
providers
.
length
===
0
)
{
if
(
providers
.
length
===
0
)
{
return
getDocumentRangeFormattingEdits
(
model
,
model
.
getFullModelRange
(),
options
,
token
);
return
getDocumentRangeFormattingEdits
(
telemetryService
,
workerService
,
model
,
model
.
getFullModelRange
(),
options
,
token
);
}
}
return
first
(
providers
.
map
(
provider
=>
()
=>
{
return
first
(
providers
.
map
(
provider
=>
()
=>
{
return
Promise
.
resolve
(
provider
.
provideDocumentFormattingEdits
(
model
,
options
,
token
))
// first with result wins...
.
then
(
undefined
,
onUnexpectedExternalError
);
return
Promise
.
resolve
(
provider
.
provideDocumentFormattingEdits
(
model
,
options
,
token
)).
catch
(
onUnexpectedExternalError
);
}),
isNonEmptyArray
);
}),
isNonEmptyArray
).
then
(
edits
=>
{
// break edits into smaller edits
return
workerService
.
computeMoreMinimalEdits
(
model
.
uri
,
edits
);
});
}
}
export
function
getOnTypeFormattingEdits
(
model
:
ITextModel
,
position
:
Position
,
ch
:
string
,
options
:
FormattingOptions
):
Promise
<
TextEdit
[]
|
null
|
undefined
>
{
export
function
getOnTypeFormattingEdits
(
const
[
support
]
=
OnTypeFormattingEditProviderRegistry
.
ordered
(
model
);
telemetryService
:
ITelemetryService
,
if
(
!
support
)
{
workerService
:
IEditorWorkerService
,
model
:
ITextModel
,
position
:
Position
,
ch
:
string
,
options
:
FormattingOptions
):
Promise
<
TextEdit
[]
|
null
|
undefined
>
{
const
providers
=
OnTypeFormattingEditProviderRegistry
.
ordered
(
model
);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
telemetryService
.
publicLog
(
'
formatterInfo
'
,
{
type
:
'
ontype
'
,
language
:
model
.
getLanguageIdentifier
().
language
,
count
:
providers
.
length
,
});
if
(
providers
.
length
===
0
)
{
return
Promise
.
resolve
(
undefined
);
return
Promise
.
resolve
(
undefined
);
}
}
if
(
support
.
autoFormatTriggerCharacters
.
indexOf
(
ch
)
<
0
)
{
if
(
providers
[
0
].
autoFormatTriggerCharacters
.
indexOf
(
ch
)
<
0
)
{
return
Promise
.
resolve
(
undefined
);
return
Promise
.
resolve
(
undefined
);
}
}
return
Promise
.
resolve
(
support
.
provideOnTypeFormattingEdits
(
model
,
position
,
ch
,
options
,
CancellationToken
.
None
)).
then
(
r
=>
r
,
onUnexpectedExternalError
);
return
Promise
.
resolve
(
providers
[
0
].
provideOnTypeFormattingEdits
(
model
,
position
,
ch
,
options
,
CancellationToken
.
None
)).
catch
(
onUnexpectedExternalError
).
then
(
edits
=>
{
return
workerService
.
computeMoreMinimalEdits
(
model
.
uri
,
edits
);
});
}
}
registerLanguageCommand
(
'
_executeFormatRangeProvider
'
,
function
(
accessor
,
args
)
{
registerLanguageCommand
(
'
_executeFormatRangeProvider
'
,
function
(
accessor
,
args
)
{
...
@@ -81,7 +153,7 @@ registerLanguageCommand('_executeFormatRangeProvider', function (accessor, args)
...
@@ -81,7 +153,7 @@ registerLanguageCommand('_executeFormatRangeProvider', function (accessor, args)
if
(
!
model
)
{
if
(
!
model
)
{
throw
illegalArgument
(
'
resource
'
);
throw
illegalArgument
(
'
resource
'
);
}
}
return
getDocumentRangeFormattingEdits
(
model
,
Range
.
lift
(
range
),
options
,
CancellationToken
.
None
);
return
getDocumentRangeFormattingEdits
(
accessor
.
get
(
ITelemetryService
),
accessor
.
get
(
IEditorWorkerService
),
model
,
Range
.
lift
(
range
),
options
,
CancellationToken
.
None
);
});
});
registerLanguageCommand
(
'
_executeFormatDocumentProvider
'
,
function
(
accessor
,
args
)
{
registerLanguageCommand
(
'
_executeFormatDocumentProvider
'
,
function
(
accessor
,
args
)
{
...
@@ -94,13 +166,18 @@ registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, ar
...
@@ -94,13 +166,18 @@ registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, ar
throw
illegalArgument
(
'
resource
'
);
throw
illegalArgument
(
'
resource
'
);
}
}
return
getDocumentFormattingEdits
(
model
,
options
,
CancellationToken
.
None
);
return
getDocumentFormattingEdits
(
accessor
.
get
(
ITelemetryService
),
accessor
.
get
(
IEditorWorkerService
),
model
,
options
,
CancellationToken
.
None
);
});
});
register
DefaultLanguageCommand
(
'
_executeFormatOnTypeProvider
'
,
function
(
model
,
position
,
args
)
{
register
LanguageCommand
(
'
_executeFormatOnTypeProvider
'
,
function
(
accessor
,
args
)
{
const
{
ch
,
options
}
=
args
;
const
{
resource
,
position
,
ch
,
options
}
=
args
;
if
(
typeof
ch
!==
'
string
'
)
{
if
(
!
(
resource
instanceof
URI
)
||
!
Position
.
isIPosition
(
position
)
||
typeof
ch
!==
'
string
'
)
{
throw
illegalArgument
(
'
ch
'
);
throw
illegalArgument
();
}
}
return
getOnTypeFormattingEdits
(
model
,
position
,
ch
,
options
);
const
model
=
accessor
.
get
(
IModelService
).
getModel
(
resource
);
if
(
!
model
)
{
throw
illegalArgument
(
'
resource
'
);
}
return
getOnTypeFormattingEdits
(
accessor
.
get
(
ITelemetryService
),
accessor
.
get
(
IEditorWorkerService
),
model
,
Position
.
lift
(
position
),
ch
,
options
);
});
});
src/vs/editor/contrib/format/formatActions.ts
浏览文件 @
0b21524f
...
@@ -5,7 +5,6 @@
...
@@ -5,7 +5,6 @@
import
{
alert
}
from
'
vs/base/browser/ui/aria/aria
'
;
import
{
alert
}
from
'
vs/base/browser/ui/aria/aria
'
;
import
{
isNonEmptyArray
}
from
'
vs/base/common/arrays
'
;
import
{
isNonEmptyArray
}
from
'
vs/base/common/arrays
'
;
import
{
sequence
}
from
'
vs/base/common/async
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
KeyChord
,
KeyCode
,
KeyMod
}
from
'
vs/base/common/keyCodes
'
;
import
{
KeyChord
,
KeyCode
,
KeyMod
}
from
'
vs/base/common/keyCodes
'
;
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
...
@@ -20,7 +19,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
...
@@ -20,7 +19,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import
{
ISingleEditOperation
}
from
'
vs/editor/common/model
'
;
import
{
ISingleEditOperation
}
from
'
vs/editor/common/model
'
;
import
{
DocumentFormattingEditProviderRegistry
,
DocumentRangeFormattingEditProviderRegistry
,
FormattingOptions
,
OnTypeFormattingEditProviderRegistry
}
from
'
vs/editor/common/modes
'
;
import
{
DocumentFormattingEditProviderRegistry
,
DocumentRangeFormattingEditProviderRegistry
,
FormattingOptions
,
OnTypeFormattingEditProviderRegistry
}
from
'
vs/editor/common/modes
'
;
import
{
IEditorWorkerService
}
from
'
vs/editor/common/services/editorWorkerService
'
;
import
{
IEditorWorkerService
}
from
'
vs/editor/common/services/editorWorkerService
'
;
import
{
getOnTypeFormattingEdits
,
NoProviderError
}
from
'
vs/editor/contrib/format/format
'
;
import
{
getOnTypeFormattingEdits
,
NoProviderError
,
getDocumentFormattingEdits
,
getDocumentRangeFormattingEdits
}
from
'
vs/editor/contrib/format/format
'
;
import
{
FormattingEdit
}
from
'
vs/editor/contrib/format/formattingEdit
'
;
import
{
FormattingEdit
}
from
'
vs/editor/contrib/format/formattingEdit
'
;
import
*
as
nls
from
'
vs/nls
'
;
import
*
as
nls
from
'
vs/nls
'
;
import
{
CommandsRegistry
}
from
'
vs/platform/commands/common/commands
'
;
import
{
CommandsRegistry
}
from
'
vs/platform/commands/common/commands
'
;
...
@@ -62,126 +61,64 @@ export const enum FormatRangeType {
...
@@ -62,126 +61,64 @@ export const enum FormatRangeType {
Selection
,
Selection
,
}
}
export
function
formatDocumentRange
(
telemetryService
:
ITelemetryService
,
workerService
:
IEditorWorkerService
,
editor
:
IActiveCodeEditor
,
rangeOrRangeType
:
Range
|
FormatRangeType
,
options
:
FormattingOptions
,
token
:
CancellationToken
):
Promise
<
void
>
{
export
function
formatDocumentRange
(
telemetryService
:
ITelemetryService
,
const
provider
=
DocumentRangeFormattingEditProviderRegistry
.
ordered
(
editor
.
getModel
());
workerService
:
IEditorWorkerService
,
if
(
provider
.
length
===
0
)
{
editor
:
IActiveCodeEditor
,
return
Promise
.
reject
(
new
NoProviderError
());
rangeOrRangeType
:
Range
|
FormatRangeType
,
}
options
:
FormattingOptions
,
token
:
CancellationToken
// Know how often multiple providers clash and (for now)
):
Promise
<
void
>
{
// continue picking the 'first' provider
if
(
provider
.
length
!==
1
)
{
/* __GDPR__
const
state
=
new
EditorState
(
editor
,
CodeEditorStateFlag
.
Value
|
CodeEditorStateFlag
.
Position
);
"manyformatters" : {
const
model
=
editor
.
getModel
();
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
let
range
:
Range
;
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
if
(
rangeOrRangeType
===
FormatRangeType
.
Full
)
{
}
// full
*/
range
=
model
.
getFullModelRange
();
telemetryService
.
publicLog
(
'
manyformatters
'
,
{
type
:
'
range
'
,
}
else
if
(
rangeOrRangeType
===
FormatRangeType
.
Selection
)
{
language
:
editor
.
getModel
().
getLanguageIdentifier
().
language
,
// selection or line (when empty)
count
:
provider
.
length
,
range
=
editor
.
getSelection
();
});
if
(
range
.
isEmpty
())
{
provider
.
length
=
1
;
range
=
new
Range
(
range
.
startLineNumber
,
1
,
range
.
endLineNumber
,
model
.
getLineMaxColumn
(
range
.
endLineNumber
));
}
}
else
{
// as is
range
=
rangeOrRangeType
;
}
}
let
allEdits
:
ISingleEditOperation
[]
=
[];
return
getDocumentRangeFormattingEdits
(
telemetryService
,
workerService
,
model
,
range
,
options
,
token
).
then
(
edits
=>
{
// make edit only when the editor didn't change while
editor
.
pushUndoStop
();
// computing and only when there are edits
return
sequence
(
provider
.
map
(
provider
=>
{
if
(
state
.
validate
(
editor
)
&&
isNonEmptyArray
(
edits
))
{
// create a formatting task per provider. they run sequentially,
FormattingEdit
.
execute
(
editor
,
edits
);
// potentially undoing the working of a previous formatter
alertFormattingEdits
(
edits
);
return
()
=>
{
editor
.
focus
();
const
state
=
new
EditorState
(
editor
,
CodeEditorStateFlag
.
Value
|
CodeEditorStateFlag
.
Position
);
editor
.
revealPositionInCenterIfOutsideViewport
(
editor
.
getPosition
(),
editorCommon
.
ScrollType
.
Immediate
);
const
model
=
editor
.
getModel
();
}
let
range
:
Range
;
if
(
rangeOrRangeType
===
FormatRangeType
.
Full
)
{
// full
range
=
model
.
getFullModelRange
();
}
else
if
(
rangeOrRangeType
===
FormatRangeType
.
Selection
)
{
// selection or line (when empty)
range
=
editor
.
getSelection
();
if
(
range
.
isEmpty
())
{
range
=
new
Range
(
range
.
startLineNumber
,
1
,
range
.
endLineNumber
,
model
.
getLineMaxColumn
(
range
.
endLineNumber
));
}
}
else
{
// as is
range
=
rangeOrRangeType
;
}
return
Promise
.
resolve
(
provider
.
provideDocumentRangeFormattingEdits
(
model
,
range
,
options
,
token
)).
then
(
edits
=>
{
// break edits into smaller edits
return
workerService
.
computeMoreMinimalEdits
(
editor
.
getModel
().
uri
,
edits
);
}).
then
(
edits
=>
{
// make edit only when the editor didn't change while
// computing and only when there are edits
if
(
state
.
validate
(
editor
)
&&
isNonEmptyArray
(
edits
))
{
FormattingEdit
.
execute
(
editor
,
edits
);
allEdits
=
allEdits
.
concat
(
edits
);
}
});
};
})).
then
(()
=>
{
alertFormattingEdits
(
allEdits
);
editor
.
pushUndoStop
();
editor
.
focus
();
editor
.
revealPositionInCenterIfOutsideViewport
(
editor
.
getPosition
(),
editorCommon
.
ScrollType
.
Immediate
);
});
});
}
}
export
function
formatDocument
(
telemetryService
:
ITelemetryService
,
workerService
:
IEditorWorkerService
,
editor
:
IActiveCodeEditor
,
options
:
FormattingOptions
,
token
:
CancellationToken
):
Promise
<
void
>
{
export
function
formatDocument
(
telemetryService
:
ITelemetryService
,
workerService
:
IEditorWorkerService
,
editor
:
IActiveCodeEditor
,
options
:
FormattingOptions
,
token
:
CancellationToken
):
Promise
<
void
>
{
const
provider
=
DocumentFormattingEditProviderRegistry
.
ordered
(
editor
.
getModel
());
if
(
provider
.
length
===
0
)
{
return
formatDocumentRange
(
telemetryService
,
workerService
,
editor
,
FormatRangeType
.
Full
,
options
,
token
);
}
// Know how often multiple providers clash and (for now)
const
allEdits
:
ISingleEditOperation
[]
=
[];
// continue picking the 'first' provider
const
state
=
new
EditorState
(
editor
,
CodeEditorStateFlag
.
Value
|
CodeEditorStateFlag
.
Position
);
if
(
provider
.
length
!==
1
)
{
/* __GDPR__
"manyformatters" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
telemetryService
.
publicLog
(
'
manyformatters
'
,
{
type
:
'
document
'
,
language
:
editor
.
getModel
().
getLanguageIdentifier
().
language
,
count
:
provider
.
length
,
});
provider
.
length
=
1
;
}
let
allEdits
:
ISingleEditOperation
[]
=
[];
return
getDocumentFormattingEdits
(
telemetryService
,
workerService
,
editor
.
getModel
(),
options
,
token
).
then
(
edits
=>
{
// make edit only when the editor didn't change while
editor
.
pushUndoStop
();
// computing and only when there are edits
return
sequence
(
provider
.
map
(
provider
=>
{
if
(
state
.
validate
(
editor
)
&&
isNonEmptyArray
(
edits
))
{
// create a formatting task per provider. they run sequentially,
FormattingEdit
.
execute
(
editor
,
edits
);
// potentially undoing the working of a previous formatter
return
()
=>
{
alertFormattingEdits
(
allEdits
);
const
state
=
new
EditorState
(
editor
,
CodeEditorStateFlag
.
Value
|
CodeEditorStateFlag
.
Position
);
editor
.
pushUndoStop
();
const
model
=
editor
.
getModel
();
editor
.
focus
();
return
Promise
.
resolve
(
provider
.
provideDocumentFormattingEdits
(
model
,
options
,
token
)).
then
(
edits
=>
{
editor
.
revealPositionInCenterIfOutsideViewport
(
editor
.
getPosition
(),
editorCommon
.
ScrollType
.
Immediate
);
// break edits into smaller edits
}
return
workerService
.
computeMoreMinimalEdits
(
editor
.
getModel
().
uri
,
edits
);
}).
then
(
edits
=>
{
// make edit only when the editor didn't change while
// computing and only when there are edits
if
(
state
.
validate
(
editor
)
&&
isNonEmptyArray
(
edits
))
{
FormattingEdit
.
execute
(
editor
,
edits
);
allEdits
=
allEdits
.
concat
(
edits
);
}
});
};
})).
then
(()
=>
{
alertFormattingEdits
(
allEdits
);
editor
.
pushUndoStop
();
editor
.
focus
();
editor
.
revealPositionInCenterIfOutsideViewport
(
editor
.
getPosition
(),
editorCommon
.
ScrollType
.
Immediate
);
});
});
}
}
...
@@ -189,39 +126,38 @@ class FormatOnType implements editorCommon.IEditorContribution {
...
@@ -189,39 +126,38 @@ class FormatOnType implements editorCommon.IEditorContribution {
private
static
readonly
ID
=
'
editor.contrib.autoFormat
'
;
private
static
readonly
ID
=
'
editor.contrib.autoFormat
'
;
private
editor
:
ICodeEditor
;
private
readonly
_editor
:
ICodeEditor
;
private
workerService
:
IEditorWorkerService
;
private
_callOnDispose
:
IDisposable
[]
=
[];
private
callOnDispose
:
IDisposable
[];
private
_callOnModel
:
IDisposable
[]
=
[];
private
callOnModel
:
IDisposable
[];
constructor
(
editor
:
ICodeEditor
,
@
IEditorWorkerService
workerService
:
IEditorWorkerService
)
{
this
.
editor
=
editor
;
this
.
workerService
=
workerService
;
this
.
callOnDispose
=
[];
this
.
callOnModel
=
[];
this
.
callOnDispose
.
push
(
editor
.
onDidChangeConfiguration
(()
=>
this
.
update
()));
constructor
(
this
.
callOnDispose
.
push
(
editor
.
onDidChangeModel
(()
=>
this
.
update
()));
editor
:
ICodeEditor
,
this
.
callOnDispose
.
push
(
editor
.
onDidChangeModelLanguage
(()
=>
this
.
update
()));
@
ITelemetryService
private
readonly
_telemetryService
:
ITelemetryService
,
this
.
callOnDispose
.
push
(
OnTypeFormattingEditProviderRegistry
.
onDidChange
(
this
.
update
,
this
));
@
IEditorWorkerService
private
readonly
_workerService
:
IEditorWorkerService
)
{
this
.
_editor
=
editor
;
this
.
_callOnDispose
.
push
(
editor
.
onDidChangeConfiguration
(()
=>
this
.
update
()));
this
.
_callOnDispose
.
push
(
editor
.
onDidChangeModel
(()
=>
this
.
update
()));
this
.
_callOnDispose
.
push
(
editor
.
onDidChangeModelLanguage
(()
=>
this
.
update
()));
this
.
_callOnDispose
.
push
(
OnTypeFormattingEditProviderRegistry
.
onDidChange
(
this
.
update
,
this
));
}
}
private
update
():
void
{
private
update
():
void
{
// clean up
// clean up
this
.
callOnModel
=
dispose
(
this
.
callOnModel
);
this
.
_callOnModel
=
dispose
(
this
.
_
callOnModel
);
// we are disabled
// we are disabled
if
(
!
this
.
editor
.
getConfiguration
().
contribInfo
.
formatOnType
)
{
if
(
!
this
.
_
editor
.
getConfiguration
().
contribInfo
.
formatOnType
)
{
return
;
return
;
}
}
// no model
// no model
if
(
!
this
.
editor
.
hasModel
())
{
if
(
!
this
.
_
editor
.
hasModel
())
{
return
;
return
;
}
}
const
model
=
this
.
editor
.
getModel
();
const
model
=
this
.
_
editor
.
getModel
();
// no support
// no support
const
[
support
]
=
OnTypeFormattingEditProviderRegistry
.
ordered
(
model
);
const
[
support
]
=
OnTypeFormattingEditProviderRegistry
.
ordered
(
model
);
...
@@ -234,7 +170,7 @@ class FormatOnType implements editorCommon.IEditorContribution {
...
@@ -234,7 +170,7 @@ class FormatOnType implements editorCommon.IEditorContribution {
for
(
let
ch
of
support
.
autoFormatTriggerCharacters
)
{
for
(
let
ch
of
support
.
autoFormatTriggerCharacters
)
{
triggerChars
.
add
(
ch
.
charCodeAt
(
0
));
triggerChars
.
add
(
ch
.
charCodeAt
(
0
));
}
}
this
.
callOnModel
.
push
(
this
.
editor
.
onDidType
((
text
:
string
)
=>
{
this
.
_callOnModel
.
push
(
this
.
_
editor
.
onDidType
((
text
:
string
)
=>
{
let
lastCharCode
=
text
.
charCodeAt
(
text
.
length
-
1
);
let
lastCharCode
=
text
.
charCodeAt
(
text
.
length
-
1
);
if
(
triggerChars
.
has
(
lastCharCode
))
{
if
(
triggerChars
.
has
(
lastCharCode
))
{
this
.
trigger
(
String
.
fromCharCode
(
lastCharCode
));
this
.
trigger
(
String
.
fromCharCode
(
lastCharCode
));
...
@@ -243,22 +179,22 @@ class FormatOnType implements editorCommon.IEditorContribution {
...
@@ -243,22 +179,22 @@ class FormatOnType implements editorCommon.IEditorContribution {
}
}
private
trigger
(
ch
:
string
):
void
{
private
trigger
(
ch
:
string
):
void
{
if
(
!
this
.
editor
.
hasModel
())
{
if
(
!
this
.
_
editor
.
hasModel
())
{
return
;
return
;
}
}
if
(
this
.
editor
.
getSelections
().
length
>
1
)
{
if
(
this
.
_
editor
.
getSelections
().
length
>
1
)
{
return
;
return
;
}
}
const
model
=
this
.
editor
.
getModel
();
const
model
=
this
.
_
editor
.
getModel
();
const
position
=
this
.
editor
.
getPosition
();
const
position
=
this
.
_
editor
.
getPosition
();
let
canceled
=
false
;
let
canceled
=
false
;
// install a listener that checks if edits happens before the
// install a listener that checks if edits happens before the
// position on which we format right now. If so, we won't
// position on which we format right now. If so, we won't
// apply the format edits
// apply the format edits
const
unbind
=
this
.
editor
.
onDidChangeModelContent
((
e
)
=>
{
const
unbind
=
this
.
_
editor
.
onDidChangeModelContent
((
e
)
=>
{
if
(
e
.
isFlush
)
{
if
(
e
.
isFlush
)
{
// a model.setValue() was called
// a model.setValue() was called
// cancel only once
// cancel only once
...
@@ -281,28 +217,32 @@ class FormatOnType implements editorCommon.IEditorContribution {
...
@@ -281,28 +217,32 @@ class FormatOnType implements editorCommon.IEditorContribution {
let
modelOpts
=
model
.
getOptions
();
let
modelOpts
=
model
.
getOptions
();
getOnTypeFormattingEdits
(
model
,
position
,
ch
,
{
getOnTypeFormattingEdits
(
tabSize
:
modelOpts
.
tabSize
,
this
.
_telemetryService
,
insertSpaces
:
modelOpts
.
insertSpaces
this
.
_workerService
,
}).
then
(
edits
=>
{
model
,
return
this
.
workerService
.
computeMoreMinimalEdits
(
model
.
uri
,
edits
);
position
,
}).
then
(
edits
=>
{
ch
,
{
tabSize
:
modelOpts
.
tabSize
,
insertSpaces
:
modelOpts
.
insertSpaces
}).
then
(
edits
=>
{
unbind
.
dispose
();
unbind
.
dispose
();
if
(
canceled
)
{
if
(
canceled
)
{
return
;
return
;
}
}
if
(
isNonEmptyArray
(
edits
))
{
if
(
isNonEmptyArray
(
edits
))
{
FormattingEdit
.
execute
(
this
.
editor
,
edits
);
FormattingEdit
.
execute
(
this
.
_
editor
,
edits
);
alertFormattingEdits
(
edits
);
alertFormattingEdits
(
edits
);
}
}
},
(
err
)
=>
{
},
(
err
)
=>
{
unbind
.
dispose
();
unbind
.
dispose
();
throw
err
;
throw
err
;
});
});
}
}
public
getId
():
string
{
public
getId
():
string
{
...
@@ -310,8 +250,8 @@ class FormatOnType implements editorCommon.IEditorContribution {
...
@@ -310,8 +250,8 @@ class FormatOnType implements editorCommon.IEditorContribution {
}
}
public
dispose
():
void
{
public
dispose
():
void
{
this
.
callOnDispose
=
dispose
(
this
.
callOnDispose
);
this
.
_callOnDispose
=
dispose
(
this
.
_
callOnDispose
);
this
.
callOnModel
=
dispose
(
this
.
callOnModel
);
this
.
_callOnModel
=
dispose
(
this
.
_
callOnModel
);
}
}
}
}
...
...
src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts
浏览文件 @
0b21524f
...
@@ -36,6 +36,7 @@ import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustom
...
@@ -36,6 +36,7 @@ import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustom
import
{
TextFileEditorModel
}
from
'
vs/workbench/services/textfile/common/textFileEditorModel
'
;
import
{
TextFileEditorModel
}
from
'
vs/workbench/services/textfile/common/textFileEditorModel
'
;
import
{
ISaveParticipant
,
ITextFileEditorModel
,
SaveReason
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
ISaveParticipant
,
ITextFileEditorModel
,
SaveReason
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
ExtHostContext
,
ExtHostDocumentSaveParticipantShape
,
IExtHostContext
}
from
'
../node/extHost.protocol
'
;
import
{
ExtHostContext
,
ExtHostDocumentSaveParticipantShape
,
IExtHostContext
}
from
'
../node/extHost.protocol
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
export
interface
ISaveParticipantParticipant
extends
ISaveParticipant
{
export
interface
ISaveParticipantParticipant
extends
ISaveParticipant
{
// progressMessage: string;
// progressMessage: string;
...
@@ -215,7 +216,8 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
...
@@ -215,7 +216,8 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
constructor
(
constructor
(
@
ICodeEditorService
private
readonly
_editorService
:
ICodeEditorService
,
@
ICodeEditorService
private
readonly
_editorService
:
ICodeEditorService
,
@
IEditorWorkerService
private
readonly
_editorWorkerService
:
IEditorWorkerService
,
@
IEditorWorkerService
private
readonly
_editorWorkerService
:
IEditorWorkerService
,
@
IConfigurationService
private
readonly
_configurationService
:
IConfigurationService
@
IConfigurationService
private
readonly
_configurationService
:
IConfigurationService
,
@
ITelemetryService
private
readonly
_telemetryService
:
ITelemetryService
,
)
{
)
{
// Nothing
// Nothing
}
}
...
@@ -235,14 +237,14 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
...
@@ -235,14 +237,14 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
return
new
Promise
<
ISingleEditOperation
[]
|
null
|
undefined
>
((
resolve
,
reject
)
=>
{
return
new
Promise
<
ISingleEditOperation
[]
|
null
|
undefined
>
((
resolve
,
reject
)
=>
{
let
source
=
new
CancellationTokenSource
();
let
source
=
new
CancellationTokenSource
();
let
request
=
getDocumentFormattingEdits
(
model
,
{
tabSize
,
insertSpaces
},
source
.
token
);
let
request
=
getDocumentFormattingEdits
(
this
.
_telemetryService
,
this
.
_editorWorkerService
,
model
,
{
tabSize
,
insertSpaces
},
source
.
token
);
setTimeout
(()
=>
{
setTimeout
(()
=>
{
reject
(
localize
(
'
timeout.formatOnSave
'
,
"
Aborted format on save after {0}ms
"
,
timeout
));
reject
(
localize
(
'
timeout.formatOnSave
'
,
"
Aborted format on save after {0}ms
"
,
timeout
));
source
.
cancel
();
source
.
cancel
();
},
timeout
);
},
timeout
);
request
.
then
(
edits
=>
this
.
_editorWorkerService
.
computeMoreMinimalEdits
(
model
.
uri
,
edits
)).
then
(
resolve
,
err
=>
{
request
.
then
(
resolve
,
err
=>
{
if
(
!
NoProviderError
.
is
(
err
))
{
if
(
!
NoProviderError
.
is
(
err
))
{
reject
(
err
);
reject
(
err
);
}
else
{
}
else
{
...
...
src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts
浏览文件 @
0b21524f
...
@@ -46,6 +46,9 @@ import { getColors } from 'vs/editor/contrib/colorPicker/color';
...
@@ -46,6 +46,9 @@ import { getColors } from 'vs/editor/contrib/colorPicker/color';
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
nullExtensionDescription
as
defaultExtension
}
from
'
vs/workbench/services/extensions/common/extensions
'
;
import
{
nullExtensionDescription
as
defaultExtension
}
from
'
vs/workbench/services/extensions/common/extensions
'
;
import
{
provideSelectionRanges
}
from
'
vs/editor/contrib/smartSelect/smartSelect
'
;
import
{
provideSelectionRanges
}
from
'
vs/editor/contrib/smartSelect/smartSelect
'
;
import
{
NullTelemetryService
}
from
'
vs/platform/telemetry/common/telemetryUtils
'
;
import
{
mock
}
from
'
vs/workbench/test/electron-browser/api/mock
'
;
import
{
IEditorWorkerService
}
from
'
vs/editor/common/services/editorWorkerService
'
;
const
defaultSelector
=
{
scheme
:
'
far
'
};
const
defaultSelector
=
{
scheme
:
'
far
'
};
const
model
:
ITextModel
=
EditorModel
.
createFromString
(
const
model
:
ITextModel
=
EditorModel
.
createFromString
(
...
@@ -64,6 +67,8 @@ let disposables: vscode.Disposable[] = [];
...
@@ -64,6 +67,8 @@ let disposables: vscode.Disposable[] = [];
let
rpcProtocol
:
TestRPCProtocol
;
let
rpcProtocol
:
TestRPCProtocol
;
let
originalErrorHandler
:
(
e
:
any
)
=>
any
;
let
originalErrorHandler
:
(
e
:
any
)
=>
any
;
suite
(
'
ExtHostLanguageFeatures
'
,
function
()
{
suite
(
'
ExtHostLanguageFeatures
'
,
function
()
{
suiteSetup
(()
=>
{
suiteSetup
(()
=>
{
...
@@ -906,6 +911,12 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -906,6 +911,12 @@ suite('ExtHostLanguageFeatures', function () {
// --- format
// --- format
const
NullWorkerService
=
new
class
extends
mock
<
IEditorWorkerService
>
()
{
computeMoreMinimalEdits
(
resource
:
URI
,
edits
:
modes
.
TextEdit
[]
|
null
|
undefined
):
Promise
<
modes
.
TextEdit
[]
|
null
|
undefined
>
{
return
Promise
.
resolve
(
edits
);
}
};
test
(
'
Format Doc, data conversion
'
,
async
()
=>
{
test
(
'
Format Doc, data conversion
'
,
async
()
=>
{
disposables
.
push
(
extHost
.
registerDocumentFormattingEditProvider
(
defaultExtension
,
defaultSelector
,
new
class
implements
vscode
.
DocumentFormattingEditProvider
{
disposables
.
push
(
extHost
.
registerDocumentFormattingEditProvider
(
defaultExtension
,
defaultSelector
,
new
class
implements
vscode
.
DocumentFormattingEditProvider
{
provideDocumentFormattingEdits
():
any
{
provideDocumentFormattingEdits
():
any
{
...
@@ -914,7 +925,7 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -914,7 +925,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
}));
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
let
value
=
await
getDocumentFormattingEdits
(
model
,
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
let
value
=
await
getDocumentFormattingEdits
(
NullTelemetryService
,
NullWorkerService
,
model
,
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
assert
.
equal
(
value
.
length
,
2
);
assert
.
equal
(
value
.
length
,
2
);
let
[
first
,
second
]
=
value
;
let
[
first
,
second
]
=
value
;
assert
.
equal
(
first
.
text
,
'
testing
'
);
assert
.
equal
(
first
.
text
,
'
testing
'
);
...
@@ -932,7 +943,7 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -932,7 +943,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
}));
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
return
getDocumentFormattingEdits
(
model
,
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
return
getDocumentFormattingEdits
(
NullTelemetryService
,
NullWorkerService
,
model
,
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
});
});
test
(
'
Format Doc, order
'
,
async
()
=>
{
test
(
'
Format Doc, order
'
,
async
()
=>
{
...
@@ -956,7 +967,7 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -956,7 +967,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
}));
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
let
value
=
await
getDocumentFormattingEdits
(
model
,
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
let
value
=
await
getDocumentFormattingEdits
(
NullTelemetryService
,
NullWorkerService
,
model
,
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
assert
.
equal
(
value
.
length
,
1
);
assert
.
equal
(
value
.
length
,
1
);
let
[
first
]
=
value
;
let
[
first
]
=
value
;
assert
.
equal
(
first
.
text
,
'
testing
'
);
assert
.
equal
(
first
.
text
,
'
testing
'
);
...
@@ -971,7 +982,7 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -971,7 +982,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
}));
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
let
value
=
await
getDocumentRangeFormattingEdits
(
model
,
new
EditorRange
(
1
,
1
,
1
,
1
),
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
let
value
=
await
getDocumentRangeFormattingEdits
(
NullTelemetryService
,
NullWorkerService
,
model
,
new
EditorRange
(
1
,
1
,
1
,
1
),
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
assert
.
equal
(
value
.
length
,
1
);
assert
.
equal
(
value
.
length
,
1
);
let
[
first
]
=
value
;
let
[
first
]
=
value
;
assert
.
equal
(
first
.
text
,
'
testing
'
);
assert
.
equal
(
first
.
text
,
'
testing
'
);
...
@@ -995,7 +1006,7 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -995,7 +1006,7 @@ suite('ExtHostLanguageFeatures', function () {
}
}
}));
}));
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
let
value
=
await
getDocumentRangeFormattingEdits
(
model
,
new
EditorRange
(
1
,
1
,
1
,
1
),
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
let
value
=
await
getDocumentRangeFormattingEdits
(
NullTelemetryService
,
NullWorkerService
,
model
,
new
EditorRange
(
1
,
1
,
1
,
1
),
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
assert
.
equal
(
value
.
length
,
1
);
assert
.
equal
(
value
.
length
,
1
);
let
[
first
]
=
value
;
let
[
first
]
=
value
;
assert
.
equal
(
first
.
text
,
'
range2
'
);
assert
.
equal
(
first
.
text
,
'
range2
'
);
...
@@ -1013,7 +1024,7 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -1013,7 +1024,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
}));
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
return
getDocumentRangeFormattingEdits
(
model
,
new
EditorRange
(
1
,
1
,
1
,
1
),
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
return
getDocumentRangeFormattingEdits
(
NullTelemetryService
,
NullWorkerService
,
model
,
new
EditorRange
(
1
,
1
,
1
,
1
),
{
insertSpaces
:
true
,
tabSize
:
4
},
CancellationToken
.
None
);
});
});
test
(
'
Format on Type, data conversion
'
,
async
()
=>
{
test
(
'
Format on Type, data conversion
'
,
async
()
=>
{
...
@@ -1025,7 +1036,7 @@ suite('ExtHostLanguageFeatures', function () {
...
@@ -1025,7 +1036,7 @@ suite('ExtHostLanguageFeatures', function () {
},
[
'
;
'
]));
},
[
'
;
'
]));
await
rpcProtocol
.
sync
();
await
rpcProtocol
.
sync
();
let
value
=
await
getOnTypeFormattingEdits
(
model
,
new
EditorPosition
(
1
,
1
),
'
;
'
,
{
insertSpaces
:
true
,
tabSize
:
2
});
let
value
=
await
getOnTypeFormattingEdits
(
NullTelemetryService
,
NullWorkerService
,
model
,
new
EditorPosition
(
1
,
1
),
'
;
'
,
{
insertSpaces
:
true
,
tabSize
:
2
});
assert
.
equal
(
value
.
length
,
1
);
assert
.
equal
(
value
.
length
,
1
);
let
[
first
]
=
value
;
let
[
first
]
=
value
;
assert
.
equal
(
first
.
text
,
'
;
'
);
assert
.
equal
(
first
.
text
,
'
;
'
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录