Merge: nitweb: rewritte stars
authorJean Privat <jean@pryen.org>
Mon, 5 Dec 2016 20:53:37 +0000 (15:53 -0500)
committerJean Privat <jean@pryen.org>
Mon, 5 Dec 2016 20:53:37 +0000 (15:53 -0500)
Upgrade the feedback stars form.

More stars and more details:

![image](https://cloud.githubusercontent.com/assets/583144/20892546/b0155e34-badc-11e6-8f89-726959021e5f.png)

Demo here: http://nitweb.moz-code.org/

Pull-Request: #2341

20 files changed:
contrib/nitrpg/README.md
lib/config.ini [new file with mode: 0644]
lib/config.nit [new file with mode: 0644]
lib/github/api.nit
lib/opts.nit
lib/popcorn/pop_config.nit
lib/popcorn/pop_repos.nit
share/nitweb/directives/entity/link.html
share/nitweb/directives/entity/location.html
share/nitweb/javascripts/nitweb.js
share/nitweb/views/classdef.html
share/nitweb/views/propdef.html
src/model/model_json.nit
src/model/test_model_json.sav/test_classdefs_to_full_json.res
src/model/test_model_json.sav/test_classes_to_full_json.res
src/model/test_model_json.sav/test_modules_to_full_json.res
src/model/test_model_json.sav/test_packages_to_full_json.res
src/model/test_model_json.sav/test_props_to_full_json.res
src/nitweb.nit
src/web/api_model.nit

index a83264e..5f6a02d 100644 (file)
@@ -42,7 +42,9 @@ It should alwaysd be up if you want your game to be kept up-to-date.
 
 To run the listener:
 
+~~~raw
        ./listener <host> <port>
+~~~
 
 The arguments `host` and `port` must correspond to what you entered in your
 GitHub hook settings.
@@ -53,7 +55,9 @@ The `web` program act as a [nitcorn](http://nitlanguage.org/doc/stdlib/module_ni
 
 To run the webserver:
 
+~~~raw
        ./web <host> <port> <root>
+~~~
 
 The arguments `host` and `port` must correspond to what you entered in your
 GitHub hook settings.
@@ -62,11 +66,15 @@ NitRPG root.
 
 For example, if NitRPG is installed in `yourdomain.com/nitrpg`:
 
+~~~raw
        ./web localhost 3000 "/nitrpg"
+~~~
 
 Leave it empty if NitRPG is installed at the root of the domain:
 
+~~~raw
        ./web localhost 3000 ""
+~~~
 
 The webserver can then be accessed at `http://yourdomain.com:3000/nitrpg/`.
 
diff --git a/lib/config.ini b/lib/config.ini
new file mode 100644 (file)
index 0000000..38dbaf5
--- /dev/null
@@ -0,0 +1,11 @@
+[package]
+name=config
+tags=config,options,ini,lib
+maintainer=Alexandre Terrasa <alexandre@moz-code.org>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/config.nit
+git=https://github.com/nitlang/nit.git
+git.directory=lib/config.nit
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
diff --git a/lib/config.nit b/lib/config.nit
new file mode 100644 (file)
index 0000000..83566a6
--- /dev/null
@@ -0,0 +1,279 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Configuration options for nit tools and apps
+#
+# This module provides basic services for options handling in your Nit programs.
+#
+# ## Basic configuration holder
+#
+# The `Config` class can be used as a simple option holder and processor:
+#
+# ~~~
+# import config
+#
+# # Create a new config option
+# var opt_my = new OptionString("My option", "--my")
+#
+# # Create the config and add the option
+# var config = new Config
+# config.add_option(opt_my)
+#
+# # Parse the program arguments, usually `args`
+# config.parse_options(["--my", "myOption", "arg1", "arg2"])
+#
+# # Access the options and args
+# assert opt_my.value == "myOption"
+# assert config.args == ["arg1", "arg2"]
+# ~~~
+#
+# ## Custom configuration class
+#
+# Instead of using basic `Config` instances, it is better to define new sublcasses
+# to store options and define custom services.
+#
+# ~~~
+# import config
+#
+# class MyConfig
+#      super Config
+#
+#      var opt_my = new OptionString("My option", "--my")
+#
+#      init do
+#              super
+#              tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
+#              add_option(opt_my)
+#      end
+#
+#      fun my: String do return opt_my.value or else "Default value"
+# end
+#
+# var config = new MyConfig
+# config.parse_options(["--my", "myOption", "arg1", "arg2"])
+#
+# assert config.my == "myOption"
+# assert config.args == ["arg1", "arg2"]
+# ~~~
+#
+# We define the `my` method to provide an elegant shortcut to `opt_my.value`
+# and define the default value if the option was not set by the user.
+#
+# The `tool_description` attribute is used to set the `usage` header printed when
+# the user request the `help` message.
+#
+# ~~~
+# config.parse_options(["-h"])
+# if config.help then
+#      config.usage
+#      exit 0
+# end
+# ~~~
+#
+# This will display the tool usage like this:
+#
+# ~~~raw
+# Usage: MyExample [OPTION]... [ARGS]...
+#  -h, --help   Show this help message
+#  --my         My option
+# ~~~
+#
+# ## Configuration with `ini` file
+#
+# The `IniConfig` class extends `Config` to add an easy way to link your
+# configuration to an ini file.
+
+# ~~~
+# class MyIniConfig
+#      super IniConfig
+#
+#      var opt_my = new OptionString("My option", "--my")
+#
+#      init do
+#              super
+#              tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
+#              opts.add_option(opt_my)
+#      end
+#
+#      fun my: String do return opt_my.value or else ini["my"] or else "Default"
+# end
+# ~~~
+#
+# This time, we define the `my` method to return the option value or the ini
+# if no option was passed. Finally, if no ini value can be found, we return the
+# default value.
+#
+# By default, `IniConfig` looks at a `config.ini` file in the execution directory.
+# This can be overrided in multiple ways.
+#
+# First by the app user by setting the `--config` option:
+#
+# ~~~
+# var config = new MyIniConfig
+# config.parse_options(["--config", "my_config.ini"])
+#
+# assert config.config_file == "my_config.ini"
+# ~~~
+#
+# Default config file can also be changed by the library client through the
+# `default_config_file` attribute:
+#
+# ~~~
+# config = new MyIniConfig
+# config.default_config_file = "my_config.ini"
+# config.parse_options(["arg"])
+#
+# assert config.config_file == "my_config.ini"
+# ~~~
+#
+# Or by the library developper in the custom config class:
+#
+# ~~~
+# class MyCustomIniConfig
+#      super IniConfig
+#
+#      redef var default_config_file = "my_config.ini"
+# end
+#
+# var config = new MyCustomIniConfig
+# config.parse_options(["arg"])
+#
+# assert config.config_file == "my_config.ini"
+# ~~~
+module config
+
+import ini
+import opts
+
+# Basic configuration class
+#
+# ~~~
+# import config
+#
+# class MyConfig
+#      super Config
+#
+#      var opt_my = new OptionString("My option", "--my")
+#
+#      init do
+#              super
+#              tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
+#              opts.add_option(opt_my)
+#      end
+#
+#      fun my: String do return opt_my.value or else "Default value"
+# end
+#
+# var config = new MyConfig
+# config.parse_options(["--my", "hello", "arg1", "arg2"])
+# assert config.my == "hello"
+# assert config.args == ["arg1", "arg2"]
+# ~~~
+class Config
+
+       # Context used to store and parse options
+       var opts = new OptionContext
+
+       # Help option
+       var opt_help = new OptionBool("Show this help message", "-h", "--help")
+
+       # Redefine this init to add your options
+       init do
+               add_option(opt_help)
+       end
+
+       # Add an option to `self`
+       #
+       # Shortcut to `opts.add_option`.
+       fun add_option(opt: Option...) do opts.add_option(opt...)
+
+       # Initialize `self` options from `args`
+       fun parse_options(args: Collection[String]) do
+               opts.parse(args)
+       end
+
+       # Return the remaining args once options are parsed by `from_args`
+       fun args: Array[String] do return opts.rest
+
+       # Name, usage and synopsis of the tool.
+       # It is mainly used in `usage`.
+       # Should be correctly set by the client before calling `usage`
+       # A multi-line string is recommended.
+       #
+       # eg. `"Usage: tool [OPTION]... [FILE]...\nDo some things."`
+       var tool_description: String = "Usage: [OPTION]... [ARG]..." is writable
+
+       # Was the `--help` option requested?
+       fun help: Bool do return opt_help.value
+
+       # Display `tool_description` and options usage in console
+       fun usage do
+               print tool_description
+               opts.usage
+       end
+end
+
+# Configuration class based on a INI file.
+#
+# ~~~
+# class MyIniConfig
+#      super IniConfig
+#
+#      var opt_my = new OptionString("My option", "--my")
+#
+#      init do
+#              super
+#              tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
+#              opts.add_option(opt_my)
+#      end
+#
+#      fun my: String do return opt_my.value or else ini["my"] or else "Default"
+# end
+#
+# var config = new MyIniConfig
+# config.default_config_file = "my_config.ini"
+# config.parse_options(args)
+#
+# if config.help then
+#      config.usage
+#      exit 0
+# end
+#
+# assert config.my == "Default"
+# ~~~
+class IniConfig
+       super Config
+
+       # Config tree used to store config options
+       var ini: ConfigTree is noinit
+
+       # Path to app config file
+       var opt_config = new OptionString("Path to config file", "--config")
+
+       init do
+               super
+               opts.add_option(opt_config)
+       end
+
+       redef fun parse_options(args) do
+               super
+               ini = new ConfigTree(config_file)
+       end
+
+       # Default config file path
+       var default_config_file = "config.ini" is writable
+
+       # Return the config file path from options or the default
+       fun config_file: String do return opt_config.value or else default_config_file
+end
index 1a9ed1a..d236427 100644 (file)
@@ -757,6 +757,9 @@ class PullRequest
 
        # Changed files count.
        var changed_files: Int is writable
+
+       # URL to patch file
+       var patch_url: nullable String is writable
 end
 
 # A pull request reference (used for head and base).
index 30ea286..c93d39a 100644 (file)
@@ -292,9 +292,7 @@ class OptionContext
        private var optmap = new HashMap[String, Option]
 
        # Add one or more options to the context
-       fun add_option(opts: Option...) do
-                       options.add_all(opts)
-       end
+       fun add_option(opts: Option...) do options.add_all(opts)
 
        # Display all the options available
        fun usage
index 1883b52..d92e9d9 100644 (file)
 # import popcorn
 # import popcorn::pop_config
 #
-# # Parse app options
-# var opts = new AppOptions.from_args(args)
-#
 # # Build config from options
-# var config = new AppConfig.from_options(opts)
+# var config = new AppConfig
+# config.parse_options(args)
 #
 # # Use options
 # var app = new App
 #      super AppConfig
 #
 #      # My secret code I don't want to share in my source repository
-#      var secret: String = value_or_default("secret", "my-secret")
-#
-#      redef init from_options(options) do
-#              super
-#              if options isa MyOptions then
-#                      var secret = options.opt_secret.value
-#                      if secret != null then self["secret"] = secret
-#              end
-#      end
-# end
-#
-# class MyOptions
-#      super AppOptions
+#      fun secret: String do return opt_secret.value or else ini["secret"] or else "my-secret"
 #
+#      # opt --secret
 #      var opt_secret = new OptionString("My secret string", "--secret")
 #
 #      redef init do
@@ -81,8 +68,8 @@
 #      end
 # end
 #
-# var opts = new MyOptions.from_args(args)
-# var config = new MyConfig.from_options(opts)
+# var config = new MyConfig
+# config.parse_options(args)
 #
 # var app = new App
 # app.use("/secret", new SecretHandler(config))
@@ -90,8 +77,7 @@
 # ~~~
 module pop_config
 
-import ini
-import opts
+import config
 
 # Configuration file for Popcorn apps
 #
@@ -100,92 +86,47 @@ import opts
 # import popcorn::pop_config
 #
 # # Build config from default values
-# var config = new AppConfig("app.ini")
+# var config = new AppConfig
+# config.parse_options(args)
 #
 # # Change config values
-# config["app.port"] = 3001.to_s
+# config.ini["app.port"] = 3001.to_s
 #
 # # Use options
 # var app = new App
 # app.listen(config.app_host, config.app_port)
 # ~~~
 class AppConfig
-       super ConfigTree
+       super IniConfig
 
-       # Kind of options used by this config
-       type OPTIONS: AppOptions
+       redef var default_config_file: String = "app.ini"
 
-       # Default configuration file path
-       var default_config_file: String = "app.ini"
+       # Host name to bind on (will overwrite the config one).
+       var opt_host = new OptionString("Host to bind the server on", "--host")
 
        # Web app host name
        #
        # * key: `app.host`
        # * default: `localhost`
-       var app_host: String is lazy do return value_or_default("app.host", "localhost")
+       fun app_host: String do return opt_host.value or else ini["app.host"] or else "localhost"
+
+       # Port number to bind on (will overwrite the config one).
+       var opt_port = new OptionInt("Port number to use", -1, "--port")
 
        # Web app port
        #
        # * key: `app.port`
        # * default: `3000`
-       var app_port: Int is lazy do return value_or_default("app.port", "3000").to_i
-
-       # Init `self` from a `AppOptions` option values
-       init from_options(opts: OPTIONS) do
-               init(opts.opt_config.value or else default_config_file)
-               var opt_host = opts.opt_host.value
-               if opt_host != null then self["app.host"] = opt_host
-               var opt_port = opts.opt_port.value
-               if opt_port > 0 then self["app.port"] = opt_port.to_s
+       fun app_port: Int do
+               var opt = opt_port.value
+               if opt > -1 then return opt
+               var val = ini["app.port"]
+               if val != null then return val.to_i
+               return 3000
        end
 
-       # Return the registered value for `key` or `default`
-       protected fun value_or_default(key: String, default: String): String do
-               return self[key] or else default
-       end
-end
-
-# Options configuration for Popcorn apps
-#
-# Use the `AppOptions` class in your app to parse command line args:
-# ~~~
-# import popcorn
-# import popcorn::pop_config
-#
-# # Parse app options
-# var opts = new AppOptions.from_args(args)
-#
-# # Build config from options
-# var config = new AppConfig.from_options(opts)
-#
-# # Use options
-# var app = new App
-# app.listen(config.app_host, config.app_port)
-# ~~~
-class AppOptions
-       super OptionContext
-
-       # Help option.
-       var opt_help = new OptionBool("Show this help message", "-h", "--help")
-
-       # Path to app config file.
-       var opt_config = new OptionString("Path to app config file", "--config")
-
-       # Host name to bind on (will overwrite the config one).
-       var opt_host = new OptionString("Host to bind the server on", "--host")
-
-       # Port number to bind on (will overwrite the config one).
-       var opt_port = new OptionInt("Port number to use", -1, "--port")
-
-       # You should redefined this method to add your options
        init do
                super
-               add_option(opt_help, opt_config, opt_host, opt_port)
-       end
-
-       # Initialize `self` and parse `args`
-       init from_args(args: Collection[String]) do
-               init
-               parse(args)
+               add_option(opt_host, opt_port)
        end
 end
index 7b02c35..1f12853 100644 (file)
@@ -131,39 +131,28 @@ redef class AppConfig
        # Default database hostname
        var default_db_name = "popcorn"
 
-       # MongoDB server used for data persistence
-       var db_host: String is lazy do return value_or_default("db.host", default_db_host)
-
-       # MongoDB DB used for data persistence
-       var db_name: String is lazy do return value_or_default("db.name", default_db_name)
-
-       # Mongo db client
-       var client = new MongoClient(db_host) is lazy
-
-       # Mongo db instance
-       var db: MongoDb = client.database(db_name) is lazy
-
-       redef init from_options(opts) do
-               super
-               var db_host = opts.opt_db_host.value
-               if db_host != null then self["db.host"] = db_host
-               var db_name = opts.opt_db_name.value
-               if db_name != null then self["db.name"] = db_name
-       end
-end
-
-redef class AppOptions
-
        # MongoDb host name
        var opt_db_host = new OptionString("MongoDb host", "--db-host")
 
        # MongoDb database name
        var opt_db_name = new OptionString("MongoDb database name", "--db-name")
 
+       # MongoDB server used for data persistence
+       fun db_host: String do return opt_db_host.value or else ini["db.host"] or else default_db_host
+
+       # MongoDB DB used for data persistence
+       fun db_name: String do return opt_db_name.value or else ini["db.name"] or else default_db_name
+
        init do
                super
                add_option(opt_db_host, opt_db_name)
        end
+
+       # Mongo db client
+       var client = new MongoClient(db_host) is lazy
+
+       # Mongo db instance
+       var db: MongoDb = client.database(db_name) is lazy
 end
 
 # A Repository is an object that can store serialized instances.
index 740ea8b..ae57696 100644 (file)
@@ -1,3 +1,3 @@
 <span>
-       <a ng-href='{{mentity.web_url}}'>{{mentity.name}}</a>
+       <a ng-href='{{mentity.web_url | encodeURI}}'>{{mentity.name}}</a>
 </span>
index 7e817c6..05f8ccb 100644 (file)
@@ -1,5 +1,4 @@
-<span ng-if='mentity.location'>
-       <a ng-href="{{mentity.web_url}}">{{mentity.location.file}}
-               <span ng-if='mentity.location.line_start'>:{{mentity.location.line_start}}</span>
-       </a>
+<span ng-if='mentity.location' class='text-muted'>
+       {{mentity.location.file}}
+       <span ng-if='mentity.location.line_start'>:{{mentity.location.line_start}}</span>
 </span>
index 73c7c2a..803b84b 100644 (file)
@@ -62,5 +62,9 @@
                                templateUrl: 'views/error.html'
                        });
                $locationProvider.html5Mode(true);
