26d67100cf60a818d86d70aba08ae02c0fed2f38
[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 phase
25
26 redef class ToolContext
27 var simple_misc_analysis_phase: Phase = new SimpleMiscAnalysisPhase(self, null)
28 end
29
30 private class SimpleMiscAnalysisPhase
31 super Phase
32 redef fun process_nmodule(nmodule) do nmodule.do_simple_misc_analysis(toolcontext)
33 end
34
35 redef class AModule
36 # Visit the module to detect easy warnings that does not need the metamodel or the importation
37 # Warnings are displayed on the toolcontext
38 fun do_simple_misc_analysis(toolcontext: ToolContext)
39 do
40 var v = new SimpleMiscVisitor(toolcontext)
41 v.enter_visit(self)
42 end
43 end
44
45 private class SimpleMiscVisitor
46 super Visitor
47 redef fun visit(n)
48 do
49 n.accept_simple_misc(self)
50 end
51
52 # Number of nested once
53 var once_count: Int = 0
54
55 var toolcontext: ToolContext
56
57 fun warning(node: ANode, msg: String)
58 do
59 toolcontext.warning(node.hot_location, msg)
60 end
61
62 init(toolcontext: ToolContext)
63 do
64 self.toolcontext = toolcontext
65 end
66 end
67
68
69 ###############################################################################
70
71 redef class ANode
72 private fun accept_simple_misc(v: SimpleMiscVisitor)
73 do
74 visit_all(v)
75 after_simple_misc(v)
76 end
77 private fun after_simple_misc(v: SimpleMiscVisitor) do end
78 end
79
80 redef class ASignature
81 redef fun after_simple_misc(v)
82 do
83 if self.n_opar != null and self.n_params.is_empty then
84 v.warning(self, "Warning: superfluous parentheses.")
85 end
86 end
87 end
88
89 redef class AExpr
90 # Warn in case of superfluous parentheses
91 private fun warn_parentheses(v: SimpleMiscVisitor) do end
92 end
93
94 redef class AParExpr
95 redef fun warn_parentheses(v)
96 do
97 v.warning(self, "Warning: superfluous parentheses.")
98 end
99 end
100
101 redef class AParExprs
102 redef fun after_simple_misc(v)
103 do
104 if n_exprs.is_empty then
105 v.warning(self, "Warning: superfluous parentheses.")
106 end
107 end
108 end
109
110 redef class AReturnExpr
111 redef fun after_simple_misc(v)
112 do
113 var e = n_expr
114 if e != null then
115 e.warn_parentheses(v)
116 end
117 end
118 end
119
120 redef class AContinueExpr
121 redef fun after_simple_misc(v)
122 do
123 var e = n_expr
124 if e != null then
125 e.warn_parentheses(v)
126 end
127 end
128 end
129
130 redef class ABreakExpr
131 redef fun after_simple_misc(v)
132 do
133 var e = n_expr
134 if e != null then
135 e.warn_parentheses(v)
136 end
137 end
138 end
139
140 redef class AWhileExpr
141 redef fun after_simple_misc(v)
142 do
143 if n_expr isa ATrueExpr then
144 v.warning(self, "Warning: use 'loop' instead of 'while true do'.")
145 else
146 n_expr.warn_parentheses(v)
147 end
148 end
149 end
150
151 redef class AForExpr
152 redef fun after_simple_misc(v)
153 do
154 n_expr.warn_parentheses(v)
155 end
156 end
157
158 redef class AIfExpr
159 redef fun after_simple_misc(v)
160 do
161 n_expr.warn_parentheses(v)
162 end
163 end
164
165 redef class AIfexprExpr
166 redef fun after_simple_misc(v)
167 do
168 n_expr.warn_parentheses(v)
169 end
170 end
171
172 redef class AOnceExpr
173 redef fun accept_simple_misc(v)
174 do
175 if v.once_count > 0 then
176 v.warning(self, "Useless once in a once expression.")
177 end
178 v.once_count = v.once_count + 1
179
180 super
181
182 v.once_count = v.once_count - 1
183 end
184 end