misc_analysis: warn on superfluous `;`
[nit.git] / src / frontend / 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 phase
25
26 redef class ToolContext
27 # Execute `AModule::do_simple_misc_analysis` on each module.
28 var simple_misc_analysis_phase: Phase = new SimpleMiscAnalysisPhase(self, null)
29 end
30
31 private class SimpleMiscAnalysisPhase
32 super Phase
33 redef fun process_nmodule(nmodule) do nmodule.do_simple_misc_analysis(toolcontext)
34 end
35
36 redef class AModule
37 # Visit the module to detect easy warnings that does not need the metamodel or the importation
38 # Warnings are displayed on the toolcontext
39 fun do_simple_misc_analysis(toolcontext: ToolContext)
40 do
41 var v = new SimpleMiscVisitor(toolcontext)
42 v.enter_visit(self)
43
44 var t = location.file.first_token
45 while t != null do
46 t.accept_simple_misc_token(v)
47 t = t.next_token
48 end
49 end
50 end
51
52 private class SimpleMiscVisitor
53 super Visitor
54 redef fun visit(n)
55 do
56 n.accept_simple_misc(self)
57 end
58
59 # Number of nested once
60 var once_count: Int = 0
61
62 var toolcontext: ToolContext
63
64 fun warning(node: ANode, tag, msg: String)
65 do
66 toolcontext.warning(node.hot_location, tag, msg)
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 Token
83 private fun accept_simple_misc_token(v: SimpleMiscVisitor)
84 do
85 end
86 end
87
88 redef class ASignature
89 redef fun after_simple_misc(v)
90 do
91 if self.n_opar != null and self.n_params.is_empty then
92 v.warning(self, "parentheses", "Warning: superfluous parentheses.")
93 end
94 end
95 end
96
97 redef class AExpr
98 # Warn in case of superfluous parentheses
99 private fun warn_parentheses(v: SimpleMiscVisitor) do end
100 end
101
102 redef class AParExpr
103 redef fun warn_parentheses(v)
104 do
105 v.warning(self, "parentheses", "Warning: superfluous parentheses.")
106 end
107 end
108
109 redef class AParExprs
110 redef fun after_simple_misc(v)
111 do
112 if n_exprs.is_empty then
113 v.warning(self, "parentheses", "Warning: superfluous parentheses.")
114 end
115 end
116 end
117
118 redef class AReturnExpr
119 redef fun after_simple_misc(v)
120 do
121 var e = n_expr
122 if e != null then
123 e.warn_parentheses(v)
124 end
125 end
126 end
127
128 redef class AEscapeExpr
129 redef fun after_simple_misc(v)
130 do
131 var e = n_expr
132 if e != null then
133 e.warn_parentheses(v)
134 end
135 end
136 end
137
138 redef class AWhileExpr
139 redef fun after_simple_misc(v)
140 do
141 if n_expr isa ATrueExpr then
142 v.warning(self, "loop", "Warning: use `loop` instead of `while true do`.")
143 else
144 n_expr.warn_parentheses(v)
145 end
146 end
147 end
148
149 redef class AForExpr
150 redef fun after_simple_misc(v)
151 do
152 n_expr.warn_parentheses(v)
153 end
154 end
155
156 redef class AIfExpr
157 redef fun after_simple_misc(v)
158 do
159 n_expr.warn_parentheses(v)
160 end
161 end
162
163 redef class AIfexprExpr
164 redef fun after_simple_misc(v)
165 do
166 n_expr.warn_parentheses(v)
167 end
168 end
169
170 redef class AOnceExpr
171 redef fun accept_simple_misc(v)
172 do
173 if v.once_count > 0 then
174 v.warning(self, "nested-once", "Warning: useless once in a once expression.")
175 end
176 v.once_count = v.once_count + 1
177
178 super
179
180 v.once_count = v.once_count - 1
181 end
182 end
183
184 redef class TSemi
185 redef fun accept_simple_misc_token(v)
186 do
187 var n = next_token
188 var p = prev_token
189 if
190 n == null or
191 n isa TEol or
192 n isa EOF or
193 n isa TComment or
194 p == null or
195 p isa TEol or
196 p isa EOF or
197 p isa TComment or
198 p isa TSemi
199 then
200 v.warning(self, "semi", "Warning: superfluous `;`.")
201 return
202 end
203 end
204 end