Seal all classes in Java/C#
authorAdvay Mengle <advay.mengle.dev1@gmail.com>
Mon, 6 Apr 2015 23:42:08 +0000 (16:42 -0700)
committerWouter van Oortmerssen <wvo@google.com>
Fri, 10 Apr 2015 18:20:19 +0000 (11:20 -0700)
Makes enums/structs/tables unsubclassable (final or sealed) and
prevents instantiation of enum classes (which are solely static
constants).

Tested (Mac OS 10.10.2):
1. run flattests
2. cd tests && ../flatc -c monster_test.fbs && ../flatc -j
monster_test.fbs && ../flatc -g monster_test.fbs && ../flatc -n
monster_test.fbs  # Note deltas for C# and Java.
3. ./JavaTest.sh

**Breaking api change**

Change-Id: Ie008c941c36d212690da58ddc72c9b228eb7a093

14 files changed:
src/idl_gen_general.cpp
tests/MyGame/Example/Any.cs
tests/MyGame/Example/Any.java
tests/MyGame/Example/Color.cs
tests/MyGame/Example/Color.java
tests/MyGame/Example/Monster.cs
tests/MyGame/Example/Monster.go
tests/MyGame/Example/Monster.java
tests/MyGame/Example/Stat.cs
tests/MyGame/Example/Stat.java
tests/MyGame/Example/Test.cs
tests/MyGame/Example/Test.java
tests/MyGame/Example/Vec3.cs
tests/MyGame/Example/Vec3.java

index f9190a2..d60ecd4 100644 (file)
@@ -50,7 +50,7 @@ void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
     // Don't output empty comment blocks with 0 lines of comment content.
     return;
   }
