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
26 import model
::model_examples
28 redef class ToolContext
30 # Examples parsing phase
31 var examples_phase
: Phase = new ExamplesPhase(self,
32 [typing_phase
, parse_annotations_phase
])
35 # Parse examples from modules, classdefs and propdefs
37 # For each node annotated with `is example` we parse the example and associate
38 # it with existing model entities.
40 # Association between examples and mentities is based on:
41 # `MModule`: Used in `import`
42 # `MClassDef`: Used in `super`, redefined class, init or other method called
43 # `MPropDef`: Used in `super`, redefined property, called
44 private class ExamplesPhase
47 redef fun process_nmodule
(nmodule
) do
48 var mmodule
= nmodule
.mmodule
49 if mmodule
== null then return
51 if not mmodule
.has_annotation
("example") then return
53 process_example
(mmodule
, nmodule
)
56 redef fun process_nclassdef
(nclassdef
) do
57 var mclassdef
= nclassdef
.mclassdef
58 if mclassdef
== null then return
60 if not mclassdef
.has_annotation
("example") and not mclassdef
.mmodule
.is_example
then return
62 process_example
(mclassdef
, nclassdef
)
65 redef fun process_npropdef
(npropdef
) do
66 var mpropdef
= npropdef
.mpropdef
67 if mpropdef
== null then return
69 if not mpropdef
.has_annotation
("example") and not mpropdef
.mclassdef
.is_example
then return
71 process_example
(mpropdef
, npropdef
)
74 # Process an mentity as an MExample
76 # This method parses the mentity node and link the mentity to possible
77 # examplified entities.
78 fun process_example
(example_mentity
: MEntity, node
: ANode) do
79 var visitor
= new ExampleVisitor(toolcontext
)
80 visitor
.enter_visit
(node
)
81 var sorted
= visitor
.counter
.sort
.reversed
83 var example
= new MExample(example_mentity
)
85 for mentity
in sorted
do
86 example
.example_for
[mentity
] = visitor
.counter
[mentity
]
87 if not mentity
.examples
.has
(example
) then mentity
.examples
.add example
93 # AST node containing the example code
94 var node
: nullable ANode = null is writable
99 # Visit examples to find what they are an example for.
100 private class ExampleVisitor
103 var counter
= new Counter[MEntity]
105 # The toolcontext is our entree point to most services
106 var toolcontext
: ToolContext
108 redef fun visit
(node
) do
109 node
.accept_example_visitor
(self)
114 private fun accept_example_visitor
(v
: ExampleVisitor) do visit_all
(v
)
118 redef fun accept_example_visitor
(v
) do
119 var recvtype
= self.recvtype
120 if recvtype
!= null then
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
178 redef class ASendExpr
179 redef fun accept_example_visitor
(v
) do
180 var callsite
= self.callsite
181 if callsite
== null then return
182 v
.counter
.inc callsite
.mpropdef
183 v
.counter
.inc callsite
.mpropdef
.mproperty
184 v
.counter
.inc callsite
.mpropdef
.mclassdef
185 v
.counter
.inc callsite
.mpropdef
.mclassdef
.mclass