+       })
+
+       .filter('encodeURI', function() {
+               return encodeURIComponent;
        });
 })();
index 04dfa46..1e1365b 100644 (file)
@@ -9,11 +9,6 @@
                        <span class='glyphicon glyphicon-arrow-down'/> Linearization
                </a>
        </li>
-       <li role='presentation'>
-               <a data-toggle='tab' data-target='#code' ng-click="entityCtrl.loadEntityCode()">
-                       <span class='glyphicon glyphicon-console'/> Code
-               </a>
-       </li>
 </ul>
 
 <div class='tab-content'>
                        list-entities='linearization'
                        list-focus='mentity' />
        </div>
-       <div role='tabpanel' class='tab-pane fade' id='code'>
-               <div class='card'>
-                       <div class='card-body'>
-                               <pre ng-bind-html='code' />
-                               <entity-location mentity='mentity' />
-                       </div>
-               </div>
-       </div>
 </div>
index 825a782..975cfb5 100644 (file)
@@ -9,11 +9,6 @@
                        <span class='glyphicon glyphicon-arrow-down'/> Linearization
                </a>
        </li>
-       <li role='presentation'>
-               <a data-toggle='tab' data-target='#code' ng-click="entityCtrl.loadEntityCode()">
-                       <span class='glyphicon glyphicon-console'/> Code
-               </a>
-       </li>
 </ul>
 
 <div class='tab-content'>
                        list-entities='linearization'
                        list-focus='mentity' />
        </div>