-  
+
   std::string &code = *code_ptr;
   if (config != nullptr && config->first_line != nullptr) {
     code += std::string(prefix) + std::string(config->first_line) + "\n";
@@ -79,6 +79,7 @@ struct LanguageParameters {
   const char *bool_type;
   const char *open_curly;
   const char *const_decl;
+  const char *unsubclassable_decl;
   const char *inheritance_marker;
   const char *namespace_ident;
   const char *namespace_begin;
@@ -97,6 +98,7 @@ LanguageParameters language_parameters[] = {
     "boolean ",
     " {\n",
     " final ",
+    "final ",
     " extends ",
     "package ",
     ";",
@@ -118,6 +120,7 @@ LanguageParameters language_parameters[] = {
     "bool ",
     "\n{\n",
     " readonly ",
+    "sealed ",
     " : ",
     "namespace ",
     "\n{",
@@ -140,6 +143,7 @@ LanguageParameters language_parameters[] = {
     "bool ",
     "\n{\n",
     "const ",
+    " ",
     "",
     "package ",
     "",
@@ -265,7 +269,9 @@ static void GenEnum(const LanguageParameters &lang, EnumDef &enum_def,
   // to map directly to how they're used in C/C++ and file formats.
   // That, and Java Enums are expensive, and not universally liked.
   GenComment(enum_def.doc_comment, code_ptr, &lang.comment_config);
-  code += "public class " + enum_def.name + lang.open_curly;
+  code += std::string("public ") + lang.unsubclassable_decl;
+  code += "class " + enum_def.name + lang.open_curly;
+  code += "  private " + enum_def.name + "() { }\n";
   for (auto it = enum_def.vals.vec.begin();
        it != enum_def.vals.vec.end();
        ++it) {
@@ -415,7 +421,8 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
   //   int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default;
   // }
   GenComment(struct_def.doc_comment, code_ptr, &lang.comment_config);
-  code += "public class " + struct_def.name + lang.inheritance_marker;
+  code += std::string("public ") + lang.unsubclassable_decl;
+  code += "class " + struct_def.name + lang.inheritance_marker;
   code += struct_def.fixed ? "Struct" : "Table";
   code += " {\n";
   if (!struct_def.fixed) {
index 5223969..af5b2c3 100644 (file)
@@ -3,8 +3,9 @@
 namespace MyGame.Example
 {
 
-public class Any
+public sealed class Any
 {
+  private Any() { }
   public static readonly byte NONE = 0;
   public static readonly byte Monster = 1;
 
index eb7514c..f811f97 100644 (file)
@@ -2,7 +2,8 @@
 
 package MyGame.Example;
 
-public class Any {
+public final class Any {
+  private Any() { }
   public static final byte NONE = 0;
   public static final byte Monster = 1;
 
index 403b9d9..c3c7647 100644 (file)
@@ -3,8 +3,9 @@
 namespace MyGame.Example
 {
 
-public class Color
+public sealed class Color
 {
+  private Color() { }
   public static readonly sbyte Red = 1;
   public static readonly sbyte Green = 2;
   public static readonly sbyte Blue = 8;
index b63493a..822d2bb 100644 (file)
@@ -2,7 +2,8 @@
 
 package MyGame.Example;
 
-public class Color {
+public final class Color {
+  private Color() { }
   public static final byte Red = 1;
   public static final byte Green = 2;
   public static final byte Blue = 8;
index aca7972..7a88205 100644 (file)
@@ -5,7 +5,7 @@ namespace MyGame.Example
 
 using FlatBuffers;
 
-public class Monster : Table {
+public sealed class Monster : Table {
   public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); }
   public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__init(_bb.GetInt(_bb.position()) + _bb.position(), _bb)); }
   public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); }
index 0ca0c80..0a6ba13 100644 (file)
@@ -148,9 +148,7 @@ func (rcv *Monster) TestarrayofstringLength() int {
 }
 
 /// an example documentation comment: this will end up in the generated code
-
 /// multiline too
-
 func (rcv *Monster) Testarrayoftables(obj *Monster, j int) bool {
        o := flatbuffers.UOffsetT(rcv._tab.Offset(26))
        if o != 0 {
index 0c5d3d6..6d1c02f 100644 (file)
@@ -7,7 +7,7 @@ import java.lang.*;
 import java.util.*;
 import com.google.flatbuffers.*;
 
-public class Monster extends Table {
+public final class Monster extends Table {
   public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); }
   public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
   public static boolean MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); }
index c269a0a..535952e 100644 (file)
@@ -5,7 +5,7 @@ namespace MyGame.Example
 
 using FlatBuffers;
 
-public class Stat : Table {
+public sealed class Stat : Table {
   public static Stat GetRootAsStat(ByteBuffer _bb) { return GetRootAsStat(_bb, new Stat()); }
   public static Stat GetRootAsStat(ByteBuffer _bb, Stat obj) { return (obj.__init(_bb.GetInt(_bb.position()) + _bb.position(), _bb)); }
   public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
index 9facdf5..e1663c1 100644 (file)
@@ -7,7 +7,7 @@ import java.lang.*;
 import java.util.*;
 import com.google.flatbuffers.*;
 
-public class Stat extends Table {
+public final class Stat extends Table {
   public static Stat getRootAsStat(ByteBuffer _bb) { return getRootAsStat(_bb, new Stat()); }
   public static Stat getRootAsStat(ByteBuffer _bb, Stat obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
   public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
index 1603582..357023f 100644 (file)
@@ -5,7 +5,7 @@ namespace MyGame.Example
 
 using FlatBuffers;
 
-public class Test : Struct {
+public sealed class Test : Struct {
   public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
 
   public short A() { return bb.GetShort(bb_pos + 0); }
index 52d09c4..d4e4094 100644 (file)
@@ -7,7 +7,7 @@ import java.lang.*;
 import java.util.*;
 import com.google.flatbuffers.*;
 
-public class Test extends Struct {
+public final class Test extends Struct {
   public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
 
   public short a() { return bb.getShort(bb_pos + 0); }
index 4284aba..bd0aceb 100644 (file)
@@ -5,7 +5,7 @@ namespace MyGame.Example
 
 using FlatBuffers;
 
-public class Vec3 : Struct {
+public sealed class Vec3 : Struct {
   public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
 
   public float X() { return bb.GetFloat(bb_pos + 0); }
index 76e219e..77b5697 100644 (file)
@@ -7,7 +7,7 @@ import java.lang.*;
 import java.util.*;
 import com.google.flatbuffers.*;
 
-public class Vec3 extends Struct {
+public final class Vec3 extends Struct {
   public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
 
   public float x() { return bb.getFloat(bb_pos + 0); }