Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
硅谷海盗
kotlin
提交
bfa64897
K
kotlin
项目概览
硅谷海盗
/
kotlin
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kotlin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bfa64897
编写于
6月 02, 2020
作者:
M
Mikhail Zarechenskiy
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Introduce call checker for `Unit`-conversions
上级
6b0a803d
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
210 addition
and
1 deletion
+210
-1
compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java
...ns/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java
+5
-0
compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt
.../org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt
+2
-1
compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/UnitConversionCallChecker.kt
...otlin/resolve/calls/checkers/UnitConversionCallChecker.kt
+34
-0
compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/UnitTypeConversions.kt
...ns/kotlin/resolve/calls/components/UnitTypeConversions.kt
+2
-0
compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt
...g/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt
+1
-0
compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt
...tbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt
+11
-0
compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.fir.kt
...s/tests/unitConversion/unitConversionCompatibility.fir.kt
+29
-0
compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt
...stics/tests/unitConversion/unitConversionCompatibility.kt
+29
-0
compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.txt
...tics/tests/unitConversion/unitConversionCompatibility.txt
+42
-0
compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.fir.kt
...onversion/unitConversionDisabledForSimpleArguments.fir.kt
+16
-0
compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.kt
...nitConversion/unitConversionDisabledForSimpleArguments.kt
+16
-0
compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.txt
...itConversion/unitConversionDisabledForSimpleArguments.txt
+13
-0
compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
...g/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
+5
-0
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java
...in/checkers/javac/DiagnosticsUsingJavacTestGenerated.java
+5
-0
未找到文件。
compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java
浏览文件 @
bfa64897
...
@@ -24476,6 +24476,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
...
@@ -24476,6 +24476,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt");
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt");
}
}
@TestMetadata("unitConversionDisabledForSimpleArguments.kt")
public void testUnitConversionDisabledForSimpleArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.kt");
}
@TestMetadata("unitConversionForAllKinds.kt")
@TestMetadata("unitConversionForAllKinds.kt")
public void testUnitConversionForAllKinds() throws Exception {
public void testUnitConversionForAllKinds() throws Exception {
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionForAllKinds.kt");
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionForAllKinds.kt");
compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt
浏览文件 @
bfa64897
...
@@ -49,7 +49,8 @@ private val DEFAULT_CALL_CHECKERS = listOf(
...
@@ -49,7 +49,8 @@ private val DEFAULT_CALL_CHECKERS = listOf(
PrimitiveNumericComparisonCallChecker
,
LambdaWithSuspendModifierCallChecker
,
PrimitiveNumericComparisonCallChecker
,
LambdaWithSuspendModifierCallChecker
,
UselessElvisCallChecker
(),
ResultTypeWithNullableOperatorsChecker
(),
NullableVarargArgumentCallChecker
,
UselessElvisCallChecker
(),
ResultTypeWithNullableOperatorsChecker
(),
NullableVarargArgumentCallChecker
,
NamedFunAsExpressionChecker
,
ContractNotAllowedCallChecker
,
ReifiedTypeParameterSubstitutionChecker
(),
NamedFunAsExpressionChecker
,
ContractNotAllowedCallChecker
,
ReifiedTypeParameterSubstitutionChecker
(),
MissingDependencySupertypeChecker
.
ForCalls
,
AbstractClassInstantiationChecker
,
SuspendConversionCallChecker
MissingDependencySupertypeChecker
.
ForCalls
,
AbstractClassInstantiationChecker
,
SuspendConversionCallChecker
,
UnitConversionCallChecker
)
)
private
val
DEFAULT_TYPE_CHECKERS
=
emptyList
<
AdditionalTypeChecker
>()
private
val
DEFAULT_TYPE_CHECKERS
=
emptyList
<
AdditionalTypeChecker
>()
private
val
DEFAULT_CLASSIFIER_USAGE_CHECKERS
=
listOf
(
private
val
DEFAULT_CLASSIFIER_USAGE_CHECKERS
=
listOf
(
...
...
compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/UnitConversionCallChecker.kt
0 → 100644
浏览文件 @
bfa64897
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package
org.jetbrains.kotlin.resolve.calls.checkers
import
com.intellij.psi.PsiElement
import
org.jetbrains.kotlin.config.LanguageFeature
import
org.jetbrains.kotlin.diagnostics.Errors
import
org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import
org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import
org.jetbrains.kotlin.resolve.calls.tower.psiCallArgument
object
UnitConversionCallChecker
:
CallChecker
{
override
fun
check
(
resolvedCall
:
ResolvedCall
<
*
>,
reportOn
:
PsiElement
,
context
:
CallCheckerContext
)
{
if
(
resolvedCall
!
is
NewResolvedCallImpl
<
*
>)
return
if
(
context
.
languageVersionSettings
.
supportsFeature
(
LanguageFeature
.
UnitConversion
))
return
// lambdas are working since 1.0, callable references are handled as part of reference adaptation
// => here we're checking only simple argument
val
argumentsWithUnitConversion
=
resolvedCall
.
resolvedCallAtom
.
argumentsWithUnitConversion
for
(
argumentWithUnitConversion
in
argumentsWithUnitConversion
.
keys
)
{
context
.
trace
.
report
(
Errors
.
UNSUPPORTED_FEATURE
.
on
(
argumentWithUnitConversion
.
psiCallArgument
.
valueArgument
.
asElement
(),
LanguageFeature
.
UnitConversion
to
context
.
languageVersionSettings
)
)
}
}
}
\ No newline at end of file
compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/UnitTypeConversions.kt
浏览文件 @
bfa64897
...
@@ -75,6 +75,8 @@ object UnitTypeConversions : ParameterTypeConversion {
...
@@ -75,6 +75,8 @@ object UnitTypeConversions : ParameterTypeConversion {
suspendFunction
=
expectedParameterType
.
isSuspendFunctionType
suspendFunction
=
expectedParameterType
.
isSuspendFunctionType
)
)
candidate
.
resolvedCall
.
registerArgumentWithUnitConversion
(
argument
,
nonUnitReturnedParameterType
)
candidate
.
addDiagnostic
(
LowerPriorityToPreserveCompatibility
)
candidate
.
addDiagnostic
(
LowerPriorityToPreserveCompatibility
)
return
nonUnitReturnedParameterType
return
nonUnitReturnedParameterType
...
...
compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt
浏览文件 @
bfa64897
...
@@ -69,6 +69,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
...
@@ -69,6 +69,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
abstract
val
knownParametersSubstitutor
:
TypeSubstitutor
abstract
val
knownParametersSubstitutor
:
TypeSubstitutor
abstract
val
argumentsWithConversion
:
Map
<
KotlinCallArgument
,
SamConversionDescription
>
abstract
val
argumentsWithConversion
:
Map
<
KotlinCallArgument
,
SamConversionDescription
>
abstract
val
argumentsWithSuspendConversion
:
Map
<
KotlinCallArgument
,
UnwrappedType
>
abstract
val
argumentsWithSuspendConversion
:
Map
<
KotlinCallArgument
,
UnwrappedType
>
abstract
val
argumentsWithUnitConversion
:
Map
<
KotlinCallArgument
,
UnwrappedType
>
abstract
val
argumentsWithConstantConversion
:
Map
<
KotlinCallArgument
,
IntegerValueTypeConstant
>
abstract
val
argumentsWithConstantConversion
:
Map
<
KotlinCallArgument
,
IntegerValueTypeConstant
>
}
}
...
...
compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt
浏览文件 @
bfa64897
...
@@ -193,6 +193,7 @@ class MutableResolvedCallAtom(
...
@@ -193,6 +193,7 @@ class MutableResolvedCallAtom(
lateinit
var
argumentToCandidateParameter
:
Map
<
KotlinCallArgument
,
ValueParameterDescriptor
>
lateinit
var
argumentToCandidateParameter
:
Map
<
KotlinCallArgument
,
ValueParameterDescriptor
>
private
var
samAdapterMap
:
HashMap
<
KotlinCallArgument
,
SamConversionDescription
>?
=
null
private
var
samAdapterMap
:
HashMap
<
KotlinCallArgument
,
SamConversionDescription
>?
=
null
private
var
suspendAdapterMap
:
HashMap
<
KotlinCallArgument
,
UnwrappedType
>?
=
null
private
var
suspendAdapterMap
:
HashMap
<
KotlinCallArgument
,
UnwrappedType
>?
=
null
private
var
unitAdapterMap
:
HashMap
<
KotlinCallArgument
,
UnwrappedType
>?
=
null
private
var
signedUnsignedConstantConversions
:
HashMap
<
KotlinCallArgument
,
IntegerValueTypeConstant
>?
=
null
private
var
signedUnsignedConstantConversions
:
HashMap
<
KotlinCallArgument
,
IntegerValueTypeConstant
>?
=
null
val
hasSamConversion
:
Boolean
val
hasSamConversion
:
Boolean
...
@@ -207,6 +208,9 @@ class MutableResolvedCallAtom(
...
@@ -207,6 +208,9 @@ class MutableResolvedCallAtom(
override
val
argumentsWithSuspendConversion
:
Map
<
KotlinCallArgument
,
UnwrappedType
>
override
val
argumentsWithSuspendConversion
:
Map
<
KotlinCallArgument
,
UnwrappedType
>
get
()
=
suspendAdapterMap
?:
emptyMap
()
get
()
=
suspendAdapterMap
?:
emptyMap
()
override
val
argumentsWithUnitConversion
:
Map
<
KotlinCallArgument
,
UnwrappedType
>
get
()
=
unitAdapterMap
?:
emptyMap
()
override
val
argumentsWithConstantConversion
:
Map
<
KotlinCallArgument
,
IntegerValueTypeConstant
>
override
val
argumentsWithConstantConversion
:
Map
<
KotlinCallArgument
,
IntegerValueTypeConstant
>
get
()
=
signedUnsignedConstantConversions
?:
emptyMap
()
get
()
=
signedUnsignedConstantConversions
?:
emptyMap
()
...
@@ -224,6 +228,13 @@ class MutableResolvedCallAtom(
...
@@ -224,6 +228,13 @@ class MutableResolvedCallAtom(
suspendAdapterMap
!!
[
argument
]
=
convertedType
suspendAdapterMap
!!
[
argument
]
=
convertedType
}
}
fun
registerArgumentWithUnitConversion
(
argument
:
KotlinCallArgument
,
convertedType
:
UnwrappedType
)
{
if
(
unitAdapterMap
==
null
)
unitAdapterMap
=
hashMapOf
()
unitAdapterMap
!!
[
argument
]
=
convertedType
}
fun
registerArgumentWithConstantConversion
(
argument
:
KotlinCallArgument
,
convertedConstant
:
IntegerValueTypeConstant
)
{
fun
registerArgumentWithConstantConversion
(
argument
:
KotlinCallArgument
,
convertedConstant
:
IntegerValueTypeConstant
)
{
if
(
signedUnsignedConstantConversions
==
null
)
if
(
signedUnsignedConstantConversions
==
null
)
signedUnsignedConstantConversions
=
hashMapOf
()
signedUnsignedConstantConversions
=
hashMapOf
()
...
...
compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.fir.kt
0 → 100644
浏览文件 @
bfa64897
// !DIAGNOSTICS: -UNUSED_PARAMETER
object
Test1
{
fun
foo
(
f
:
()
->
Int
)
{}
object
Scope
{
fun
foo
(
f
:
()
->
Unit
)
{}
fun
test
(
f
:
()
->
Int
)
{
<!
DEBUG_INFO_CALL
(
"fqName: Test1.foo; typeCall: function"
)!>
foo
(
f
)<!>
}
}
}
object
Test2
{
fun
interface
KRunnable
{
fun
run
()
}
fun
foo
(
f
:
()
->
Unit
)
{}
object
Scope1
{
fun
foo
(
f
:
KRunnable
)
{}
fun
test
(
f
:
()
->
Int
)
{
<!
DEBUG_INFO_CALL
(
"fqName: fqName is unknown; typeCall: unresolved"
)!><!
INAPPLICABLE_CANDIDATE
!>
foo
<!>(
f
)<!>
}
}
}
compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt
浏览文件 @
bfa64897
// !DIAGNOSTICS: -UNUSED_PARAMETER
object
Test1
{
fun
foo
(
f
:
()
->
Int
)
{}
object
Scope
{
fun
foo
(
f
:
()
->
Unit
)
{}
fun
test
(
f
:
()
->
Int
)
{
<!
DEBUG_INFO_CALL
(
"fqName: Test1.foo; typeCall: function"
)!><!
COMPATIBILITY_WARNING
!>
foo
<!>(
f
)<!>
}
}
}
object
Test2
{
fun
interface
KRunnable
{
fun
run
()
}
fun
foo
(
f
:
()
->
Unit
)
{}
object
Scope1
{
fun
foo
(
f
:
KRunnable
)
{}
fun
test
(
f
:
()
->
Int
)
{
<!
DEBUG_INFO_CALL
(
"fqName: Test2.Scope1.foo; typeCall: function"
)!>
foo
(<!
UNSUPPORTED_FEATURE
!>
f
<!>)<!>
}
}
}
compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.txt
0 → 100644
浏览文件 @
bfa64897
package
public object Test1 {
private constructor Test1()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ f: () -> kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public object Scope {
private constructor Scope()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(/*0*/ f: () -> kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public object Test2 {
private constructor Test2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public fun interface KRunnable {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public abstract fun run(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Scope1 {
private constructor Scope1()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ f: Test2.KRunnable): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(/*0*/ f: () -> kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.fir.kt
0 → 100644
浏览文件 @
bfa64897
// !LANGUAGE: -SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
fun
foo
(
f
:
()
->
Unit
)
{}
fun
bar
():
Int
=
0
abstract
class
SubInt
:
()
->
Int
fun
test
(
f
:
()
->
String
,
s
:
SubInt
)
{
foo
{
"lambda"
}
foo
(
::
bar
)
<!
INAPPLICABLE_CANDIDATE
!>
foo
<!>(
f
)
<!
INAPPLICABLE_CANDIDATE
!>
foo
<!>(
s
)
}
\ No newline at end of file
compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.kt
0 → 100644
浏览文件 @
bfa64897
// !LANGUAGE: -SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
fun
foo
(
f
:
()
->
Unit
)
{}
fun
bar
():
Int
=
0
abstract
class
SubInt
:
()
->
Int
fun
test
(
f
:
()
->
String
,
s
:
SubInt
)
{
foo
{
"lambda"
}
foo
(
::
bar
)
foo
(<!
UNSUPPORTED_FEATURE
!>
f
<!>)
foo
(<!
UNSUPPORTED_FEATURE
!>
s
<!>)
}
\ No newline at end of file
compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.txt
0 → 100644
浏览文件 @
bfa64897
package
public fun bar(): kotlin.Int
public fun foo(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
public fun test(/*0*/ f: () -> kotlin.String, /*1*/ s: SubInt): kotlin.Unit
public abstract class SubInt : () -> kotlin.Int {
public constructor SubInt()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public abstract override /*1*/ /*fake_override*/ fun invoke(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
浏览文件 @
bfa64897
...
@@ -24558,6 +24558,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
...
@@ -24558,6 +24558,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt");
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt");
}
}
@TestMetadata("unitConversionDisabledForSimpleArguments.kt")
public void testUnitConversionDisabledForSimpleArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.kt");
}
@TestMetadata("unitConversionForAllKinds.kt")
@TestMetadata("unitConversionForAllKinds.kt")
public void testUnitConversionForAllKinds() throws Exception {
public void testUnitConversionForAllKinds() throws Exception {
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionForAllKinds.kt");
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionForAllKinds.kt");
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java
浏览文件 @
bfa64897
...
@@ -24478,6 +24478,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
...
@@ -24478,6 +24478,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt");
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt");
}
}
@TestMetadata("unitConversionDisabledForSimpleArguments.kt")
public void testUnitConversionDisabledForSimpleArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionDisabledForSimpleArguments.kt");
}
@TestMetadata("unitConversionForAllKinds.kt")
@TestMetadata("unitConversionForAllKinds.kt")
public void testUnitConversionForAllKinds() throws Exception {
public void testUnitConversionForAllKinds() throws Exception {
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionForAllKinds.kt");
runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionForAllKinds.kt");
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录