-       <div role='tabpanel' class='tab-pane fade' id='code'>
-               <div class='card'>
-                       <div class='card-body'>
-                               <pre ng-bind-html='code' />
-                               <entity-location mentity='mentity' />
-                       </div>
-               </div>
-       </div>
 </div>
index ddd7023..8fe8754 100644 (file)
@@ -77,6 +77,14 @@ redef class MEntity
 
        # Same as `to_full_json` but with pretty json.
        fun to_pretty_full_json: String do return serialize_to_full_json(plain=true, pretty=true)
+
+       # Sort mentities by name
+       private fun sort_entities(mentities: Collection[MEntity]): Array[MEntity] do
+               var sorter = new MEntityNameSorter
+               var sorted = mentities.to_a
+               sorter.sort(sorted)
+               return sorted
+       end
 end
 
 redef class MDoc
@@ -111,7 +119,7 @@ redef class MPackage
                super
                if v isa FullJsonSerializer then
                        v.serialize_attribute("root", to_mentity_ref(root))
-                       v.serialize_attribute("mgroups", to_mentity_refs(mgroups))
+                       v.serialize_attribute("mgroups", to_mentity_refs(sort_entities(mgroups)))
                        var ini = self.ini
                        if ini != null then v.serialize_attribute("ini", ini.to_map)
                end
@@ -126,8 +134,8 @@ redef class MGroup
                        v.serialize_attribute("mpackage", to_mentity_ref(mpackage))
                        v.serialize_attribute("default_mmodule", to_mentity_ref(default_mmodule))
                        v.serialize_attribute("parent", to_mentity_ref(parent))
-                       v.serialize_attribute("mmodules", to_mentity_refs(mmodules))
-                       v.serialize_attribute("mgroups", to_mentity_refs(in_nesting.direct_smallers))
+                       v.serialize_attribute("mmodules", to_mentity_refs(sort_entities(mmodules)))
+                       v.serialize_attribute("mgroups", to_mentity_refs(sort_entities(in_nesting.direct_smallers)))
                end
        end
 end
@@ -139,10 +147,10 @@ redef class MModule
                        var view = private_view
                        v.serialize_attribute("mpackage", to_mentity_ref(mpackage))
                        v.serialize_attribute("mgroup", to_mentity_ref(mgroup))
-                       v.serialize_attribute("intro_mclasses", to_mentity_refs(intro_mclasses))
-                       v.serialize_attribute("mclassdefs", to_mentity_refs(mclassdefs))
-                       v.serialize_attribute("intro_mclassdefs", to_mentity_refs(collect_intro_mclassdefs(view)))
-                       v.serialize_attribute("redef_mclassdefs", to_mentity_refs(collect_redef_mclassdefs(view)))
+                       v.serialize_attribute("intro_mclasses", to_mentity_refs(sort_entities(intro_mclasses)))
+                       v.serialize_attribute("mclassdefs", to_mentity_refs(sort_entities(mclassdefs)))
+                       v.serialize_attribute("intro_mclassdefs", to_mentity_refs(sort_entities(collect_intro_mclassdefs(view))))
+                       v.serialize_attribute("redef_mclassdefs", to_mentity_refs(sort_entities(collect_redef_mclassdefs(view))))
                        v.serialize_attribute("imports", to_mentity_refs(in_importation.direct_greaters))
                end
        end
@@ -158,10 +166,10 @@ redef class MClass
                        v.serialize_attribute("intro_mmodule", to_mentity_ref(intro_mmodule))
                        v.serialize_attribute("mpackage", to_mentity_ref(intro_mmodule.mpackage))
                        v.serialize_attribute("mclassdefs", to_mentity_refs(mclassdefs))
-                       v.serialize_attribute("all_mproperties", to_mentity_refs(collect_accessible_mproperties(view)))
-                       v.serialize_attribute("intro_mproperties", to_mentity_refs(collect_intro_mproperties(view)))
-                       v.serialize_attribute("redef_mproperties", to_mentity_refs(collect_redef_mproperties(view)))
-                       v.serialize_attribute("parents", to_mentity_refs(collect_parents(view)))
+                       v.serialize_attribute("all_mproperties", to_mentity_refs(sort_entities(collect_accessible_mproperties(view))))
+                       v.serialize_attribute("intro_mproperties", to_mentity_refs(sort_entities(collect_intro_mproperties(view))))
+                       v.serialize_attribute("redef_mproperties", to_mentity_refs(sort_entities(collect_redef_mproperties(view))))
+                       v.serialize_attribute("parents", to_mentity_refs(sort_entities(collect_parents(view))))
                end
        end
 end
@@ -175,12 +183,12 @@ redef class MClassDef
                        var view = private_view
                        v.serialize_attribute("mmodule", to_mentity_ref(mmodule))
                        v.serialize_attribute("mclass", to_mentity_ref(mclass))
-                       v.serialize_attribute("mpropdefs", to_mentity_refs(mpropdefs))
-                       v.serialize_attribute("intro_mproperties", to_mentity_refs(intro_mproperties))
+                       v.serialize_attribute("mpropdefs", to_mentity_refs(sort_entities(mpropdefs)))
+                       v.serialize_attribute("intro_mproperties", to_mentity_refs(sort_entities(intro_mproperties)))
                        v.serialize_attribute("intro", to_mentity_ref(mclass.intro))
                        v.serialize_attribute("mpackage", to_mentity_ref(mmodule.mpackage))
-                       v.serialize_attribute("intro_mpropdefs", to_mentity_refs(collect_intro_mpropdefs(view)))
-                       v.serialize_attribute("redef_mpropdefs", to_mentity_refs(collect_redef_mpropdefs(view)))
+                       v.serialize_attribute("intro_mpropdefs", to_mentity_refs(sort_entities(collect_intro_mpropdefs(view))))
+                       v.serialize_attribute("redef_mpropdefs", to_mentity_refs(sort_entities(collect_redef_mpropdefs(view))))
                end
        end
 end
@@ -191,7 +199,7 @@ redef class MProperty
                if v isa FullJsonSerializer then
                        v.serialize_attribute("intro", to_mentity_ref(intro))
                        v.serialize_attribute("intro_mclassdef", to_mentity_ref(intro_mclassdef))
-                       v.serialize_attribute("mpropdefs", to_mentity_refs(mpropdefs))
+                       v.serialize_attribute("mpropdefs", to_mentity_refs(sort_entities(mpropdefs)))
                        v.serialize_attribute("intro_mclass", to_mentity_ref(intro_mclassdef.mclass))
                        v.serialize_attribute("mpackage", to_mentity_ref(intro_mclassdef.mmodule.mpackage))
                end
