1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
17 # This module parses example from mentities annotated with `is example`.
24 import parse_annotations
25 import model
::model_examples
27 redef class ToolContext
29 # Examples parsing phase
30 var examples_phase
: Phase = new ExamplesPhase(self,
31 [typing_phase
, parse_annotations_phase
])
34 # Parse examples from modules, classdefs and propdefs
36 # For each node annotated with `is example` we parse the example and associate
37 # it with existing model entities.
39 # Association between examples and mentities is based on:
40 # `MModule`: Used in `import`
41 # `MClassDef`: Used in `super`, redefined class, init or other method called
42 # `MPropDef`: Used in `super`, redefined property, called
43 private class ExamplesPhase
46 redef fun process_nmodule
(nmodule
) do
47 var mmodule
= nmodule
.mmodule
48 if mmodule
== null then return
50 if not mmodule
.has_annotation
("example") then return
52 process_example
(mmodule
, nmodule
)
55 redef fun process_nclassdef
(nclassdef
) do
56 var mclassdef
= nclassdef
.mclassdef
57 if mclassdef
== null then return
59 if not mclassdef
.has_annotation
("example") and not mclassdef
.mmodule
.is_example
then return
61 process_example
(mclassdef
, nclassdef
)
64 redef fun process_npropdef
(npropdef
) do
65 var mpropdef
= npropdef
.mpropdef
66 if mpropdef
== null then return
68 if not mpropdef
.has_annotation
("example") and not mpropdef
.mclassdef
.is_example
then return
70 process_example
(mpropdef
, npropdef
)
73 # Process an mentity as an MExample
75 # This method parses the mentity node and link the mentity to possible
76 # examplified entities.
77 fun process_example
(example_mentity
: MEntity, node
: ANode) do
78 var visitor
= new ExampleVisitor(toolcontext
)
79 visitor
.enter_visit
(node
)
80 var sorted
= visitor
.counter
.sort
.reversed
82 var example
= new MExample(example_mentity
)
84 for mentity
in sorted
do
85 example
.example_for
[mentity
] = visitor
.counter
[mentity
]
86 if not mentity
.examples
.has
(example
) then mentity
.examples
.add example
92 # AST node containing the example code
93 var node
: nullable ANode = null is writable
98 # Visit examples to find what they are an example for.
99 private class ExampleVisitor
102 var counter
= new Counter[MEntity]
104 # The toolcontext is our entree point to most services
105 var toolcontext
: ToolContext
107 redef fun visit
(node
) do
108 node
.accept_example_visitor
(self)
113 private fun accept_example_visitor
(v
: ExampleVisitor) do visit_all
(v
)
117 redef fun accept_example_visitor
(v
) do
118 var recvtype
= self.recvtype
119 if recvtype
!= null then
120 v
.counter
.inc recvtype
.mclass
121 v
.counter
.inc recvtype
.mclass
.intro
127 redef class AStdImport
128 redef fun accept_example_visitor
(v
) do
129 var mmodule
= self.mmodule
130 if mmodule
!= null then
131 v
.counter
.inc mmodule
133 var mgroup
= mmodule
.mgroup
134 if mgroup
!= null then
136 v
.counter
.inc mgroup
.mpackage
142 redef class AStdClassdef
143 redef fun accept_example_visitor
(v
) do
144 var mclassdef
= self.mclassdef
145 if mclassdef
== null then return
147 if not mclassdef
.is_intro
then
148 v
.counter
.inc mclassdef
.mclass
.intro
155 redef fun accept_example_visitor
(v
) do
156 var mpropdef
= self.mpropdef
157 if mpropdef
== null then return
159 if not mpropdef
.is_intro
then
160 v
.counter
.inc mpropdef
.mproperty
.intro
.mclassdef
.mclass
161 v
.counter
.inc mpropdef
.mproperty
.intro
.mclassdef
162 v
.counter
.inc mpropdef
.mproperty
.intro
168 redef class ASuperPropdef
169 redef fun accept_example_visitor
(v
) do
170 var mtype
= self.n_type
.mtype
171 if mtype
isa MClassType then
172 v
.counter
.inc mtype
.mclass
173 v
.counter
.inc mtype
.mclass
.intro
179 redef class ASendExpr
180 redef fun accept_example_visitor
(v
) do
181 var callsite
= self.callsite
182 if callsite
== null then return
183 v
.counter
.inc callsite
.mpropdef
184 v
.counter
.inc callsite
.mpropdef
.mproperty
185 v
.counter
.inc callsite
.mpropdef
.mclassdef
186 v
.counter
.inc callsite
.mpropdef
.mclassdef
.mclass