Merge: Locally disable warnings
authorJean Privat <jean@pryen.org>
Sat, 20 Dec 2014 01:24:27 +0000 (20:24 -0500)
committerJean Privat <jean@pryen.org>
Sat, 20 Dec 2014 01:24:27 +0000 (20:24 -0500)
The new annotation `no_warning`, used in module, will disable specific (or all) warnings in the module.

~~~
module lexer is no_warning("missing-doc")
module parser is no_warning("missing-doc", "unread-variable")
module toto is no_warning("all")
~~~

Note: Now there is less noise, a future PR (currently in writing) will remove a lot of warnings in the `src/` directory.

Close #774

Pull-Request: #1048
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

13 files changed:
src/annotation.nit
src/frontend/check_annotation.nit
src/frontend/frontend.nit
src/frontend/no_warning.nit [new file with mode: 0644]
src/literal.nit
src/parser/lexer.nit
src/parser/parser.nit
src/parser/parser_abs.nit
src/parser/parser_nodes.nit
src/parser/parser_prod.nit
src/parser/xss/main.xss
src/parser_util.nit
src/toolcontext.nit

index af63ad3..19653a3 100644 (file)
@@ -16,7 +16,7 @@
 module annotation
 
 import modelbuilder
-private import literal
+import literal
 import model::mmodule_data
 
 redef class Prod
@@ -34,29 +34,9 @@ redef class Prod
                end
                return res.first
        end
-
-       # Return all its annotations of a given name in the order of their declaration
-       # Retun an empty array if no such an annotation.
-       fun get_annotations(name: String): Array[AAnnotation]
-       do
-               var res = new Array[AAnnotation]
-               var nas = n_annotations
-               if nas == null then return res
-               for na in nas.n_items do
-                       if na.name != name then continue
-                       res.add(na)
-               end
-               return res
-       end
 end
 
 redef class AAnnotation
-       # The name of the annotation
-       fun name: String
-       do
-               return n_atid.n_id.text
-       end
-
        # Get the single argument of `self` as a `String`.
        # Raise error and return null on any inconsistency.
        fun arg_as_string(modelbuilder: ModelBuilder): nullable String
@@ -100,37 +80,6 @@ redef class AAnnotation
        end
 end
 
-redef class AExpr
-       # Get `self` as a `String`.
-       # Return null if not a string.
-       fun as_string: nullable String
-       do
-               if not self isa AStringFormExpr then return null
-               return self.value.as(not null)
-       end
-
-       # Get `self` as an `Int`.
-       # Return null if not an integer.
-       fun as_int: nullable Int
-       do
-               if not self isa AIntExpr then return null
-               return self.value.as(not null)
-       end
-
-       # Get `self` as a single identifier.
-       # Return null if not a single identifier.
-       fun as_id: nullable String
-       do
-               if self isa AMethidExpr then
-                       return self.collect_text
-               end
-               if not self isa ACallExpr then return null
-               if not self.n_expr isa AImplicitSelfExpr then return null
-               if not self.n_args.n_exprs.is_empty then return null
-               return self.n_id.text
-       end
-end
-
 redef class ModelBuilder
        # Collect all annotations by `name` assocated to `mmodule` and its imported modules.
        # Note that visibility is not considered.
index 7cd186e..2e45627 100644 (file)
@@ -88,6 +88,7 @@ old_style_init
 abstract
 intern
 extern
+no_warning
 
 pkgconfig
 c_compiler_option
index 53c1a77..713c6fa 100644 (file)
@@ -15,6 +15,7 @@
 # Collect and orchestration of main frontend phases
 module frontend
 
+import no_warning
 import simple_misc_analysis
 import literal
 import modelize
diff --git a/src/frontend/no_warning.nit b/src/frontend/no_warning.nit
new file mode 100644 (file)
index 0000000..c862075
--- /dev/null
@@ -0,0 +1,70 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Fill toolcontext information about blacklisting of warnings.
+module no_warning
+
+import modelbuilder
+private import literal
+
+redef class ToolContext
+       # The phase should be executed before any warning on the module is processed.
+       var no_warning_phase: Phase = new NoWarningPhase(self, [literal_phase])
+end
+
+private class NoWarningPhase
+       super Phase
+
+       redef fun process_nmodule(nmodule)
+       do
+               # Get the mmodule
+               var mmodule = nmodule.mmodule
+               assert mmodule != null
+
+               # If no decl block then quit
+               var nmoduledecl = nmodule.n_moduledecl
+               if nmoduledecl == null then return
+
+               var modelbuilder = toolcontext.modelbuilder
+
+               # Get all the new annotations
+               var name = "no_warning"
+               var annots = nmoduledecl.get_annotations(name)
+
+               if annots.is_empty then return
+
+               var source = nmodule.location.file
+               if source == null then
+                       modelbuilder.warning(annots.first, "file-less-module", "Warning: annotation `{name}` does not currently work on file-less modules.")
+                       return
+               end
+
+               for annot in annots do
+                       var args = annot.n_args
+                       if args.is_empty then
+                               modelbuilder.error(annot, "Annotation error: `{name}` needs a list of warnings. Use `\"all\"` to disable all warnings.")
+                               continue
+                       end
+                       for arg in args do
+                               var tag = arg.as_string
+                               if tag == null then
+                                       modelbuilder.error(arg, "Annotation error: `{name}` expects String as arguments.")
+                                       continue
+                               end
+
+                               toolcontext.warning_blacklist[source].add(tag)
+                       end
+               end
+       end
+end
index e39409f..5af1808 100644 (file)
@@ -55,6 +55,38 @@ redef class ANode
        private fun accept_literal(v: LiteralVisitor) do end
 end
 
