Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
78397045
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,发现更多精彩内容 >>
提交
78397045
编写于
12月 11, 2019
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
debt - migrate more language api commands onto new format
上级
41f07052
变更
9
展开全部
隐藏空白更改
内联
并排
Showing
9 changed file
with
227 addition
and
292 deletion
+227
-292
src/vs/editor/browser/editorExtensions.ts
src/vs/editor/browser/editorExtensions.ts
+55
-1
src/vs/editor/contrib/format/format.ts
src/vs/editor/contrib/format/format.ts
+18
-16
src/vs/editor/contrib/gotoSymbol/goToSymbol.ts
src/vs/editor/contrib/gotoSymbol/goToSymbol.ts
+6
-6
src/vs/editor/contrib/hover/getHover.ts
src/vs/editor/contrib/hover/getHover.ts
+2
-2
src/vs/editor/contrib/quickOpen/quickOpen.ts
src/vs/editor/contrib/quickOpen/quickOpen.ts
+12
-19
src/vs/editor/contrib/smartSelect/smartSelect.ts
src/vs/editor/contrib/smartSelect/smartSelect.ts
+4
-3
src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts
src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts
+2
-2
src/vs/workbench/api/common/extHostApiCommands.ts
src/vs/workbench/api/common/extHostApiCommands.ts
+106
-243
src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts
...ench/test/electron-browser/api/extHostApiCommands.test.ts
+22
-0
未找到文件。
src/vs/editor/browser/editorExtensions.ts
浏览文件 @
78397045
...
...
@@ -20,7 +20,7 @@ import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccess
import
{
IKeybindings
,
KeybindingsRegistry
}
from
'
vs/platform/keybinding/common/keybindingsRegistry
'
;
import
{
Registry
}
from
'
vs/platform/registry/common/platform
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
withNullAsUndefined
}
from
'
vs/base/common/types
'
;
import
{
withNullAsUndefined
,
assertType
}
from
'
vs/base/common/types
'
;
export
type
ServicesAccessor
=
InstantiationServicesAccessor
;
export
type
IEditorContributionCtor
=
IConstructorSignature1
<
ICodeEditor
,
IEditorContribution
>
;
...
...
@@ -311,6 +311,60 @@ export function registerDefaultLanguageCommand(id: string, handler: (model: ITex
});
}
export
function
registerModelAndPositionCommand
(
id
:
string
,
handler
:
(
model
:
ITextModel
,
position
:
Position
,
...
args
:
any
[])
=>
any
)
{
CommandsRegistry
.
registerCommand
(
id
,
function
(
accessor
,
...
args
)
{
const
[
resource
,
position
]
=
args
;
assertType
(
URI
.
isUri
(
resource
));
assertType
(
Position
.
isIPosition
(
position
));
const
model
=
accessor
.
get
(
IModelService
).
getModel
(
resource
);
if
(
model
)
{
const
editorPosition
=
Position
.
lift
(
position
);
return
handler
(
model
,
editorPosition
,
args
.
slice
(
2
));
}
return
accessor
.
get
(
ITextModelService
).
createModelReference
(
resource
).
then
(
reference
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
const
result
=
handler
(
reference
.
object
.
textEditorModel
,
Position
.
lift
(
position
),
args
.
slice
(
2
));
resolve
(
result
);
}
catch
(
err
)
{
reject
(
err
);
}
}).
finally
(()
=>
{
reference
.
dispose
();
});
});
});
}
export
function
registerModelCommand
(
id
:
string
,
handler
:
(
model
:
ITextModel
,
...
args
:
any
[])
=>
any
)
{
CommandsRegistry
.
registerCommand
(
id
,
function
(
accessor
,
...
args
)
{
const
[
resource
]
=
args
;
assertType
(
URI
.
isUri
(
resource
));
const
model
=
accessor
.
get
(
IModelService
).
getModel
(
resource
);
if
(
model
)
{
return
handler
(
model
,
args
.
slice
(
1
));
}
return
accessor
.
get
(
ITextModelService
).
createModelReference
(
resource
).
then
(
reference
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
const
result
=
handler
(
reference
.
object
.
textEditorModel
,
args
.
slice
(
1
));
resolve
(
result
);
}
catch
(
err
)
{
reject
(
err
);
}
}).
finally
(()
=>
{
reference
.
dispose
();
});
});
});
}
export
function
registerEditorCommand
<
T
extends
EditorCommand
>
(
editorCommand
:
T
):
T
{
EditorContributionRegistry
.
INSTANCE
.
registerEditorCommand
(
editorCommand
);
return
editorCommand
;
...
...
src/vs/editor/contrib/format/format.ts
浏览文件 @
78397045
...
...
@@ -10,7 +10,7 @@ import { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/error
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
CodeEditorStateFlag
,
EditorStateCancellationTokenSource
,
TextModelCancellationTokenSource
}
from
'
vs/editor/browser/core/editorState
'
;
import
{
IActiveCodeEditor
,
isCodeEditor
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
registerLanguageCommand
,
ServicesAccessor
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
ServicesAccessor
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
...
...
@@ -25,6 +25,8 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
LinkedList
}
from
'
vs/base/common/linkedList
'
;
import
{
CommandsRegistry
}
from
'
vs/platform/commands/common/commands
'
;
import
{
assertType
}
from
'
vs/base/common/types
'
;
export
function
alertFormattingEdits
(
edits
:
ISingleEditOperation
[]):
void
{
...
...
@@ -354,11 +356,11 @@ export function getOnTypeFormattingEdits(
});
}
registerLanguageCommand
(
'
_executeFormatRangeProvider
'
,
function
(
accessor
,
args
)
{
const
{
resource
,
range
,
options
}
=
args
;
if
(
!
(
resource
instanceof
URI
)
||
!
Range
.
isIRange
(
range
))
{
throw
illegalArgument
(
);
}
CommandsRegistry
.
registerCommand
(
'
_executeFormatRangeProvider
'
,
function
(
accessor
,
...
args
)
{
const
[
resource
,
range
,
options
]
=
args
;
assertType
(
URI
.
isUri
(
resource
));
assertType
(
Range
.
isIRange
(
range
)
);
const
model
=
accessor
.
get
(
IModelService
).
getModel
(
resource
);
if
(
!
model
)
{
throw
illegalArgument
(
'
resource
'
);
...
...
@@ -366,11 +368,10 @@ registerLanguageCommand('_executeFormatRangeProvider', function (accessor, args)
return
getDocumentRangeFormattingEditsUntilResult
(
accessor
.
get
(
IEditorWorkerService
),
model
,
Range
.
lift
(
range
),
options
,
CancellationToken
.
None
);
});
registerLanguageCommand
(
'
_executeFormatDocumentProvider
'
,
function
(
accessor
,
args
)
{
const
{
resource
,
options
}
=
args
;
if
(
!
(
resource
instanceof
URI
))
{
throw
illegalArgument
(
'
resource
'
);
}
CommandsRegistry
.
registerCommand
(
'
_executeFormatDocumentProvider
'
,
function
(
accessor
,
...
args
)
{
const
[
resource
,
options
]
=
args
;
assertType
(
URI
.
isUri
(
resource
));
const
model
=
accessor
.
get
(
IModelService
).
getModel
(
resource
);
if
(
!
model
)
{
throw
illegalArgument
(
'
resource
'
);
...
...
@@ -379,11 +380,12 @@ registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, ar
return
getDocumentFormattingEditsUntilResult
(
accessor
.
get
(
IEditorWorkerService
),
model
,
options
,
CancellationToken
.
None
);
});
registerLanguageCommand
(
'
_executeFormatOnTypeProvider
'
,
function
(
accessor
,
args
)
{
const
{
resource
,
position
,
ch
,
options
}
=
args
;
if
(
!
(
resource
instanceof
URI
)
||
!
Position
.
isIPosition
(
position
)
||
typeof
ch
!==
'
string
'
)
{
throw
illegalArgument
();
}
CommandsRegistry
.
registerCommand
(
'
_executeFormatOnTypeProvider
'
,
function
(
accessor
,
...
args
)
{
const
[
resource
,
position
,
ch
,
options
]
=
args
;
assertType
(
URI
.
isUri
(
resource
));
assertType
(
Position
.
isIPosition
(
position
));
assertType
(
typeof
ch
===
'
string
'
);
const
model
=
accessor
.
get
(
IModelService
).
getModel
(
resource
);
if
(
!
model
)
{
throw
illegalArgument
(
'
resource
'
);
...
...
src/vs/editor/contrib/gotoSymbol/goToSymbol.ts
浏览文件 @
78397045
...
...
@@ -6,7 +6,7 @@
import
{
flatten
,
coalesce
}
from
'
vs/base/common/arrays
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
onUnexpectedExternalError
}
from
'
vs/base/common/errors
'
;
import
{
register
DefaultLanguage
Command
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
register
ModelAndPosition
Command
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
LocationLink
,
DefinitionProviderRegistry
,
ImplementationProviderRegistry
,
TypeDefinitionProviderRegistry
,
DeclarationProviderRegistry
,
ProviderResult
,
ReferenceProviderRegistry
}
from
'
vs/editor/common/modes
'
;
...
...
@@ -72,8 +72,8 @@ export function getReferencesAtPosition(model: ITextModel, position: Position, c
});
}
register
DefaultLanguage
Command
(
'
_executeDefinitionProvider
'
,
(
model
,
position
)
=>
getDefinitionsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
DefaultLanguage
Command
(
'
_executeDeclarationProvider
'
,
(
model
,
position
)
=>
getDeclarationsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
DefaultLanguage
Command
(
'
_executeImplementationProvider
'
,
(
model
,
position
)
=>
getImplementationsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
DefaultLanguage
Command
(
'
_executeTypeDefinitionProvider
'
,
(
model
,
position
)
=>
getTypeDefinitionsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
DefaultLanguage
Command
(
'
_executeReferenceProvider
'
,
(
model
,
position
)
=>
getReferencesAtPosition
(
model
,
position
,
false
,
CancellationToken
.
None
));
register
ModelAndPosition
Command
(
'
_executeDefinitionProvider
'
,
(
model
,
position
)
=>
getDefinitionsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
ModelAndPosition
Command
(
'
_executeDeclarationProvider
'
,
(
model
,
position
)
=>
getDeclarationsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
ModelAndPosition
Command
(
'
_executeImplementationProvider
'
,
(
model
,
position
)
=>
getImplementationsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
ModelAndPosition
Command
(
'
_executeTypeDefinitionProvider
'
,
(
model
,
position
)
=>
getTypeDefinitionsAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
ModelAndPosition
Command
(
'
_executeReferenceProvider
'
,
(
model
,
position
)
=>
getReferencesAtPosition
(
model
,
position
,
false
,
CancellationToken
.
None
));
src/vs/editor/contrib/hover/getHover.ts
浏览文件 @
78397045
...
...
@@ -6,7 +6,7 @@
import
{
coalesce
}
from
'
vs/base/common/arrays
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
onUnexpectedExternalError
}
from
'
vs/base/common/errors
'
;
import
{
register
DefaultLanguage
Command
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
register
ModelAndPosition
Command
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
Hover
,
HoverProviderRegistry
}
from
'
vs/editor/common/modes
'
;
...
...
@@ -27,7 +27,7 @@ export function getHover(model: ITextModel, position: Position, token: Cancellat
return
Promise
.
all
(
promises
).
then
(
coalesce
);
}
register
DefaultLanguage
Command
(
'
_executeHoverProvider
'
,
(
model
,
position
)
=>
getHover
(
model
,
position
,
CancellationToken
.
None
));
register
ModelAndPosition
Command
(
'
_executeHoverProvider
'
,
(
model
,
position
)
=>
getHover
(
model
,
position
,
CancellationToken
.
None
));
function
isValid
(
result
:
Hover
)
{
const
hasRange
=
(
typeof
result
.
range
!==
'
undefined
'
);
...
...
src/vs/editor/contrib/quickOpen/quickOpen.ts
浏览文件 @
78397045
...
...
@@ -3,17 +3,17 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
illegalArgument
}
from
'
vs/base/common/errors
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
registerLanguageCommand
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
DocumentSymbol
}
from
'
vs/editor/common/modes
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
ITextModelService
}
from
'
vs/editor/common/services/resolverService
'
;
import
{
OutlineModel
,
OutlineElement
}
from
'
vs/editor/contrib/documentSymbols/outlineModel
'
;
import
{
values
}
from
'
vs/base/common/collections
'
;
import
{
CommandsRegistry
}
from
'
vs/platform/commands/common/commands
'
;
import
{
assertType
}
from
'
vs/base/common/types
'
;
export
async
function
getDocumentSymbols
(
document
:
ITextModel
,
flat
:
boolean
,
token
:
CancellationToken
):
Promise
<
DocumentSymbol
[]
>
{
...
...
@@ -63,26 +63,19 @@ function flatten(bucket: DocumentSymbol[], entries: DocumentSymbol[], overrideCo
}
registerLanguageCommand
(
'
_executeDocumentSymbolProvider
'
,
function
(
accessor
,
args
)
{
const
{
resource
}
=
args
;
if
(
!
(
resource
instanceof
URI
))
{
throw
illegalArgument
(
'
resource
'
);
}
CommandsRegistry
.
registerCommand
(
'
_executeDocumentSymbolProvider
'
,
async
function
(
accessor
,
...
args
)
{
const
[
resource
]
=
args
;
assertType
(
URI
.
isUri
(
resource
));
const
model
=
accessor
.
get
(
IModelService
).
getModel
(
resource
);
if
(
model
)
{
return
getDocumentSymbols
(
model
,
false
,
CancellationToken
.
None
);
}
return
accessor
.
get
(
ITextModelService
).
createModelReference
(
resource
).
then
(
reference
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
const
result
=
getDocumentSymbols
(
reference
.
object
.
textEditorModel
,
false
,
CancellationToken
.
None
);
resolve
(
result
);
}
catch
(
err
)
{
reject
(
err
);
}
}).
finally
(()
=>
{
reference
.
dispose
();
});
});
const
reference
=
await
accessor
.
get
(
ITextModelService
).
createModelReference
(
resource
);
try
{
return
await
getDocumentSymbols
(
reference
.
object
.
textEditorModel
,
false
,
CancellationToken
.
None
);
}
finally
{
reference
.
dispose
();
}
});
src/vs/editor/contrib/smartSelect/smartSelect.ts
浏览文件 @
78397045
...
...
@@ -7,7 +7,7 @@ import * as arrays from 'vs/base/common/arrays';
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
KeyCode
,
KeyMod
}
from
'
vs/base/common/keyCodes
'
;
import
{
ICodeEditor
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
EditorAction
,
IActionOptions
,
registerEditorAction
,
registerEditorContribution
,
ServicesAccessor
,
register
DefaultLanguage
Command
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
EditorAction
,
IActionOptions
,
registerEditorAction
,
registerEditorContribution
,
ServicesAccessor
,
register
Model
Command
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
...
...
@@ -302,6 +302,7 @@ export function provideSelectionRanges(model: ITextModel, positions: Position[],
});
}
registerDefaultLanguageCommand
(
'
_executeSelectionRangeProvider
'
,
function
(
model
,
_position
,
args
)
{
return
provideSelectionRanges
(
model
,
args
.
positions
,
CancellationToken
.
None
);
registerModelCommand
(
'
_executeSelectionRangeProvider
'
,
function
(
model
,
...
args
)
{
const
[
positions
]
=
args
;
return
provideSelectionRanges
(
model
,
positions
,
CancellationToken
.
None
);
});
src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts
浏览文件 @
78397045
...
...
@@ -11,7 +11,7 @@ import { onUnexpectedError, onUnexpectedExternalError } from 'vs/base/common/err
import
{
KeyCode
,
KeyMod
}
from
'
vs/base/common/keyCodes
'
;
import
{
Disposable
,
DisposableStore
}
from
'
vs/base/common/lifecycle
'
;
import
{
IActiveCodeEditor
,
ICodeEditor
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
EditorAction
,
IActionOptions
,
register
DefaultLanguageCommand
,
registerEditorAction
,
registerEditorContribution
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
EditorAction
,
IActionOptions
,
register
EditorAction
,
registerEditorContribution
,
registerModelAndPositionCommand
}
from
'
vs/editor/browser/editorExtensions
'
;
import
{
CursorChangeReason
,
ICursorPositionChangedEvent
}
from
'
vs/editor/common/controller/cursorEvents
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
...
...
@@ -155,7 +155,7 @@ function computeOccurencesAtPosition(model: ITextModel, selection: Selection, wo
return
new
TextualOccurenceAtPositionRequest
(
model
,
selection
,
wordSeparators
);
}
register
DefaultLanguage
Command
(
'
_executeDocumentHighlights
'
,
(
model
,
position
)
=>
getOccurrencesAtPosition
(
model
,
position
,
CancellationToken
.
None
));
register
ModelAndPosition
Command
(
'
_executeDocumentHighlights
'
,
(
model
,
position
)
=>
getOccurrencesAtPosition
(
model
,
position
,
CancellationToken
.
None
));
class
WordHighlighter
{
...
...
src/vs/workbench/api/common/extHostApiCommands.ts
浏览文件 @
78397045
此差异已折叠。
点击以展开。
src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts
浏览文件 @
78397045
...
...
@@ -30,6 +30,8 @@ import { NullLogService } from 'vs/platform/log/common/log';
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
nullExtensionDescription
}
from
'
vs/workbench/services/extensions/common/extensions
'
;
import
{
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
IEditorWorkerService
}
from
'
vs/editor/common/services/editorWorkerService
'
;
import
{
mock
}
from
'
vs/workbench/test/electron-browser/api/mock
'
;
const
defaultSelector
=
{
scheme
:
'
far
'
};
const
model
:
ITextModel
=
EditorModel
.
createFromString
(
...
...
@@ -90,6 +92,11 @@ suite('ExtHostLanguageFeatureCommands', function () {
onModelRemoved
:
undefined
!
,
getCreationOptions
()
{
throw
new
Error
();
}
});
instantiationService
.
stub
(
IEditorWorkerService
,
new
class
extends
mock
<
IEditorWorkerService
>
()
{
async
computeMoreMinimalEdits
(
_uri
:
any
,
edits
:
any
)
{
return
edits
||
undefined
;
}
});
inst
=
instantiationService
;
}
...
...
@@ -195,6 +202,21 @@ suite('ExtHostLanguageFeatureCommands', function () {
assert
.
equal
(
symbols
.
length
,
1
);
});
// --- formatting
test
(
'
executeFormatDocumentProvider, back and forth
'
,
async
function
()
{
disposables
.
push
(
extHost
.
registerDocumentFormattingEditProvider
(
nullExtensionDescription
,
defaultSelector
,
new
class
implements
vscode
.
DocumentFormattingEditProvider
{
provideDocumentFormattingEdits
()
{
return
[
types
.
TextEdit
.
insert
(
new
types
.
Position
(
0
,
0
),
'
42
'
)];
}
}));
await
rpcProtocol
.
sync
();
let
edits
=
await
commands
.
executeCommand
<
vscode
.
SymbolInformation
[]
>
(
'
vscode.executeFormatDocumentProvider
'
,
model
.
uri
);
assert
.
equal
(
edits
.
length
,
1
);
});
// --- definition
test
(
'
Definition, invalid arguments
'
,
function
()
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录