index 2dd320b..404065b 100644 (file)
                "full_name": "test_prog::Object"
        },
        "mpropdefs": [{
-               "full_name": "test_prog$Object$OTHER"
+               "full_name": "test_prog$Object$!="
        }, {
                "full_name": "test_prog$Object$=="
        }, {
-               "full_name": "test_prog$Object$!="
+               "full_name": "test_prog$Object$OTHER"
        }, {
                "full_name": "test_prog$Object$init"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
        }],
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
-               "full_name": "test_prog$Object$OTHER"
+               "full_name": "test_prog$Object$!="
        }, {
                "full_name": "test_prog$Object$=="
        }, {
-               "full_name": "test_prog$Object$!="
+               "full_name": "test_prog$Object$OTHER"
        }, {
                "full_name": "test_prog$Object$init"
        }],
                "full_name": "test_prog::Int"
        },
        "mpropdefs": [{
-               "full_name": "test_prog$Int$unary -"
+               "full_name": "test_prog$Int$*"
        }, {
                "full_name": "test_prog$Int$+"
        }, {
                "full_name": "test_prog$Int$-"
        }, {
-               "full_name": "test_prog$Int$*"
-       }, {
                "full_name": "test_prog$Int$/"
        }, {
                "full_name": "test_prog$Int$>"
        }, {
                "full_name": "test_prog$Int$to_f"
+       }, {
+               "full_name": "test_prog$Int$unary -"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Int::unary -"
+               "full_name": "test_prog::Int::*"
        }, {
                "full_name": "test_prog::Int::+"
        }, {
                "full_name": "test_prog::Int::-"
        }, {
-               "full_name": "test_prog::Int::*"
-       }, {
                "full_name": "test_prog::Int::/"
        }, {
                "full_name": "test_prog::Int::>"
        }, {
                "full_name": "test_prog::Int::to_f"
+       }, {
+               "full_name": "test_prog::Int::unary -"
        }],
        "intro": {
                "full_name": "test_prog$Int"
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
-               "full_name": "test_prog$Int$unary -"
+               "full_name": "test_prog$Int$*"
        }, {
                "full_name": "test_prog$Int$+"
        }, {
                "full_name": "test_prog$Int$-"
        }, {
-               "full_name": "test_prog$Int$*"
-       }, {
                "full_name": "test_prog$Int$/"
        }, {
                "full_name": "test_prog$Int$>"
        }, {
                "full_name": "test_prog$Int$to_f"
+       }, {
+               "full_name": "test_prog$Int$unary -"
        }],
        "redef_mpropdefs": []
 }
                "full_name": "test_prog::Float"
        },
        "mpropdefs": [{
+               "full_name": "test_prog$Float$*"
+       }, {
                "full_name": "test_prog$Float$+"
        }, {
                "full_name": "test_prog$Float$-"
        }, {
-               "full_name": "test_prog$Float$*"
-       }, {
                "full_name": "test_prog$Float$/"
        }, {
                "full_name": "test_prog$Float$>"
        }],
        "intro_mproperties": [{
+               "full_name": "test_prog::Float::*"
+       }, {
                "full_name": "test_prog::Float::+"
        }, {
                "full_name": "test_prog::Float::-"
        }, {
-               "full_name": "test_prog::Float::*"
-       }, {
                "full_name": "test_prog::Float::/"
        }, {
                "full_name": "test_prog::Float::>"
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
+               "full_name": "test_prog$Float$*"
+       }, {
                "full_name": "test_prog$Float$+"
        }, {
                "full_name": "test_prog$Float$-"
        }, {
-               "full_name": "test_prog$Float$*"
-       }, {
                "full_name": "test_prog$Float$/"
        }, {
                "full_name": "test_prog$Float$>"
                "full_name": "test_prog::Career"
        },
        "mpropdefs": [{
-               "full_name": "test_prog$Career$_strength_bonus"
-       }, {
-               "full_name": "test_prog$Career$strength_bonus"
+               "full_name": "test_prog$Career$_endurance_bonus"
        }, {
-               "full_name": "test_prog$Career$strength_bonus="
+               "full_name": "test_prog$Career$_intelligence_bonus"
        }, {
-               "full_name": "test_prog$Career$_endurance_bonus"
+               "full_name": "test_prog$Career$_strength_bonus"
        }, {
                "full_name": "test_prog$Career$endurance_bonus"
        }, {
                "full_name": "test_prog$Career$endurance_bonus="
        }, {
-               "full_name": "test_prog$Career$_intelligence_bonus"
+               "full_name": "test_prog$Career$Object::init"
        }, {
                "full_name": "test_prog$Career$intelligence_bonus"
        }, {
                "full_name": "test_prog$Career$intelligence_bonus="
        }, {
-               "full_name": "test_prog$Career$Object::init"
+               "full_name": "test_prog$Career$strength_bonus"
+       }, {
+               "full_name": "test_prog$Career$strength_bonus="
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::careers::Career::_strength_bonus"
-       }, {
-               "full_name": "test_prog::Career::strength_bonus"
+               "full_name": "test_prog::careers::Career::_endurance_bonus"
        }, {
-               "full_name": "test_prog::Career::strength_bonus="
+               "full_name": "test_prog::careers::Career::_intelligence_bonus"
        }, {
-               "full_name": "test_prog::careers::Career::_endurance_bonus"
+               "full_name": "test_prog::careers::Career::_strength_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus="
        }, {
-               "full_name": "test_prog::careers::Career::_intelligence_bonus"
-       }, {
                "full_name": "test_prog::Career::intelligence_bonus"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus="
+       }, {
+               "full_name": "test_prog::Career::strength_bonus"
+       }, {
+               "full_name": "test_prog::Career::strength_bonus="
        }],
        "intro": {
                "full_name": "test_prog$Career"
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
-               "full_name": "test_prog$Career$_strength_bonus"
-       }, {
-               "full_name": "test_prog$Career$strength_bonus"
+               "full_name": "test_prog$Career$_endurance_bonus"
        }, {
-               "full_name": "test_prog$Career$strength_bonus="
+               "full_name": "test_prog$Career$_intelligence_bonus"
        }, {
-               "full_name": "test_prog$Career$_endurance_bonus"
+               "full_name": "test_prog$Career$_strength_bonus"
        }, {
                "full_name": "test_prog$Career$endurance_bonus"
        }, {
                "full_name": "test_prog$Career$endurance_bonus="
        }, {
-               "full_name": "test_prog$Career$_intelligence_bonus"
-       }, {
                "full_name": "test_prog$Career$intelligence_bonus"
        }, {
                "full_name": "test_prog$Career$intelligence_bonus="
+       }, {
+               "full_name": "test_prog$Career$strength_bonus"
+       }, {
+               "full_name": "test_prog$Career$strength_bonus="
        }],
        "redef_mpropdefs": [{
                "full_name": "test_prog$Career$Object::init"
                "full_name": "test_prog::Race"
        },
        "mpropdefs": [{
-               "full_name": "test_prog$Race$_base_strength"
-       }, {
-               "full_name": "test_prog$Race$base_strength"
+               "full_name": "test_prog$Race$_base_endurance"
        }, {
-               "full_name": "test_prog$Race$base_strength="
+               "full_name": "test_prog$Race$_base_intelligence"
        }, {
-               "full_name": "test_prog$Race$_base_endurance"
+               "full_name": "test_prog$Race$_base_strength"
        }, {
                "full_name": "test_prog$Race$base_endurance"
        }, {
                "full_name": "test_prog$Race$base_endurance="
        }, {
-               "full_name": "test_prog$Race$_base_intelligence"
-       }, {
                "full_name": "test_prog$Race$base_intelligence"
        }, {
                "full_name": "test_prog$Race$base_intelligence="
        }, {
+               "full_name": "test_prog$Race$base_strength"
+       }, {
+               "full_name": "test_prog$Race$base_strength="
+       }, {
                "full_name": "test_prog$Race$Object::init"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::races::Race::_base_strength"
-       }, {
-               "full_name": "test_prog::Race::base_strength"
+               "full_name": "test_prog::races::Race::_base_endurance"
        }, {
-               "full_name": "test_prog::Race::base_strength="
+               "full_name": "test_prog::races::Race::_base_intelligence"
        }, {
-               "full_name": "test_prog::races::Race::_base_endurance"
+               "full_name": "test_prog::races::Race::_base_strength"
        }, {
                "full_name": "test_prog::Race::base_endurance"
        }, {
                "full_name": "test_prog::Race::base_endurance="
        }, {
-               "full_name": "test_prog::races::Race::_base_intelligence"
-       }, {
                "full_name": "test_prog::Race::base_intelligence"
        }, {
                "full_name": "test_prog::Race::base_intelligence="
+       }, {
+               "full_name": "test_prog::Race::base_strength"
+       }, {
+               "full_name": "test_prog::Race::base_strength="
        }],
        "intro": {
                "full_name": "test_prog$Race"
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
-               "full_name": "test_prog$Race$_base_strength"
-       }, {
-               "full_name": "test_prog$Race$base_strength"
+               "full_name": "test_prog$Race$_base_endurance"
        }, {
-               "full_name": "test_prog$Race$base_strength="
+               "full_name": "test_prog$Race$_base_intelligence"
        }, {
-               "full_name": "test_prog$Race$_base_endurance"
+               "full_name": "test_prog$Race$_base_strength"
        }, {
                "full_name": "test_prog$Race$base_endurance"
        }, {
                "full_name": "test_prog$Race$base_endurance="
        }, {
-               "full_name": "test_prog$Race$_base_intelligence"
-       }, {
                "full_name": "test_prog$Race$base_intelligence"
        }, {
                "full_name": "test_prog$Race$base_intelligence="
+       }, {
+               "full_name": "test_prog$Race$base_strength"
+       }, {
+               "full_name": "test_prog$Race$base_strength="
        }],
        "redef_mpropdefs": [{
                "full_name": "test_prog$Race$Object::init"
                "full_name": "test_prog::Character"
        },
        "mpropdefs": [{
+               "full_name": "test_prog$Character$_age"
+       }, {
+               "full_name": "test_prog$Character$_career"
+       }, {
+               "full_name": "test_prog$Character$_health"
+       }, {
+               "full_name": "test_prog$Character$_name"
+       }, {
                "full_name": "test_prog$Character$_race"
        }, {
-               "full_name": "test_prog$Character$race"
+               "full_name": "test_prog$Character$_sex"
        }, {
-               "full_name": "test_prog$Character$race="
+               "full_name": "test_prog$Character$age"
        }, {
-               "full_name": "test_prog$Character$_career"
+               "full_name": "test_prog$Character$age="
        }, {
                "full_name": "test_prog$Character$career"
        }, {
                "full_name": "test_prog$Character$career="
        }, {
-               "full_name": "test_prog$Character$quit"
+               "full_name": "test_prog$Character$health"
        }, {
-               "full_name": "test_prog$Character$_name"
+               "full_name": "test_prog$Character$health="
+       }, {
+               "full_name": "test_prog$Character$Object::init"
+       }, {
+               "full_name": "test_prog$Character$max_health"
        }, {
                "full_name": "test_prog$Character$name"
        }, {
                "full_name": "test_prog$Character$name="
        }, {
-               "full_name": "test_prog$Character$_age"
-       }, {
-               "full_name": "test_prog$Character$age"
+               "full_name": "test_prog$Character$quit"
        }, {
-               "full_name": "test_prog$Character$age="
+               "full_name": "test_prog$Character$race"
        }, {
-               "full_name": "test_prog$Character$_sex"
+               "full_name": "test_prog$Character$race="
        }, {
                "full_name": "test_prog$Character$sex"
        }, {
                "full_name": "test_prog$Character$sex="
        }, {
-               "full_name": "test_prog$Character$total_strengh"
-       }, {
                "full_name": "test_prog$Character$total_endurance"
        }, {
                "full_name": "test_prog$Character$total_intelligence"
        }, {
-               "full_name": "test_prog$Character$max_health"
+               "full_name": "test_prog$Character$total_strengh"
+       }],
+       "intro_mproperties": [{
+               "full_name": "test_prog::character::Character::_age"
        }, {
-               "full_name": "test_prog$Character$_health"
+               "full_name": "test_prog::character::Character::_career"
        }, {
-               "full_name": "test_prog$Character$health"
+               "full_name": "test_prog::character::Character::_health"
        }, {
-               "full_name": "test_prog$Character$health="
+               "full_name": "test_prog::character::Character::_name"
        }, {
-               "full_name": "test_prog$Character$Object::init"
-       }],
-       "intro_mproperties": [{
                "full_name": "test_prog::character::Character::_race"
        }, {
-               "full_name": "test_prog::Character::race"
+               "full_name": "test_prog::character::Character::_sex"
        }, {
-               "full_name": "test_prog::Character::race="
+               "full_name": "test_prog::Character::age"
        }, {
-               "full_name": "test_prog::character::Character::_career"
+               "full_name": "test_prog::Character::age="
        }, {
                "full_name": "test_prog::Character::career"
        }, {
                "full_name": "test_prog::Character::career="
        }, {
-               "full_name": "test_prog::Character::quit"
+               "full_name": "test_prog::Character::health"
        }, {
-               "full_name": "test_prog::character::Character::_name"
+               "full_name": "test_prog::Character::health="
+       }, {
+               "full_name": "test_prog::Character::max_health"
        }, {
                "full_name": "test_prog::Character::name"
        }, {
                "full_name": "test_prog::Character::name="
        }, {
-               "full_name": "test_prog::character::Character::_age"
-       }, {
-               "full_name": "test_prog::Character::age"
+               "full_name": "test_prog::Character::quit"
        }, {
-               "full_name": "test_prog::Character::age="
+               "full_name": "test_prog::Character::race"
        }, {
-               "full_name": "test_prog::character::Character::_sex"
+               "full_name": "test_prog::Character::race="
        }, {
                "full_name": "test_prog::Character::sex"
        }, {
                "full_name": "test_prog::Character::sex="
        }, {
-               "full_name": "test_prog::Character::total_strengh"
-       }, {
                "full_name": "test_prog::Character::total_endurance"
        }, {
                "full_name": "test_prog::Character::total_intelligence"
        }, {
-               "full_name": "test_prog::Character::max_health"
-       }, {
-               "full_name": "test_prog::character::Character::_health"
-       }, {
-               "full_name": "test_prog::Character::health"
-       }, {
-               "full_name": "test_prog::Character::health="
+               "full_name": "test_prog::Character::total_strengh"
        }],
        "intro": {
                "full_name": "test_prog$Character"
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
+               "full_name": "test_prog$Character$_age"
+       }, {
+               "full_name": "test_prog$Character$_career"
+       }, {
+               "full_name": "test_prog$Character$_health"
+       }, {
+               "full_name": "test_prog$Character$_name"
+       }, {
                "full_name": "test_prog$Character$_race"
        }, {
-               "full_name": "test_prog$Character$race"
+               "full_name": "test_prog$Character$_sex"
        }, {
-               "full_name": "test_prog$Character$race="
+               "full_name": "test_prog$Character$age"
        }, {
-               "full_name": "test_prog$Character$_career"
+               "full_name": "test_prog$Character$age="
        }, {
                "full_name": "test_prog$Character$career"
        }, {
                "full_name": "test_prog$Character$career="
        }, {
-               "full_name": "test_prog$Character$quit"
+               "full_name": "test_prog$Character$health"
        }, {
-               "full_name": "test_prog$Character$_name"
+               "full_name": "test_prog$Character$health="
+       }, {
+               "full_name": "test_prog$Character$max_health"
        }, {
                "full_name": "test_prog$Character$name"
        }, {
                "full_name": "test_prog$Character$name="
        }, {
-               "full_name": "test_prog$Character$_age"
-       }, {
-               "full_name": "test_prog$Character$age"
+               "full_name": "test_prog$Character$quit"
        }, {
-               "full_name": "test_prog$Character$age="
+               "full_name": "test_prog$Character$race"
        }, {
-               "full_name": "test_prog$Character$_sex"
+               "full_name": "test_prog$Character$race="
        }, {
                "full_name": "test_prog$Character$sex"
        }, {
                "full_name": "test_prog$Character$sex="
        }, {
-               "full_name": "test_prog$Character$total_strengh"
-       }, {
                "full_name": "test_prog$Character$total_endurance"
        }, {
                "full_name": "test_prog$Character$total_intelligence"
        }, {
-               "full_name": "test_prog$Character$max_health"
-       }, {
-               "full_name": "test_prog$Character$_health"
-       }, {
-               "full_name": "test_prog$Character$health"
-       }, {
-               "full_name": "test_prog$Character$health="
+               "full_name": "test_prog$Character$total_strengh"
        }],
        "redef_mpropdefs": [{
                "full_name": "test_prog$Character$Object::init"
                "full_name": "test_prog::Combatable"
        },
        "mpropdefs": [{
-               "full_name": "test_prog$Combatable$hit_points"
-       }, {
                "full_name": "test_prog$Combatable$attack"
        }, {
+               "full_name": "test_prog$Combatable$defend"
+       }, {
                "full_name": "test_prog$Combatable$direct_attack"
        }, {
-               "full_name": "test_prog$Combatable$defend"
+               "full_name": "test_prog$Combatable$hit_points"
        }, {
                "full_name": "test_prog$Combatable$is_dead"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Combatable::hit_points"
-       }, {
                "full_name": "test_prog::Combatable::attack"
        }, {
+               "full_name": "test_prog::Combatable::defend"
+       }, {
                "full_name": "test_prog::Combatable::direct_attack"
        }, {
-               "full_name": "test_prog::Combatable::defend"
+               "full_name": "test_prog::Combatable::hit_points"
        }, {
                "full_name": "test_prog::Combatable::is_dead"
        }],
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
-               "full_name": "test_prog$Combatable$hit_points"
-       }, {
                "full_name": "test_prog$Combatable$attack"
        }, {
+               "full_name": "test_prog$Combatable$defend"
+       }, {
                "full_name": "test_prog$Combatable$direct_attack"
        }, {
-               "full_name": "test_prog$Combatable$defend"
+               "full_name": "test_prog$Combatable$hit_points"
        }, {
                "full_name": "test_prog$Combatable$is_dead"
        }],
                "full_name": "test_prog::Game"
        },
        "mpropdefs": [{
-               "full_name": "test_prog$Game$player_characters"
-       }, {
                "full_name": "test_prog$Game$computer_characters"
        }, {
-               "full_name": "test_prog$Game$start_game"
-       }, {
                "full_name": "test_prog$Game$pause_game"
        }, {
+               "full_name": "test_prog$Game$player_characters"
+       }, {
+               "full_name": "test_prog$Game$start_game"
+       }, {
                "full_name": "test_prog$Game$stop_game"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Game::player_characters"
-       }, {
                "full_name": "test_prog::Game::computer_characters"
        }, {
-               "full_name": "test_prog::Game::start_game"
-       }, {
                "full_name": "test_prog::Game::pause_game"
        }, {
+               "full_name": "test_prog::Game::player_characters"
+       }, {
+               "full_name": "test_prog::Game::start_game"
+       }, {
                "full_name": "test_prog::Game::stop_game"
        }],
        "intro": {
                "full_name": "test_prog"
        },
        "intro_mpropdefs": [{
-               "full_name": "test_prog$Game$player_characters"
-       }, {
                "full_name": "test_prog$Game$computer_characters"
        }, {
-               "full_name": "test_prog$Game$start_game"
-       }, {
                "full_name": "test_prog$Game$pause_game"
        }, {
+               "full_name": "test_prog$Game$player_characters"
+       }, {
+               "full_name": "test_prog$Game$start_game"
+       }, {
                "full_name": "test_prog$Game$stop_game"
        }],
        "redef_mpropdefs": []