+redef class AExpr
+       # Get `self` as a `String`.
+       # Return null if not a string.
+       fun as_string: nullable String
+       do
+               if not self isa AStringFormExpr then return null
+               return self.value.as(not null)
+       end
+
+       # Get `self` as an `Int`.
+       # Return null if not an integer.
+       fun as_int: nullable Int
+       do
+               if not self isa AIntExpr then return null
+               return self.value.as(not null)
+       end
+
+       # Get `self` as a single identifier.
+       # Return null if not a single identifier.
+       fun as_id: nullable String
+       do
+               if self isa AMethidExpr then
+                       return self.collect_text
+               end
+               if not self isa ACallExpr then return null
+               if not self.n_expr isa AImplicitSelfExpr then return null
+               if not self.n_args.n_exprs.is_empty then return null
+               return self.n_id.text
+       end
+end
+
+
 redef class AIntExpr
        # The value of the literal int once computed.
        var value: nullable Int
index e7d48a0..2335cd3 100644 (file)
@@ -1,6 +1,6 @@
 # Lexer and its tokens.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module lexer
+module lexer is no_warning("missing-doc")
 
 intrude import parser_nodes
 intrude import lexer_work
index d9b49c2..00a3106 100644 (file)
@@ -1,6 +1,6 @@
 # Parser.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module parser
+module parser is no_warning("missing-doc", "unread-variable")
 
 intrude import parser_prod
 intrude import parser_work
index 1aaa263..bc9b980 100644 (file)
@@ -1,6 +1,6 @@
 # Raw AST node hierarchy.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module parser_abs
+module parser_abs is no_warning("missing-doc")
 
 import location
 
index 493ed0e..189c306 100644 (file)
@@ -117,8 +117,48 @@ abstract class ANode
        # Visit all nodes in order.
        # Thus, call `v.enter_visit(e)` for each child `e`
        fun visit_all(v: Visitor) is abstract
+
+       # Do a deep search and return an array of tokens that match a given text
+       fun collect_tokens_by_text(text: String): Array[Token]
+       do
+               var v = new CollectTokensByTextVisitor(text)
+               v.enter_visit(self)
+               return v.result
+       end
+
+       # Do a deep search and return an array of node that are annotated
+       # The attached node can be retrieved by two invocations of parent
+       fun collect_annotations_by_name(name: String): Array[AAnnotation]
+       do
+               var v = new CollectAnnotationsByNameVisitor(name)
+               v.enter_visit(self)
+               return v.result
+       end
 end
 
+private class CollectTokensByTextVisitor
+       super Visitor
+       var text: String
+       var result = new Array[Token]
+       redef fun visit(node)
+       do
+               node.visit_all(self)
+               if node isa Token and node.text == text then result.add(node)
+       end
+end
+
+private class CollectAnnotationsByNameVisitor
+       super Visitor
+       var name: String
+       var result = new Array[AAnnotation]
+       redef fun visit(node)
+       do
+               node.visit_all(self)
+               if node isa AAnnotation and node.n_atid.n_id.text == name then result.add(node)
+       end
+end
+
+
 # A sequence of nodes
 # It is a specific class (instead of using a Array) to track the parent/child relation when nodes are added or removed
 class ANodes[E: ANode]
@@ -269,6 +309,20 @@ abstract class Prod
        # All the annotations attached directly to the node
        var n_annotations: nullable AAnnotations = null is writable
 
+       # Return all its annotations of a given name in the order of their declaration
+       # Retun an empty array if no such an annotation.
+       fun get_annotations(name: String): Array[AAnnotation]
+       do
+               var res = new Array[AAnnotation]
+               var nas = n_annotations
+               if nas == null then return res
+               for na in nas.n_items do
+                       if na.name != name then continue
+                       res.add(na)
+               end
+               return res
+       end
+
        redef fun replace_with(n: ANode)
        do
                super
