Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / frontend / parse_examples.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Example parsing
16 #
17 # This module parses example from mentities annotated with `is example`.
18 #
19 # TODO rank examples
20 module parse_examples
21
22 import counter
23 import typing
24 import parse_annotations
25 import model::model_examples
26
27 redef class ToolContext
28
29 # Examples parsing phase
30 var examples_phase: Phase = new ExamplesPhase(self,
31 [typing_phase, parse_annotations_phase])
32 end
33
34 # Parse examples from modules, classdefs and propdefs
35 #
36 # For each node annotated with `is example` we parse the example and associate
37 # it with existing model entities.
38 #
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
44 super Phase
45
46 redef fun process_nmodule(nmodule) do
47 var mmodule = nmodule.mmodule
48 if mmodule == null then return
49
50 if not mmodule.has_annotation("example") then return
51
52 process_example(mmodule, nmodule)
53 end
54
55 redef fun process_nclassdef(nclassdef) do
56 var mclassdef = nclassdef.mclassdef
57 if mclassdef == null then return
58
59 if not mclassdef.has_annotation("example") and not mclassdef.mmodule.is_example then return
60
61 process_example(mclassdef, nclassdef)
62 end
63
64 redef fun process_npropdef(npropdef) do
65 var mpropdef = npropdef.mpropdef
66 if mpropdef == null then return
67
68 if not mpropdef.has_annotation("example") and not mpropdef.mclassdef.is_example then return
69
70 process_example(mpropdef, npropdef)
71 end
72
73 # Process an mentity as an MExample
74 #
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
81
82 var example = new MExample(example_mentity)
83 example.node = node
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
87 end
88 end
89 end
90
91 redef class MExample
92 # AST node containing the example code
93 var node: nullable ANode = null is writable
94 end
95
96 # Example parsing
97
98 # Visit examples to find what they are an example for.
99 private class ExampleVisitor
100 super Visitor
101
102 var counter = new Counter[MEntity]
103
104 # The toolcontext is our entree point to most services
105 var toolcontext: ToolContext
106
107 redef fun visit(node) do
108 node.accept_example_visitor(self)
109 end
110 end
111
112 redef class ANode
113 private fun accept_example_visitor(v: ExampleVisitor) do visit_all(v)
114 end
115
116 redef class ANewExpr
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
122 end
123 visit_all(v)
124 end
125 end
126
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
132
133 var mgroup = mmodule.mgroup
134 if mgroup != null then
135 v.counter.inc mgroup
136 v.counter.inc mgroup.mpackage
137 end
138 end
139 end
140 end
141
142 redef class AStdClassdef
143 redef fun accept_example_visitor(v) do
144 var mclassdef = self.mclassdef
145 if mclassdef == null then return
146
147 if not mclassdef.is_intro then
148 v.counter.inc mclassdef.mclass.intro
149 end
150 visit_all(v)
151 end
152 end
153
154 redef class APropdef
155 redef fun accept_example_visitor(v) do
156 var mpropdef = self.mpropdef
157 if mpropdef == null then return
158
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
163 end
164 visit_all(v)
165 end
166 end
167
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
174 end
175 visit_all(v)
176 end
177 end
178
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
187 visit_all(v)
188 end
189 end