index 2fc7104..d5eb364 100644 (file)
                "full_name": "test_prog$Object"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
        }],
                "full_name": "test_prog$Int"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Int::unary -"
+               "full_name": "test_prog::Object::!="
+       }, {
+               "full_name": "test_prog::Int::*"
        }, {
                "full_name": "test_prog::Int::+"
        }, {
                "full_name": "test_prog::Int::-"
        }, {
-               "full_name": "test_prog::Int::*"
-       }, {
                "full_name": "test_prog::Int::/"
        }, {
-               "full_name": "test_prog::Int::>"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Int::to_f"
+               "full_name": "test_prog::Int::>"
        }, {
                "full_name": "test_prog::Object::OTHER"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Object::init"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Int::to_f"
        }, {
-               "full_name": "test_prog::Object::init"
+               "full_name": "test_prog::Int::unary -"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Int::unary -"
+               "full_name": "test_prog::Int::*"
        }, {
                "full_name": "test_prog::Int::+"
        }, {
                "full_name": "test_prog::Int::-"
        }, {
-               "full_name": "test_prog::Int::*"
-       }, {
                "full_name": "test_prog::Int::/"
        }, {
                "full_name": "test_prog::Int::>"
        }, {
                "full_name": "test_prog::Int::to_f"
+       }, {
+               "full_name": "test_prog::Int::unary -"
        }],
        "redef_mproperties": [],
        "parents": [{
                "full_name": "test_prog$Float"
        }],
        "all_mproperties": [{
+               "full_name": "test_prog::Object::!="
+       }, {
+               "full_name": "test_prog::Float::*"
+       }, {
                "full_name": "test_prog::Float::+"
        }, {
                "full_name": "test_prog::Float::-"
        }, {
-               "full_name": "test_prog::Float::*"
-       }, {
                "full_name": "test_prog::Float::/"
        }, {
+               "full_name": "test_prog::Object::=="
+       }, {
                "full_name": "test_prog::Float::>"
        }, {
                "full_name": "test_prog::Object::OTHER"
        }, {
-               "full_name": "test_prog::Object::=="
-       }, {
-               "full_name": "test_prog::Object::!="
-       }, {
                "full_name": "test_prog::Object::init"
        }],
        "intro_mproperties": [{
+               "full_name": "test_prog::Float::*"
+       }, {
                "full_name": "test_prog::Float::+"
        }, {
                "full_name": "test_prog::Float::-"
        }, {
-               "full_name": "test_prog::Float::*"
-       }, {
                "full_name": "test_prog::Float::/"
        }, {
                "full_name": "test_prog::Float::>"
                "full_name": "test_prog$Bool"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
        }],
                "full_name": "test_prog$String"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
        }],
                "full_name": "test_prog$List"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
        }],
                "full_name": "test_prog$Career"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::careers::Career::_strength_bonus"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Career::strength_bonus"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Career::strength_bonus="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::careers::Career::_endurance_bonus"
        }, {
+               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+       }, {
+               "full_name": "test_prog::careers::Career::_strength_bonus"
+       }, {
                "full_name": "test_prog::Career::endurance_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus="
        }, {
-               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+               "full_name": "test_prog::Object::init"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus="
        }, {
-               "full_name": "test_prog::Object::init"
-       }, {
-               "full_name": "test_prog::Object::OTHER"
-       }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Career::strength_bonus"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Career::strength_bonus="
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::careers::Career::_strength_bonus"
-       }, {
-               "full_name": "test_prog::Career::strength_bonus"
+               "full_name": "test_prog::careers::Career::_endurance_bonus"
        }, {
-               "full_name": "test_prog::Career::strength_bonus="
+               "full_name": "test_prog::careers::Career::_intelligence_bonus"
        }, {
-               "full_name": "test_prog::careers::Career::_endurance_bonus"
+               "full_name": "test_prog::careers::Career::_strength_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus="
        }, {
-               "full_name": "test_prog::careers::Career::_intelligence_bonus"
-       }, {
                "full_name": "test_prog::Career::intelligence_bonus"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus="
+       }, {
+               "full_name": "test_prog::Career::strength_bonus"
+       }, {
+               "full_name": "test_prog::Career::strength_bonus="
        }],
        "redef_mproperties": [{
                "full_name": "test_prog::Object::init"
                "full_name": "test_prog$Warrior"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::init"
-       }, {
-               "full_name": "test_prog::careers::Career::_strength_bonus"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Career::strength_bonus"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Career::strength_bonus="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::careers::Career::_endurance_bonus"
        }, {
+               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+       }, {
+               "full_name": "test_prog::careers::Career::_strength_bonus"
+       }, {
                "full_name": "test_prog::Career::endurance_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus="
        }, {
-               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+               "full_name": "test_prog::Object::init"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus="
        }, {
-               "full_name": "test_prog::Object::OTHER"
-       }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Career::strength_bonus"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Career::strength_bonus="
        }],
        "intro_mproperties": [],
        "redef_mproperties": [{
                "full_name": "test_prog$Magician"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::init"
-       }, {
-               "full_name": "test_prog::careers::Career::_strength_bonus"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Career::strength_bonus"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Career::strength_bonus="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::careers::Career::_endurance_bonus"
        }, {
+               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+       }, {
+               "full_name": "test_prog::careers::Career::_strength_bonus"
+       }, {
                "full_name": "test_prog::Career::endurance_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus="
        }, {
-               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+               "full_name": "test_prog::Object::init"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus="
        }, {
-               "full_name": "test_prog::Object::OTHER"
-       }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Career::strength_bonus"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Career::strength_bonus="
        }],
        "intro_mproperties": [],
        "redef_mproperties": [{
                "full_name": "test_prog$Alcoholic"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::init"
-       }, {
-               "full_name": "test_prog::careers::Career::_strength_bonus"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Career::strength_bonus"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Career::strength_bonus="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::careers::Career::_endurance_bonus"
        }, {
+               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+       }, {
+               "full_name": "test_prog::careers::Career::_strength_bonus"
+       }, {
                "full_name": "test_prog::Career::endurance_bonus"
        }, {
                "full_name": "test_prog::Career::endurance_bonus="
        }, {
-               "full_name": "test_prog::careers::Career::_intelligence_bonus"
+               "full_name": "test_prog::Object::init"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus"
        }, {
                "full_name": "test_prog::Career::intelligence_bonus="
        }, {
-               "full_name": "test_prog::Object::OTHER"
-       }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Career::strength_bonus"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Career::strength_bonus="
        }],
        "intro_mproperties": [],
        "redef_mproperties": [{
                "full_name": "test_prog$Race"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::races::Race::_base_strength"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Race::base_strength"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Race::base_strength="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::races::Race::_base_endurance"
        }, {
+               "full_name": "test_prog::races::Race::_base_intelligence"
+       }, {
+               "full_name": "test_prog::races::Race::_base_strength"
+       }, {
                "full_name": "test_prog::Race::base_endurance"
        }, {
                "full_name": "test_prog::Race::base_endurance="
        }, {
-               "full_name": "test_prog::races::Race::_base_intelligence"
-       }, {
                "full_name": "test_prog::Race::base_intelligence"
        }, {
                "full_name": "test_prog::Race::base_intelligence="
        }, {
-               "full_name": "test_prog::Object::init"
-       }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Race::base_strength"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Race::base_strength="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::init"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::races::Race::_base_strength"
-       }, {
-               "full_name": "test_prog::Race::base_strength"
+               "full_name": "test_prog::races::Race::_base_endurance"
        }, {
-               "full_name": "test_prog::Race::base_strength="
+               "full_name": "test_prog::races::Race::_base_intelligence"
        }, {
-               "full_name": "test_prog::races::Race::_base_endurance"
+               "full_name": "test_prog::races::Race::_base_strength"
        }, {
                "full_name": "test_prog::Race::base_endurance"
        }, {
                "full_name": "test_prog::Race::base_endurance="
        }, {
-               "full_name": "test_prog::races::Race::_base_intelligence"
-       }, {
                "full_name": "test_prog::Race::base_intelligence"
        }, {
                "full_name": "test_prog::Race::base_intelligence="
+       }, {
+               "full_name": "test_prog::Race::base_strength"
+       }, {
+               "full_name": "test_prog::Race::base_strength="
        }],
        "redef_mproperties": [{
                "full_name": "test_prog::Object::init"
                "full_name": "test_prog$Human"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::init"
-       }, {
-               "full_name": "test_prog::races::Race::_base_strength"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Race::base_strength"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Race::base_strength="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::races::Race::_base_endurance"
        }, {
+               "full_name": "test_prog::races::Race::_base_intelligence"
+       }, {
+               "full_name": "test_prog::races::Race::_base_strength"
+       }, {
                "full_name": "test_prog::Race::base_endurance"
        }, {
                "full_name": "test_prog::Race::base_endurance="
        }, {
-               "full_name": "test_prog::races::Race::_base_intelligence"
-       }, {
                "full_name": "test_prog::Race::base_intelligence"
        }, {
                "full_name": "test_prog::Race::base_intelligence="
        }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Race::base_strength"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Race::base_strength="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::init"
        }],
        "intro_mproperties": [],
        "redef_mproperties": [{
                "full_name": "test_prog::combat$Dwarf"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::init"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Weapon::dps"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::races::Race::_base_strength"
+               "full_name": "test_prog::Object::OTHER"
        }, {
-               "full_name": "test_prog::Race::base_strength"
+               "full_name": "test_prog::races::Race::_base_endurance"
        }, {
-               "full_name": "test_prog::Race::base_strength="
+               "full_name": "test_prog::races::Race::_base_intelligence"
        }, {
-               "full_name": "test_prog::races::Race::_base_endurance"
+               "full_name": "test_prog::races::Race::_base_strength"
        }, {
                "full_name": "test_prog::Race::base_endurance"
        }, {
                "full_name": "test_prog::Race::base_endurance="
        }, {
-               "full_name": "test_prog::races::Race::_base_intelligence"
-       }, {
                "full_name": "test_prog::Race::base_intelligence"
        }, {
                "full_name": "test_prog::Race::base_intelligence="
        }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Race::base_strength"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Race::base_strength="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Weapon::dps"
+       }, {
+               "full_name": "test_prog::Object::init"
        }],
        "intro_mproperties": [],
        "redef_mproperties": [{
-               "full_name": "test_prog::Object::init"
-       }, {
                "full_name": "test_prog::Weapon::dps"
+       }, {
+               "full_name": "test_prog::Object::init"
        }],
        "parents": [{
                "full_name": "test_prog::Race"
                "full_name": "test_prog$Elf"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Object::init"
-       }, {
-               "full_name": "test_prog::races::Race::_base_strength"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Race::base_strength"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Race::base_strength="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::races::Race::_base_endurance"
        }, {
+               "full_name": "test_prog::races::Race::_base_intelligence"
+       }, {
+               "full_name": "test_prog::races::Race::_base_strength"
+       }, {
                "full_name": "test_prog::Race::base_endurance"
        }, {
                "full_name": "test_prog::Race::base_endurance="
        }, {
-               "full_name": "test_prog::races::Race::_base_intelligence"
-       }, {
                "full_name": "test_prog::Race::base_intelligence"
        }, {
                "full_name": "test_prog::Race::base_intelligence="
        }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Race::base_strength"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Race::base_strength="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::init"
        }],
        "intro_mproperties": [],
        "redef_mproperties": [{
                "full_name": "test_prog::combat$Character"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::character::Character::_race"
-       }, {
-               "full_name": "test_prog::Character::race"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Character::race="
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::character::Character::_career"
+               "full_name": "test_prog::Object::OTHER"
        }, {
-               "full_name": "test_prog::Character::career"
+               "full_name": "test_prog::character::Character::_age"
        }, {
-               "full_name": "test_prog::Character::career="
+               "full_name": "test_prog::character::Character::_career"
        }, {
-               "full_name": "test_prog::Character::quit"
+               "full_name": "test_prog::character::Character::_health"
        }, {
                "full_name": "test_prog::character::Character::_name"
        }, {
-               "full_name": "test_prog::Character::name"
-       }, {
-               "full_name": "test_prog::Character::name="
+               "full_name": "test_prog::character::Character::_race"
        }, {
-               "full_name": "test_prog::character::Character::_age"
+               "full_name": "test_prog::character::Character::_sex"
        }, {
                "full_name": "test_prog::Character::age"
        }, {
                "full_name": "test_prog::Character::age="
        }, {
-               "full_name": "test_prog::character::Character::_sex"
-       }, {
-               "full_name": "test_prog::Character::sex"
-       }, {
-               "full_name": "test_prog::Character::sex="
-       }, {
-               "full_name": "test_prog::Character::total_strengh"
+               "full_name": "test_prog::Combatable::attack"
        }, {
-               "full_name": "test_prog::Character::total_endurance"
+               "full_name": "test_prog::Character::career"
        }, {
-               "full_name": "test_prog::Character::total_intelligence"
+               "full_name": "test_prog::Character::career="
        }, {
-               "full_name": "test_prog::Character::max_health"
+               "full_name": "test_prog::Combatable::defend"
        }, {
-               "full_name": "test_prog::character::Character::_health"
+               "full_name": "test_prog::Combatable::direct_attack"
        }, {
                "full_name": "test_prog::Character::health"
        }, {
                "full_name": "test_prog::Character::health="
        }, {
+               "full_name": "test_prog::Combatable::hit_points"
+       }, {
                "full_name": "test_prog::Object::init"
        }, {
-               "full_name": "test_prog::Combatable::hit_points"
+               "full_name": "test_prog::Combatable::is_dead"
        }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Character::max_health"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Character::name"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Character::name="
        }, {
-               "full_name": "test_prog::Combatable::attack"
+               "full_name": "test_prog::Character::quit"
        }, {
-               "full_name": "test_prog::Combatable::direct_attack"
+               "full_name": "test_prog::Character::race"
        }, {
-               "full_name": "test_prog::Combatable::defend"
+               "full_name": "test_prog::Character::race="
        }, {
-               "full_name": "test_prog::Combatable::is_dead"
+               "full_name": "test_prog::Character::sex"
+       }, {
+               "full_name": "test_prog::Character::sex="
+       }, {
+               "full_name": "test_prog::Character::total_endurance"
+       }, {
+               "full_name": "test_prog::Character::total_intelligence"
+       }, {
+               "full_name": "test_prog::Character::total_strengh"
        }],
        "intro_mproperties": [{
+               "full_name": "test_prog::character::Character::_age"
+       }, {
+               "full_name": "test_prog::character::Character::_career"
+       }, {
+               "full_name": "test_prog::character::Character::_health"
+       }, {
+               "full_name": "test_prog::character::Character::_name"
+       }, {
                "full_name": "test_prog::character::Character::_race"
        }, {
-               "full_name": "test_prog::Character::race"
+               "full_name": "test_prog::character::Character::_sex"
        }, {
-               "full_name": "test_prog::Character::race="
+               "full_name": "test_prog::Character::age"
        }, {
-               "full_name": "test_prog::character::Character::_career"
+               "full_name": "test_prog::Character::age="
        }, {
                "full_name": "test_prog::Character::career"
        }, {
                "full_name": "test_prog::Character::career="
        }, {
-               "full_name": "test_prog::Character::quit"
+               "full_name": "test_prog::Character::health"
        }, {
-               "full_name": "test_prog::character::Character::_name"
+               "full_name": "test_prog::Character::health="
+       }, {
+               "full_name": "test_prog::Character::max_health"
        }, {
                "full_name": "test_prog::Character::name"
        }, {
                "full_name": "test_prog::Character::name="
        }, {
-               "full_name": "test_prog::character::Character::_age"
-       }, {
-               "full_name": "test_prog::Character::age"
+               "full_name": "test_prog::Character::quit"
        }, {
-               "full_name": "test_prog::Character::age="
+               "full_name": "test_prog::Character::race"
        }, {
-               "full_name": "test_prog::character::Character::_sex"
+               "full_name": "test_prog::Character::race="
        }, {
                "full_name": "test_prog::Character::sex"
        }, {
                "full_name": "test_prog::Character::sex="
        }, {
-               "full_name": "test_prog::Character::total_strengh"
-       }, {
                "full_name": "test_prog::Character::total_endurance"
        }, {
                "full_name": "test_prog::Character::total_intelligence"
        }, {
-               "full_name": "test_prog::Character::max_health"
-       }, {
-               "full_name": "test_prog::character::Character::_health"
-       }, {
-               "full_name": "test_prog::Character::health"
-       }, {
-               "full_name": "test_prog::Character::health="
+               "full_name": "test_prog::Character::total_strengh"
        }],
        "redef_mproperties": [{
-               "full_name": "test_prog::Object::init"
-       }, {
                "full_name": "test_prog::Combatable::hit_points"
+       }, {
+               "full_name": "test_prog::Object::init"
        }],
        "parents": [{
-               "full_name": "test_prog::Object"
-       }, {
                "full_name": "test_prog::Combatable"
+       }, {
+               "full_name": "test_prog::Object"
        }]
 }
 {
                "full_name": "test_prog$Weapon"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Weapon::dps"
-       }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
+       }, {
+               "full_name": "test_prog::Weapon::dps"
        }, {
                "full_name": "test_prog::Object::init"
        }],
                "full_name": "test_prog$Combatable"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Combatable::hit_points"