@@ -2038,6 +2092,12 @@ class AAnnotation
        var n_opar: nullable TOpar = null is writable
        var n_args = new ANodes[AExpr](self)
        var n_cpar: nullable TCpar = null is writable
+
+       # The name of the annotation
+       fun name: String
+       do
+               return n_atid.n_id.text
+       end
 end
 
 # An annotation name
index 39fafc6..d49b809 100644 (file)
@@ -1,6 +1,6 @@
 # Production AST nodes full definition.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module parser_prod
+module parser_prod is no_warning("missing-doc")
 
 import lexer
 intrude import parser_nodes
index 00507f9..fae2ea4 100644 (file)
@@ -23,7 +23,7 @@ $ include 'prods.xss'
 $ output 'parser_abs.nit'
 # Raw AST node hierarchy.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module parser_abs
+module parser_abs is no_warning("missing-doc")
 
 import location
 
@@ -34,7 +34,7 @@ $ end output
 $ output 'lexer.nit'
 # Lexer and its tokens.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module lexer
+module lexer is no_warning("missing-doc")
 
 $ if $usermodule
 intrude import $usermodule
@@ -51,7 +51,7 @@ $ end output
 $ output 'parser_prod.nit'
 # Production AST nodes full definition.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module parser_prod
+module parser_prod is no_warning("missing-doc")
 
 import lexer
 $ if $usermodule
@@ -67,7 +67,7 @@ $ end output
 $ output 'parser.nit'
 # Parser.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module parser
+module parser is no_warning("missing-doc", "unread-variable")
 
 intrude import parser_prod
 intrude import parser_work
index 82aec57..17aa012 100644 (file)
@@ -246,44 +246,3 @@ class InjectedLexer
                return tok
        end
 end
-
-redef class ANode
-       # Do a deep search and return an array of tokens that match a given text
-       fun collect_tokens_by_text(text: String): Array[Token]
-       do
-               var v = new CollectTokensByTextVisitor(text)
-               v.enter_visit(self)
-               return v.result
-       end
-
-       # Do a deep search and return an array of node that are annotated
-       # The attached node can be retrieved by two invocation of parent
-       fun collect_annotations_by_name(name: String): Array[AAnnotation]
-       do
-               var v = new CollectAnnotationsByNameVisitor(name)
-               v.enter_visit(self)
-               return v.result
-       end
-end
-
-private class CollectTokensByTextVisitor
-       super Visitor
-       var text: String
-       var result = new Array[Token]
-       redef fun visit(node)
-       do
-               node.visit_all(self)
-               if node isa Token and node.text == text then result.add(node)
-       end
-end
-
-private class CollectAnnotationsByNameVisitor
-       super Visitor
-       var name: String
-       var result = new Array[AAnnotation]
-       redef fun visit(node)
-       do
-               node.visit_all(self)
-               if node isa AAnnotation and node.n_atid.n_id.text == name then result.add(node)
-       end
-end
index 4547fb7..3e99de2 100644 (file)
@@ -24,6 +24,7 @@ import opts
 import location
 import version
 import template
+import more_collections
 
 # A warning or an error
 class Message
@@ -111,6 +112,25 @@ class ToolContext
        # Set this value to `true` if you need to keep the program going in case of error.
        var keep_going = false is writable
 
+       # List of tags per source-file whose warnings are not displayed.
+       #
+       # Initially empty, it is up to the toll to fill it.
+       # The tag "all" means all warnings and advices.
+       var warning_blacklist = new MultiHashMap[SourceFile, String]
+
+       # Is the source-file of `l` associated with `tag` in `warning_blacklist`?
+       #
+       # currently returns `false` if `l` is null or does not have a source-file.
+       fun is_warning_blacklisted(l: nullable Location, tag: String): Bool
+       do
+               if l == null then return false
+               var f = l.file
+               if f == null then return false
+               var tags = warning_blacklist.get_or_null(f)
+               if tags == null then return false
+               return tags.has("all") or tags.has(tag)
+       end
+
        # Output all current stacked messages and display total error informations
        #
        # Return true if no errors occurred.
@@ -181,6 +201,7 @@ class ToolContext
        do
                if opt_warning.value.has("no-{tag}") then return
                if not opt_warning.value.has(tag) and opt_warn.value == 0 then return
+               if is_warning_blacklisted(l, tag) then return
                messages.add(new Message(l, tag, text))
                warning_count = warning_count + 1
                if opt_stop_on_first_error.value then check_errors
@@ -203,6 +224,7 @@ class ToolContext
        do
                if opt_warning.value.has("no-{tag}") then return
                if not opt_warning.value.has(tag) and opt_warn.value <= 1 then return
+               if is_warning_blacklisted(l, tag) then return
                messages.add(new Message(l, tag, text))
                warning_count = warning_count + 1
                if opt_stop_on_first_error.value then check_errors