35fa66c1927c3f952dbae1aee5369f0c88019398
[nit.git] / src / simple_misc_analysis.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Simple vavious processing on a AST
18 # The analysis warns on :
19 # * superfluous parentheses
20 # * nested "once" expressions
21 # * use of "while true" instead of "loop"
22 module simple_misc_analysis
23
24 import toolcontext
25 import parser
26 import phase
27
28 redef class ToolContext
29 var simple_misc_analysis_phase: Phase = new SimpleMiscAnalysisPhase(self, null)
30 end
31
32 private class SimpleMiscAnalysisPhase
33 super Phase
34 redef fun process_nmodule(nmodule) do nmodule.do_simple_misc_analysis(toolcontext)
35 end
36
37 redef class AModule
38 # Visit the module to detect easy warnings that does not need the metamodel or the importation
39 # Warnings are displayed on the toolcontext
40 fun do_simple_misc_analysis(toolcontext: ToolContext)
41 do
42 var v = new SimpleMiscVisitor(toolcontext)
43 v.enter_visit(self)
44 end
45 end
46
47 private class SimpleMiscVisitor
48 super Visitor
49 redef fun visit(n)
50 do
51 n.accept_simple_misc(self)
52 end
53
54 # Number of nested once
55 var once_count: Int = 0
56
57 var toolcontext: ToolContext
58
59 fun warning(node: ANode, msg: String)
60 do
61 toolcontext.warning(node.hot_location, msg)
62 end
63
64 init(toolcontext: ToolContext)
65 do
66 self.toolcontext = toolcontext
67 end
68 end
69
70
71 ###############################################################################
72
73 redef class ANode
74 private fun accept_simple_misc(v: SimpleMiscVisitor)
75 do
76 visit_all(v)
77 after_simple_misc(v)
78 end
79 private fun after_simple_misc(v: SimpleMiscVisitor) do end
80 end
81
82 redef class ASignature
83 redef fun after_simple_misc(v)
84 do
85 if self.n_opar != null and self.n_params.is_empty then
86 v.warning(self, "Warning: superfluous parentheses.")
87 end
88 end
89 end
90
91 redef class AExpr
92 # Warn in case of superfluous parentheses
93 private fun warn_parentheses(v: SimpleMiscVisitor) do end
94 end
95
96 redef class AParExpr
97 redef fun warn_parentheses(v)
98 do
99 v.warning(self, "Warning: superfluous parentheses.")
100 end
101 end
102
103 redef class AParExprs
104 redef fun after_simple_misc(v)
105 do
106 if n_exprs.is_empty then
107 v.warning(self, "Warning: superfluous parentheses.")
108 end
109 end
110 end
111
112 redef class AReturnExpr
113 redef fun after_simple_misc(v)
114 do
115 var e = n_expr
116 if e != null then
117 e.warn_parentheses(v)
118 end
119 end
120 end
121
122 redef class AContinueExpr
123 redef fun after_simple_misc(v)
124 do
125 var e = n_expr
126 if e != null then
127 e.warn_parentheses(v)
128 end
129 end
130 end
131
132 redef class ABreakExpr
133 redef fun after_simple_misc(v)
134 do
135 var e = n_expr
136 if e != null then
137 e.warn_parentheses(v)
138 end
139 end
140 end
141
142 redef class AWhileExpr
143 redef fun after_simple_misc(v)
144 do
145 if n_expr isa ATrueExpr then
146 v.warning(self, "Warning: use 'loop' instead of 'while true do'.")
147 else
148 n_expr.warn_parentheses(v)
149 end
150 end
151 end
152
153 redef class AForExpr
154 redef fun after_simple_misc(v)
155 do
156 n_expr.warn_parentheses(v)
157 end
158 end
159
160 redef class AIfExpr
161 redef fun after_simple_misc(v)
162 do
163 n_expr.warn_parentheses(v)
164 end
165 end
166
167 redef class AIfexprExpr
168 redef fun after_simple_misc(v)
169 do
170 n_expr.warn_parentheses(v)
171 end
172 end
173
174 redef class AOnceExpr
175 redef fun accept_simple_misc(v)
176 do
177 if v.once_count > 0 then
178 v.warning(self, "Useless once in a once expression.")
179 end
180 v.once_count = v.once_count + 1
181
182 super
183
184 v.once_count = v.once_count - 1
185 end
186 end