-       }, {
-               "full_name": "test_prog::Combatable::attack"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Combatable::direct_attack"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Combatable::defend"
+               "full_name": "test_prog::Object::OTHER"
        }, {
-               "full_name": "test_prog::Combatable::is_dead"
+               "full_name": "test_prog::Combatable::attack"
        }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Combatable::defend"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Combatable::direct_attack"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Combatable::hit_points"
        }, {
                "full_name": "test_prog::Object::init"
+       }, {
+               "full_name": "test_prog::Combatable::is_dead"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Combatable::hit_points"
-       }, {
                "full_name": "test_prog::Combatable::attack"
        }, {
+               "full_name": "test_prog::Combatable::defend"
+       }, {
                "full_name": "test_prog::Combatable::direct_attack"
        }, {
-               "full_name": "test_prog::Combatable::defend"
+               "full_name": "test_prog::Combatable::hit_points"
        }, {
                "full_name": "test_prog::Combatable::is_dead"
        }],
                "full_name": "test_prog$Game"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Game::player_characters"
+               "full_name": "test_prog::Object::!="
        }, {
-               "full_name": "test_prog::Game::computer_characters"
+               "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Game::start_game"
+               "full_name": "test_prog::Object::OTHER"
        }, {
-               "full_name": "test_prog::Game::pause_game"
+               "full_name": "test_prog::Game::computer_characters"
        }, {
-               "full_name": "test_prog::Game::stop_game"
+               "full_name": "test_prog::Object::init"
        }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Game::pause_game"
        }, {
-               "full_name": "test_prog::Object::=="
+               "full_name": "test_prog::Game::player_characters"
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Game::start_game"
        }, {
-               "full_name": "test_prog::Object::init"
+               "full_name": "test_prog::Game::stop_game"
        }],
        "intro_mproperties": [{
-               "full_name": "test_prog::Game::player_characters"
-       }, {
                "full_name": "test_prog::Game::computer_characters"
        }, {
-               "full_name": "test_prog::Game::start_game"
-       }, {
                "full_name": "test_prog::Game::pause_game"
        }, {
+               "full_name": "test_prog::Game::player_characters"
+       }, {
+               "full_name": "test_prog::Game::start_game"
+       }, {
                "full_name": "test_prog::Game::stop_game"
        }],
        "redef_mproperties": [],
                "full_name": "test_prog$Starter"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Starter::start"
