jsduck 3.0.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/Rakefile +73 -41
- data/js-classes/String.js +10 -8
- data/jsduck.gemspec +2 -2
- data/lib/jsduck/accessors.rb +3 -0
- data/lib/jsduck/aggregator.rb +34 -1
- data/lib/jsduck/api_exporter.rb +48 -0
- data/lib/jsduck/app.rb +47 -182
- data/lib/jsduck/app_data.rb +34 -0
- data/lib/jsduck/{exporter.rb → app_exporter.rb} +21 -19
- data/lib/jsduck/categories.rb +13 -62
- data/lib/jsduck/class.rb +23 -9
- data/lib/jsduck/class_formatter.rb +2 -2
- data/lib/jsduck/class_writer.rb +49 -0
- data/lib/jsduck/doc_formatter.rb +16 -8
- data/lib/jsduck/doc_parser.rb +42 -36
- data/lib/jsduck/examples.rb +9 -5
- data/lib/jsduck/file_categories.rb +65 -0
- data/lib/jsduck/full_exporter.rb +29 -0
- data/lib/jsduck/guides.rb +12 -10
- data/lib/jsduck/images.rb +2 -2
- data/lib/jsduck/index_html.rb +67 -0
- data/lib/jsduck/inherit_doc.rb +75 -0
- data/lib/jsduck/js_parser.rb +8 -1
- data/lib/jsduck/lint.rb +9 -9
- data/lib/jsduck/logger.rb +64 -6
- data/lib/jsduck/merger.rb +29 -25
- data/lib/jsduck/null_object.rb +19 -0
- data/lib/jsduck/options.rb +46 -20
- data/lib/jsduck/renderer.rb +24 -18
- data/lib/jsduck/search_data.rb +2 -2
- data/lib/jsduck/source_writer.rb +19 -6
- data/lib/jsduck/stats.rb +103 -0
- data/lib/jsduck/template_dir.rb +51 -0
- data/lib/jsduck/videos.rb +9 -6
- data/lib/jsduck/welcome.rb +14 -8
- data/opt/extjs-welcome.html +74 -0
- data/opt/touch-iframe.html +85 -0
- data/opt/touch-welcome.html +122 -0
- metadata +401 -389
- data/bin/stats +0 -92
- data/lib/jsduck/aliases.rb +0 -54
data/lib/jsduck/examples.rb
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
require 'jsduck/json_duck'
|
2
|
+
require 'jsduck/null_object'
|
2
3
|
|
3
4
|
module JsDuck
|
4
5
|
|
5
6
|
# Reads in examples JSON file
|
6
7
|
class Examples
|
7
|
-
|
8
|
-
|
8
|
+
# Creates Examples object from filename.
|
9
|
+
def self.create(filename)
|
10
|
+
if filename
|
11
|
+
Examples.new(filename)
|
12
|
+
else
|
13
|
+
NullObject.new(:to_array => [])
|
14
|
+
end
|
9
15
|
end
|
10
16
|
|
11
17
|
# Parses examples config file
|
12
|
-
def
|
18
|
+
def initialize(filename)
|
13
19
|
@examples = JsonDuck.read(filename)
|
14
20
|
end
|
15
21
|
|
16
22
|
# Writes examples JSON file to dir
|
17
23
|
def write(dir)
|
18
|
-
return if @examples.length == 0
|
19
|
-
|
20
24
|
FileUtils.mkdir(dir) unless File.exists?(dir)
|
21
25
|
# Write the JSON to output dir, so it's available in released
|
22
26
|
# version of docs and people can use it with JSDuck by themselves.
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module JsDuck
|
2
|
+
|
3
|
+
# Reads categories info from config file
|
4
|
+
class FileCategories
|
5
|
+
def initialize(filename, relations)
|
6
|
+
@filename = filename
|
7
|
+
@relations = relations
|
8
|
+
end
|
9
|
+
|
10
|
+
# Parses categories in JSON file
|
11
|
+
def generate
|
12
|
+
@categories = JsonDuck.read(@filename)
|
13
|
+
|
14
|
+
# Don't crash if old syntax is used.
|
15
|
+
if @categories.is_a?(Hash) && @categories["categories"]
|
16
|
+
Logger.instance.warn(:old_cat_format, 'Update categories file to contain just the array inside {"categories": [...]}')
|
17
|
+
@categories = @categories["categories"]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Perform expansion on all class names containing * wildcard
|
21
|
+
@categories.each do |cat|
|
22
|
+
cat["groups"].each do |group|
|
23
|
+
group["classes"] = group["classes"].map do |name|
|
24
|
+
expand(name) # name =~ /\*/ ? expand(name) : name
|
25
|
+
end.flatten
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
validate
|
30
|
+
|
31
|
+
@categories
|
32
|
+
end
|
33
|
+
|
34
|
+
# Expands class name like 'Foo.*' into multiple class names.
|
35
|
+
def expand(name)
|
36
|
+
re = Regexp.new("^" + name.split(/\*/, -1).map {|part| Regexp.escape(part) }.join('.*') + "$")
|
37
|
+
classes = @relations.to_a.find_all {|cls| re =~ cls[:name] && !cls[:private] }.map {|cls| cls[:name] }.sort
|
38
|
+
if classes.length == 0
|
39
|
+
Logger.instance.warn(:cat_no_match, "No class found matching a pattern '#{name}' in categories file.")
|
40
|
+
end
|
41
|
+
classes
|
42
|
+
end
|
43
|
+
|
44
|
+
# Prints warnings for missing classes in categories file
|
45
|
+
def validate
|
46
|
+
# Build a map of all classes listed in categories
|
47
|
+
listed_classes = {}
|
48
|
+
@categories.each do |cat|
|
49
|
+
cat["groups"].each do |group|
|
50
|
+
group["classes"].each do |cls_name|
|
51
|
+
listed_classes[cls_name] = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Check that each existing non-private class is listed
|
57
|
+
@relations.each do |cls|
|
58
|
+
unless listed_classes[cls[:name]] || cls[:private]
|
59
|
+
Logger.instance.warn(:cat_class_missing, "Class '#{cls[:name]}' not found in categories file")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'jsduck/class'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
|
5
|
+
# Exporter for all the class docs.
|
6
|
+
class FullExporter
|
7
|
+
def initialize(relations, opts)
|
8
|
+
@relations = relations
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns all data in Class object as hash.
|
12
|
+
def export(cls)
|
13
|
+
h = cls.to_hash
|
14
|
+
h[:members] = {}
|
15
|
+
Class.default_members_hash.each_key do |key|
|
16
|
+
h[:members][key] = cls.members(key)
|
17
|
+
h[:statics][key] = cls.members(key, :statics)
|
18
|
+
end
|
19
|
+
h[:component] = cls.inherits_from?("Ext.Component")
|
20
|
+
h[:superclasses] = cls.superclasses.collect {|c| c.full_name }
|
21
|
+
h[:subclasses] = @relations.subclasses(cls).collect {|c| c.full_name }
|
22
|
+
h[:mixedInto] = @relations.mixed_into(cls).collect {|c| c.full_name }
|
23
|
+
h[:allMixins] = cls.all_mixins.collect {|c| c.full_name }
|
24
|
+
h
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/jsduck/guides.rb
CHANGED
@@ -1,26 +1,30 @@
|
|
1
1
|
require 'jsduck/logger'
|
2
2
|
require 'jsduck/json_duck'
|
3
|
+
require 'jsduck/null_object'
|
3
4
|
require 'fileutils'
|
4
5
|
|
5
6
|
module JsDuck
|
6
7
|
|
7
8
|
# Reads in guides and converts them to JsonP files
|
8
9
|
class Guides
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
# Creates Guides object from filename and formatter
|
11
|
+
def self.create(filename, formatter)
|
12
|
+
if filename
|
13
|
+
Guides.new(filename, formatter)
|
14
|
+
else
|
15
|
+
NullObject.new(:to_array => [], :to_html => "")
|
16
|
+
end
|
12
17
|
end
|
13
18
|
|
14
19
|
# Parses guides config file
|
15
|
-
def
|
20
|
+
def initialize(filename, formatter)
|
16
21
|
@path = File.dirname(filename)
|
17
22
|
@guides = JsonDuck.read(filename)
|
23
|
+
@formatter = formatter
|
18
24
|
end
|
19
25
|
|
20
26
|
# Writes all guides to given dir in JsonP format
|
21
27
|
def write(dir)
|
22
|
-
return if @guides.length == 0
|
23
|
-
|
24
28
|
FileUtils.mkdir(dir) unless File.exists?(dir)
|
25
29
|
@guides.each {|group| group["items"].each {|g| write_guide(g, dir) } }
|
26
30
|
# Write the JSON to output dir, so it's available in released
|
@@ -38,11 +42,11 @@ module JsDuck
|
|
38
42
|
elsif File.exists?(tutorial_dir)
|
39
43
|
in_dir = tutorial_dir
|
40
44
|
else
|
41
|
-
return Logger.instance.warn("Guide #{guide_dir} / #{tutorial_dir} not found")
|
45
|
+
return Logger.instance.warn(:guide, "Guide #{guide_dir} / #{tutorial_dir} not found")
|
42
46
|
end
|
43
47
|
|
44
48
|
guide_file = in_dir + "/README.md"
|
45
|
-
return Logger.instance.warn("README.md not found in #{in_dir}") unless File.exists?(guide_file)
|
49
|
+
return Logger.instance.warn(:guide, "README.md not found in #{in_dir}") unless File.exists?(guide_file)
|
46
50
|
|
47
51
|
Logger.instance.log("Writing guide", out_dir)
|
48
52
|
# Copy the whole guide dir over
|
@@ -63,8 +67,6 @@ module JsDuck
|
|
63
67
|
|
64
68
|
# Returns HTML listing of guides
|
65
69
|
def to_html
|
66
|
-
return "" if @guides.length == 0
|
67
|
-
|
68
70
|
html = @guides.map do |group|
|
69
71
|
[
|
70
72
|
"<h3>#{group['title']}</h3>",
|
data/lib/jsduck/images.rb
CHANGED
@@ -35,7 +35,7 @@ module JsDuck
|
|
35
35
|
def copy(output_dir)
|
36
36
|
@images.each_key do |img|
|
37
37
|
unless copy_img(img, output_dir)
|
38
|
-
Logger.instance.warn("Image not found.", img)
|
38
|
+
Logger.instance.warn(:image, "Image not found.", img)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
report_unused
|
@@ -62,7 +62,7 @@ module JsDuck
|
|
62
62
|
def report_unused
|
63
63
|
@paths.each_pair do |path, map|
|
64
64
|
map.each_pair do |img, used|
|
65
|
-
Logger.instance.warn("Image not used.", img) unless used
|
65
|
+
Logger.instance.warn(:image_unused, "Image not used.", img) unless used
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'jsduck/logger'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
|
6
|
+
# Deals with creation of main HTML or PHP files.
|
7
|
+
class IndexHtml
|
8
|
+
attr_accessor :welcome
|
9
|
+
attr_accessor :categories
|
10
|
+
attr_accessor :guides
|
11
|
+
|
12
|
+
def initialize(opts)
|
13
|
+
@opts = opts
|
14
|
+
end
|
15
|
+
|
16
|
+
# In normal mode creates index.html.
|
17
|
+
#
|
18
|
+
# When --seo enabled, creates index.php, template.html and print-template.html.
|
19
|
+
def write
|
20
|
+
if @opts.seo
|
21
|
+
FileUtils.cp(@opts.template_dir+"/index.php", @opts.output_dir+"/index.php")
|
22
|
+
create_template_html(@opts.template_dir+"/template.html", @opts.output_dir+"/template.html")
|
23
|
+
create_print_template_html(@opts.template_dir+"/print-template.html", @opts.output_dir+"/print-template.html")
|
24
|
+
else
|
25
|
+
create_template_html(@opts.template_dir+"/template.html", @opts.output_dir+"/index.html")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def create_template_html(in_file, out_file)
|
32
|
+
write_template(in_file, out_file, {
|
33
|
+
"{title}" => @opts.title,
|
34
|
+
"{header}" => @opts.header,
|
35
|
+
"{footer}" => "<div id='footer-content' style='display: none'>#{@opts.footer}</div>",
|
36
|
+
"{extjs_path}" => @opts.extjs_path,
|
37
|
+
"{local_storage_db}" => @opts.local_storage_db,
|
38
|
+
"{show_print_button}" => @opts.seo ? "true" : "false",
|
39
|
+
"{touch_examples_ui}" => @opts.touch_examples_ui ? "true" : "false",
|
40
|
+
"{welcome}" => @welcome.to_html,
|
41
|
+
"{categories}" => @categories.to_html,
|
42
|
+
"{guides}" => @guides.to_html,
|
43
|
+
"{head_html}" => @opts.head_html,
|
44
|
+
"{body_html}" => @opts.body_html,
|
45
|
+
})
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_print_template_html(in_file, out_file)
|
49
|
+
write_template(in_file, out_file, {
|
50
|
+
"{title}" => @opts.title,
|
51
|
+
"{header}" => @opts.header,
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
# Opens in_file, replaces {keys} inside it, writes to out_file
|
56
|
+
def write_template(in_file, out_file, replacements)
|
57
|
+
Logger.instance.log("Writing", out_file)
|
58
|
+
html = IO.read(in_file)
|
59
|
+
html.gsub!(/\{\w+\}/) do |key|
|
60
|
+
replacements[key] ? replacements[key] : key
|
61
|
+
end
|
62
|
+
File.open(out_file, 'w') {|f| f.write(html) }
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'jsduck/logger'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
|
5
|
+
# Deals with inheriting documentation
|
6
|
+
class InheritDoc
|
7
|
+
def initialize(relations)
|
8
|
+
@relations = relations
|
9
|
+
end
|
10
|
+
|
11
|
+
# Performs all inheriting
|
12
|
+
def resolve_all
|
13
|
+
@relations.each do |cls|
|
14
|
+
cls.all_local_members.each do |member|
|
15
|
+
if member[:inheritdoc]
|
16
|
+
resolve(member)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Copy over doc/params/return from parent member.
|
23
|
+
def resolve(m)
|
24
|
+
parent = find_parent(m)
|
25
|
+
m[:doc] = (m[:doc] + "\n\n" + parent[:doc]).strip
|
26
|
+
m[:params] = parent[:params] if parent[:params]
|
27
|
+
m[:return] = parent[:return] if parent[:return]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Finds parent member of the given member. When @inheritdoc names
|
31
|
+
# a member to inherit from, finds that member instead.
|
32
|
+
#
|
33
|
+
# If the parent also has @inheritdoc, continues recursively.
|
34
|
+
def find_parent(m)
|
35
|
+
context = m[:files][0]
|
36
|
+
inherit = m[:inheritdoc]
|
37
|
+
|
38
|
+
if inherit[:cls]
|
39
|
+
parent_cls = @relations[inherit[:cls]]
|
40
|
+
unless parent_cls
|
41
|
+
warn("@inheritdoc #{inherit[:cls]}##{inherit[:member]} - class not found", context)
|
42
|
+
return m
|
43
|
+
end
|
44
|
+
parent = parent_cls.get_member(inherit[:member], inherit[:type] || m[:tagname])
|
45
|
+
unless parent
|
46
|
+
warn("@inheritdoc #{inherit[:cls]}##{inherit[:member]} - member not found", context)
|
47
|
+
return m
|
48
|
+
end
|
49
|
+
else
|
50
|
+
parent_cls = @relations[m[:owner]].parent
|
51
|
+
unless parent_cls
|
52
|
+
warn("@inheritdoc - parent class not found", context)
|
53
|
+
return m
|
54
|
+
end
|
55
|
+
parent = parent_cls.get_member(m[:name], m[:tagname])
|
56
|
+
unless parent
|
57
|
+
warn("@inheritdoc - parent member not found", context)
|
58
|
+
return m
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if parent[:inheritdoc]
|
63
|
+
find_parent(parent)
|
64
|
+
else
|
65
|
+
parent
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def warn(msg, context)
|
70
|
+
Logger.instance.warn(:inheritdoc, msg, context[:filename], context[:linenr])
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/lib/jsduck/js_parser.rb
CHANGED
@@ -172,7 +172,7 @@ module JsDuck
|
|
172
172
|
# <literal> := ...see JsLiteralParser...
|
173
173
|
def my_literal
|
174
174
|
lit = literal
|
175
|
-
return unless lit
|
175
|
+
return unless lit && literal_expression_end?
|
176
176
|
|
177
177
|
cls_map = {
|
178
178
|
:string => "String",
|
@@ -195,6 +195,13 @@ module JsDuck
|
|
195
195
|
{:type => :literal, :class => cls, :value => value}
|
196
196
|
end
|
197
197
|
|
198
|
+
# True when we're at the end of literal expression.
|
199
|
+
# ",", ";" and "}" are the normal closing symbols, but for
|
200
|
+
# our docs purposes doc-comment and file end work too.
|
201
|
+
def literal_expression_end?
|
202
|
+
look(",") || look(";") || look("}") || look(:doc_comment) || @lex.empty?
|
203
|
+
end
|
204
|
+
|
198
205
|
# <ext-extend> := "Ext" "." "extend" "(" <ident-chain> "," ...
|
199
206
|
def ext_extend
|
200
207
|
match(:ident, ".", "extend", "(")
|
data/lib/jsduck/lint.rb
CHANGED
@@ -22,8 +22,8 @@ module JsDuck
|
|
22
22
|
def warn_globals
|
23
23
|
global = @relations["global"]
|
24
24
|
return unless global
|
25
|
-
global.
|
26
|
-
warn("Global #{member[:tagname]}: #{member[:name]}", member)
|
25
|
+
global.all_local_members.each do |member|
|
26
|
+
warn(:global, "Global #{member[:tagname]}: #{member[:name]}", member)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -31,11 +31,11 @@ module JsDuck
|
|
31
31
|
def warn_unnamed
|
32
32
|
each_member do |member|
|
33
33
|
if !member[:name] || member[:name] == ""
|
34
|
-
warn("Unnamed #{member[:tagname]}", member)
|
34
|
+
warn(:name_missing, "Unnamed #{member[:tagname]}", member)
|
35
35
|
end
|
36
36
|
(member[:params] || []).each do |p|
|
37
37
|
if !p[:name] || p[:name] == ""
|
38
|
-
warn("Unnamed parameter", member)
|
38
|
+
warn(:name_missing, "Unnamed parameter", member)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -48,7 +48,7 @@ module JsDuck
|
|
48
48
|
optional_found = false
|
49
49
|
member[:params].each do |p|
|
50
50
|
if optional_found && !p[:optional]
|
51
|
-
warn("Optional param
|
51
|
+
warn(:req_after_opt, "Optional param followed by regular param #{p[:name]}", member)
|
52
52
|
end
|
53
53
|
optional_found = optional_found || p[:optional]
|
54
54
|
end
|
@@ -62,7 +62,7 @@ module JsDuck
|
|
62
62
|
params = {}
|
63
63
|
(member[:params] || []).each do |p|
|
64
64
|
if params[p[:name]]
|
65
|
-
warn("Duplicate parameter name #{p[:name]}", member)
|
65
|
+
warn(:dup_param, "Duplicate parameter name #{p[:name]}", member)
|
66
66
|
end
|
67
67
|
params[p[:name]] = true
|
68
68
|
end
|
@@ -71,13 +71,13 @@ module JsDuck
|
|
71
71
|
|
72
72
|
# Loops through all members of all classes
|
73
73
|
def each_member(&block)
|
74
|
-
@relations.each {|cls| cls.
|
74
|
+
@relations.each {|cls| cls.all_local_members.each(&block) }
|
75
75
|
end
|
76
76
|
|
77
77
|
# Prints warning + filename and linenumber from doc-context
|
78
|
-
def warn(msg, member)
|
78
|
+
def warn(type, msg, member)
|
79
79
|
context = member[:files][0]
|
80
|
-
Logger.instance.warn(msg, context[:filename], context[:linenr])
|
80
|
+
Logger.instance.warn(type, msg, context[:filename], context[:linenr])
|
81
81
|
end
|
82
82
|
|
83
83
|
end
|
data/lib/jsduck/logger.rb
CHANGED
@@ -7,12 +7,39 @@ module JsDuck
|
|
7
7
|
class Logger
|
8
8
|
include Singleton
|
9
9
|
|
10
|
+
# Set to true to enable verbose logging
|
10
11
|
attr_accessor :verbose
|
11
|
-
attr_accessor :warnings
|
12
12
|
|
13
13
|
def initialize
|
14
14
|
@verbose = false
|
15
|
-
@
|
15
|
+
@warning_docs = [
|
16
|
+
[:global, "Member doesn't belong to any class"],
|
17
|
+
[:inheritdoc, "@inheritdoc referring to unknown class or member"],
|
18
|
+
[:extend, "@extend or @mixin referring to unknown class"],
|
19
|
+
[:link, "{@link} to unknown class or member"],
|
20
|
+
|
21
|
+
[:alt_name, "Name used as both classname and alternate classname"],
|
22
|
+
[:name_missing, "Member or parameter has no name"],
|
23
|
+
[:dup_param, "Method has two parameters with same name"],
|
24
|
+
[:req_after_opt, "Required parameter comes after optional"],
|
25
|
+
[:subproperty, "@param foo.bar where foo param doesn't exist"],
|
26
|
+
[:sing_static, "Singleton class member marked as @static"],
|
27
|
+
[:type_syntax, "Syntax error in {type definition}"],
|
28
|
+
[:type_name, "Unknown type referenced in {type definition}"],
|
29
|
+
|
30
|
+
[:image, "{@img} referring to missing file"],
|
31
|
+
[:image_unused, "An image exists in --images dir that's not used"],
|
32
|
+
[:cat_old_format, "Categories file uses old deprecated format"],
|
33
|
+
[:cat_no_match, "Class pattern in categories file matches nothing"],
|
34
|
+
[:cat_class_missing, "Class is missing from categories file"],
|
35
|
+
[:guide, "Guide is missing from --guides dir"],
|
36
|
+
]
|
37
|
+
# Turn on all warnings by default
|
38
|
+
@warnings = {}
|
39
|
+
@warning_docs.each do |w|
|
40
|
+
@warnings[w[0]] = true
|
41
|
+
end
|
42
|
+
|
16
43
|
@shown_warnings = {}
|
17
44
|
end
|
18
45
|
|
@@ -23,19 +50,50 @@ module JsDuck
|
|
23
50
|
end
|
24
51
|
end
|
25
52
|
|
53
|
+
# Enabled or disables a particular warning
|
54
|
+
# or all warnings when type == :all
|
55
|
+
def set_warning(type, enabled)
|
56
|
+
if type == :all
|
57
|
+
@warnings.each_key do |key|
|
58
|
+
@warnings[key] = enabled
|
59
|
+
end
|
60
|
+
elsif @warnings.has_key?(type)
|
61
|
+
@warnings[type] = enabled
|
62
|
+
else
|
63
|
+
warn(nil, "Warning of type '#{type} doesn't exist")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# get documentation for all warnings
|
68
|
+
def doc_warnings
|
69
|
+
@warning_docs.map {|w| "+#{w[0]} - #{w[1]}" } + [
|
70
|
+
" ",
|
71
|
+
"+all - to turn on all warnings (default)",
|
72
|
+
" ",
|
73
|
+
]
|
74
|
+
end
|
75
|
+
|
26
76
|
# Prints warning message.
|
27
77
|
#
|
78
|
+
# The type must be one of predefined warning types which can be
|
79
|
+
# toggled on/off with command-line options, or it can be nil, in
|
80
|
+
# which case the warning is always shown.
|
81
|
+
#
|
28
82
|
# Ignores duplicate warnings - only prints the first one.
|
29
83
|
# Works best when --processes=0, but it reduces the amount of
|
30
84
|
# warnings greatly also when run multiple processes.
|
31
85
|
#
|
32
86
|
# Optionally filename and line number will be inserted to message.
|
33
|
-
def warn(msg, filename=nil, line=nil)
|
87
|
+
def warn(type, msg, filename=nil, line=nil)
|
34
88
|
msg = "Warning: " + format(filename, line) + " " + msg
|
35
89
|
|
36
|
-
if @warnings
|
37
|
-
|
38
|
-
|
90
|
+
if type == nil || @warnings[type]
|
91
|
+
if !@shown_warnings[msg]
|
92
|
+
$stderr.puts msg
|
93
|
+
@shown_warnings[msg] = true
|
94
|
+
end
|
95
|
+
elsif !@warnings.has_key?(type)
|
96
|
+
warn(nil, "Unknown warning type #{type}")
|
39
97
|
end
|
40
98
|
end
|
41
99
|
|