From: Alexandre Terrasa Date: Tue, 24 Oct 2017 03:15:49 +0000 (-0400) Subject: doc/commands: introduce usage commands X-Git-Url: http://nitlanguage.org doc/commands: introduce usage commands Signed-off-by: Alexandre Terrasa --- diff --git a/src/doc/commands/commands_usage.nit b/src/doc/commands/commands_usage.nit new file mode 100644 index 0000000..3b4efab --- /dev/null +++ b/src/doc/commands/commands_usage.nit @@ -0,0 +1,224 @@ +# 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. + +# Commands about how mentities are used +module commands_usage + +import commands_model +import semantize + +# Retrieve all the mproperties using `mentity` as a type for its parameters +# +# `mentity` must be a MClass or a MClassDef. +class CmdParam + super CmdEntityList + + redef fun init_results do + if results != null then return new CmdSuccess + + var res = super + if not res isa CmdSuccess then return res + var mentity = self.mentity.as(not null) + + if mentity isa MClassDef then mentity = mentity.mclass + if not mentity isa MClass then return new ErrorNotClass(mentity) + + var mentities = new HashSet[MEntity] + for mproperty in view.mproperties do + if not mproperty isa MMethod then continue + var msignature = mproperty.intro.msignature + if msignature != null then + for mparam in msignature.mparameters do + var mtype = mparam.mtype + if mtype isa MNullableType then mtype = mtype.mtype + if not mtype isa MClassType then continue + if mtype.mclass != mentity then continue + mentities.add mproperty + end + end + end + results = mentities.to_a + return res + end +end + +# Retrieve all the mproperties that return somethinf of the `mentity` type. +# +# `mentity` must be a MClass or a MClassDef. +class CmdReturn + super CmdEntityList + + redef fun init_results do + if results != null then return new CmdSuccess + + var res = super + if not res isa CmdSuccess then return res + var mentity = self.mentity.as(not null) + + if mentity isa MClassDef then mentity = mentity.mclass + if not mentity isa MClass then return new ErrorNotClass(mentity) + + var mentities = new HashSet[MEntity] + for mproperty in view.mproperties do + if not mproperty isa MMethod then continue + var msignature = mproperty.intro.msignature + if msignature != null then + var mtype = msignature.return_mtype + if mtype == null then continue + if mtype isa MNullableType then mtype = mtype.mtype + if not mtype isa MClassType then continue + if mtype.mclass != mentity then continue + mentities.add mproperty + end + end + results = mentities.to_a + return res + end +end + +# Retrieve all the mproperties that initialize `mentity` +# +# `mentity` must be a MClass or a MClassDef. +class CmdNew + super CmdEntityList + + autoinit(view, modelbuilder, mentity, mentity_name, limit, page, count, max) + + # ModelBuilder used to retrieve AST nodes + var modelbuilder: ModelBuilder + + redef fun init_results do + if results != null then return new CmdSuccess + + var res = super + if not res isa CmdSuccess then return res + var mentity = self.mentity.as(not null) + + if mentity isa MClassDef then mentity = mentity.mclass + if not mentity isa MClass then return new ErrorNotClass(mentity) + + var mentities = new HashSet[MEntity] + for mpropdef in view.mpropdefs do + var visitor = new TypeInitVisitor(mentity) + var npropdef = modelbuilder.mpropdef2node(mpropdef) + if npropdef == null then continue + visitor.enter_visit(npropdef) + if visitor.called then + mentities.add mpropdef + end + end + results = mentities.to_a + return res + end +end + +# Retrieve all the mproperties that call `mentity` +# +# `mentity` must be a MProperty or a MPropDef. +class CmdCall + super CmdEntityList + + autoinit(view, modelbuilder, mentity, mentity_name, limit, page, count, max) + + # ModelBuilder used to retrieve AST nodes + var modelbuilder: ModelBuilder + + redef fun init_results do + if results != null then return new CmdSuccess + + var res = super + if not res isa CmdSuccess then return res + var mentity = self.mentity.as(not null) + + if mentity isa MPropDef then mentity = mentity.mproperty + if not mentity isa MProperty then return new ErrorNotProperty(mentity) + + var mentities = new HashSet[MEntity] + for mpropdef in view.mpropdefs do + if mpropdef.mproperty == mentity then continue + var visitor = new MPropertyCallVisitor + var npropdef = modelbuilder.mpropdef2node(mpropdef) + if npropdef == null then continue + visitor.enter_visit(npropdef) + if visitor.calls.has(mentity) then + mentities.add mpropdef + end + end + results = mentities.to_a + return res + end +end + +## exploration + +# Visitor looking for initialized `MType` (new T). +# +# See `NewCmd`. +private class TypeInitVisitor + super Visitor + + var mclass: MClass + + var called = false + + redef fun visit(node) + do + node.visit_all(self) + # look for init + if not node isa ANewExpr then return + var mtype = node.n_type.mtype + + if mtype == null then return + if mtype isa MNullableType then mtype = mtype.mtype + if not mtype isa MClassType then return + if mtype.mclass != mclass then return + + called = true + end +end + +# Visitor looking for calls to a `MProperty` (new T). +# +# See `CallCmd`. +private class MPropertyCallVisitor + super Visitor + + var calls = new HashSet[MProperty] + redef fun visit(node) + do + node.visit_all(self) + if not node isa ASendExpr then return + calls.add node.callsite.as(not null).mproperty + end +end + +# The MEntity is not a MClass or a MClassDef +class ErrorNotClass + super CmdError + + # MEntity provided + var mentity: MEntity + + redef fun to_s do return "`{mentity.full_name}` is not a class" +end + +# The MEntity is not a MProperty or a MClassDef +class ErrorNotProperty + super CmdError + + # MEntity provided + var mentity: MEntity + + redef fun to_s do return "`{mentity.full_name}` is not a property" +end diff --git a/src/doc/commands/tests/test_commands_usage.nit b/src/doc/commands/tests/test_commands_usage.nit new file mode 100644 index 0000000..b07c336 --- /dev/null +++ b/src/doc/commands/tests/test_commands_usage.nit @@ -0,0 +1,63 @@ +# 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. + +module test_commands_usage is test + +import test_commands +import doc::commands::commands_usage + +class TestCommandsUsage + super TestCommands + test + + fun test_cmd_new is test do + var cmd = new CmdNew(test_view, test_builder, mentity_name = "test_prog::Character") + var res = cmd.init_command + assert res isa CmdSuccess + assert cmd.results != null + end + + fun test_cmd_new_not_class is test do + var cmd = new CmdNew(test_view, test_builder, mentity_name = "strength_bonus") + var res = cmd.init_command + assert res isa ErrorNotClass + end + + fun test_cmd_call is test do + var cmd = new CmdCall(test_view, test_builder, mentity_name = "strength_bonus") + var res = cmd.init_command + assert res isa CmdSuccess + assert cmd.results != null + end + + fun test_cmd_call_not_prop is test do + var cmd = new CmdCall(test_view, test_builder, mentity_name = "test_prog::Character") + var res = cmd.init_command + assert res isa ErrorNotProperty + end + + fun test_cmd_return is test do + var cmd = new CmdReturn(test_view, mentity_name = "test_prog::Character") + var res = cmd.init_command + assert res isa CmdSuccess + assert cmd.results != null + end + + fun test_cmd_param is test do + var cmd = new CmdParam(test_view, mentity_name = "test_prog::Character") + var res = cmd.init_command + assert res isa CmdSuccess + assert cmd.results != null + end +end