Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
硅谷海盗
kotlin
提交
2d55b8db
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,发现更多精彩内容 >>
提交
2d55b8db
编写于
6月 08, 2020
作者:
J
Jinseong Jeon
提交者:
Mikhail Glukhikh
6月 11, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
FIR deserializer: build property accessors if non-default ones exist
上级
369c0821
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
116 addition
and
33 deletion
+116
-33
compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt
...lin/annotations/withUseSiteTarget/PropertyAndAccessor.txt
+2
-2
compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt
...edKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt
+1
-1
compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInClassStaticFields.txt
...iledKotlin/classObject/ClassObjectInClassStaticFields.txt
+2
-2
compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInTraitStaticFields.txt
...iledKotlin/classObject/ClassObjectInTraitStaticFields.txt
+2
-2
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarInClass.txt
...-tests/testData/loadCompiledKotlin/prop/ExtVarInClass.txt
+1
-1
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTInClass.txt
...ts/testData/loadCompiledKotlin/prop/ExtVarIntTInClass.txt
+1
-1
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTQInClass.txt
...s/testData/loadCompiledKotlin/prop/ExtVarIntTQInClass.txt
+1
-1
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTIntInClass.txt
...ts/testData/loadCompiledKotlin/prop/ExtVarTIntInClass.txt
+1
-1
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTQIntInClass.txt
...s/testData/loadCompiledKotlin/prop/ExtVarTQIntInClass.txt
+1
-1
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/VarWithDelegated.txt
...sts/testData/loadCompiledKotlin/prop/VarWithDelegated.txt
+1
-1
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarModality.txt
...CompiledKotlin/prop/defaultAccessors/ClassVarModality.txt
+2
-2
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarWithSet.txt
...dCompiledKotlin/prop/defaultAccessors/ClassVarWithSet.txt
+9
-9
compiler/fir/analysis-tests/testData/loadCompiledKotlin/visibility/PrivateClassMembers.txt
...ata/loadCompiledKotlin/visibility/PrivateClassMembers.txt
+1
-1
compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt
...lin/fir/deserialization/AbstractAnnotationDeserializer.kt
+20
-0
compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt
...rains/kotlin/fir/deserialization/FirMemberDeserializer.kt
+71
-8
未找到文件。
compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt
浏览文件 @
2d55b8db
...
...
@@ -17,7 +17,7 @@ public final annotation class B : R|kotlin/Annotation| {
public abstract interface I : R|kotlin/Any| {
public abstract var getterAndSetter: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public abstract var propertyAndGetter: R|kotlin/Int|
public get(): R|kotlin/Int|
...
...
@@ -25,6 +25,6 @@ public abstract interface I : R|kotlin/Any| {
public abstract var propertyAndSetter: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
}
compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt
浏览文件 @
2d55b8db
...
...
@@ -6,7 +6,7 @@ public final class A : R|kotlin/Any| {
public final var R|kotlin/String|.myLength3: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(v
alue
: R|kotlin/Int|): R|kotlin/Unit|
public set(v: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|test/A|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInClassStaticFields.txt
浏览文件 @
2d55b8db
...
...
@@ -12,7 +12,7 @@ public final class Test : R|kotlin/Any| {
public final var prop2: R|kotlin/Int|
public get(): R|kotlin/Int|
protected set(
value
: R|kotlin/Int|): R|kotlin/Unit|
protected set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public final val prop3: R|kotlin/Int|
public get(): R|kotlin/Int|
...
...
@@ -27,7 +27,7 @@ public final class Test : R|kotlin/Any| {
public final var prop7: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
i
: R|kotlin/Int|): R|kotlin/Unit|
private constructor(): R|test/Test.Companion|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInTraitStaticFields.txt
浏览文件 @
2d55b8db
...
...
@@ -10,7 +10,7 @@ public abstract interface Test : R|kotlin/Any| {
public final var prop2: R|kotlin/Int|
public get(): R|kotlin/Int|
protected set(
value
: R|kotlin/Int|): R|kotlin/Unit|
protected set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public final val prop3: R|kotlin/Int|
public get(): R|kotlin/Int|
...
...
@@ -25,7 +25,7 @@ public abstract interface Test : R|kotlin/Any| {
public final var prop7: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
i
: R|kotlin/Int|): R|kotlin/Unit|
private constructor(): R|test/Test.Companion|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarInClass.txt
浏览文件 @
2d55b8db
public final class ExtPropInClass : R|kotlin/Any| {
public final var R|kotlin/Int|.itIs: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
p
: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|test/ExtPropInClass|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTInClass.txt
浏览文件 @
2d55b8db
public final class ExtValInClass<P> : R|kotlin/Any| {
public final var R|kotlin/Int|.asas: R|P|
public get(): R|P|
public set(
value
: R|P|): R|kotlin/Unit|
public set(
p
: R|P|): R|kotlin/Unit|
public constructor<P>(): R|test/ExtValInClass<P>|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTQInClass.txt
浏览文件 @
2d55b8db
public final class ExtValInClass<P> : R|kotlin/Any| {
public final var R|kotlin/Int|.asas: R|P?|
public get(): R|P?|
public set(
value
: R|P?|): R|kotlin/Unit|
public set(
p
: R|P?|): R|kotlin/Unit|
public constructor<P>(): R|test/ExtValInClass<P>|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTIntInClass.txt
浏览文件 @
2d55b8db
public final class ExtValPIntInClass<P> : R|kotlin/Any| {
public final var R|P|.asas: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
p
: R|kotlin/Int|): R|kotlin/Unit|
public constructor<P>(): R|test/ExtValPIntInClass<P>|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTQIntInClass.txt
浏览文件 @
2d55b8db
public final class ExtValPIntInClass<P> : R|kotlin/Any| {
public final var R|P?|.asas: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
p
: R|kotlin/Int|): R|kotlin/Unit|
public constructor<P>(): R|test/ExtValPIntInClass<P>|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/VarWithDelegated.txt
浏览文件 @
2d55b8db
public final class A : R|kotlin/Any| {
public final var a: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|test/A|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarModality.txt
浏览文件 @
2d55b8db
...
...
@@ -13,7 +13,7 @@ public open class ClassVarModality : R|kotlin/Any| {
internal final var property4: R|kotlin/Int|
internal get(): R|kotlin/Int|
private set(
value
: R|kotlin/Int|): R|kotlin/Unit|
private set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|test/ClassVarModality|
...
...
@@ -22,7 +22,7 @@ public open class ClassVarModality : R|kotlin/Any| {
public abstract class ClassVarModalityAbstract : R|kotlin/Any| {
public abstract var property1: R|java/util/Date|
public get(): R|java/util/Date|
public set(
value
: R|java/util/Date|): R|kotlin/Unit|
public set(
<set-?>
: R|java/util/Date|): R|kotlin/Unit|
public constructor(): R|test/ClassVarModalityAbstract|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarWithSet.txt
浏览文件 @
2d55b8db
public final class ClassVal : R|kotlin/Any| {
public final var property1: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public final var property10: R|kotlin/Int|
public get(): R|kotlin/Int|
protected set(
value
: R|kotlin/Int|): R|kotlin/Unit|
protected set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public final var property11: R|kotlin/Int|
public get(): R|kotlin/Int|
internal set(
value
: R|kotlin/Int|): R|kotlin/Unit|
internal set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public final var property2: R|java/lang/Object|
public get(): R|java/lang/Object|
protected set(
value
: R|java/lang/Object|): R|kotlin/Unit|
protected set(
<set-?>
: R|java/lang/Object|): R|kotlin/Unit|
public final var property3: R|java/lang/Object|
public get(): R|java/lang/Object|
private set(
value
: R|java/lang/Object|): R|kotlin/Unit|
private set(
<set-?>
: R|java/lang/Object|): R|kotlin/Unit|
protected final var property4: R|kotlin/String|
protected get(): R|kotlin/String|
protected set(
value
: R|kotlin/String|): R|kotlin/Unit|
protected set(
<set-?>
: R|kotlin/String|): R|kotlin/Unit|
protected final var property5: R|kotlin/String|
protected get(): R|kotlin/String|
private set(
value
: R|kotlin/String|): R|kotlin/Unit|
private set(
<set-?>
: R|kotlin/String|): R|kotlin/Unit|
public final var property8: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(
value
: R|kotlin/Int|): R|kotlin/Unit|
public set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public final var property9: R|kotlin/Int|
public get(): R|kotlin/Int|
private set(
value
: R|kotlin/Int|): R|kotlin/Unit|
private set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|test/ClassVal|
...
...
compiler/fir/analysis-tests/testData/loadCompiledKotlin/visibility/PrivateClassMembers.txt
浏览文件 @
2d55b8db
...
...
@@ -6,7 +6,7 @@ public final class PrivateClassMembers : R|kotlin/Any| {
private final var r: R|kotlin/Int|
private get(): R|kotlin/Int|
private set(
value
: R|kotlin/Int|): R|kotlin/Unit|
private set(
<set-?>
: R|kotlin/Int|): R|kotlin/Unit|
private final val v: R|kotlin/Int|
private get(): R|kotlin/Int|
...
...
compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt
浏览文件 @
2d55b8db
...
...
@@ -56,6 +56,26 @@ abstract class AbstractAnnotationDeserializer(
return
annotations
.
map
{
deserializeAnnotation
(
it
,
nameResolver
)
}
}
fun
loadPropertyGetterAnnotations
(
propertyProto
:
ProtoBuf
.
Property
,
nameResolver
:
NameResolver
,
getterFlags
:
Int
):
List
<
FirAnnotationCall
>
{
if
(!
Flags
.
HAS_ANNOTATIONS
.
get
(
getterFlags
))
return
emptyList
()
val
annotations
=
propertyProto
.
getExtension
(
protocol
.
propertyGetterAnnotation
).
orEmpty
()
return
annotations
.
map
{
deserializeAnnotation
(
it
,
nameResolver
)
}
}
fun
loadPropertySetterAnnotations
(
propertyProto
:
ProtoBuf
.
Property
,
nameResolver
:
NameResolver
,
setterFlags
:
Int
):
List
<
FirAnnotationCall
>
{
if
(!
Flags
.
HAS_ANNOTATIONS
.
get
(
setterFlags
))
return
emptyList
()
val
annotations
=
propertyProto
.
getExtension
(
protocol
.
propertySetterAnnotation
).
orEmpty
()
return
annotations
.
map
{
deserializeAnnotation
(
it
,
nameResolver
)
}
}
fun
loadConstructorAnnotations
(
constructorProto
:
ProtoBuf
.
Constructor
,
nameResolver
:
NameResolver
):
List
<
FirAnnotationCall
>
{
if
(!
Flags
.
HAS_ANNOTATIONS
.
get
(
constructorProto
.
flags
))
return
emptyList
()
val
annotations
=
constructorProto
.
getExtension
(
protocol
.
constructorAnnotation
).
orEmpty
()
...
...
compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt
浏览文件 @
2d55b8db
...
...
@@ -20,15 +20,16 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
import
org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import
org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import
org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import
org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
import
org.jetbrains.kotlin.metadata.ProtoBuf
import
org.jetbrains.kotlin.metadata.deserialization.*
import
org.jetbrains.kotlin.name.ClassId
import
org.jetbrains.kotlin.name.FqName
import
org.jetbrains.kotlin.name.Name
import
org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
import
org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import
org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import
org.jetbrains.kotlin.serialization.deserialization.getName
import
org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class
FirDeserializationContext
(
val
nameResolver
:
NameResolver
,
...
...
@@ -172,13 +173,77 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
val
symbol
=
FirPropertySymbol
(
CallableId
(
c
.
packageFqName
,
c
.
relativeClassName
,
callableName
))
val
local
=
c
.
childContext
(
proto
.
typeParameterList
)
val
getterFlags
=
if
(
proto
.
hasGetterFlags
())
proto
.
getterFlags
else
flags
val
setterFlags
=
if
(
proto
.
hasSetterFlags
())
proto
.
setterFlags
else
flags
// Per documentation on Property.getter_flags in metadata.proto, if an accessor flags field is absent, its value should be computed
// by taking hasAnnotations/visibility/modality from property flags, and using false for the rest
val
defaultAccessorFlags
=
Flags
.
getAccessorFlags
(
Flags
.
HAS_ANNOTATIONS
.
get
(
flags
),
Flags
.
VISIBILITY
.
get
(
flags
),
Flags
.
MODALITY
.
get
(
flags
),
false
,
false
,
false
)
val
returnTypeRef
=
proto
.
returnType
(
c
.
typeTable
).
toTypeRef
(
local
)
val
getter
=
if
(
Flags
.
HAS_GETTER
.
get
(
flags
))
{
val
getterFlags
=
if
(
proto
.
hasGetterFlags
())
proto
.
getterFlags
else
defaultAccessorFlags
val
visibility
=
ProtoEnumFlags
.
visibility
(
Flags
.
VISIBILITY
.
get
(
getterFlags
))
val
modality
=
ProtoEnumFlags
.
modality
(
Flags
.
MODALITY
.
get
(
getterFlags
))
if
(
Flags
.
IS_NOT_DEFAULT
.
get
(
getterFlags
))
{
buildPropertyAccessor
{
session
=
c
.
session
origin
=
FirDeclarationOrigin
.
Library
this
.
returnTypeRef
=
returnTypeRef
isGetter
=
true
status
=
FirDeclarationStatusImpl
(
visibility
,
modality
)
annotations
+=
c
.
annotationDeserializer
.
loadPropertyGetterAnnotations
(
proto
,
local
.
nameResolver
,
getterFlags
)
this
.
symbol
=
FirPropertyAccessorSymbol
()
}
}
else
{
FirDefaultPropertyGetter
(
null
,
c
.
session
,
FirDeclarationOrigin
.
Library
,
returnTypeRef
,
visibility
)
}
}
else
{
null
}
val
setter
=
if
(
Flags
.
HAS_SETTER
.
get
(
flags
))
{
val
setterFlags
=
if
(
proto
.
hasSetterFlags
())
proto
.
setterFlags
else
defaultAccessorFlags
val
visibility
=
ProtoEnumFlags
.
visibility
(
Flags
.
VISIBILITY
.
get
(
setterFlags
))
val
modality
=
ProtoEnumFlags
.
modality
(
Flags
.
MODALITY
.
get
(
setterFlags
))
if
(
Flags
.
IS_NOT_DEFAULT
.
get
(
setterFlags
))
{
buildPropertyAccessor
{
session
=
c
.
session
origin
=
FirDeclarationOrigin
.
Library
this
.
returnTypeRef
=
FirImplicitUnitTypeRef
(
source
)
isGetter
=
false
status
=
FirDeclarationStatusImpl
(
visibility
,
modality
)
annotations
+=
c
.
annotationDeserializer
.
loadPropertySetterAnnotations
(
proto
,
local
.
nameResolver
,
setterFlags
)
this
.
symbol
=
FirPropertyAccessorSymbol
()
valueParameters
+=
proto
.
setterValueParameter
.
let
{
val
parameterFlags
=
if
(
it
.
hasFlags
())
it
.
flags
else
0
buildValueParameter
{
session
=
c
.
session
origin
=
FirDeclarationOrigin
.
Library
this
.
returnTypeRef
=
returnTypeRef
name
=
if
(
it
.
hasName
())
c
.
nameResolver
.
getName
(
it
.
name
)
else
Name
.
special
(
"<default-setter-parameter>"
)
this
.
symbol
=
FirVariableSymbol
(
CallableId
(
FqName
.
ROOT
,
name
))
isCrossinline
=
Flags
.
IS_CROSSINLINE
.
get
(
parameterFlags
)
isNoinline
=
Flags
.
IS_NOINLINE
.
get
(
parameterFlags
)
isVararg
=
it
.
hasVarargElementType
()
}
}
}
}
else
{
FirDefaultPropertySetter
(
null
,
c
.
session
,
FirDeclarationOrigin
.
Library
,
returnTypeRef
,
visibility
)
}
}
else
{
null
}
val
isVar
=
Flags
.
IS_VAR
.
get
(
flags
)
return
buildProperty
{
session
=
c
.
session
origin
=
FirDeclarationOrigin
.
Library
returnTypeRef
=
proto
.
returnType
(
c
.
typeTable
).
toTypeRef
(
local
)
this
.
returnTypeRef
=
returnTypeRef
receiverTypeRef
=
proto
.
receiverType
(
c
.
typeTable
)
?.
toTypeRef
(
local
)
name
=
callableName
this
.
isVar
=
isVar
...
...
@@ -198,10 +263,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
resolvePhase
=
FirResolvePhase
.
ANALYZED_DEPENDENCIES
typeParameters
+=
local
.
typeDeserializer
.
ownTypeParameters
.
map
{
it
.
fir
}
annotations
+=
c
.
annotationDeserializer
.
loadPropertyAnnotations
(
proto
,
local
.
nameResolver
)
getter
=
FirDefaultPropertyGetter
(
null
,
c
.
session
,
FirDeclarationOrigin
.
Library
,
returnTypeRef
,
ProtoEnumFlags
.
visibility
(
Flags
.
VISIBILITY
.
get
(
getterFlags
)))
setter
=
if
(
isVar
)
{
FirDefaultPropertySetter
(
null
,
c
.
session
,
FirDeclarationOrigin
.
Library
,
returnTypeRef
,
ProtoEnumFlags
.
visibility
(
Flags
.
VISIBILITY
.
get
(
setterFlags
)))
}
else
null
this
.
getter
=
getter
this
.
setter
=
setter
this
.
containerSource
=
c
.
containerSource
this
.
initializer
=
if
(
Flags
.
HAS_CONSTANT
.
get
(
flags
))
{
proto
.
getExtensionOrNull
(
BuiltInSerializerProtocol
.
compileTimeValue
)
?.
let
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录