Commit a80db853 authored by John Luxford's avatar John Luxford Committed by Wouter van Oortmerssen

[C#, Java, C++] Fixes issue #5399 by always including namespaces (#5404)

* [C#] Fixes issue #5399 by always including namespaces

* Updated tests for code generator changes

* Fixed 'As' method names
parent a6be1d0d
......@@ -109,8 +109,9 @@ class BaseGenerator {
// which works for js and php
virtual const Namespace *CurrentNameSpace() const { return nullptr; }
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
// Ensure that a type is prefixed with its namespace even within
// its own namespace to avoid conflict between generated method
// names and similarly named classes or structs
std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) const;
......
This diff is collapsed.
This diff is collapsed.
......@@ -105,11 +105,9 @@ std::string BaseGenerator::LastNamespacePart(const Namespace &ns) {
return std::string("");
}
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
// Ensure that a type is prefixed with its namespace.
std::string BaseGenerator::WrapInNameSpace(const Namespace *ns,
const std::string &name) const {
if (CurrentNameSpace() == ns) return name;
std::string qualified_name = qualifying_start_;
for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
qualified_name += *it + qualifying_separator_;
......
......@@ -1182,7 +1182,7 @@ class GeneralGenerator : public BaseGenerator {
auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
auto nested_method_name =
MakeCamel(field.name, lang_.first_camel_upper) + "As" +
nested_type_name;
field.nested_flatbuffer->name;
auto get_nested_method_name = nested_method_name;
if (lang_.language == IDLOptions::kCSharp) {
get_nested_method_name = "Get" + nested_method_name;
......
......@@ -20,11 +20,11 @@ public struct Ability : IFlatbufferObject
public uint Distance { get { return __p.bb.GetUint(__p.bb_pos + 4); } }
public void MutateDistance(uint distance) { __p.bb.PutUint(__p.bb_pos + 4, distance); }
public static Offset<Ability> CreateAbility(FlatBufferBuilder builder, uint Id, uint Distance) {
public static Offset<MyGame.Example.Ability> CreateAbility(FlatBufferBuilder builder, uint Id, uint Distance) {
builder.Prep(4, 8);
builder.PutUint(Distance);
builder.PutUint(Id);
return new Offset<Ability>(builder.Offset);
return new Offset<MyGame.Example.Ability>(builder.Offset);
}
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -20,7 +20,7 @@ public struct Referrable : IFlatbufferObject
public ulong Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
public bool MutateId(ulong id) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, id); return true; } else { return false; } }
public static Offset<Referrable> CreateReferrable(FlatBufferBuilder builder,
public static Offset<MyGame.Example.Referrable> CreateReferrable(FlatBufferBuilder builder,
ulong id = 0) {
builder.StartTable(1);
Referrable.AddId(builder, id);
......@@ -29,9 +29,9 @@ public struct Referrable : IFlatbufferObject
public static void StartReferrable(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddId(FlatBufferBuilder builder, ulong id) { builder.AddUlong(0, id, 0); }
public static Offset<Referrable> EndReferrable(FlatBufferBuilder builder) {
public static Offset<MyGame.Example.Referrable> EndReferrable(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<Referrable>(o);
return new Offset<MyGame.Example.Referrable>(o);
}
public static VectorOffset CreateSortedVectorOfReferrable(FlatBufferBuilder builder, Offset<Referrable>[] offsets) {
......
......@@ -29,7 +29,7 @@ public struct Stat : IFlatbufferObject
public ushort Count { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetUshort(o + __p.bb_pos) : (ushort)0; } }
public bool MutateCount(ushort count) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutUshort(o + __p.bb_pos, count); return true; } else { return false; } }
public static Offset<Stat> CreateStat(FlatBufferBuilder builder,
public static Offset<MyGame.Example.Stat> CreateStat(FlatBufferBuilder builder,
StringOffset idOffset = default(StringOffset),
long val = 0,
ushort count = 0) {
......@@ -44,9 +44,9 @@ public struct Stat : IFlatbufferObject
public static void AddId(FlatBufferBuilder builder, StringOffset idOffset) { builder.AddOffset(0, idOffset.Value, 0); }
public static void AddVal(FlatBufferBuilder builder, long val) { builder.AddLong(1, val, 0); }
public static void AddCount(FlatBufferBuilder builder, ushort count) { builder.AddUshort(2, count, 0); }
public static Offset<Stat> EndStat(FlatBufferBuilder builder) {
public static Offset<MyGame.Example.Stat> EndStat(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<Stat>(o);
return new Offset<MyGame.Example.Stat>(o);
}
};
......
......@@ -20,12 +20,12 @@ public struct Test : IFlatbufferObject
public sbyte B { get { return __p.bb.GetSbyte(__p.bb_pos + 2); } }
public void MutateB(sbyte b) { __p.bb.PutSbyte(__p.bb_pos + 2, b); }
public static Offset<Test> CreateTest(FlatBufferBuilder builder, short A, sbyte B) {
public static Offset<MyGame.Example.Test> CreateTest(FlatBufferBuilder builder, short A, sbyte B) {
builder.Prep(2, 4);
builder.Pad(1);
builder.PutSbyte(B);
builder.PutShort(A);
return new Offset<Test>(builder.Offset);
return new Offset<MyGame.Example.Test>(builder.Offset);
}
};
......
......@@ -17,21 +17,21 @@ internal partial struct TestSimpleTableWithEnum : IFlatbufferObject
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public TestSimpleTableWithEnum __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public Color Color { get { int o = __p.__offset(4); return o != 0 ? (Color)__p.bb.Get(o + __p.bb_pos) : Color.Green; } }
public bool MutateColor(Color color) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)color); return true; } else { return false; } }
public MyGame.Example.Color Color { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.Color)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Color.Green; } }
public bool MutateColor(MyGame.Example.Color color) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)color); return true; } else { return false; } }
public static Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(FlatBufferBuilder builder,
Color color = Color.Green) {
public static Offset<MyGame.Example.TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(FlatBufferBuilder builder,
MyGame.Example.Color color = MyGame.Example.Color.Green) {
builder.StartTable(1);
TestSimpleTableWithEnum.AddColor(builder, color);
return TestSimpleTableWithEnum.EndTestSimpleTableWithEnum(builder);
}
public static void StartTestSimpleTableWithEnum(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddColor(FlatBufferBuilder builder, Color color) { builder.AddByte(0, (byte)color, 2); }
public static Offset<TestSimpleTableWithEnum> EndTestSimpleTableWithEnum(FlatBufferBuilder builder) {
public static void AddColor(FlatBufferBuilder builder, MyGame.Example.Color color) { builder.AddByte(0, (byte)color, 2); }
public static Offset<MyGame.Example.TestSimpleTableWithEnum> EndTestSimpleTableWithEnum(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<TestSimpleTableWithEnum>(o);
return new Offset<MyGame.Example.TestSimpleTableWithEnum>(o);
}
};
......
......@@ -56,7 +56,7 @@ public struct TypeAliases : IFlatbufferObject
public double[] GetVf64Array() { return __p.__vector_as_array<double>(26); }
public bool MutateVf64(int j, double vf64) { int o = __p.__offset(26); if (o != 0) { __p.bb.PutDouble(__p.__vector(o) + j * 8, vf64); return true; } else { return false; } }
public static Offset<TypeAliases> CreateTypeAliases(FlatBufferBuilder builder,
public static Offset<MyGame.Example.TypeAliases> CreateTypeAliases(FlatBufferBuilder builder,
sbyte i8 = 0,
byte u8 = 0,
short i16 = 0,
......@@ -104,9 +104,9 @@ public struct TypeAliases : IFlatbufferObject
public static VectorOffset CreateVf64Vector(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddDouble(data[i]); return builder.EndVector(); }
public static VectorOffset CreateVf64VectorBlock(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); builder.Add(data); return builder.EndVector(); }
public static void StartVf64Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); }
public static Offset<TypeAliases> EndTypeAliases(FlatBufferBuilder builder) {
public static Offset<MyGame.Example.TypeAliases> EndTypeAliases(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<TypeAliases>(o);
return new Offset<MyGame.Example.TypeAliases>(o);
}
};
......
......@@ -23,11 +23,11 @@ public struct Vec3 : IFlatbufferObject
public void MutateZ(float z) { __p.bb.PutFloat(__p.bb_pos + 8, z); }
public double Test1 { get { return __p.bb.GetDouble(__p.bb_pos + 16); } }
public void MutateTest1(double test1) { __p.bb.PutDouble(__p.bb_pos + 16, test1); }
public Color Test2 { get { return (Color)__p.bb.Get(__p.bb_pos + 24); } }
public void MutateTest2(Color test2) { __p.bb.Put(__p.bb_pos + 24, (byte)test2); }
public Test Test3 { get { return (new Test()).__assign(__p.bb_pos + 26, __p.bb); } }
public MyGame.Example.Color Test2 { get { return (MyGame.Example.Color)__p.bb.Get(__p.bb_pos + 24); } }
public void MutateTest2(MyGame.Example.Color test2) { __p.bb.Put(__p.bb_pos + 24, (byte)test2); }
public MyGame.Example.Test Test3 { get { return (new MyGame.Example.Test()).__assign(__p.bb_pos + 26, __p.bb); } }
public static Offset<Vec3> CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, Color Test2, short test3_A, sbyte test3_B) {
public static Offset<MyGame.Example.Vec3> CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, MyGame.Example.Color Test2, short test3_A, sbyte test3_B) {
builder.Prep(8, 32);
builder.Pad(2);
builder.Prep(2, 4);
......@@ -41,7 +41,7 @@ public struct Vec3 : IFlatbufferObject
builder.PutFloat(Z);
builder.PutFloat(Y);
builder.PutFloat(X);
return new Offset<Vec3>(builder.Offset);
return new Offset<MyGame.Example.Vec3>(builder.Offset);
}
};
......
......@@ -22,8 +22,8 @@ public final class Vec3 extends Struct {
public void mutateTest1(double test1) { bb.putDouble(bb_pos + 16, test1); }
public int test2() { return bb.get(bb_pos + 24) & 0xFF; }
public void mutateTest2(int test2) { bb.put(bb_pos + 24, (byte)test2); }
public Test test3() { return test3(new Test()); }
public Test test3(Test obj) { return obj.__assign(bb_pos + 26, bb); }
public MyGame.Example.Test test3() { return test3(new MyGame.Example.Test()); }
public MyGame.Example.Test test3(MyGame.Example.Test obj) { return obj.__assign(bb_pos + 26, bb); }
public static int createVec3(FlatBufferBuilder builder, float x, float y, float z, double test1, int test2, short test3_a, byte test3_b) {
builder.prep(8, 32);
......
......@@ -19,9 +19,9 @@ public struct Monster : IFlatbufferObject
public static void StartMonster(FlatBufferBuilder builder) { builder.StartTable(0); }
public static Offset<Monster> EndMonster(FlatBufferBuilder builder) {
public static Offset<MyGame.Example2.Monster> EndMonster(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<Monster>(o);
return new Offset<MyGame.Example2.Monster>(o);
}
};
......
......@@ -19,9 +19,9 @@ public struct InParentNamespace : IFlatbufferObject
public static void StartInParentNamespace(FlatBufferBuilder builder) { builder.StartTable(0); }
public static Offset<InParentNamespace> EndInParentNamespace(FlatBufferBuilder builder) {
public static Offset<MyGame.InParentNamespace> EndInParentNamespace(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<InParentNamespace>(o);
return new Offset<MyGame.InParentNamespace>(o);
}
};
......
......@@ -49,7 +49,7 @@ public struct MonsterExtra : IFlatbufferObject
public double[] GetTestdVecArray() { return __p.__vector_as_array<double>(18); }
public bool MutateTestdVec(int j, double testd_vec) { int o = __p.__offset(18); if (o != 0) { __p.bb.PutDouble(__p.__vector(o) + j * 8, testd_vec); return true; } else { return false; } }
public static Offset<MonsterExtra> CreateMonsterExtra(FlatBufferBuilder builder,
public static Offset<MyGame.MonsterExtra> CreateMonsterExtra(FlatBufferBuilder builder,
float testf_nan = Single.NaN,
float testf_pinf = Single.PositiveInfinity,
float testf_ninf = Single.NegativeInfinity,
......@@ -85,12 +85,12 @@ public struct MonsterExtra : IFlatbufferObject
public static VectorOffset CreateTestdVecVector(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddDouble(data[i]); return builder.EndVector(); }
public static VectorOffset CreateTestdVecVectorBlock(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); builder.Add(data); return builder.EndVector(); }
public static void StartTestdVecVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); }
public static Offset<MonsterExtra> EndMonsterExtra(FlatBufferBuilder builder) {
public static Offset<MyGame.MonsterExtra> EndMonsterExtra(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<MonsterExtra>(o);
return new Offset<MyGame.MonsterExtra>(o);
}
public static void FinishMonsterExtraBuffer(FlatBufferBuilder builder, Offset<MonsterExtra> offset) { builder.Finish(offset.Value, "MONE"); }
public static void FinishSizePrefixedMonsterExtraBuffer(FlatBufferBuilder builder, Offset<MonsterExtra> offset) { builder.FinishSizePrefixed(offset.Value, "MONE"); }
public static void FinishMonsterExtraBuffer(FlatBufferBuilder builder, Offset<MyGame.MonsterExtra> offset) { builder.Finish(offset.Value, "MONE"); }
public static void FinishSizePrefixedMonsterExtraBuffer(FlatBufferBuilder builder, Offset<MyGame.MonsterExtra> offset) { builder.FinishSizePrefixed(offset.Value, "MONE"); }
};
......
......@@ -343,16 +343,16 @@ inline void FinishSizePrefixedMonsterExtraBuffer(
fbb.FinishSizePrefixed(root, MonsterExtraIdentifier());
}
inline std::unique_ptr<MonsterExtraT> UnPackMonsterExtra(
inline std::unique_ptr<MyGame::MonsterExtraT> UnPackMonsterExtra(
const void *buf,
const flatbuffers::resolver_function_t *res = nullptr) {
return std::unique_ptr<MonsterExtraT>(GetMonsterExtra(buf)->UnPack(res));
return std::unique_ptr<MyGame::MonsterExtraT>(GetMonsterExtra(buf)->UnPack(res));
}
inline std::unique_ptr<MonsterExtraT> UnPackSizePrefixedMonsterExtra(
inline std::unique_ptr<MyGame::MonsterExtraT> UnPackSizePrefixedMonsterExtra(
const void *buf,
const flatbuffers::resolver_function_t *res = nullptr) {
return std::unique_ptr<MonsterExtraT>(GetSizePrefixedMonsterExtra(buf)->UnPack(res));
return std::unique_ptr<MyGame::MonsterExtraT>(GetSizePrefixedMonsterExtra(buf)->UnPack(res));
}
} // namespace MyGame
......
This diff is collapsed.
......@@ -20,11 +20,11 @@ public struct StructInNestedNS : IFlatbufferObject
public int B { get { return __p.bb.GetInt(__p.bb_pos + 4); } }
public void MutateB(int b) { __p.bb.PutInt(__p.bb_pos + 4, b); }
public static Offset<StructInNestedNS> CreateStructInNestedNS(FlatBufferBuilder builder, int A, int B) {
public static Offset<NamespaceA.NamespaceB.StructInNestedNS> CreateStructInNestedNS(FlatBufferBuilder builder, int A, int B) {
builder.Prep(4, 8);
builder.PutInt(B);
builder.PutInt(A);
return new Offset<StructInNestedNS>(builder.Offset);
return new Offset<NamespaceA.NamespaceB.StructInNestedNS>(builder.Offset);
}
};
......
......@@ -20,7 +20,7 @@ public struct TableInNestedNS : IFlatbufferObject
public int Foo { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
public bool MutateFoo(int foo) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, foo); return true; } else { return false; } }
public static Offset<TableInNestedNS> CreateTableInNestedNS(FlatBufferBuilder builder,
public static Offset<NamespaceA.NamespaceB.TableInNestedNS> CreateTableInNestedNS(FlatBufferBuilder builder,
int foo = 0) {
builder.StartTable(1);
TableInNestedNS.AddFoo(builder, foo);
......@@ -29,9 +29,9 @@ public struct TableInNestedNS : IFlatbufferObject
public static void StartTableInNestedNS(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddFoo(FlatBufferBuilder builder, int foo) { builder.AddInt(0, foo, 0); }
public static Offset<TableInNestedNS> EndTableInNestedNS(FlatBufferBuilder builder) {
public static Offset<NamespaceA.NamespaceB.TableInNestedNS> EndTableInNestedNS(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<TableInNestedNS>(o);
return new Offset<NamespaceA.NamespaceB.TableInNestedNS>(o);
}
};
......
......@@ -19,7 +19,7 @@ public struct SecondTableInA : IFlatbufferObject
public NamespaceC.TableInC? ReferToC { get { int o = __p.__offset(4); return o != 0 ? (NamespaceC.TableInC?)(new NamespaceC.TableInC()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public static Offset<SecondTableInA> CreateSecondTableInA(FlatBufferBuilder builder,
public static Offset<NamespaceA.SecondTableInA> CreateSecondTableInA(FlatBufferBuilder builder,
Offset<NamespaceC.TableInC> refer_to_cOffset = default(Offset<NamespaceC.TableInC>)) {
builder.StartTable(1);
SecondTableInA.AddReferToC(builder, refer_to_cOffset);
......@@ -28,9 +28,9 @@ public struct SecondTableInA : IFlatbufferObject
public static void StartSecondTableInA(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddReferToC(FlatBufferBuilder builder, Offset<NamespaceC.TableInC> referToCOffset) { builder.AddOffset(0, referToCOffset.Value, 0); }
public static Offset<SecondTableInA> EndSecondTableInA(FlatBufferBuilder builder) {
public static Offset<NamespaceA.SecondTableInA> EndSecondTableInA(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<SecondTableInA>(o);
return new Offset<NamespaceA.SecondTableInA>(o);
}
};
......
......@@ -26,9 +26,9 @@ public struct TableInFirstNS : IFlatbufferObject
public static void AddFooTable(FlatBufferBuilder builder, Offset<NamespaceA.NamespaceB.TableInNestedNS> fooTableOffset) { builder.AddOffset(0, fooTableOffset.Value, 0); }
public static void AddFooEnum(FlatBufferBuilder builder, NamespaceA.NamespaceB.EnumInNestedNS fooEnum) { builder.AddSbyte(1, (sbyte)fooEnum, 0); }
public static void AddFooStruct(FlatBufferBuilder builder, Offset<NamespaceA.NamespaceB.StructInNestedNS> fooStructOffset) { builder.AddStruct(2, fooStructOffset.Value, 0); }
public static Offset<TableInFirstNS> EndTableInFirstNS(FlatBufferBuilder builder) {
public static Offset<NamespaceA.TableInFirstNS> EndTableInFirstNS(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<TableInFirstNS>(o);
return new Offset<NamespaceA.TableInFirstNS>(o);
}
};
......
......@@ -20,7 +20,7 @@ public struct TableInC : IFlatbufferObject
public NamespaceA.TableInFirstNS? ReferToA1 { get { int o = __p.__offset(4); return o != 0 ? (NamespaceA.TableInFirstNS?)(new NamespaceA.TableInFirstNS()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public NamespaceA.SecondTableInA? ReferToA2 { get { int o = __p.__offset(6); return o != 0 ? (NamespaceA.SecondTableInA?)(new NamespaceA.SecondTableInA()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public static Offset<TableInC> CreateTableInC(FlatBufferBuilder builder,
public static Offset<NamespaceC.TableInC> CreateTableInC(FlatBufferBuilder builder,
Offset<NamespaceA.TableInFirstNS> refer_to_a1Offset = default(Offset<NamespaceA.TableInFirstNS>),
Offset<NamespaceA.SecondTableInA> refer_to_a2Offset = default(Offset<NamespaceA.SecondTableInA>)) {
builder.StartTable(2);
......@@ -32,9 +32,9 @@ public struct TableInC : IFlatbufferObject
public static void StartTableInC(FlatBufferBuilder builder) { builder.StartTable(2); }
public static void AddReferToA1(FlatBufferBuilder builder, Offset<NamespaceA.TableInFirstNS> referToA1Offset) { builder.AddOffset(0, referToA1Offset.Value, 0); }
public static void AddReferToA2(FlatBufferBuilder builder, Offset<NamespaceA.SecondTableInA> referToA2Offset) { builder.AddOffset(1, referToA2Offset.Value, 0); }
public static Offset<TableInC> EndTableInC(FlatBufferBuilder builder) {
public static Offset<NamespaceC.TableInC> EndTableInC(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<TableInC>(o);
return new Offset<NamespaceC.TableInC>(o);
}
};
......
......@@ -134,7 +134,7 @@ inline const flatbuffers::TypeTable *EnumInNestedNSTypeTable() {
{ flatbuffers::ET_CHAR, 0, 0 }
};
static const flatbuffers::TypeFunction type_refs[] = {
EnumInNestedNSTypeTable
NamespaceA::NamespaceB::EnumInNestedNSTypeTable
};
static const char * const names[] = {
"A",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment