You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2013/07/01 20:48:09 UTC

[lucy-commits] [4/4] git commit: refs/heads/master - Check for class name and nickname clashes

Check for class name and nickname clashes


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/25b290f5
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/25b290f5
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/25b290f5

Branch: refs/heads/master
Commit: 25b290f56009dc942583085a921dbf4d76b5eb36
Parents: 2198b8b
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon Jul 1 02:36:29 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Mon Jul 1 20:41:33 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/perl/t/105-object_type.t     |   7 +-
 clownfish/compiler/perl/t/401-class.t           |  26 ++++-
 clownfish/compiler/perl/t/404-file.t            | 102 ++++++++++---------
 clownfish/compiler/perl/t/502-clash.t           |  24 +----
 clownfish/compiler/perl/t/600-parser.t          |   2 +-
 .../perl/t/cfclash/class/Animal/DogClash.cfh    |   4 +-
 .../perl/t/cfclash/class/AnimalExtension.cfp    |   5 +
 clownfish/compiler/src/CFCClass.c               |  38 +++++--
 clownfish/compiler/src/CFCTestFile.c            |   5 +-
 clownfish/compiler/src/CFCTestParser.c          |   2 +-
 clownfish/compiler/src/CFCTestType.c            |   4 +-
 11 files changed, 126 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/perl/t/105-object_type.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/105-object_type.t b/clownfish/compiler/perl/t/105-object_type.t
index 2298f91..d20d01f 100644
--- a/clownfish/compiler/perl/t/105-object_type.t
+++ b/clownfish/compiler/perl/t/105-object_type.t
@@ -86,7 +86,7 @@ ok( !$foo_type->equals($bar_type), "different specifier spoils equals" );
 
 my $foreign_foo_class = Clownfish::CFC::Model::Class->create(
     parcel     => 'Foreign',
-    class_name => 'Foo',
+    class_name => 'Foreign::Foo',
 );
 my $foreign_foo = Clownfish::CFC::Model::Type->new_object(
     specifier => 'Foo',
@@ -117,14 +117,11 @@ ok( !$foo_type->equals($decremented_foo),
     "different decremented spoils equals"
 );
 
-my $foo_class = Clownfish::CFC::Model::Class->create(
-    class_name => 'Foo',
-);
 my $const_foo = Clownfish::CFC::Model::Type->new_object(
     specifier => 'Foo',
     const     => 1,
 );
-$const_foo->resolve([ $foo_class ]);
+$const_foo->resolve(\@classes);
 ok( !$foo_type->equals($const_foo), "different const spoils equals" );
 like( $const_foo->to_c, qr/const/, "const included in C representation" );
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/perl/t/401-class.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/401-class.t b/clownfish/compiler/perl/t/401-class.t
index d611440..5e37cc3 100644
--- a/clownfish/compiler/perl/t/401-class.t
+++ b/clownfish/compiler/perl/t/401-class.t
@@ -16,7 +16,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 52;
+use Test::More tests => 54;
 use Clownfish::CFC::Model::Class;
 use Clownfish::CFC::Parser;
 
@@ -49,15 +49,33 @@ my $foo = Clownfish::CFC::Model::Class->create(%foo_create_args);
 $foo->add_function($tread_water);
 $foo->add_member_var($thing);
 $foo->add_inert_var($widget);
-eval { Clownfish::CFC::Model::Class->create(%foo_create_args) };
-like( $@, qr/conflict/i,
-    "Can't call create for the same class more than once" );
 my $should_be_foo = Clownfish::CFC::Model::Class->fetch_singleton(
     parcel     => 'Neato',
     class_name => 'Foo',
 );
 is( $$foo, $$should_be_foo, "fetch_singleton" );
 
+eval { Clownfish::CFC::Model::Class->create(%foo_create_args) };
+like( $@, qr/two classes with name/i,
+      "Can't call create for the same class more than once" );
+eval {
+    Clownfish::CFC::Model::Class->create(
+        parcel     => 'Neato',
+        class_name => 'Other::Foo',
+    );
+};
+like( $@, qr/class name conflict/i,
+      "Can't create classes wth the same final component" );
+eval {
+    Clownfish::CFC::Model::Class->create(
+        parcel     => 'Neato',
+        class_name => 'Bar',
+        cnick      => 'Foo',
+    );
+};
+like( $@, qr/class nickname conflict/i,
+      "Can't create classes wth the same nickname" );
+
 my $foo_jr = Clownfish::CFC::Model::Class->create(
     parcel            => 'Neato',
     class_name        => 'Foo::FooJr',

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/perl/t/404-file.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/404-file.t b/clownfish/compiler/perl/t/404-file.t
index 8f8a700..11668c4 100644
--- a/clownfish/compiler/perl/t/404-file.t
+++ b/clownfish/compiler/perl/t/404-file.t
@@ -40,50 +40,60 @@ my $file_spec = Clownfish::CFC::Model::FileSpec->new(
     source_dir  => '.',
     path_part   => $path_part,
 );
-my $file
-    = $parser->_parse_file( "$parcel_declaration\n$class_content\n$c_block",
-    $file_spec );
-
-is( $file->get_source_dir, ".", "get_source_dir" );
-is( $file->get_path_part, $path_part, "get_path_part" );
-ok( !$file->included, "included" );
-
-my $guard_name = $file->guard_name;
-is( $guard_name, "H_STUFF_THING", "guard_name" );
-like( $file->guard_start, qr/$guard_name/, "guard_start" );
-like( $file->guard_close, qr/$guard_name/,
-    "guard_close includes guard_name" );
-
-ok( !$file->get_modified, "modified false at start" );
-$file->set_modified(1);
-ok( $file->get_modified, "set_modified, get_modified" );
-
-my $path_sep = $^O =~ /^mswin/i ? '\\' : '/';
-my $path_to_stuff_thing = join( $path_sep, qw( path to Stuff Thing ) );
-is( $file->cfh_path('path/to'), "$path_to_stuff_thing.cfh", "cfh_path" );
-is( $file->c_path('path/to'),   "$path_to_stuff_thing.c",   "c_path" );
-is( $file->h_path('path/to'),   "$path_to_stuff_thing.h",   "h_path" );
-
-my $classes = $file->classes;
-is( scalar @$classes, 3, "classes() filters blocks" );
-my $class = $classes->[0];
-my ( $foo, $bar ) = @{ $class->member_vars };
-$foo->resolve_type($classes);
-$bar->resolve_type($classes);
-is( $foo->get_type->get_specifier,
-    'stuff_Foo', 'file production picked up parcel def' );
-is( $bar->get_type->get_specifier, 'stuff_Bar', 'parcel def is sticky' );
-
-my $blocks = $file->blocks;
-is( scalar @$blocks, 5, "all five blocks" );
-isa_ok( $blocks->[0], "Clownfish::CFC::Model::Parcel" );
-isa_ok( $blocks->[1], "Clownfish::CFC::Model::Class" );
-isa_ok( $blocks->[2], "Clownfish::CFC::Model::Class" );
-isa_ok( $blocks->[3], "Clownfish::CFC::Model::Class" );
-isa_ok( $blocks->[4], "Clownfish::CFC::Model::CBlock" );
-
-$file = $parser->_parse_file( $class_content, $file_spec );
-($class) = @{ $file->classes };
-( $foo, $bar ) = @{ $class->member_vars };
-is( $foo->get_type->get_specifier, 'Foo', 'file production resets parcel' );
+
+{
+    my $file
+        = $parser->_parse_file( "$parcel_declaration\n$class_content\n$c_block",
+        $file_spec );
+
+    is( $file->get_source_dir, ".", "get_source_dir" );
+    is( $file->get_path_part, $path_part, "get_path_part" );
+    ok( !$file->included, "included" );
+
+    my $guard_name = $file->guard_name;
+    is( $guard_name, "H_STUFF_THING", "guard_name" );
+    like( $file->guard_start, qr/$guard_name/, "guard_start" );
+    like( $file->guard_close, qr/$guard_name/,
+        "guard_close includes guard_name" );
+
+    ok( !$file->get_modified, "modified false at start" );
+    $file->set_modified(1);
+    ok( $file->get_modified, "set_modified, get_modified" );
+
+    my $path_sep = $^O =~ /^mswin/i ? '\\' : '/';
+    my $path_to_stuff_thing = join( $path_sep, qw( path to Stuff Thing ) );
+    is( $file->cfh_path('path/to'), "$path_to_stuff_thing.cfh", "cfh_path" );
+    is( $file->c_path('path/to'),   "$path_to_stuff_thing.c",   "c_path" );
+    is( $file->h_path('path/to'),   "$path_to_stuff_thing.h",   "h_path" );
+
+    my $classes = $file->classes;
+    is( scalar @$classes, 3, "classes() filters blocks" );
+    my $class = $classes->[0];
+    my ( $foo, $bar ) = @{ $class->member_vars };
+    $foo->resolve_type($classes);
+    $bar->resolve_type($classes);
+    is( $foo->get_type->get_specifier,
+        'stuff_Foo', 'file production picked up parcel def' );
+    is( $bar->get_type->get_specifier, 'stuff_Bar', 'parcel def is sticky' );
+
+    my $blocks = $file->blocks;
+    is( scalar @$blocks, 5, "all five blocks" );
+    isa_ok( $blocks->[0], "Clownfish::CFC::Model::Parcel" );
+    isa_ok( $blocks->[1], "Clownfish::CFC::Model::Class" );
+    isa_ok( $blocks->[2], "Clownfish::CFC::Model::Class" );
+    isa_ok( $blocks->[3], "Clownfish::CFC::Model::Class" );
+    isa_ok( $blocks->[4], "Clownfish::CFC::Model::CBlock" );
+
+    Clownfish::CFC::Model::Class->_clear_registry();
+}
+
+{
+    my $file = $parser->_parse_file( $class_content, $file_spec );
+    my ($class) = @{ $file->classes };
+    my ( $foo, $bar ) = @{ $class->member_vars };
+    is( $foo->get_type->get_specifier, 'Foo', 'file production resets parcel' );
+
+    Clownfish::CFC::Model::Class->_clear_registry();
+}
+
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/perl/t/502-clash.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/502-clash.t b/clownfish/compiler/perl/t/502-clash.t
index b095c34..85df4d0 100644
--- a/clownfish/compiler/perl/t/502-clash.t
+++ b/clownfish/compiler/perl/t/502-clash.t
@@ -16,7 +16,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 6;
+use Test::More tests => 5;
 
 use Clownfish::CFC::Model::Hierarchy;
 use File::Spec::Functions qw( catdir catfile splitpath );
@@ -32,21 +32,6 @@ my $file_clash_dir  = catdir(qw( t cfclash file ));
     my $hierarchy = Clownfish::CFC::Model::Hierarchy->new(dest => $dest_dir);
 
     $hierarchy->add_source_dir($base_dir);
-    $hierarchy->add_source_dir($class_clash_dir);
-
-    eval { $hierarchy->build; };
-
-    like( $@, qr/Conflict with existing class Animal::Dog/,
-          "source/source class name clash" );
-
-    Clownfish::CFC::Model::Class->_clear_registry();
-    Clownfish::CFC::Model::Parcel->reap_singletons();
-}
-
-{
-    my $hierarchy = Clownfish::CFC::Model::Hierarchy->new(dest => $dest_dir);
-
-    $hierarchy->add_source_dir($base_dir);
     $hierarchy->add_source_dir($file_clash_dir);
 
     eval { $hierarchy->build; };
@@ -62,13 +47,12 @@ my $file_clash_dir  = catdir(qw( t cfclash file ));
 {
     my $hierarchy = Clownfish::CFC::Model::Hierarchy->new(dest => $dest_dir);
 
-    $hierarchy->add_source_dir($base_dir);
-    $hierarchy->add_include_dir($class_clash_dir);
+    $hierarchy->add_source_dir($class_clash_dir);
+    $hierarchy->add_include_dir($base_dir);
 
     eval { $hierarchy->build; };
 
-    like( $@, qr/Class .* from include dir .* parcel .* from source dir/,
-          "source/include class name clash" );
+    like( $@, qr/Two classes with name/, "source/include class name clash" );
 
     Clownfish::CFC::Model::Class->_clear_registry();
     Clownfish::CFC::Model::Parcel->reap_singletons();

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/perl/t/600-parser.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/600-parser.t b/clownfish/compiler/perl/t/600-parser.t
index 5ac2269..6d9f297 100644
--- a/clownfish/compiler/perl/t/600-parser.t
+++ b/clownfish/compiler/perl/t/600-parser.t
@@ -156,7 +156,7 @@ SKIP: {
 
 is( $parser->parse(qq|class Foodie$_ cnick $_ { }|)->get_cnick,
     $_, "cnick: $_" )
-    for (qw( Foo FF ));
+    for (qw( Food FF ));
 
 SKIP: {
     skip( "Can't recover from bad cnick under flex/lemon parser", 3 );

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/perl/t/cfclash/class/Animal/DogClash.cfh
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/cfclash/class/Animal/DogClash.cfh b/clownfish/compiler/perl/t/cfclash/class/Animal/DogClash.cfh
index 6d54baa..3eba020 100644
--- a/clownfish/compiler/perl/t/cfclash/class/Animal/DogClash.cfh
+++ b/clownfish/compiler/perl/t/cfclash/class/Animal/DogClash.cfh
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-parcel Animal;
+parcel AnimalExtension;
 
-class Animal::Dog inherits Animal {
+class Animal::Dog inherits Clownfish::Obj {
     public inert incremented Dog*
     new();
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/perl/t/cfclash/class/AnimalExtension.cfp
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/cfclash/class/AnimalExtension.cfp b/clownfish/compiler/perl/t/cfclash/class/AnimalExtension.cfp
new file mode 100644
index 0000000..76f31d3
--- /dev/null
+++ b/clownfish/compiler/perl/t/cfclash/class/AnimalExtension.cfp
@@ -0,0 +1,5 @@
+{
+    "name": "AnimalExtension",
+    "nickname": "AniExt",
+    "version": "v0.1.0"
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCClass.c b/clownfish/compiler/src/CFCClass.c
index a84c5f6..2476071 100644
--- a/clownfish/compiler/src/CFCClass.c
+++ b/clownfish/compiler/src/CFCClass.c
@@ -254,10 +254,6 @@ CFCClass_destroy(CFCClass *self) {
 
 static void
 S_register(CFCClass *self) {
-    /*
-     * TODO: Verify that there isn't a class with the same class_name in
-     * another parcel. Verify that cnick is unique within this parcel.
-     */
     if (registry_size == registry_cap) {
         size_t new_cap = registry_cap + 10;
         registry = (CFCClassRegEntry*)REALLOCATE(
@@ -269,15 +265,35 @@ S_register(CFCClass *self) {
         }
         registry_cap = new_cap;
     }
-    CFCParcel *parcel = CFCClass_get_parcel(self);
+
+    CFCParcel  *parcel     = CFCClass_get_parcel(self);
+    const char *prefix     = CFCParcel_get_prefix(parcel);
     const char *class_name = CFCClass_get_class_name(self);
-    CFCClass *existing = CFCClass_fetch_singleton(parcel, class_name);
-    const char *key = self->full_struct_sym;
-    if (existing) {
-        CFCBase_decref((CFCBase*)self);
-        CFCUtil_die("Conflict with existing class %s",
-                    CFCClass_get_class_name(existing));
+    const char *cnick      = CFCClass_get_cnick(self);
+    const char *key        = self->full_struct_sym;
+
+    for (size_t i = 0; i < registry_size; i++) {
+        CFCClass   *other            = registry[i].klass;
+        CFCParcel  *other_parcel     = CFCClass_get_parcel(other);
+        const char *other_prefix     = CFCParcel_get_prefix(other_parcel);
+        const char *other_class_name = CFCClass_get_class_name(other);
+        const char *other_cnick      = CFCClass_get_cnick(other);
+
+        if (strcmp(class_name, other_class_name) == 0) {
+            CFCUtil_die("Two classes with name %s", class_name);
+        }
+        if (strcmp(registry[i].key, key) == 0) {
+            CFCUtil_die("Class name conflict between %s and %s",
+                        class_name, other_class_name);
+        }
+        if (strcmp(prefix, other_prefix) == 0
+            && strcmp(cnick, other_cnick) == 0
+           ) {
+            CFCUtil_die("Class nickname conflict between %s and %s",
+                        class_name, other_class_name);
+        }
     }
+
     registry[registry_size].key   = CFCUtil_strdup(key);
     registry[registry_size].klass = (CFCClass*)CFCBase_incref((CFCBase*)self);
     registry_size++;

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/src/CFCTestFile.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestFile.c b/clownfish/compiler/src/CFCTestFile.c
index f62b919..ad1cd5c 100644
--- a/clownfish/compiler/src/CFCTestFile.c
+++ b/clownfish/compiler/src/CFCTestFile.c
@@ -119,6 +119,8 @@ S_run_tests(CFCTest *test) {
         OK(test, blocks[5] == NULL, "blocks[5]");
 
         CFCBase_decref((CFCBase*)file);
+
+        CFCClass_clear_registry();
     }
 
     {
@@ -135,12 +137,13 @@ S_run_tests(CFCTest *test) {
                "file production resets parcel");
 
         CFCBase_decref((CFCBase*)file);
+
+        CFCClass_clear_registry();
     }
 
     CFCBase_decref((CFCBase*)file_spec);
     CFCBase_decref((CFCBase*)parser);
 
-    CFCClass_clear_registry();
     CFCParcel_reap_singletons();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/src/CFCTestParser.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestParser.c b/clownfish/compiler/src/CFCTestParser.c
index 04c39e7..ca8ad2c 100644
--- a/clownfish/compiler/src/CFCTestParser.c
+++ b/clownfish/compiler/src/CFCTestParser.c
@@ -293,7 +293,7 @@ S_run_tests(CFCTest *test) {
     }
 
     {
-        static const char *const cnicks[2] =  { "Foo", "FF" };
+        static const char *const cnicks[2] =  { "Food", "FF" };
         for (int i = 0; i < 2; ++i) {
             const char *cnick = cnicks[i];
             char *class_string

http://git-wip-us.apache.org/repos/asf/lucy/blob/25b290f5/clownfish/compiler/src/CFCTestType.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestType.c b/clownfish/compiler/src/CFCTestType.c
index d1d9b08..af85017 100644
--- a/clownfish/compiler/src/CFCTestType.c
+++ b/clownfish/compiler/src/CFCTestType.c
@@ -354,8 +354,8 @@ S_run_object_tests(CFCTest *test) {
         CFCParcel *foreign_parcel
             = CFCParcel_new("Foreign", NULL, NULL, false);
         CFCClass *foreign_foo_class
-            = CFCClass_create(foreign_parcel, NULL, "Foo", NULL, NULL, NULL,
-                              NULL, NULL, false, false);
+            = CFCClass_create(foreign_parcel, NULL, "Foreign::Foo", NULL, NULL,
+                              NULL, NULL, NULL, false, false);
         CFCClass *foreign_class_list[2] = { foreign_foo_class, NULL };
         CFCType *foreign_foo = CFCType_new_object(0, foreign_parcel, "Foo", 1);
         CFCType_resolve(foreign_foo, foreign_class_list);