-       }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
+       }, {
+               "full_name": "test_prog::Starter::start"
        }],
        "intro_mproperties": [{
                "full_name": "test_prog::Starter::start"
                "full_name": "test_prog$Sys"
        }],
        "all_mproperties": [{
-               "full_name": "test_prog::Sys::main"
-       }, {
-               "full_name": "test_prog::Object::OTHER"
+               "full_name": "test_prog::Object::!="
        }, {
                "full_name": "test_prog::Object::=="
        }, {
-               "full_name": "test_prog::Object::!="
+               "full_name": "test_prog::Object::OTHER"
        }, {
                "full_name": "test_prog::Object::init"
+       }, {
+               "full_name": "test_prog::Sys::main"
        }],
        "intro_mproperties": [{
                "full_name": "test_prog::Sys::main"
index 92690d1..e0c653a 100644 (file)
                "full_name": "test_prog>platform>"
        },
        "intro_mclasses": [{
-               "full_name": "test_prog::Object"
+               "full_name": "test_prog::Bool"
+       }, {
+               "full_name": "test_prog::Float"
        }, {
                "full_name": "test_prog::Int"
        }, {
-               "full_name": "test_prog::Float"
+               "full_name": "test_prog::List"
        }, {
-               "full_name": "test_prog::Bool"
+               "full_name": "test_prog::Object"
        }, {
                "full_name": "test_prog::String"
-       }, {
-               "full_name": "test_prog::List"
        }],
        "mclassdefs": [{
-               "full_name": "test_prog$Object"
+               "full_name": "test_prog$Bool"
+       }, {
+               "full_name": "test_prog$Float"
        }, {
                "full_name": "test_prog$Int"
        }, {
-               "full_name": "test_prog$Float"
+               "full_name": "test_prog$List"
        }, {
-               "full_name": "test_prog$Bool"
+               "full_name": "test_prog$Object"
        }, {
                "full_name": "test_prog$String"
-       }, {
-               "full_name": "test_prog$List"
        }],
        "intro_mclassdefs": [{
-               "full_name": "test_prog$Object"
+               "full_name": "test_prog$Bool"
+       }, {
+               "full_name": "test_prog$Float"
        }, {
                "full_name": "test_prog$Int"
        }, {
-               "full_name": "test_prog$Float"
+               "full_name": "test_prog$List"
        }, {
-               "full_name": "test_prog$Bool"
+               "full_name": "test_prog$Object"
        }, {
                "full_name": "test_prog$String"
-       }, {
-               "full_name": "test_prog$List"
        }],
        "redef_mclassdefs": [],
        "imports": []
                "full_name": "test_prog>rpg>"
        },
        "intro_mclasses": [{
-               "full_name": "test_prog::Career"
+               "full_name": "test_prog::Alcoholic"
        }, {
-               "full_name": "test_prog::Warrior"
+               "full_name": "test_prog::Career"
        }, {
                "full_name": "test_prog::Magician"
        }, {
-               "full_name": "test_prog::Alcoholic"
+               "full_name": "test_prog::Warrior"
        }],
        "mclassdefs": [{
-               "full_name": "test_prog$Career"
+               "full_name": "test_prog$Alcoholic"
        }, {
-               "full_name": "test_prog$Warrior"
+               "full_name": "test_prog$Career"
        }, {
                "full_name": "test_prog$Magician"
        }, {
-               "full_name": "test_prog$Alcoholic"
+               "full_name": "test_prog$Warrior"
        }],
        "intro_mclassdefs": [{
-               "full_name": "test_prog$Career"
+               "full_name": "test_prog$Alcoholic"
        }, {
-               "full_name": "test_prog$Warrior"
+               "full_name": "test_prog$Career"
        }, {
                "full_name": "test_prog$Magician"
        }, {
-               "full_name": "test_prog$Alcoholic"
+               "full_name": "test_prog$Warrior"
        }],
        "redef_mclassdefs": [],
        "imports": [{
                "full_name": "test_prog>rpg>"
        },
        "intro_mclasses": [{
-               "full_name": "test_prog::Weapon"
-       }, {
                "full_name": "test_prog::Combatable"
+       }, {
+               "full_name": "test_prog::Weapon"
        }],
        "mclassdefs": [{
-               "full_name": "test_prog$Weapon"
+               "full_name": "test_prog::combat$Character"
        }, {
                "full_name": "test_prog$Combatable"
        }, {
-               "full_name": "test_prog::combat$Character"
-       }, {
                "full_name": "test_prog::combat$Dwarf"
+       }, {
+               "full_name": "test_prog$Weapon"
        }],
        "intro_mclassdefs": [{
-               "full_name": "test_prog$Weapon"
-       }, {
                "full_name": "test_prog$Combatable"
+       }, {
+               "full_name": "test_prog$Weapon"
        }],
        "redef_mclassdefs": [{
                "full_name": "test_prog::combat$Character"
                "full_name": "test_prog>rpg>"
        },
        "intro_mclasses": [{
-               "full_name": "test_prog::Race"
-       }, {
-               "full_name": "test_prog::Human"
-       }, {
                "full_name": "test_prog::Dwarf"
        }, {
                "full_name": "test_prog::Elf"
-       }],
-       "mclassdefs": [{
-               "full_name": "test_prog$Race"
        }, {
-               "full_name": "test_prog$Human"
+               "full_name": "test_prog::Human"
        }, {
+               "full_name": "test_prog::Race"
+       }],
+       "mclassdefs": [{
                "full_name": "test_prog$Dwarf"
        }, {
                "full_name": "test_prog$Elf"
-       }],
-       "intro_mclassdefs": [{
-               "full_name": "test_prog$Race"
        }, {
                "full_name": "test_prog$Human"
        }, {
+               "full_name": "test_prog$Race"
+       }],
+       "intro_mclassdefs": [{
                "full_name": "test_prog$Dwarf"
        }, {
                "full_name": "test_prog$Elf"
+       }, {
+               "full_name": "test_prog$Human"
+       }, {
+               "full_name": "test_prog$Race"
        }],
        "redef_mclassdefs": [],
        "imports": [{
index 81a0cae..ef7ced3 100644 (file)
                "full_name": "test_prog>"
        },
        "mgroups": [{
-               "full_name": "test_prog>"
-       }, {
                "full_name": "test_prog>game>"
        }, {
                "full_name": "test_prog>platform>"
        }, {
                "full_name": "test_prog>rpg>"
+       }, {
+               "full_name": "test_prog>"
        }],
        "ini": {
                "upstream.issues": "https://github.com/nitlang/nit/issues",
index d61dd81..f3c8146 100644 (file)
                "full_name": "test_prog$Object"
        },
        "mpropdefs": [{
-               "full_name": "test_prog$Object$init"
+               "full_name": "test_prog$Elf$Object::init"
        }, {
                "full_name": "test_prog$Career$Object::init"
        }, {
        }, {
                "full_name": "test_prog$Dwarf$Object::init"
        }, {
-               "full_name": "test_prog$Elf$Object::init"
-       }, {
                "full_name": "test_prog$Character$Object::init"
+       }, {
+               "full_name": "test_prog$Object$init"
        }],
        "intro_mclass": {
                "full_name": "test_prog::Object"
index 419f257..95b1671 100644 (file)
@@ -15,7 +15,6 @@
 # Runs a webserver based on nitcorn that render things from model.
 module nitweb
 
-import popcorn::pop_config
 import popcorn::pop_auth
 import frontend
 import web
@@ -27,15 +26,13 @@ redef class NitwebConfig
        #
        # * key: `github.client_id`
        # * default: ``
-       var github_client_id: String is lazy do return value_or_default("github.client.id", "")
+       fun github_client_id: String do return ini["github.client.id"] or else ""
 
        # Github client secret used for Github OAuth login.
        #
        # * key: `github.client_secret`
        # * default: ``
-       var github_client_secret: String is lazy do
-               return value_or_default("github.client.secret", "")
-       end
+       fun github_client_secret: String do return ini["github.client.secret"] or else ""
 end
 
 redef class ToolContext
@@ -64,17 +61,17 @@ private class NitwebPhase
 
        # Build the nitweb config from `toolcontext` options.
        fun build_config(toolcontext: ToolContext, mainmodule: MModule): NitwebConfig do
-               var config_file = toolcontext.opt_config.value
-               if config_file == null then config_file = "nitweb.ini"
                var config = new NitwebConfig(
-                       config_file,
                        toolcontext.modelbuilder.model,
                        mainmodule,
                        toolcontext.modelbuilder)
+               var config_file = toolcontext.opt_config.value
+               if config_file == null then config.default_config_file = "nitweb.ini"
+               config.parse_options(args)
                var opt_host = toolcontext.opt_host.value
-               if opt_host != null then config["app.host"] = opt_host
+               if opt_host != null then config.ini["app.host"] = opt_host
                var opt_port = toolcontext.opt_port.value
-               if opt_port >= 0 then config["app.port"] = opt_port.to_s
+               if opt_port >= 0 then config.ini["app.port"] = opt_port.to_s
                return config
        end
 
index dbf93ab..31077c4 100644 (file)
@@ -69,6 +69,16 @@ class APIList
                return mentities
        end
 
+       # Sort mentities by lexicographic order
+       #
+       # TODO choose order from request
+       fun sort_mentities(req: HttpRequest, mentities: Array[MEntity]) : Array[MEntity] do
+               var sorted = mentities.to_a
+               var sorter = new MEntityNameSorter
+               sorter.sort(sorted)
+               return sorted
+       end
+
        # Limit mentities depending on the `n` parameter.
        fun limit_mentities(req: HttpRequest, mentities: Array[MEntity]): Array[MEntity] do
                var n = req.int_arg("n")
@@ -80,6 +90,7 @@ class APIList
 
        redef fun get(req, res) do
                var mentities = list_mentities(req)
+               mentities = sort_mentities(req, mentities)
                mentities = limit_mentities(req, mentities)
                res.json new JsonArray.from(mentities)
        end
@@ -173,25 +184,27 @@ end
 #
 # Example: `GET /defs/core::Array`
 class APIEntityDefs
-       super APIHandler
+       super APIList
 
        redef fun get(req, res) do
                var mentity = mentity_from_uri(req, res)
                if mentity == null then return
-               var arr = new JsonArray
+               var mentities: Array[MEntity]
                if mentity isa MModule then
-                       for mclassdef in mentity.mclassdefs do arr.add mclassdef
+                       mentities = mentity.mclassdefs
                else if mentity isa MClass then
-                       for mclassdef in mentity.mclassdefs do arr.add mclassdef
+                       mentities = mentity.mclassdefs
                else if mentity isa MClassDef then
-                       for mpropdef in mentity.mpropdefs do arr.add mpropdef
+                       mentities = mentity.mpropdefs
                else if mentity isa MProperty then
-                       for mpropdef in mentity.mpropdefs do arr.add mpropdef
+                       mentities = mentity.mpropdefs
                else
                        res.api_error(404, "No definition list for mentity `{mentity.full_name}`")
                        return
                end
-               res.json arr
+               mentities = sort_mentities(req, mentities)
+               mentities = limit_mentities(req, mentities)
+               res.json new JsonArray.from(mentities)
        end
 end