Merge: Loader refactor
authorJean Privat <jean@pryen.org>
Mon, 19 Oct 2015 12:50:24 +0000 (08:50 -0400)
committerJean Privat <jean@pryen.org>
Mon, 19 Oct 2015 12:50:24 +0000 (08:50 -0400)
A big refactorization of the loader

This include cleanup, renaming and documentation of the existing code.

The major change is the removal of `ModulePath` used to designate an identified module that is not yet loaded. This caused major issues since once the module was loaded, the MModule object has to be used instead.
Now, genuine `MModule` are used to also represent modules identified in the file system but not yet loaded.
This simplify the code of the loader, nitls and nitcatalog.

By the way, the option `-d` (and `-M`) of nitls that was broken by the previous changes in the loader is now fixed.

Another change is the introduction of `scan_full` that is a high-level method to be used by clients like nitls or nitcatalog that just need to identify packages, groups and modules in the filesystem without loading them.

By the way, nitcalatog works on directories of projects now. eg. `nitcatalog ../lib)

Note, because this PR introduces a lot of interrelated changes, It was hard to come up with nice commits. The alternative was to have a single big commit.

Pull-Request: #1750
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

27 files changed:
contrib/benitlux/Makefile
contrib/crazy_moles/Makefile
contrib/jwrapper/Makefile
contrib/memory/Makefile
contrib/nitc [new symlink]
contrib/objcwrapper/Makefile
contrib/online_ide/Makefile
contrib/online_ide/sources/nit/pnacl_nit.nit
contrib/simplan/Makefile
contrib/tinks/Makefile
lib/core/collection/hash_collection.nit
lib/core/text/abstract_text.nit
lib/core/text/flat.nit
lib/github/api.nit
lib/github/events.nit
lib/graphs/digraph.nit
lib/graphs/pagerank.nit [new file with mode: 0644]
lib/json/Makefile
lib/mnit/android/android_app.nit
lib/mnit/linux/linux_app.nit
lib/mongodb/mongodb.nit
src/Makefile
src/metrics/mendel_metrics.nit
src/metrics/metrics_base.nit
tests/sav/ballz_linux.res [deleted file]
tests/sav/dino_linux.res [deleted file]
tests/sav/shoot_linux.res [deleted file]

index 9bf30ac..7041b04 100644 (file)
@@ -1,5 +1,7 @@
 all: server
 
+pre-build: src/benitlux_serial.nit
+
 server:
        mkdir -p bin/
        ../../bin/nitc --dir bin/ src/benitlux_daily.nit src/benitlux_web.nit
index 113329d..232ec08 100644 (file)
@@ -4,6 +4,8 @@ SVG2PNG=../inkscape_tools/bin/svg_to_png_and_nit
 
 default: bin/moles
 
+pre-build: assets/images/drawing.png
+
 bin/moles: $(shell ../../bin/nitls -M src/moles_linux.nit) assets/images/drawing.png
        mkdir -p bin
        ../../bin/nitc -o bin/moles src/moles_linux.nit
index 7c41505..3173333 100644 (file)
@@ -1,5 +1,7 @@
 all: bin/jwrapper
 
+pre-build: src/javap_test_parser.nit src/serial.nit
+
 ../nitcc/src/nitcc:
        make -C ../nitcc
 
index ac91a73..a5a8c6d 100644 (file)
@@ -14,6 +14,8 @@
 
 all: bin/memory
 
+pre-build: assets/images/drawing.png
+
 bin/memory: assets/images/drawing.png src/*.nit
        mkdir -p bin
        ../../bin/nitc -o bin/memory src/memory.nit -m ../../lib/mnit/linux/linux.nit
diff --git a/contrib/nitc b/contrib/nitc
new file mode 120000 (symlink)
index 0000000..5cd551c
--- /dev/null
@@ -0,0 +1 @@
+../src
\ No newline at end of file
index e248fb1..33ed110 100644 (file)
@@ -1,5 +1,7 @@
 all: bin/objcwrapper
 
+pre-build: src/objc_parser.nit
+
 ../nitcc/src/nitcc:
        make -C ../nitcc
 
index 6c06cf5..c8d231e 100644 (file)
@@ -2,7 +2,7 @@
 ACE_BUILDS ?= ../../../ace-builds/
 
 default:
-       ../../bin/nitc --semi-global sources/nit/pnacl_nit.nit -I ../../src/
+       ../../bin/nitc --semi-global sources/nit/pnacl_nit.nit
        cp pnacl_nit/pnacl_nit.pexe www/pnacl/ -f
        rm -rf pnacl_nit/
 
index 9522036..122b507 100644 (file)
 # A version of the naive Nit interpreter for PNaCl.
 module pnacl_nit
 
-import interpreter::naive_interpreter
-import interpreter::debugger
+import nitc::interpreter::naive_interpreter
+import nitc::interpreter::debugger
 import pnacl
-intrude import toolcontext
-intrude import loader
+intrude import nitc::toolcontext
+intrude import nitc::loader
 intrude import core::file
 
 # We redefine exit to start a new thread before killing the one that called exit.
index 530c25e..367868e 100644 (file)
@@ -3,6 +3,8 @@ NITCC=../nitcc/src/nitcc
 
 all: simplan
 
+pre-build: simplan_parser.nit
+
 simplan: simplan.nit simplan_parser.nit
        ${NITC} simplan.nit
 
index ee13360..aeb7fbf 100644 (file)
 
 all: bin/server bin/tinks
 
+pre-build: assets/images/drawing.png src/client/client_serialize.nit src/server/server_serialize.nit
+
 # Client
 bin/tinks: assets/images/drawing.png src/client/client_serialize.nit $(shell ../../bin/nitls -M src/client/linux_client.nit)
        ../../bin/nitc -o bin/tinks src/client/linux_client.nit -m src/client/client_serialize.nit
 
-src/client/client_serialize.nit: $(shell ../../bin/nitls -M src/client/client.nit)
+src/client/client_serialize.nit: assets/images/drawing.png $(shell ../../bin/nitls -M src/client/client.nit)
        ../../bin/nitserial -o src/client/client_serialize.nit src/client/client.nit
 
 assets/images/drawing.png: art/drawing.svg
index 1c9c17c..8ee3491 100644 (file)
@@ -376,7 +376,7 @@ private class HashMapNode[K, V]
 end
 
 # A `MapIterator` over a `HashMap`.
-class HashMapIterator[K, V]
+private class HashMapIterator[K, V]
        super MapIterator[K, V]
        redef fun is_ok do return _node != null
 
@@ -405,10 +405,10 @@ class HashMapIterator[K, V]
        end
 
        # The map to iterate on
-       private var map: HashMap[K, V]
+       var map: HashMap[K, V]
 
        # The current node
-       private var node: nullable HashMapNode[K, V] = null
+       var node: nullable HashMapNode[K, V] = null
 
        init
        do
index 01d0eab..baf8ae7 100644 (file)
@@ -966,14 +966,14 @@ abstract class Text
 end
 
 # All kinds of array-based text representations.
-abstract class FlatText
+private abstract class FlatText
        super Text
 
        # Underlying C-String (`char*`)
        #
        # Warning : Might be void in some subclasses, be sure to check
        # if set before using it.
-       private var items: NativeString is noinit
+       var items: NativeString is noinit
 
        # Returns a char* starting at position `first_byte`
        #
@@ -990,7 +990,7 @@ abstract class FlatText
        #
        # As always, do not modify the content of the String in C code, if this is what you want
        # copy locally the char* as Nit Strings are immutable.
-       private fun fast_cstring: NativeString is abstract
+       fun fast_cstring: NativeString is abstract
 
        redef var length = 0
 
index 5bc76fc..6cf1584 100644 (file)
@@ -36,18 +36,18 @@ end
 
 redef class FlatText
 
-       private fun first_byte: Int do return 0
+       fun first_byte: Int do return 0
 
-       private fun last_byte: Int do return _bytelen - 1
+       fun last_byte: Int do return _bytelen - 1
 
        # Cache of the latest position (char) explored in the string
-       private var position: Int = 0
+       var position: Int = 0
 
        # Cached position (bytes) in the NativeString underlying the String
-       private var bytepos: Int = 0
+       var bytepos: Int = 0
 
        # Index of the character `index` in `_items`
-       private fun char_to_byte_index(index: Int): Int do
+       fun char_to_byte_index(index: Int): Int do
                var ln = length
                assert index >= 0
                assert index < ln
@@ -90,7 +90,7 @@ redef class FlatText
        # This enables a double-optimization in `escape_to_c` since if this
        # method returns 0, then `self` does not need escaping and can be
        # returned as-is
-       protected fun chars_to_escape_to_c: Int do
+       fun chars_to_escape_to_c: Int do
                var its = _items
                var max = last_byte
                var pos = first_byte
@@ -1148,8 +1148,9 @@ redef class Array[E]
        do
                var l = length
                if l == 0 then return ""
-               if l == 1 then if self[0] == null then return "" else return self[0].to_s
-               var its = _items
+               var its = _items.as(not null)
+               var first = its[0]
+               if l == 1 then if first == null then return "" else return first.to_s
                var na = new NativeArray[String](l)
                var i = 0
                var sl = 0
index dc4e586..7e7400c 100644 (file)
@@ -351,7 +351,10 @@ abstract class GithubEntity
        redef fun to_s do return json.to_json
 
        # Github page url.
-       fun html_url: String do return json["html_url"].to_s
+       fun html_url: String do return json["html_url"].as(String)
+
+       # Set page url.
+       fun html_url=(url: String) do json["html_url"] = url
 end
 
 # A Github user
@@ -368,12 +371,15 @@ class User
 
        # Init `self` from a `json` object.
        init from_json(api: GithubAPI, json: JsonObject) do
-               init(api, json["login"].to_s)
+               init(api, json["login"].as(String))
                self.json = json
        end
 
        # Avatar image url for this user.
-       fun avatar_url: String do return json["avatar_url"].to_s
+       fun avatar_url: String do return json["avatar_url"].as(String)
+
+       # Set avatar url.
+       fun avatar_url=(url: String) do json["avatar_url"] = url
 end
 
 # A Github repository.
@@ -390,17 +396,21 @@ class Repo
 
        # Init `self` from a `json` object.
        init from_json(api: GithubAPI, json: JsonObject) do
-               init(api, json["full_name"].to_s)
+               init(api, json["full_name"].as(String))
                self.json = json
        end
 
        # Repo short name on Github.
-       fun name: String do return json["name"].to_s
+       fun name: String do return json["name"].as(String)
+
+       # Set repo full name
+       fun name=(name: String) do json["name"] = name
 
        # Get the repo owner.
-       fun owner: User do
-               return new User.from_json(api, json["owner"].as(JsonObject))
-       end
+       fun owner: User do return new User.from_json(api, json["owner"].as(JsonObject))
+
+       # Set repo owner
+       fun owner=(owner: User) do json["owner"] = owner.json
 
        # List of branches associated with their names.
        fun branches: Map[String, Branch] do
@@ -410,7 +420,7 @@ class Repo
                if not array isa JsonArray then return res
                for obj in array do
                        if not obj isa JsonObject then continue
-                       var name = obj["name"].to_s
+                       var name = obj["name"].as(String)
                        res[name] = new Branch.from_json(api, self, obj)
                end
                return res
@@ -470,7 +480,7 @@ class Repo
                if not array isa JsonArray then return res
                for obj in array do
                        if not obj isa JsonObject then continue
-                       var name = obj["name"].to_s
+                       var name = obj["name"].as(String)
                        res[name] = new Label.from_json(api, self, obj)
                end
                return res
@@ -528,11 +538,14 @@ class Repo
 
        # Repo default branch.
        fun default_branch: Branch do
-               var name = json["default_branch"].to_s
+               var name = json["default_branch"].as(String)
                var branch = api.load_branch(self, name)
                assert branch isa Branch
                return branch
        end
+
+       # Set the default branch
+       fun default_branch=(branch: Branch) do json["default_branch"] = branch.json
 end
 
 # A `RepoEntity` is something contained in a `Repo`.
@@ -564,14 +577,15 @@ class Branch
        var name: String
 
        redef init from_json(api, repo, json) do
-               self.name = json["name"].to_s
+               self.name = json["name"].as(String)
                super
        end
 
        # Get the last commit of `self`.
-       fun commit: Commit do
-               return new Commit.from_json(api, repo, json["commit"].as(JsonObject))
-       end
+       fun commit: Commit do return new Commit.from_json(api, repo, json["commit"].as(JsonObject))
+
+       # Set the last commit
+       fun commit=(commit: Commit) do json["commit"] = commit.json
 
        # List all commits in `self`.
        #
@@ -609,56 +623,79 @@ class Commit
        var sha: String
 
        redef init from_json(api, repo, json) do
-               self.sha = json["sha"].to_s
+               self.sha = json["sha"].as(String)
                super
        end
 
        # Parent commits of `self`.
        fun parents: Array[Commit] do
                var res = new Array[Commit]
-               var parents = json["parents"]
+               var parents = json.get_or_null("parents")
                if not parents isa JsonArray then return res
                for obj in parents do
                        if not obj isa JsonObject then continue
-                       res.add(api.load_commit(repo, obj["sha"].to_s).as(not null))
+                       res.add(api.load_commit(repo, obj["sha"].as(String)).as(not null))
                end
                return res
        end
 
+       # Set parent commits.
+       fun parents=(parents: Array[Commit]) do
+               var res = new JsonArray
+               for parent in parents do res.add parent.json
+               json["parents"] = res
+       end
+
        # Author of the commit.
        fun author: nullable User do
-               if not json.has_key("author") then return null
-               var user = json["author"]
-               if not user isa JsonObject then return null
-               return new User.from_json(api, user)
+               var user = json.get_or_null("author")
+               if user isa JsonObject then return new User.from_json(api, user)
+               return null
+       end
+
+       # Set commit author.
+       fun author=(user: nullable User) do
+               if user == null then
+                       json["author"] = null
+               else
+                       json["author"] = user.json
+               end
        end
 
        # Committer of the commit.
        fun committer: nullable User do
-               if not json.has_key("committer") then return null
-               var user = json["author"]
-               if not user isa JsonObject then return null
-               return new User.from_json(api, user)
+               var user = json.get_or_null("author")
+               if user isa JsonObject then return new User.from_json(api, user)
+               return null
+       end
+
+       # Set commit committer.
+       fun committer=(user: nullable User) do
+               if user == null then
+                       json["committer"] = null
+               else
+                       json["committer"] = user.json
+               end
        end
 
        # Authoring date as ISODate.
        fun author_date: ISODate do
                var commit = json["commit"].as(JsonObject)
                var author = commit["author"].as(JsonObject)
-               return new ISODate.from_string(author["date"].to_s)
+               return new ISODate.from_string(author["date"].as(String))
        end
 
        # Commit date as ISODate.
        fun commit_date: ISODate do
                var commit = json["commit"].as(JsonObject)
                var author = commit["committer"].as(JsonObject)
-               return new ISODate.from_string(author["date"].to_s)
+               return new ISODate.from_string(author["date"].as(String))
        end
 
        # List files staged in this commit.
        fun files: Array[GithubFile] do
                var res = new Array[GithubFile]
-               var files = json["files"]
+               var files = json.get_or_null("files")
                if not files isa JsonArray then return res
                for obj in files do
                        res.add(new GithubFile(obj.as(JsonObject)))
@@ -666,8 +703,15 @@ class Commit
                return res
        end
 
+       # Set commit files.
+       fun files=(files: Array[GithubFile]) do
+               var res = new JsonArray
+               for file in files do res.add file.json
+               json["files"] = res
+       end
+
        # Commit message.
-       fun message: String do return json["commit"].as(JsonObject)["message"].to_s
+       fun message: String do return json["commit"].as(JsonObject)["message"].as(String)
 end
 
 # A Github issue.
@@ -689,43 +733,72 @@ class Issue
        end
 
        # Issue title.
-       fun title: String do return json["title"].to_s
+       fun title: String do return json["title"].as(String)
+
+       # Set issue title
+       fun title=(title: String) do json["title"] = title
 
        # User that created this issue.
-       fun user: User do
-               return new User.from_json(api, json["user"].as(JsonObject))
-       end
+       fun user: User do return new User.from_json(api, json["user"].as(JsonObject))
+
+       # Set issue creator.
+       fun user=(user: User) do json["user"] = user.json
 
        # List of labels on this issue associated to their names.
        fun labels: Map[String, Label] do
                var res = new HashMap[String, Label]
-               if not json.has_key("labels") then return res
-               for obj in json["labels"].as(JsonArray) do
+               var lbls = json.get_or_null("labels")
+               if not lbls isa JsonArray then return res
+               for obj in lbls do
                        if not obj isa JsonObject then continue
-                       var name = obj["name"].to_s
+                       var name = obj["name"].as(String)
                        res[name] = new Label.from_json(api, repo, obj)
                end
                return res
        end
 
        # State of the issue on Github.
-       fun state: String do return json["state"].to_s
+       fun state: String do return json["state"].as(String)
+
+       # Set the state of this issue.
+       fun state=(state: String) do json["state"] = state
 
        # Is the issue locked?
        fun locked: Bool do return json["locked"].as(Bool)
 
+       # Set issue locked state.
+       fun locked=(locked: Bool) do json["locked"] = locked
+
        # Assigned `User` (if any).
        fun assignee: nullable User do
-               var assignee = json["assignee"]
-               if not assignee isa JsonObject then return null
-               return new User.from_json(api, assignee)
+               var assignee = json.get_or_null("assignee")
+               if assignee isa JsonObject then return new User.from_json(api, assignee)
+               return null
+       end
+
+       # Set issue assignee.
+       fun assignee=(user: nullable User) do
+               if user == null then
+                       json["assignee"] = null
+               else
+                       json["assignee"] = user.json
+               end
        end
 
        # `Milestone` (if any).
        fun milestone: nullable Milestone do
-               var milestone = json["milestone"]
-               if not milestone isa JsonObject then return null
-               return new Milestone.from_json(api, repo, milestone)
+               var milestone = json.get_or_null("milestone")
+               if milestone isa JsonObject then return new Milestone.from_json(api, repo, milestone)
+               return null
+       end
+
+       # Set issue milestone.
+       fun milestone=(milestone: nullable Milestone) do
+               if milestone == null then
+                       json["milestone"] = null
+               else
+                       json["milestone"] = milestone.json
+               end
        end
 
        # List of comments made on this issue.
@@ -750,37 +823,66 @@ class Issue
        end
 
        # Number of comments on this issue.
-       fun comments_count: Int do return json["comments"].to_s.to_i
+       fun comments_count: Int do return json["comments"].as(Int)
 
        # Creation time in ISODate format.
-       fun created_at: ISODate do
-               return new ISODate.from_string(json["created_at"].to_s)
+       fun created_at: ISODate do return new ISODate.from_string(json["created_at"].as(String))
+
+       # Set issue creation time.
+       fun created_at=(created_at: nullable ISODate) do
+               if created_at == null then
+                       json["created_at"] = null
+               else
+                       json["created_at"] = created_at.to_s
+               end
        end
 
        # Last update time in ISODate format (if any).
        fun updated_at: nullable ISODate do
-               var res = json["updated_at"]
-               if res == null then return null
-               return new ISODate.from_string(res.to_s)
+               var res = json.get_or_null("updated_at")
+               if res isa String then return new ISODate.from_string(res)
+               return null
+       end
+
+       # Set issue last update time.
+       fun updated_at=(updated_at: nullable ISODate) do
+               if updated_at == null then
+                       json["updated_at"] = null
+               else
+                       json["updated_at"] = updated_at.to_s
+               end
        end
 
        # Close time in ISODate format (if any).
        fun closed_at: nullable ISODate do
-               var res = json["closed_at"]
-               if res == null then return null
-               return new ISODate.from_string(res.to_s)
+               var res = json.get_or_null("closed_at")
+               if res isa String then return new ISODate.from_string(res)
+               return null
+       end
+
+       # Set issue close time.
+       fun closed_at=(closed_at: nullable ISODate) do
+               if closed_at == null then
+                       json["closed_at"] = null
+               else
+                       json["closed_at"] = closed_at.to_s
+               end
        end
 
        # TODO link to pull request
 
        # Full description of the issue.
-       fun body: String  do return json["body"].to_s
+       fun body: String do return json["body"].as(String)
+
+       # Set description body
+       fun body=(body: String) do json["body"] = body
 
        # List of events on this issue.
        fun events: Array[IssueEvent] do
                var res = new Array[IssueEvent]
                var page = 1
-               var array = api.get("{key}/events?page={page}").as(JsonArray)
+               var array = api.get("{key}/events?page={page}")
+               if not array isa JsonArray then return res
                while not array.is_empty do
                        for obj in array do
                                if not obj isa JsonObject then continue
@@ -794,10 +896,22 @@ class Issue
 
        # User that closed this issue (if any).
        fun closed_by: nullable User do
-               var closer = json["closed_by"]
-               if not closer isa JsonObject then return null
-               return new User.from_json(api, closer)
+               var closer = json.get_or_null("closed_by")
+               if closer isa JsonObject then return new User.from_json(api, closer)
+               return null
+       end
+
+       # Set user that closed the issue.
+       fun closed_by=(user: nullable User) do
+               if user == null then
+                       json["closed_by"] = null
+               else
+                       json["closed_by"] = user.json
+               end
        end
+
+       # Is this issue linked to a pull request?
+       fun is_pull_request: Bool do return json.has_key("pull_request")
 end
 
 # A Github pull request.
@@ -813,16 +927,31 @@ class PullRequest
 
        # Merge time in ISODate format (if any).
        fun merged_at: nullable ISODate do
-               var res = json["merged_at"]
-               if res == null then return null
-               return new ISODate.from_string(res.to_s)
+               var res = json.get_or_null("merged_at")
+               if res isa String then return new ISODate.from_string(res)
+               return null
+       end
+
+       # Set pull request merge time.
+       fun merged_at=(merged_at: nullable ISODate) do
+               if merged_at == null then
+                       json["merged_at"] = null
+               else
+                       json["merged_at"] = merged_at.to_s
+               end
        end
 
        # Merge commit SHA.
-       fun merge_commit_sha: String do return json["merge_commit_sha"].to_s
+       fun merge_commit_sha: String do return json["merge_commit_sha"].as(String)
+
+       # Set merge_commit_sha
+       fun merge_commit_sha=(sha: String) do json["merge_commit_sha"] = sha
 
        # Count of comments made on the pull request diff.
-       fun review_comments: Int do return json["review_comments"].to_s.to_i
+       fun review_comments: Int do return json["review_comments"].as(Int)
+
+       # Set review_comments
+       fun review_comments=(count: Int) do json["review_comments"] = count
 
        # Pull request head (can be a commit SHA or a branch name).
        fun head: PullRef do
@@ -830,41 +959,77 @@ class PullRequest
                return new PullRef(api, json)
        end
 
+       # Set head
+       fun head=(head: PullRef) do json["head"] = head.json
+
        # Pull request base (can be a commit SHA or a branch name).
        fun base: PullRef do
                var json = json["base"].as(JsonObject)
                return new PullRef(api, json)
        end
 
+       # Set base
+       fun base=(base: PullRef) do json["base"] = base.json
+
        # Is this pull request merged?
        fun merged: Bool do return json["merged"].as(Bool)
 
+       # Set merged
+       fun merged=(merged: Bool) do json["merged"] = merged
+
        # Is this pull request mergeable?
        fun mergeable: Bool do return json["mergeable"].as(Bool)
 
+       # Set mergeable
+       fun mergeable=(mergeable: Bool) do json["mergeable"] = mergeable
+
        # Mergeable state of this pull request.
        #
        # See <https://developer.github.com/v3/pulls/#list-pull-requests>.
-       fun mergeable_state: Int do return json["mergeable_state"].to_s.to_i
+       fun mergeable_state: Int do return json["mergeable_state"].as(Int)
+
+       # Set mergeable_state
+       fun mergeable_state=(mergeable_state: Int) do json["mergeable_state"] = mergeable_state
 
        # User that merged this pull request (if any).
        fun merged_by: nullable User do
-               var merger = json["merged_by"]
-               if not merger isa JsonObject then return null
-               return new User.from_json(api, merger)
+               var merger = json.get_or_null("merged_by")
+               if merger isa JsonObject then return new User.from_json(api, merger)
+               return null
+       end
+
+       # Set merged_by.
+       fun merged_by=(merged_by: nullable User) do
+               if merged_by == null then
+                       json["merged_by"] = null
+               else
+                       json["merged_by"] = merged_by.json
+               end
        end
 
        # Count of commits in this pull request.
-       fun commits: Int do return json["commits"].to_s.to_i
+       fun commits: Int do return json["commits"].as(Int)
+
+       # Set commits
+       fun commits=(commits: Int) do json["commits"] = commits
 
        # Added line count.
-       fun additions: Int do return json["additions"].to_s.to_i
+       fun additions: Int do return json["additions"].as(Int)
+
+       # Set additions
+       fun additions=(additions: Int) do json["additions"] = additions
 
        # Deleted line count.
-       fun deletions: Int do return json["deletions"].to_s.to_i
+       fun deletions: Int do return json["deletions"].as(Int)
+
+       # Set deletions
+       fun deletions=(deletions: Int) do json["deletions"] = deletions
 
        # Changed files count.
-       fun changed_files: Int do return json["changed_files"].to_s.to_i
+       fun changed_files: Int do return json["changed_files"].as(Int)
+
+       # Set changed_files
+       fun changed_files=(changed_files: Int) do json["changed_files"] = changed_files
 end
 
 # A pull request reference (used for head and base).
@@ -877,23 +1042,38 @@ class PullRef
        var json: JsonObject
 
        # Label pointed by `self`.
-       fun labl: String do return json["label"].to_s
+       fun labl: String do return json["label"].as(String)
+
+       # Set labl
+       fun labl=(labl: String) do json["label"] = labl
 
        # Reference pointed by `self`.
-       fun ref: String do return json["ref"].to_s
+       fun ref: String do return json["ref"].as(String)
+
+       # Set ref
+       fun ref=(ref: String) do json["ref"] = ref
 
        # Commit SHA pointed by `self`.
-       fun sha: String do return json["sha"].to_s
+       fun sha: String do return json["sha"].as(String)
+
+       # Set sha
+       fun sha=(sha: String) do json["sha"] = sha
 
        # User pointed by `self`.
        fun user: User do
                return new User.from_json(api, json["user"].as(JsonObject))
        end
 
+       # Set user
+       fun user=(user: User) do json["user"] = user.json
+
        # Repo pointed by `self`.
        fun repo: Repo do
                return new Repo.from_json(api, json["repo"].as(JsonObject))
        end
+
+       # Set repo
+       fun repo=(repo: Repo) do json["repo"] = repo.json
 end
 
 # A Github label.
@@ -910,12 +1090,15 @@ class Label
        var name: String
 
        redef init from_json(api, repo, json) do
-               self.name = json["name"].to_s
+               self.name = json["name"].as(String)
                super
        end
 
        # Label color code.
-       fun color: String do return json["color"].to_s
+       fun color: String do return json["color"].as(String)
+
+       # Set color
+       fun color=(color: String) do json["color"] = color
 end
 
 # A Github milestone.
@@ -937,49 +1120,97 @@ class Milestone
        end
 
        # Milestone title.
-       fun title: String do return json["title"].to_s
+       fun title: String do return json["title"].as(String)
+
+       # Set title
+       fun title=(title: String) do json["title"] = title
 
        # Milestone long description.
-       fun description: String do return json["description"].to_s
+       fun description: String do return json["description"].as(String)
+
+       # Set description
+       fun description=(description: String) do json["description"] = description
 
        # Count of opened issues linked to this milestone.
-       fun open_issues: Int do return json["open_issues"].to_s.to_i
+       fun open_issues: Int do return json["open_issues"].as(Int)
+
+       # Set open_issues
+       fun open_issues=(open_issues: Int) do json["open_issues"] = open_issues
 
        # Count of closed issues linked to this milestone.
-       fun closed_issues: Int do return json["closed_issues"].to_s.to_i
+       fun closed_issues: Int do return json["closed_issues"].as(Int)
+
+       # Set closed_issues
+       fun closed_issues=(closed_issues: Int) do json["closed_issues"] = closed_issues
 
        # Milestone state.
-       fun state: String do return json["state"].to_s
+       fun state: String do return json["state"].as(String)
+
+       # Set state
+       fun state=(state: String) do json["state"] = state
 
        # Creation time in ISODate format.
        fun created_at: ISODate do
-               return new ISODate.from_string(json["created_at"].to_s)
+               return new ISODate.from_string(json["created_at"].as(String))
        end
 
+       # Set created_at
+       fun created_at=(created_at: ISODate) do json["created_at"] = created_at.to_s
+
        # User that created this milestone.
        fun creator: User do
                return new User.from_json(api, json["creator"].as(JsonObject))
        end
 
+       # Set creator
+       fun creator=(creator: User) do json["creator"] = creator.json
+
        # Due time in ISODate format (if any).
        fun due_on: nullable ISODate do
-               var res = json["updated_at"]
-               if res == null then return null
-               return new ISODate.from_string(res.to_s)
+               var res = json.get_or_null("updated_at")
+               if res isa String then return new ISODate.from_string(res)
+               return null
+       end
+
+       # Set due_on.
+       fun due_on=(due_on: nullable ISODate) do
+               if due_on == null then
+                       json["due_on"] = null
+               else
+                       json["due_on"] = due_on.to_s
+               end
        end
 
        # Update time in ISODate format (if any).
        fun updated_at: nullable ISODate do
-               var res = json["updated_at"]
-               if res == null then return null
-               return new ISODate.from_string(res.to_s)
+               var res = json.get_or_null("updated_at")
+               if res isa String then return new ISODate.from_string(res)
+               return null
+       end
+
+       # Set updated_at.
+       fun updated_at=(updated_at: nullable ISODate) do
+               if updated_at == null then
+                       json["updated_at"] = null
+               else
+                       json["updated_at"] = updated_at.to_s
+               end
        end
 
        # Close time in ISODate format (if any).
        fun closed_at: nullable ISODate do
-               var res = json["closed_at"]
-               if res == null then return null
-               return new ISODate.from_string(res.to_s)
+               var res = json.get_or_null("closed_at")
+               if res isa String then return new ISODate.from_string(res)
+               return null
+       end
+
+       # Set closed_at.
+       fun closed_at=(closed_at: nullable ISODate) do
+               if closed_at == null then
+                       json["closed_at"] = null
+               else
+                       json["closed_at"] = closed_at.to_s
+               end
        end
 end
 
@@ -1006,19 +1237,38 @@ abstract class Comment
                return new User.from_json(api, json["user"].as(JsonObject))
        end
 
+       # Set user
+       fun user=(user: User) do json["user"] = user.json
+
        # Creation time in ISODate format.
        fun created_at: ISODate do
-               return new ISODate.from_string(json["created_at"].to_s)
+               return new ISODate.from_string(json["created_at"].as(String))
        end
 
+       # Set created_at
+       fun created_at=(created_at: ISODate) do json["created_at"] = created_at.to_s
+
        # Last update time in ISODate format (if any).
        fun updated_at: nullable ISODate do
-               if not json.has_key("updated_at") then return null
-               return new ISODate.from_string(json["updated_at"].to_s)
+               var res = json.get_or_null("updated_at")
+               if res isa String then return new ISODate.from_string(res)
+               return null
+       end
+
+       # Set updated_at.
+       fun updated_at=(updated_at: nullable ISODate) do
+               if updated_at == null then
+                       json["updated_at"] = null
+               else
+                       json["updated_at"] = updated_at.to_s
+               end
        end
 
        # Comment body text.
-       fun body: String do return json["body"].to_s
+       fun body: String do return json["body"].as(String)
+
+       # Set body
+       fun body=(body: String) do json["body"] = body
 
        # Does the comment contain an acknowledgement (+1)
        fun is_ack: Bool
@@ -1035,27 +1285,37 @@ class CommitComment
 
        # Commented commit.
        fun commit: Commit do
-               return api.load_commit(repo, json["commit_id"].to_s).as(not null)
+               return api.load_commit(repo, json["commit_id"].as(String)).as(not null)
        end
 
+       # Set commit
+       fun commit=(commit: Commit) do json["commit_id"] = commit.json
+
        # Position of the comment on the line.
        fun position: nullable String do
-               if not json.has_key("position") then return null
-               var res = json["position"]
-               if res == null then return null
-               return res.to_s
+               var res = json.get_or_null("position")
+               if res isa String then return res
+               return null
        end
 
+       # Set position.
+       fun position=(position: nullable String) do json["position"] = position
+
        # Line of the comment.
        fun line: nullable String do
-               if not json.has_key("line") then return null
-               var res = json["line"]
-               if res == null then return null
-               return res.to_s
+               var res = json.get_or_null("line")
+               if res isa String then return res
+               return null
        end
 
+       # Set line.
+       fun line=(line: nullable String) do json["line"] = line
+
        # Path of the commented file.
-       fun path: String do return json["path"].to_s
+       fun path: String do return json["path"].as(String)
+
+       # Set path.
+       fun path=(path: String) do json["path"] = path
 end
 
 # Comments made on Github issue and pull request pages.
@@ -1075,7 +1335,10 @@ class IssueComment
        end
 
        # Link to the issue document on API.
-       fun issue_url: String do return json["issue_url"].to_s
+       fun issue_url: String do return json["issue_url"].as(String)
+
+       # Set issue_url.
+       fun issue_url=(issue_url: String) do json["issue_url"] = issue_url
 end
 
 # Comments made on Github pull request diffs.
@@ -1095,25 +1358,46 @@ class ReviewComment
        end
 
        # Link to the pull request on API.
-       fun pull_request_url: String do return json["pull_request_url"].to_s
+       fun pull_request_url: String do return json["pull_request_url"].as(String)
+
+       # Set pull_request_url.
+       fun pull_request_url=(pull_request_url: String) do json["pull_request_url"] = pull_request_url
 
        # Diff hunk.
-       fun diff_hunk: String do return json["diff_hunk"].to_s
+       fun diff_hunk: String do return json["diff_hunk"].as(String)
+
+       # Set diff_hunk.
+       fun diff_hunk=(diff_hunk: String) do json["diff_hunk"] = diff_hunk
 
        # Path of commented file.
-       fun path: String do return json["path"].to_s
+       fun path: String do return json["path"].as(String)
+
+       # Set path.
+       fun path=(path: String) do json["path"] = path
 
        # Position of the comment on the file.
-       fun position: Int do return json["position"].to_s.to_i
+       fun position: Int do return json["position"].as(Int)
+
+       # Set position.
+       fun position=(position: Int) do json["position"] = position
 
        # Original position in the diff.
-       fun original_position: Int do return json["original_position"].to_s.to_i
+       fun original_position: Int do return json["original_position"].as(Int)
+
+       # Set original_position.
+       fun original_position=(original_position: Int) do json["original_position"] = original_position
 
        # Commit referenced by this comment.
-       fun commit_id: String do return json["commit_id"].to_s
+       fun commit_id: String do return json["commit_id"].as(String)
+
+       # Set commit_id.
+       fun commit_id=(commit_id: String) do json["commit_id"] = commit_id
 
        # Original commit id.
-       fun original_commit_id: String do return json["original_commit_id"].to_s
+       fun original_commit_id: String do return json["original_commit_id"].as(String)
+
+       # Set original_commit_id.
+       fun original_commit_id=(commit_id: String) do json["original_commit_id"] = commit_id
 end
 
 # An event that occurs on a Github `Issue`.
@@ -1139,52 +1423,103 @@ class IssueEvent
                return new Issue.from_json(api, repo, json["issue"].as(JsonObject))
        end
 
+       # Set issue.
+       fun issue=(issue: Issue) do json["issue"] = issue.json
+
        # User that initiated the event.
        fun actor: User do
                return new User.from_json(api, json["actor"].as(JsonObject))
        end
 
+       # Set actor.
+       fun actor=(actor: User) do json["actor"] = actor.json
+
        # Creation time in ISODate format.
        fun created_at: ISODate do
-               return new ISODate.from_string(json["created_at"].to_s)
+               return new ISODate.from_string(json["created_at"].as(String))
        end
 
+       # Set created_at.
+       fun created_at=(created_at: ISODate) do json["created_at"] = created_at.to_s
+
        # Event descriptor.
-       fun event: String do return json["event"].to_s
+       fun event: String do return json["event"].as(String)
+
+       # Set event.
+       fun event=(event: String) do json["event"] = event
 
        # Commit linked to this event (if any).
        fun commit_id: nullable String do
-               var res = json["commit_id"]
-               if res == null then return null
-               return res.to_s
+               var res = json.get_or_null("commit_id")
+               if res isa String then return res
+               return null
        end
 
+       # Set commit_id.
+       fun commit_id=(commit_id: nullable String) do json["commit_id"] = commit_id
+
        # Label linked to this event (if any).
        fun labl: nullable Label do
-               var res = json["label"]
-               if not res isa JsonObject then return null
-               return new Label.from_json(api, repo, res)
+               var res = json.get_or_null("label")
+               if res isa JsonObject then return new Label.from_json(api, repo, res)
+               return null
+       end
+
+       # Set labl.
+       fun labl=(labl: nullable Label) do
+               if labl == null then
+                       json["labl"] = null
+               else
+                       json["labl"] = labl.json
+               end
        end
 
        # User linked to this event (if any).
        fun assignee: nullable User do
-               var res = json["assignee"]
-               if not res isa JsonObject then return null
-               return new User.from_json(api, res)
+               var res = json.get_or_null("assignee")
+               if res isa JsonObject then return new User.from_json(api, res)
+               return null
+       end
+
+       # Set assignee.
+       fun assignee=(assignee: nullable User) do
+               if assignee == null then
+                       json["assignee"] = null
+               else
+                       json["assignee"] = assignee.json
+               end
        end
 
        # Milestone linked to this event (if any).
        fun milestone: nullable Milestone do
-               var res = json["milestone"]
-               if not res isa JsonObject then return null
-               return new Milestone.from_json(api, repo, res)
+               var res = json.get_or_null("milestone")
+               if res isa JsonObject then return new Milestone.from_json(api, repo, res)
+               return null
+       end
+
+       # Set milestone.
+       fun milestone=(milestone: nullable User) do
+               if milestone == null then
+                       json["milestone"] = null
+               else
+                       json["milestone"] = milestone.json
+               end
        end
 
        # Rename linked to this event (if any).
        fun rename: nullable RenameAction do
-               var res = json["rename"]
-               if res == null then return null
-               return new RenameAction(res.as(JsonObject))
+               var res = json.get_or_null("rename")
+               if res isa JsonObject then return new RenameAction(res)
+               return null
+       end
+
+       # Set rename.
+       fun rename=(rename: nullable User) do
+               if rename == null then
+                       json["rename"] = null
+               else
+                       json["rename"] = rename.json
+               end
        end
 end
 
@@ -1195,10 +1530,16 @@ class RenameAction
        var json: JsonObject
 
        # Name before renaming.
-       fun from: String do return json["from"].to_s
+       fun from: String do return json["from"].as(String)
+
+       # Set from.
+       fun from=(from: String) do json["from"] = from
 
        # Name after renaming.
-       fun to: String do return json["to"].to_s
+       fun to: String do return json["to"].as(String)
+
+       # Set to.
+       fun to=(to: String) do json["to"] = to
 end
 
 # Contributors list with additions, deletions, and commit counts.
@@ -1228,12 +1569,21 @@ class ContributorStats
                return new User.from_json(api, json["author"].as(JsonObject))
        end
 
+       # Set author.
+       fun author=(author: User) do json["author"] = author.json
+
        # Total number of commit.
-       fun total: Int do return json["total"].to_s.to_i
+       fun total: Int do return json["total"].as(Int)
+
+       # Set total.
+       fun total=(total: Int) do json["total"] = total
 
        # Are of weeks of activity with detailed statistics.
        fun weeks: JsonArray do return json["weeks"].as(JsonArray)
 
+       # Set weeks.
+       fun weeks=(weeks: JsonArray) do json["weeks"] = weeks
+
        # ContributorStats can be compared on the total amount of commits.
        redef fun <(o) do return total < o.total
 end
@@ -1247,5 +1597,8 @@ class GithubFile
        var json: JsonObject
 
        # File name.
-       fun filename: String do return json["filename"].to_s
+       fun filename: String do return json["filename"].as(String)
+
+       # Set filename.
+       fun filename=(filename: String) do json["filename"] = filename
 end
index b6e5af3..df7c8c3 100644 (file)
@@ -39,12 +39,18 @@ class GithubEvent
        end
 
        # Action performed by the event.
-       fun action: String do return json["action"].to_s
+       fun action: String do return json["action"].as(String)
+
+       # Set action.
+       fun action=(action: String) do json["action"] = action
 
        # Repo where this event occured.
        fun repo: Repo do
                return new Repo.from_json(api, json["repository"].as(JsonObject))
        end
+
+       # Set repo.
+       fun repo=(repo: Repo) do json["repository"] = repo.json
 end
 
 # Triggered when a commit comment is created.
@@ -55,6 +61,9 @@ class CommitCommentEvent
        fun comment: CommitComment do
                return new CommitComment.from_json(api, repo, json["comment"].as(JsonObject))
        end
+
+       # Set comment.
+       fun comment=(comment: CommitComment) do json["comment"] = comment.json
 end
 
 # Triggered when a repository, branch, or tag is created.
@@ -64,16 +73,28 @@ class CreateEvent
        # Oject type that was created.
        #
        # Can be one of `repository`, `branch`, or `tag`.
-       fun ref_type: String do return json["ref_type"].to_s
+       fun ref_type: String do return json["ref_type"].as(String)
+
+       # Set ref_type.
+       fun ref_type=(ref_type: String) do json["ref_type"] = ref_type
 
        # Git ref (or null if only a repository was created).
-       fun ref: String do return json["ref"].to_s
+       fun ref: String do return json["ref"].as(String)
+
+       # Set ref.
+       fun ref=(ref: String) do json["ref"] = ref
 
        # Name of the repo's default branch (usually master).
-       fun master_branch: String do return json["master_branch"].to_s
+       fun master_branch: String do return json["master_branch"].as(String)
+
+       # Set master_branch.
+       fun master_branch=(master_branch: String) do json["master_branch"] = master_branch
 
        # Repo's current description.
-       fun description: String do return json["description"].to_s
+       fun description: String do return json["description"].as(String)
+
+       # Set description.
+       fun description=(description: String) do json["description"] = description
 end
 
 # Triggered when a branch or a tag is deleted.
@@ -83,10 +104,16 @@ class DeleteEvent
        # Object type that was deleted.
        #
        # Can be one of `repository`, `branch`, or `tag`.
-       fun ref_type: String do return json["ref_type"].to_s
+       fun ref_type: String do return json["ref_type"].as(String)
+
+       # Set ref_type.
+       fun ref_type=(ref_type: String) do json["ref_type"] = ref_type
 
        # Git ref (or null if only a repository was deleted).
-       fun ref: String do return json["ref"].to_s
+       fun ref: String do return json["ref"].as(String)
+
+       # Set ref.
+       fun ref=(ref: String) do json["ref"] = ref
 end
 
 # Triggered when a new snapshot is deployed.
@@ -96,29 +123,44 @@ class DeploymentEvent
        super GithubEvent
 
        # Commit SHA for which this deployment was created.
-       fun sha: String do return json["sha"].to_s
+       fun sha: String do return json["sha"].as(String)
+
+       # Set sha.
+       fun sha=(sha: String) do json["sha"] = sha
 
        # Name of repository for this deployment, formatted as :owner/:repo.
-       fun name: String do return json["name"].to_s
+       fun name: String do return json["name"].as(String)
+
+       # Set name.
+       fun name=(name: String) do json["name"] = name
 
        # Optional extra information for this deployment.
        fun payload: nullable String do
-               if not json.has_key("payload") then return null
-               return json["payload"].to_s
+               var res = json.get_or_null("payload")
+               if res isa String then return res else return null
        end
 
+       # Set payload.
+       fun payload=(payload: nullable String) do json["payload"] = payload
+
        # Optional environment to deploy to.
        # Default: "production"
        fun environment: nullable String do
-               if not json.has_key("environment") then return null
-               return json["environment"].to_s
+               var res = json.get_or_null("environment")
+               if res isa String then return res else return null
        end
 
+       # Set environment.
+       fun environment=(environment: nullable String) do json["environment"] = environment
+
        # Optional human-readable description added to the deployment.
        fun description: nullable String do
-               if not json.has_key("description") then return null
-               return json["description"].to_s
+               var res = json.get_or_null("description")
+               if res isa String then return res else return null
        end
+
+       # Set description.
+       fun description=(description: nullable String) do json["description"] = description
 end
 
 # Triggered when a deployement's status changes.
@@ -128,22 +170,31 @@ class DeploymentStatusEvent
        # New deployment state.
        #
        # Can be `pending`, `success`, `failure`, or `error`.
-       fun state: String do return json["state"].to_s
+       fun state: String do return json["state"].as(String)
 
        # Optional link added to the status.
        fun target_url: nullable String do
-               if not json.has_key("target_url") then return null
-               return json["target_url"].to_s
+               var res = json.get_or_null("target_url")
+               if res isa String then return res else return null
        end
 
+       # Set target_url.
+       fun target_url=(target_url: nullable String) do json["target_url"] = target_url
+
        # Deployment hash that this status is associated with.
-       fun deployment: String do return json["deployment"].to_s
+       fun deployment: String do return json["deployment"].as(String)
+
+       # Set deployment.
+       fun deployment=(deployment: String) do json["deployment"] = deployment
 
        # Optional human-readable description added to the status.
        fun description: nullable String do
-               if not json.has_key("description") then return null
-               return json["description"].to_s
+               var res = json.get_or_null("description")
+               if res isa String then return res else return null
        end
+
+       # Set description.
+       fun description=(description: nullable String) do json["description"] = description
 end
 
 # Triggered when a user forks a repository.
@@ -152,6 +203,9 @@ class ForkEvent
 
        # Created repository.
        fun forkee: Repo do return new Repo.from_json(api, json["forkee"].as(JsonObject))
+
+       # Set forkee.
+       fun forkee=(forkee: Repo) do json["forkee"] = forkee.json
 end
 
 # Triggered when an issue comment is created.
@@ -163,10 +217,16 @@ class IssueCommentEvent
                return new Issue.from_json(api, repo, json["issue"].as(JsonObject))
        end
 
+       # Set issue.
+       fun issue=(issue: Issue) do json["issue"] = issue.json
+
        # The `Comment` itself.
        fun comment: IssueComment do
                return new IssueComment.from_json(api, repo, json["comment"].as(JsonObject))
        end
+
+       # Set comment.
+       fun comment=(comment: IssueComment) do json["comment"] = comment.json
 end
 
 # Triggered when an event occurs on an issue.
@@ -179,16 +239,37 @@ class IssuesEvent
        # The `Issue` itself.
        fun issue: Issue do return new Issue.from_json(api, repo, json["issue"].as(JsonObject))
 
+       # Set issue.
+       fun issue=(issue: Issue) do json["issue"] = issue.json
+
        # Optional `Label` that was added or removed from the issue.
        fun lbl: nullable Label do
-               if not json.has_key("label") then return null
-               return new Label.from_json(api, repo, json["label"].as(JsonObject))
+               var res = json.get_or_null("label")
+               if res isa JsonObject then return new Label.from_json(api, repo, res) else return null
+       end
+
+       # Set lbl.
+       fun lbl=(lbl: nullable Label) do
+               if lbl == null then
+                       json["lbl"] = null
+               else
+                       json["lbl"] = lbl.json
+               end
        end
 
        # Optional `User` that was assigned or unassigned from the issue.
        fun assignee: nullable User do
-               if not json.has_key("assignee") then return null
-               return new User.from_json(api, json["assignee"].as(JsonObject))
+               var res = json.get_or_null("assignee")
+               if res isa JsonObject then return new User.from_json(api, res) else return null
+       end
+
+       # Set assignee.
+       fun assignee=(assignee: nullable User) do
+               if assignee == null then
+                       json["assignee"] = null
+               else
+                       json["assignee"] = assignee.json
+               end
        end
 end
 
@@ -198,6 +279,9 @@ class MemberEvent
 
        # `User` that was added.
        fun member: User do return new User.from_json(api, json["member"].as(JsonObject))
+
+       # Set member.
+       fun member=(member: User) do json["member"] = member.json
 end
 
 # Triggered when an event occurs on a pull request.
@@ -210,10 +294,16 @@ class PullRequestEvent
        # The pull request number.
        fun number: Int do return json["number"].as(Int)
 
+       # Set number.
+       fun number=(number: Int) do json["number"] = number
+
        # The `PullRequest` itself.
        fun pull: PullRequest do
                return new PullRequest.from_json(api, repo, json["pull_request"].as(JsonObject))
        end
+
+       # Set pull.
+       fun pull=(pull: PullRequest) do json["pull_request"] = pull.json
 end
 
 # Triggered when a comment is created on a pull request diff.
@@ -225,10 +315,16 @@ class PullRequestReviewCommentEvent
                return new ReviewComment.from_json(api, repo, json["comment"].as(JsonObject))
        end
 
+       # Set comment.
+       fun comment=(comment: ReviewComment) do json["comment"] = comment.json
+
        # `PullRequest` the `comment` belongs to.
        fun pull: PullRequest do
                return new PullRequest.from_json(api, repo, json["pull_request"].as(JsonObject))
        end
+
+       # Set pull.
+       fun pull=(pull: PullRequest) do json["pull_request"] = pull.json
 end
 
 # Triggered when a repository branch is pushed to.
@@ -236,26 +332,42 @@ class PushEvent
        super GithubEvent
 
        # SHA of the HEAD commit on the repository.
-       fun head: String do return json["head"].to_s
+       fun head: String do return json["head"].as(String)
+
+       # Set head.
+       fun head=(head: String) do json["head"] = head
 
        # Full Git ref that was pushed.
        #
        # Example: “refs/heads/master”
-       fun ref: String do return json["ref"].to_s
+       fun ref: String do return json["ref"].as(String)
+
+       # Set ref.
+       fun ref=(ref: String) do json["ref"] = ref
 
        # Number of commits in the push.
        fun size: Int do return json["size"].as(Int)
 
+       # Set size.
+       fun size=(size: Int) do json["size"] = size
+
        # Array of pushed commits.
        fun commits: Array[Commit] do
                var res = new Array[Commit]
                var arr = json["commits"].as(JsonArray)
                for obj in arr do
                        if not obj isa JsonObject then continue
-                       res.add api.load_commit(repo, obj["sha"].to_s).as(not null)
+                       res.add api.load_commit(repo, obj["sha"].as(String)).as(not null)
                end
                return res
        end
+
+       # Set commits.
+       fun commits=(commits: Array[Commit]) do
+               var arr = new JsonArray
+               for commit in commits do arr.add commit.json
+               json["commits"] = arr
+       end
 end
 
 # Triggered when the status of a Git commit changes.
@@ -264,26 +376,38 @@ class StatusEvent
 
        # The `Commit` itself.
        fun commit: Commit do
-               return api.load_commit(repo, json["sha"].to_s).as(not null)
+               return api.load_commit(repo, json["sha"].as(String)).as(not null)
        end
 
+       # Set commit.
+       fun commit=(commit: Commit) do json["sha"] = commit.sha
+
        # New state.
        #
        # Can be `pending`, `success`, `failure`, or `error`.
-       fun state: String do return json["state"].to_s
+       fun state: String do return json["state"].as(String)
+
+       # Set state.
+       fun state=(state: String) do json["state"] = state
 
        # Optional human-readable description added to the status.
        fun description: nullable String do
-               if not json.has_key("description") then return null
-               return json["description"].to_s
+               var res = json.get_or_null("description")
+               if res isa String then return res else return null
        end
 
+       # Set description.
+       fun description=(description: nullable String) do json["description"] = description
+
        # Optional link added to the status.
        fun target_url: nullable String do
-               if not json.has_key("target_url") then return null
-               return json["target_url"].to_s
+               var res = json.get_or_null("target_url")
+               if res isa String then return res else return null
        end
 
+       # Set target_url.
+       fun target_url=(target_url: nullable String) do json["target_url"] = target_url
+
        # Array of branches containing the status' SHA.
        #
        # Each branch contains the given SHA,
@@ -295,8 +419,15 @@ class StatusEvent
                var arr = json["branches"].as(JsonArray)
                for obj in arr do
                        if not obj isa JsonObject then continue
-                       res.add api.load_branch(repo, obj["name"].to_s).as(not null)
+                       res.add api.load_branch(repo, obj["name"].as(String)).as(not null)
                end
                return res
        end
+
+       # Set branches.
+       fun branches=(branches: Array[Commit]) do
+               var arr = new JsonArray
+               for branch in branches do arr.add branch.json
+               json["branches"] = arr
+       end
 end
index 8f45495..bc9a8af 100644 (file)
 # g.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
 # for component in g.strongly_connected_components.to_partitions
 # do
-#      print component
+#      print component
 # end
 # # Prints [1,2] and [3,4,5]
 # ~~~
@@ -291,7 +291,7 @@ interface Digraph[V: Object]
        # g.add_arc(0, 2)
        # g.add_arc(1, 2)
        # for arc in g.arcs_iterator do
-       #       assert g.has_arc(arc[0], arc[1])
+       #       assert g.has_arc(arc[0], arc[1])
        # end
        # ~~~
        fun arcs_iterator: Iterator[Array[V]] do return new ArcsIterator[V](self)
@@ -317,7 +317,7 @@ interface Digraph[V: Object]
        # g.add_arc(1, 3)
        # g.add_arc(2, 3)
        # for arc in g.incoming_arcs(3) do
-       #       assert g.is_predecessor(arc[0], arc[1])
+       #       assert g.is_predecessor(arc[0], arc[1])
        # end
        # ~~~
        fun incoming_arcs(u: V): Collection[Array[V]]
@@ -340,7 +340,7 @@ interface Digraph[V: Object]
        # g.add_arc(2, 3)
        # g.add_arc(1, 2)
        # for arc in g.outgoing_arcs(1) do
-       #       assert g.is_successor(arc[1], arc[0])
+       #       assert g.is_successor(arc[1], arc[0])
        # end
        # ~~~
        fun outgoing_arcs(u: V): Collection[Array[V]]
@@ -383,6 +383,15 @@ interface Digraph[V: Object]
                return s
        end
 
+       # Open Graphviz with `self.to_dot`.
+       #
+       # Mainly used for debugging.
+       fun show_dot do
+               var f = new ProcessWriter("dot", "-Txlib")
+               f.write to_dot
+               f.close
+       end
+
        ## ------------ ##
        ## Neighborhood ##
        ## ------------ ##
diff --git a/lib/graphs/pagerank.nit b/lib/graphs/pagerank.nit
new file mode 100644 (file)
index 0000000..5177e5a
--- /dev/null
@@ -0,0 +1,88 @@
+# 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.
+
+# Add PageRank computation for vertices in Digraph.
+module pagerank
+
+import graphs::digraph
+
+redef class Digraph[V]
+
+       # Compute PageRank for each vertex
+       #
+       # Details of the algorithm can be found in:
+       # > L. Page, S. Brin, R. Motwani, and T.Winograd.
+       # > **The pagerank citation ranking: Bringing order to the web.**
+       # > *Technical report, Stanford Digital Library Technologies Project, 1998*
+       #
+       # Example:
+       # ~~~
+       # var g = new HashDigraph[String]
+       # g.add_arc("A", "B")
+       # g.add_arc("A", "C")
+       # g.add_arc("B", "C")
+       # g.add_arc("C", "A")
+       # g.add_arc("D", "C")
+       #
+       # assert g.pagerank.join(", ", ":") == "A:1.488, B:0.782, C:1.575, D:0.15"
+       # ~~~
+       fun pagerank: PRMap[V] do
+               # `d` constant such as `initial_pagerank(node) == (1 - d) != 0`
+               var d = 0.85 # commonly-choosen value
+               # Init each node page rank with an initial_value
+               var values = new PRMap[V]
+               var vertices = self.vertices
+               for v in vertices do values[v] = 1.0 - d
+               # Compute page rank until convergence
+               var prev = new PRMap[V]
+               while not values.is_approx(prev, 0.001) do
+                       prev = new PRMap[V].from(values)
+                       for v in vertices do
+                               var in_pr = 0.0
+                               for o in predecessors(v) do
+                                       in_pr += values[o] / out_degree(o).to_f
+                               end
+                               values[v] = (1.0 - d) + d * in_pr
+                       end
+               end
+               return values
+       end
+end
+
+# Map each Vertice of a Digraph to it's PageRank.
+#
+# See: `Digraph::pagerank`.
+class PRMap[V]
+       super HashMap[V, Float]
+
+       # Init `self` by copying `other` values.
+       init from(other: PRMap[V]) do
+               init
+               for k, v in other do self[k] = v
+       end
+
+       # Is `self` approximately equal to another PRMap?
+       #
+       # `self` is approximately equal to `o` if `o` contains all the key from `self`
+       # with the same values.
+       #
+       # Values equality is based on `Float::is_approx` with `precision`.
+       fun is_approx(o: SELF, precision: Float): Bool do
+               for k1, v1 in self do
+                       if not o.has_key(k1) then return false
+                       if not v1.is_approx(o[k1], precision) then return false
+               end
+               return true
+       end
+end
index 8d0650f..a8a5eb9 100644 (file)
@@ -1,6 +1,6 @@
 NITCCDIR=../../contrib/nitcc/
 
-compile-parser: $(NITCCDIR)src/nitcc
+pre-build: $(NITCCDIR)src/nitcc
        $(NITCCDIR)src/nitcc $(NITCCDIR)examples/json.sablecc
 
 $(NITCCDIR)src/nitcc:
index 61af9df..c8f02e3 100644 (file)
@@ -37,8 +37,6 @@ in "C" `{
 `}
 
 redef class App
-       redef type D: Opengles1Display
-
        redef fun init_window
        do
                display = new Opengles1Display
index 7bc03a0..c191a60 100644 (file)
@@ -26,9 +26,6 @@ in "C" `{
 `}
 
 redef class App
-       redef type D: Opengles1Display
-       redef type I: Opengles1Image
-
        redef fun setup
        do
                if "NIT_TESTING".environ == "true" then exit 0
@@ -39,8 +36,11 @@ redef class App
 
        redef fun generate_input
        do
+               var display = display
+               assert display isa Opengles1Display
+
                for event in display.sdl_display.events do
-                       input( event )
+                       input event
                end
        end
 end
index 1e9b9bd..624dc8a 100644 (file)
@@ -600,14 +600,12 @@ class MongoCollection
        # ~~~
        fun find(query: JsonObject): nullable JsonObject do
                assert is_alive
-               var c = native.find(query.to_bson.native)
-               assert is_alive # FIXME used to avoid segfault (so `self` isn't garbage collected to soon)
+               var q = new NativeBSON.from_json_string(query.to_json.to_cstring)
+               var c = native.find(q)
+               q.destroy
                if c == null then return null
                var cursor = new MongoCursor(c)
-               if cursor.is_ok then
-                       cursor.next
-                       return cursor.item
-               end
+               if cursor.is_ok then return cursor.item
                return null
        end
 
index b46e488..6b9866a 100644 (file)
@@ -22,6 +22,9 @@ BINS=$(patsubst %,../bin/%,$(OBJS))
 
 all: bin/nitc
 
+pre-build:
+       ./git-gen-version.sh
+
 nitc_0: ../c_src/nitc parser/parser.nit
        @echo '***************************************************************'
        @echo '* Compile nitc_0 from NIT source files                        *'
index 23daf06..81201a2 100644 (file)
@@ -45,6 +45,7 @@ module mendel_metrics
 
 import metrics_base
 import mclasses_metrics
+import mmodules_metrics
 import modelize
 
 redef class ToolContext
@@ -149,6 +150,24 @@ class CBMS
        end
 end
 
+# Module Branch Mean Size
+# mbms(module) = |mclassdefs(module)| / (DIT(module) + 1)
+class MBMS
+       super MModuleMetric
+       super FloatMetric
+       redef fun name do return "mbms"
+       redef fun desc do return "branch mean size, mean number of class definition available among ancestors"
+
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       var totc = mmodule.collect_intro_mclassdefs(protected_visibility).length
+                       totc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+                       var ditc = mmodule.in_importation.depth
+                       values[mmodule] = totc.to_f / (ditc + 1).to_f
+               end
+       end
+end
+
 # Class Novelty Index
 # cnvi = |LocS(class)| / cbms(parents(class))
 class CNVI
@@ -178,6 +197,33 @@ class CNVI
        end
 end
 
+# Module Novelty Index
+# mnvi = |LocS(module)| / mbms(parents(module))
+class MNVI
+       super MModuleMetric
+       super FloatMetric
+       redef fun name do return "mnvi"
+       redef fun desc do return "module novelty index, contribution of the module to its branch in term of introductions"
+
+       redef fun collect(mmodules) do
+               var mbms = new MBMS
+               for mmodule in mmodules do
+                       # compute branch mean size
+                       var parents = mmodule.in_importation.direct_greaters
+                       if parents.length > 0 then
+                               mbms.clear
+                               mbms.collect(new HashSet[MModule].from(parents))
+                               # compute module novelty index
+                               var locc = mmodule.collect_intro_mclassdefs(protected_visibility).length
+                               locc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+                               values[mmodule] = locc.to_f / mbms.avg
+                       else
+                               values[mmodule] = 0.0
+                       end
+               end
+       end
+end
+
 # Class Novelty Score
 # cnvs = |LocS(class)| x nvi
 class CNVS
@@ -199,6 +245,25 @@ class CNVS
        end
 end
 
+# Module Novelty Score
+# mnvs = |LocS(module)| x nvi
+class MNVS
+       super MModuleMetric
+       super FloatMetric
+       redef fun name do return "mnvs"
+       redef fun desc do return "module novelty score, importance of the contribution of the module to its branch"
+
+       redef fun collect(mmodules) do
+               var mnvi = new MNVI
+               mnvi.collect(mmodules)
+               for mmodule in mmodules do
+                       var locc = mmodule.collect_intro_mclassdefs(protected_visibility).length
+                       locc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+                       values[mmodule] = mnvi.values[mmodule] * locc.to_f
+               end
+       end
+end
+
 redef class MClass
        # the set of redefition that call to super
        fun extended_mproperties(min_visibility: MVisibility): Set[MProperty] do
@@ -303,4 +368,3 @@ redef class MClass
                return false
        end
 end
-
index 605f4d3..342d5c7 100644 (file)
@@ -166,7 +166,7 @@ interface Metric
        fun values: RES is abstract
 
        # Collect metric values on elements
-       fun collect(elements: Set[ELM]) is abstract
+       fun collect(elements: Collection[ELM]) is abstract
 
        # The value calculated for the element
        fun [](element: ELM): VAL do return values[element]
@@ -299,7 +299,10 @@ class FloatMetric
 
        redef fun sum do
                var sum = 0.0
-               for v in values.values do sum += v
+               for v in values.values do
+                       if v.is_nan then continue
+                       sum += v
+               end
                return sum
        end
 
@@ -337,6 +340,7 @@ class FloatMetric
        redef fun std_dev do
                var sum = 0.0
                for value in values.values do
+                       if value.is_nan then continue
                        sum += (value - avg).pow(2.to_f)
                end
                return (sum / values.length.to_f).sqrt
diff --git a/tests/sav/ballz_linux.res b/tests/sav/ballz_linux.res
deleted file mode 100644 (file)
index 18bfeab..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-../lib/mnit/linux/linux_app.nit:29,16--31: Redef Error: a virtual type cannot be refined.
-../lib/mnit/linux/linux_app.nit:30,16--29: Redef Error: a virtual type cannot be refined.
diff --git a/tests/sav/dino_linux.res b/tests/sav/dino_linux.res
deleted file mode 100644 (file)
index 18bfeab..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-../lib/mnit/linux/linux_app.nit:29,16--31: Redef Error: a virtual type cannot be refined.
-../lib/mnit/linux/linux_app.nit:30,16--29: Redef Error: a virtual type cannot be refined.
diff --git a/tests/sav/shoot_linux.res b/tests/sav/shoot_linux.res
deleted file mode 100644 (file)
index 18bfeab..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-../lib/mnit/linux/linux_app.nit:29,16--31: Redef Error: a virtual type cannot be refined.
-../lib/mnit/linux/linux_app.nit:30,16--29: Redef Error: a virtual type cannot be refined.