Merge: class annotation `autoinit` to explicitly lists initializers.
[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 end
44 end
45
46 private class SimpleMiscVisitor
47 super Visitor
48 redef fun visit(n)
49 do
50 n.accept_simple_misc(self)
51 end
52
53 # Number of nested once
54 var once_count: Int = 0
55
56 var toolcontext: ToolContext
57
58 fun warning(node: ANode, tag, msg: String)
59 do
60 toolcontext.warning(node.hot_location, tag, msg)
61 end
62 end
63
64
65 ###############################################################################
66
67 redef class ANode
68 private fun accept_simple_misc(v: SimpleMiscVisitor)
69 do
70 visit_all(v)
71 after_simple_misc(v)
72 end
73 private fun after_simple_misc(v: SimpleMiscVisitor) do end
74 end
75
76 redef class ASignature
77 redef fun after_simple_misc(v)
78 do
79 if self.n_opar != null and self.n_params.is_empty then
80 v.warning(self, "parentheses", "Warning: superfluous parentheses.")
81 end
82 end
83 end
84
85 redef class AExpr
86 # Warn in case of superfluous parentheses
87 private fun warn_parentheses(v: SimpleMiscVisitor) do end
88 end
89
90 redef class AParExpr
91 redef fun warn_parentheses(v)
92 do
93 v.warning(self, "parentheses", "Warning: superfluous parentheses.")
94 end
95 end
96
97 redef class AParExprs
98 redef fun after_simple_misc(v)
99 do
100 if n_exprs.is_empty then
101 v.warning(self, "parentheses", "Warning: superfluous parentheses.")
102 end
103 end
104 end
105
106 redef class AReturnExpr
107 redef fun after_simple_misc(v)
108 do
109 var e = n_expr
110 if e != null then
111 e.warn_parentheses(v)
112 end
113 end
114 end
115
116 redef class AEscapeExpr
117 redef fun after_simple_misc(v)
118 do
119 var e = n_expr
120 if e != null then
121 e.warn_parentheses(v)
122 end
123 end
124 end
125
126 redef class AWhileExpr
127 redef fun after_simple_misc(v)
128 do
129 if n_expr isa ATrueExpr then
130 v.warning(self, "loop", "Warning: use `loop` instead of `while true do`.")
131 else
132 n_expr.warn_parentheses(v)
133 end
134 end
135 end
136
137 redef class AForExpr
138 redef fun after_simple_misc(v)
139 do
140 n_expr.warn_parentheses(v)
141 end
142 end
143
144 redef class AIfExpr
145 redef fun after_simple_misc(v)
146 do
147 n_expr.warn_parentheses(v)
148 end
149 end
150
151 redef class AIfexprExpr
152 redef fun after_simple_misc(v)
153 do
154 n_expr.warn_parentheses(v)
155 end
156 end
157
158 redef class AOnceExpr
159 redef fun accept_simple_misc(v)
160 do
161 if v.once_count > 0 then
162 v.warning(self, "nested-once", "Warning: useless once in a once expression.")
163 end
164 v.once_count = v.once_count + 1
165
166 super
167
168 v.once_count = v.once_count - 1
169 end
170 end