jsduck 5.1.0 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ require 'jsduck/warning/warn_exception'
2
+
3
+ module JsDuck
4
+ module Warning
5
+
6
+ # A basic warning type.
7
+ class Basic
8
+
9
+ # Creates a simple warning with a message text.
10
+ # The warning is disabled by default.
11
+ def initialize(type, msg)
12
+ @type = type
13
+ @msg = msg
14
+ @enabled = false
15
+ @patterns = []
16
+ end
17
+
18
+ # Enables or disables the warning.
19
+ # Optionally enables/disables it for files matching a path_pattern.
20
+ def set(enabled, path_pattern=nil, params=[])
21
+ if path_pattern
22
+ if @enabled == enabled
23
+ raise WarnException, "Warning rule '#{enabled ? '+' : '-'}#{@type}:#{path_pattern}' has no effect"
24
+ else
25
+ @patterns << Regexp.new(Regexp.escape(path_pattern))
26
+ end
27
+ else
28
+ @enabled = enabled
29
+ @patterns = []
30
+ end
31
+ end
32
+
33
+ # True when warning is enabled for the given filename.
34
+ # (The params parameter is ignored).
35
+ def enabled?(filename="", params=[])
36
+ if @patterns.any? {|re| filename =~ re }
37
+ !@enabled
38
+ else
39
+ @enabled
40
+ end
41
+ end
42
+
43
+ # Documentation for the warning.
44
+ def doc
45
+ " #{@enabled ? '+' : '-'}#{@type} - #{@msg}"
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ require 'jsduck/warning/warn_exception'
2
+
3
+ module JsDuck
4
+ module Warning
5
+
6
+ # A deprecated :no_doc* warning which maps to the new :nodoc
7
+ # warning.
8
+ class Deprecated
9
+
10
+ # Creates a deprecated warning with a mapping to :nodoc warning
11
+ # type with given parameters. The warning is disabled by
12
+ # default.
13
+ def initialize(type, msg, nodoc, params)
14
+ @type = type
15
+ @msg = msg
16
+ @enabled = false
17
+ @nodoc = nodoc
18
+ @params = params
19
+ end
20
+
21
+ # Enables or disables the mapped :nodoc warning.
22
+ def set(enabled, path_pattern=nil, params=[])
23
+ @nodoc.set(enabled, path_pattern, @params)
24
+ raise WarnException, "Warning type #{@type} is deprecated, use nodoc(#{@params.join(',')}) instead"
25
+ end
26
+
27
+ # This method shouldn't be called.
28
+ def enabled?(filename="", params=[])
29
+ raise "Deprecated warning '#{@type}' must not be checked for enabled/disabled"
30
+ end
31
+
32
+ # Documentation for the warning.
33
+ def doc
34
+ " -#{@type} - #{@msg} DEPRECATED"
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,79 @@
1
+ require 'jsduck/warning/warn_exception'
2
+ require 'set'
3
+
4
+ module JsDuck
5
+ module Warning
6
+
7
+ # Missing documentation warning.
8
+ class Nodoc
9
+
10
+ TYPES = Set[nil, :class, :member, :param]
11
+ VISIBILITIES = Set[nil, :public, :protected, :private]
12
+
13
+ # Creates the :nodoc warning type
14
+ def initialize
15
+ @rules = []
16
+ # disable by default
17
+ set(false)
18
+ end
19
+
20
+ # Enables or disables a particular sub-warning
21
+ def set(enabled, path_pattern=nil, params=[])
22
+ type = params[0]
23
+ visibility = params[1]
24
+
25
+ unless TYPES.include?(type) && VISIBILITIES.include?(visibility)
26
+ raise WarnException, "Invalid warning parameters: nodoc(#{type},#{visibility})"
27
+ end
28
+
29
+ @rules << {
30
+ :enabled => enabled,
31
+ :type => type,
32
+ :visibility => visibility,
33
+ :path_re => path_pattern ? Regexp.new(Regexp.escape(path_pattern)) : nil
34
+ }
35
+ end
36
+
37
+ # True when the warning is enabled for the given filename and
38
+ # params combination, where the params contain type and
39
+ # visibility setting.
40
+ def enabled?(filename="", params=[])
41
+ type = params[0]
42
+ visibility = params[1]
43
+
44
+ # Filter out rules that apply to our current item
45
+ matches = @rules.find_all do |r|
46
+ (r[:type].nil? || r[:type] == type) &&
47
+ (r[:visibility].nil? || r[:visibility] == visibility) &&
48
+ (r[:path_re].nil? || r[:path_re] =~ filename)
49
+ end
50
+
51
+ return matches.last[:enabled]
52
+ end
53
+
54
+ # Extensive documentation for :nodoc warning
55
+ def doc
56
+ [
57
+ "",
58
+ " -nodoc(<type>,<visibility>) - Missing documentation",
59
+ "",
60
+ " This warning can take parameters with the following values:",
61
+ "",
62
+ " <type> = class | member | param",
63
+ " <visibility> = public | protected | private",
64
+ "",
65
+ " So, to report missing documentation of public classes:",
66
+ "",
67
+ " --warnings='+nodoc(class,public)'",
68
+ "",
69
+ " Or, to report missing docs of all protected items in /etc:",
70
+ "",
71
+ " --warnings='+nodoc(,protected):/etc/'",
72
+ "",
73
+ ]
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,168 @@
1
+ require 'strscan'
2
+ require 'jsduck/warning/warn_exception'
3
+
4
+ module JsDuck
5
+ module Warning
6
+
7
+ # Parses the warnings passed in from command line
8
+ #
9
+ # Grammar:
10
+ #
11
+ # <warnings> := <warning> [ "," <warning> ]*
12
+ #
13
+ # <warning> := ["+" | "-"] <type> [<params-block>] [<path-block>]
14
+ #
15
+ # <type> := \w+
16
+ #
17
+ # <params-block> := "(" [<params>] ")"
18
+ #
19
+ # <params> := <param> [ "," <param> ]*
20
+ #
21
+ # <param> := \w+ | ""
22
+ #
23
+ # <path-block> := ":" <path>
24
+ #
25
+ # <path> := .*
26
+ #
27
+ class Parser
28
+ def initialize(string)
29
+ @scanner = StringScanner.new(string)
30
+ end
31
+
32
+ # Parses the warnings string.
33
+ #
34
+ # For example the following string:
35
+ #
36
+ # +tag,-nodoc(class,private):/some/path
37
+ #
38
+ # is parsed into the following structure:
39
+ #
40
+ # [
41
+ # {
42
+ # :type => :tag,
43
+ # :enabled => true,
44
+ # :params => [],
45
+ # :path => nil,
46
+ # },
47
+ # {
48
+ # :type => :nodoc,
49
+ # :enabled => false,
50
+ # :params => [:class, :private],
51
+ # :path => "/some/path",
52
+ # },
53
+ # ]
54
+ #
55
+ # When scanning fails, raises an exception with a descriptive
56
+ # message.
57
+ def parse
58
+ results = []
59
+
60
+ while !eos?
61
+ results << warning
62
+ match(/,/)
63
+ end
64
+
65
+ results
66
+ end
67
+
68
+ private
69
+
70
+ def warning
71
+ return {
72
+ :enabled => enabled,
73
+ :type => type,
74
+ :params => params,
75
+ :path => path,
76
+ }
77
+ end
78
+
79
+ def enabled
80
+ if match(/\+/)
81
+ true
82
+ elsif match(/-/)
83
+ false
84
+ else
85
+ true
86
+ end
87
+ end
88
+
89
+ def type
90
+ require(/\w+/).to_sym
91
+ end
92
+
93
+ def params
94
+ if match(/\(/)
95
+ ps = []
96
+
97
+ while !look(/\)/)
98
+ ps << param
99
+ break unless match(/,/)
100
+ end
101
+
102
+ require(/\)/)
103
+
104
+ ps
105
+ else
106
+ []
107
+ end
108
+ end
109
+
110
+ def param
111
+ if p = match(/\w+/)
112
+ p.to_sym
113
+ elsif look(/,/)
114
+ nil
115
+ else
116
+ unexpected_char
117
+ end
118
+ end
119
+
120
+ def path
121
+ if match(/:/)
122
+ match(/[^,]*/).strip
123
+ else
124
+ nil
125
+ end
126
+ end
127
+
128
+ # scans a pattern, throws error on failure
129
+ def require(re)
130
+ if m = match(re)
131
+ m
132
+ else
133
+ unexpected_char
134
+ end
135
+ end
136
+
137
+ # Reports unexpected character
138
+ def unexpected_char
139
+ # do successful empty scan, so we can use #pre_match and #post_match
140
+ @scanner.scan(//)
141
+ raise WarnException, "Unexpected '#{@scanner.peek(1)}' at " +
142
+ "--warnings='#{@scanner.pre_match}<HERE>#{@scanner.post_match}'"
143
+ end
144
+
145
+ # scans a pattern, ignoring the optional whitespace before it
146
+ def match(re)
147
+ skip_ws
148
+ @scanner.scan(re)
149
+ end
150
+
151
+ def look(re)
152
+ skip_ws
153
+ @scanner.check(re)
154
+ end
155
+
156
+ def eos?
157
+ skip_ws
158
+ @scanner.eos?
159
+ end
160
+
161
+ def skip_ws
162
+ @scanner.scan(/\s*/)
163
+ end
164
+
165
+ end
166
+
167
+ end
168
+ end
@@ -0,0 +1,106 @@
1
+ require 'jsduck/warning/basic'
2
+ require 'jsduck/warning/nodoc'
3
+ require 'jsduck/warning/deprecated'
4
+ require 'jsduck/warning/all'
5
+ require 'jsduck/warning/warn_exception'
6
+
7
+ module JsDuck
8
+ module Warning
9
+
10
+ # Warnings management
11
+ class Registry
12
+
13
+ def initialize
14
+ @warnings = []
15
+ @warnings_map = {}
16
+
17
+ # Basic warnings
18
+ [
19
+ [:global, "Member doesn't belong to any class"],
20
+ [:inheritdoc, "@inheritdoc referring to unknown class or member"],
21
+ [:extend, "@extend/mixin/requires/uses referring to unknown class"],
22
+ [:tag, "Use of unsupported @tag"],
23
+ [:tag_repeated, "An @tag used multiple times, but only once allowed"],
24
+ [:tag_syntax, "@tag syntax error"],
25
+ [:link, "{@link} to unknown class or member"],
26
+ [:link_ambiguous, "{@link} is ambiguous"],
27
+ [:link_auto, "Auto-detected link to unknown class or member"],
28
+ [:html, "Unclosed HTML tag"],
29
+
30
+ [:alt_name, "Name used as both classname and alternate classname"],
31
+ [:name_missing, "Member or parameter has no name"],
32
+ [:dup_param, "Method has two parameters with the same name"],
33
+ [:dup_member, "Class has two members with the same name"],
34
+ [:req_after_opt, "Required parameter comes after optional"],
35
+ [:param_count, "Less parameters documented than detected from code"],
36
+ [:subproperty, "@param foo.bar where foo param doesn't exist"],
37
+ [:sing_static, "Singleton class member marked as @static"],
38
+ [:type_syntax, "Syntax error in {type definition}"],
39
+ [:type_name, "Unknown type referenced in {type definition}"],
40
+ [:enum, "Enum with invalid values or no values at all"],
41
+ [:fires, "@fires references unknown event"],
42
+
43
+ [:image, "{@img} referring to missing file"],
44
+ [:image_unused, "An image exists in --images dir that's not used"],
45
+ [:cat_old_format, "Categories file uses old deprecated format"],
46
+ [:cat_no_match, "Class pattern in categories file matches nothing"],
47
+ [:cat_class_missing, "Class is missing from categories file"],
48
+ [:guide, "Guide is missing from --guides dir"],
49
+
50
+ [:aside, "Problem with @aside tag"],
51
+ [:hide, "Problem with @hide tag"],
52
+ ].each do |w|
53
+ register(w[0], Warning::Basic.new(w[0], w[1]))
54
+ end
55
+
56
+ # :nodoc warning
57
+ register(:nodoc, Warning::Nodoc.new)
58
+
59
+ # :all warning (encompasses all other warning types)
60
+ register(:all, Warning::All.new(@warnings.clone))
61
+
62
+ # :deprecated warnings (linking to :nodoc warning)
63
+ [
64
+ {:type => :no_doc, :msg => "Alias for nodoc(class,public)", :params => [:class, :public]},
65
+ {:type => :no_doc_member, :msg => "Alias for nodoc(member,public)", :params => [:member, :public]},
66
+ {:type => :no_doc_param, :msg => "Alias for nodoc(param,public)", :params => [:param, :public]},
67
+ ].each do |w|
68
+ register(w[:type], Warning::Deprecated.new(w[:type], w[:msg], @warnings_map[:nodoc], w[:params]))
69
+ end
70
+
71
+ end
72
+
73
+ def register(type, warning)
74
+ @warnings << warning
75
+ @warnings_map[type] = warning
76
+ end
77
+
78
+ # Enables or disables a particular warning type.
79
+ # Additionally a filename pattern and params for the warning can be specified.
80
+ def set(type, enabled, path_pattern=nil, params=[])
81
+ if @warnings_map[type]
82
+ @warnings_map[type].set(enabled, path_pattern, params)
83
+ else
84
+ raise WarnException, "Warning of type '#{type}' doesn't exist"
85
+ end
86
+ end
87
+
88
+ # get documentation for all warnings
89
+ def doc
90
+ @warnings.map {|w| w.doc }.compact.flatten
91
+ end
92
+
93
+ # True when the warning is enabled for the given type and
94
+ # filename combination.
95
+ def enabled?(type, filename, params=[])
96
+ @warnings_map[type].enabled?(filename, params)
97
+ end
98
+
99
+ def has?(type)
100
+ @warnings_map.has_key?(type)
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,10 @@
1
+ module JsDuck
2
+ module Warning
3
+
4
+ # An exception thrown by JsDuck::Warning classes that is supposed
5
+ # to result in a warning being logged by Logger.
6
+ class WarnException < Exception
7
+ end
8
+
9
+ end
10
+ end