jsduck 4.10.4 → 5.0.0.beta01
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +0 -1
- data/README.md +32 -6
- data/Rakefile +10 -18
- data/bin/compare +5 -5
- data/bin/jsduck +2 -3
- data/jsduck.gemspec +3 -4
- data/lib/jsduck/aggregator.rb +21 -80
- data/lib/jsduck/app.rb +7 -14
- data/lib/jsduck/app_data.rb +4 -5
- data/lib/jsduck/assets.rb +4 -7
- data/lib/jsduck/base_type.rb +53 -0
- data/lib/jsduck/batch_parser.rb +8 -87
- data/lib/jsduck/batch_processor.rb +77 -0
- data/lib/jsduck/categories/auto.rb +83 -0
- data/lib/jsduck/categories/class_name.rb +63 -0
- data/lib/jsduck/categories/factory.rb +113 -0
- data/lib/jsduck/categories/file.rb +75 -0
- data/lib/jsduck/class.rb +3 -9
- data/lib/jsduck/class_doc_expander.rb +1 -1
- data/lib/jsduck/css/lexer.rb +203 -0
- data/lib/jsduck/css/parser.rb +121 -0
- data/lib/jsduck/doc/comment.rb +40 -0
- data/lib/jsduck/doc/map.rb +23 -0
- data/lib/jsduck/doc/parser.rb +128 -0
- data/lib/jsduck/doc/processor.rb +52 -0
- data/lib/jsduck/doc/scanner.rb +76 -0
- data/lib/jsduck/doc/standard_tag_parser.rb +154 -0
- data/lib/jsduck/doc/subproperties.rb +64 -0
- data/lib/jsduck/docs_code_comparer.rb +31 -0
- data/lib/jsduck/export_writer.rb +2 -2
- data/lib/jsduck/exporter/app.rb +16 -4
- data/lib/jsduck/exporter/full.rb +2 -2
- data/lib/jsduck/format/batch.rb +58 -0
- data/lib/jsduck/format/class.rb +62 -0
- data/lib/jsduck/format/doc.rb +172 -0
- data/lib/jsduck/format/html_stack.rb +109 -0
- data/lib/jsduck/format/shortener.rb +55 -0
- data/lib/jsduck/format/subproperties.rb +64 -0
- data/lib/jsduck/guides.rb +32 -14
- data/lib/jsduck/index_html.rb +3 -1
- data/lib/jsduck/inline/auto_link.rb +2 -2
- data/lib/jsduck/inline/link.rb +4 -3
- data/lib/jsduck/inline/link_renderer.rb +2 -2
- data/lib/jsduck/inline/video.rb +8 -2
- data/lib/jsduck/js/ast.rb +361 -0
- data/lib/jsduck/js/esprima.rb +39 -0
- data/lib/jsduck/{esprima → js/esprima}/esprima.js +0 -0
- data/lib/jsduck/js/evaluator.rb +70 -0
- data/lib/jsduck/js/ext_patterns.rb +70 -0
- data/lib/jsduck/js/function.rb +206 -0
- data/lib/jsduck/js/node.rb +194 -0
- data/lib/jsduck/js/node_array.rb +36 -0
- data/lib/jsduck/js/parser.rb +223 -0
- data/lib/jsduck/js/serializer.rb +263 -0
- data/lib/jsduck/js/utils.rb +21 -0
- data/lib/jsduck/logger.rb +3 -13
- data/lib/jsduck/members_index.rb +3 -4
- data/lib/jsduck/merger.rb +25 -145
- data/lib/jsduck/options.rb +29 -132
- data/lib/jsduck/parser.rb +76 -0
- data/lib/jsduck/process/accessors.rb +133 -0
- data/lib/jsduck/process/circular_deps.rb +58 -0
- data/lib/jsduck/process/enums.rb +91 -0
- data/lib/jsduck/process/ext4_events.rb +43 -0
- data/lib/jsduck/process/global_members.rb +36 -0
- data/lib/jsduck/process/ignored_classes.rb +16 -0
- data/lib/jsduck/process/importer.rb +58 -0
- data/lib/jsduck/process/inherit_doc.rb +197 -0
- data/lib/jsduck/process/lint.rb +135 -0
- data/lib/jsduck/process/overrides.rb +99 -0
- data/lib/jsduck/process/return_values.rb +72 -0
- data/lib/jsduck/process/versions.rb +102 -0
- data/lib/jsduck/relations.rb +5 -0
- data/lib/jsduck/render/class.rb +144 -0
- data/lib/jsduck/render/sidebar.rb +97 -0
- data/lib/jsduck/render/signature.rb +94 -0
- data/lib/jsduck/render/subproperties.rb +99 -0
- data/lib/jsduck/render/tags.rb +38 -0
- data/lib/jsduck/search_data.rb +19 -13
- data/lib/jsduck/source/file.rb +8 -17
- data/lib/jsduck/tag/abstract.rb +4 -7
- data/lib/jsduck/tag/accessor.rb +10 -0
- data/lib/jsduck/tag/alias.rb +61 -0
- data/lib/jsduck/tag/alternate_class_names.rb +17 -0
- data/lib/jsduck/tag/aside.rb +28 -31
- data/lib/jsduck/tag/author.rb +9 -5
- data/lib/jsduck/tag/boolean_tag.rb +24 -0
- data/lib/jsduck/tag/cfg.rb +45 -0
- data/lib/jsduck/tag/chainable.rb +5 -7
- data/lib/jsduck/tag/class.rb +28 -0
- data/lib/jsduck/tag/class_list_tag.rb +40 -0
- data/lib/jsduck/tag/constructor.rb +24 -0
- data/lib/jsduck/tag/css_mixin.rb +17 -0
- data/lib/jsduck/tag/css_var.rb +29 -0
- data/lib/jsduck/tag/default.rb +31 -0
- data/lib/jsduck/tag/deprecated.rb +13 -27
- data/lib/jsduck/tag/deprecated_tag.rb +58 -0
- data/lib/jsduck/tag/doc.rb +32 -0
- data/lib/jsduck/tag/docauthor.rb +4 -5
- data/lib/jsduck/tag/enum.rb +70 -0
- data/lib/jsduck/tag/event.rb +28 -0
- data/lib/jsduck/tag/evented.rb +10 -0
- data/lib/jsduck/tag/extends.rb +45 -0
- data/lib/jsduck/tag/ftype.rb +18 -0
- data/lib/jsduck/tag/hide.rb +4 -11
- data/lib/jsduck/tag/ignore.rb +6 -7
- data/lib/jsduck/tag/inheritable.rb +10 -0
- data/lib/jsduck/tag/inheritdoc.rb +48 -0
- data/lib/jsduck/tag/markdown.rb +8 -6
- data/lib/jsduck/tag/member.rb +24 -0
- data/lib/jsduck/tag/method.rb +35 -0
- data/lib/jsduck/tag/mixins.rb +26 -0
- data/lib/jsduck/tag/name.rb +36 -0
- data/lib/jsduck/tag/new.rb +13 -27
- data/lib/jsduck/tag/override.rb +37 -0
- data/lib/jsduck/tag/overrides.rb +29 -0
- data/lib/jsduck/tag/param.rb +87 -0
- data/lib/jsduck/tag/preventable.rb +19 -10
- data/lib/jsduck/tag/private.rb +28 -13
- data/lib/jsduck/tag/property.rb +39 -0
- data/lib/jsduck/tag/protected.rb +5 -7
- data/lib/jsduck/tag/ptype.rb +18 -0
- data/lib/jsduck/tag/readonly.rb +4 -7
- data/lib/jsduck/tag/removed.rb +21 -29
- data/lib/jsduck/tag/required.rb +11 -9
- data/lib/jsduck/tag/requires.rb +12 -0
- data/lib/jsduck/tag/return.rb +47 -0
- data/lib/jsduck/tag/since.rb +19 -11
- data/lib/jsduck/tag/singleton.rb +15 -0
- data/lib/jsduck/tag/static.rb +5 -7
- data/lib/jsduck/tag/subproperties.rb +23 -0
- data/lib/jsduck/tag/tag.rb +208 -0
- data/lib/jsduck/tag/template.rb +14 -9
- data/lib/jsduck/tag/throws.rb +38 -0
- data/lib/jsduck/tag/type.rb +48 -0
- data/lib/jsduck/tag/uses.rb +12 -0
- data/lib/jsduck/tag/xtype.rb +30 -0
- data/lib/jsduck/tag_loader.rb +39 -0
- data/lib/jsduck/tag_registry.rb +189 -0
- data/lib/jsduck/type_parser.rb +3 -3
- data/lib/jsduck/web_writer.rb +2 -2
- data/lib/jsduck/welcome.rb +1 -1
- metadata +578 -538
- data/lib/jsduck/accessors.rb +0 -136
- data/lib/jsduck/ast.rb +0 -524
- data/lib/jsduck/auto_categories.rb +0 -80
- data/lib/jsduck/batch_formatter.rb +0 -60
- data/lib/jsduck/categories.rb +0 -73
- data/lib/jsduck/categories_class_name.rb +0 -37
- data/lib/jsduck/circular_deps.rb +0 -56
- data/lib/jsduck/class_formatter.rb +0 -102
- data/lib/jsduck/columns.rb +0 -56
- data/lib/jsduck/css_lexer.rb +0 -201
- data/lib/jsduck/css_parser.rb +0 -119
- data/lib/jsduck/doc_ast.rb +0 -319
- data/lib/jsduck/doc_formatter.rb +0 -142
- data/lib/jsduck/doc_parser.rb +0 -611
- data/lib/jsduck/doc_type.rb +0 -59
- data/lib/jsduck/enum.rb +0 -73
- data/lib/jsduck/esprima.rb +0 -51
- data/lib/jsduck/evaluator.rb +0 -69
- data/lib/jsduck/ext_patterns.rb +0 -58
- data/lib/jsduck/file_categories.rb +0 -76
- data/lib/jsduck/function_ast.rb +0 -206
- data/lib/jsduck/guide_anchors.rb +0 -32
- data/lib/jsduck/guide_toc.rb +0 -49
- data/lib/jsduck/html_stack.rb +0 -105
- data/lib/jsduck/importer.rb +0 -121
- data/lib/jsduck/inherit_doc.rb +0 -193
- data/lib/jsduck/js_parser.rb +0 -221
- data/lib/jsduck/lint.rb +0 -133
- data/lib/jsduck/meta_tag.rb +0 -88
- data/lib/jsduck/meta_tag_loader.rb +0 -67
- data/lib/jsduck/meta_tag_registry.rb +0 -111
- data/lib/jsduck/meta_tag_renderer.rb +0 -34
- data/lib/jsduck/news.rb +0 -128
- data/lib/jsduck/override.rb +0 -87
- data/lib/jsduck/renderer.rb +0 -361
- data/lib/jsduck/return_values.rb +0 -72
- data/lib/jsduck/serializer.rb +0 -262
- data/lib/jsduck/shortener.rb +0 -58
- data/lib/jsduck/signature_renderer.rb +0 -91
- data/lib/jsduck/source/file_parser.rb +0 -72
@@ -0,0 +1,23 @@
|
|
1
|
+
module JsDuck
|
2
|
+
module Doc
|
3
|
+
|
4
|
+
# Helper for building at-tags lookup table.
|
5
|
+
class Map
|
6
|
+
|
7
|
+
# Builds map of at-tags for quick lookup
|
8
|
+
def self.build(docs)
|
9
|
+
map = {}
|
10
|
+
docs.each do |tag|
|
11
|
+
if map[tag[:tagname]]
|
12
|
+
map[tag[:tagname]] << tag
|
13
|
+
else
|
14
|
+
map[tag[:tagname]] = [tag]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
map
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
require 'jsduck/doc/comment'
|
3
|
+
require 'jsduck/doc/scanner'
|
4
|
+
require 'jsduck/tag_registry'
|
5
|
+
require 'jsduck/logger'
|
6
|
+
|
7
|
+
module JsDuck
|
8
|
+
module Doc
|
9
|
+
|
10
|
+
# Parses doc-comment into array of @tags
|
11
|
+
#
|
12
|
+
# For each @tag it produces Hash like the following:
|
13
|
+
#
|
14
|
+
# {
|
15
|
+
# :tagname => :cfg/:property/:type/:extends/...,
|
16
|
+
# :doc => "Some documentation for this tag",
|
17
|
+
# ...@tag specific stuff like :name, :type, and so on...
|
18
|
+
# }
|
19
|
+
#
|
20
|
+
# When doc-comment begins with comment, not preceded by @tag, then
|
21
|
+
# the comment will be placed into Hash with :tagname => :default.
|
22
|
+
#
|
23
|
+
# Unrecognized @tags are left as is into documentation as if they
|
24
|
+
# were normal text.
|
25
|
+
#
|
26
|
+
# @example, {@img}, {@link} and {@video} are parsed separately in
|
27
|
+
# JsDuck::DocFormatter.
|
28
|
+
#
|
29
|
+
class Parser < Doc::Scanner
|
30
|
+
def parse(input, filename="", linenr=0)
|
31
|
+
@filename = filename
|
32
|
+
@linenr = linenr
|
33
|
+
@tags = []
|
34
|
+
@input = StringScanner.new(Doc::Comment.purify(input))
|
35
|
+
|
36
|
+
parse_loop
|
37
|
+
|
38
|
+
strip_docs
|
39
|
+
@tags
|
40
|
+
end
|
41
|
+
|
42
|
+
# The parsing process can leave whitespace at the ends of
|
43
|
+
# doc-strings, here we get rid of it.
|
44
|
+
def strip_docs
|
45
|
+
@tags.each do |tag|
|
46
|
+
tag[:doc].strip! if tag[:doc]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# The main loop of the DocParser
|
51
|
+
def parse_loop
|
52
|
+
add_tag({:tagname => :doc, :doc => :multiline})
|
53
|
+
|
54
|
+
while !@input.eos? do
|
55
|
+
if look(/@/)
|
56
|
+
parse_at_tag
|
57
|
+
elsif look(/[^@]/)
|
58
|
+
skip_to_next_at_tag
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Appends new @tag to parsed tags list
|
64
|
+
def add_tag(tag)
|
65
|
+
@tags << tag
|
66
|
+
|
67
|
+
if tag[:doc] == :multiline
|
68
|
+
tag[:doc] = ""
|
69
|
+
@multiline_tag = tag
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Processes anything beginning with @-sign.
|
74
|
+
#
|
75
|
+
# - When @ is not followed by any word chars, do nothing.
|
76
|
+
# - When it's one of the builtin tags, process it as such.
|
77
|
+
# - When it's something else, print a warning.
|
78
|
+
#
|
79
|
+
def parse_at_tag
|
80
|
+
match(/@/)
|
81
|
+
name = look(/\w+/)
|
82
|
+
|
83
|
+
if !name
|
84
|
+
# ignore
|
85
|
+
elsif tag = TagRegistry.get_by_pattern(name)
|
86
|
+
match(/\w+/)
|
87
|
+
hw # Skip the whitespace right after the tag.
|
88
|
+
|
89
|
+
tags = tag.parse_doc(self)
|
90
|
+
if tags.is_a?(Hash)
|
91
|
+
add_tag(tags)
|
92
|
+
elsif tags.is_a?(Array)
|
93
|
+
tags.each {|t| add_tag(t) }
|
94
|
+
end
|
95
|
+
|
96
|
+
skip_white
|
97
|
+
else
|
98
|
+
Logger.warn(:tag, "Unsupported tag: @#{name}", @filename, @linenr)
|
99
|
+
@multiline_tag[:doc] += "@"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Skips until the beginning of next @tag.
|
104
|
+
#
|
105
|
+
# There must be space before the next @tag - this ensures that we
|
106
|
+
# don't detect tags inside "foo@example.com" or "{@link}".
|
107
|
+
#
|
108
|
+
# Also check that the @tag is not part of an indented code block -
|
109
|
+
# in which case we also ignore the tag.
|
110
|
+
def skip_to_next_at_tag
|
111
|
+
@multiline_tag[:doc] += match(/[^@]+/)
|
112
|
+
|
113
|
+
while look(/@/) && (!prev_char_is_whitespace? || indented_as_code?)
|
114
|
+
@multiline_tag[:doc] += match(/@+[^@]+/)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def prev_char_is_whitespace?
|
119
|
+
@multiline_tag[:doc][-1,1] =~ /\s/
|
120
|
+
end
|
121
|
+
|
122
|
+
def indented_as_code?
|
123
|
+
@multiline_tag[:doc] =~ /^ {4,}[^\n]*\z/
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'jsduck/tag_registry'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
module Doc
|
5
|
+
|
6
|
+
# Processes @tag data detected from doc-comment, transforming it
|
7
|
+
# into a class/member hash which can be then later further merged
|
8
|
+
# with code hash.
|
9
|
+
#
|
10
|
+
# Its main work is done through calling the #process_doc method of
|
11
|
+
# all the Tag classes that have registered themselves to process a
|
12
|
+
# particular set of @tags through defining a .tagname attribute.
|
13
|
+
class Processor
|
14
|
+
# Allow passing in filename and line for error reporting
|
15
|
+
attr_accessor :filename
|
16
|
+
attr_accessor :linenr
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@filename = ""
|
20
|
+
@linenr = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
# Given tagname and map of tags from DocParser, produces docs
|
24
|
+
# of the type determined by tagname.
|
25
|
+
def process(tagname, doc_map)
|
26
|
+
hash = {
|
27
|
+
:tagname => tagname,
|
28
|
+
:doc => extract_doc(doc_map),
|
29
|
+
}
|
30
|
+
|
31
|
+
position = {:filename => @filename, :linenr => @linenr}
|
32
|
+
|
33
|
+
doc_map.each_pair do |name, value|
|
34
|
+
if tag = TagRegistry.get_by_name(name)
|
35
|
+
tag.process_doc(hash, value, position)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
return hash
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def extract_doc(doc_map)
|
45
|
+
tag = doc_map[:doc] ? doc_map[:doc].first : {}
|
46
|
+
return tag[:doc] || ""
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'jsduck/doc/standard_tag_parser'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
module Doc
|
5
|
+
|
6
|
+
# Abstract base class for parsing doc-comments.
|
7
|
+
#
|
8
|
+
# The methods of this class are to be called from implementations
|
9
|
+
# of concrete @tags. Although the @tag classes will get passed an
|
10
|
+
# instance of Doc::Parser, only methods of Doc::Scanner should be
|
11
|
+
# called by them.
|
12
|
+
#
|
13
|
+
class Scanner
|
14
|
+
def initialize
|
15
|
+
@ident_pattern = /[$\w-]+/
|
16
|
+
@ident_chain_pattern = /[$\w-]+(\.[$\w-]+)*/
|
17
|
+
|
18
|
+
@input = nil # set to StringScanner in subclass
|
19
|
+
end
|
20
|
+
|
21
|
+
# Provides access to StringScanner
|
22
|
+
attr_reader :input
|
23
|
+
|
24
|
+
# Parses standard pattern common in several builtin tags, which
|
25
|
+
# goes like this:
|
26
|
+
#
|
27
|
+
# @tag {Type} [some.name=default]
|
28
|
+
#
|
29
|
+
# See StandardTagParser#parse for details.
|
30
|
+
#
|
31
|
+
def standard_tag(cfg)
|
32
|
+
Doc::StandardTagParser.new(self).parse(cfg)
|
33
|
+
end
|
34
|
+
|
35
|
+
# matches chained.identifier.name and returns it
|
36
|
+
def ident_chain
|
37
|
+
@input.scan(@ident_chain_pattern)
|
38
|
+
end
|
39
|
+
|
40
|
+
# matches identifier and returns its name
|
41
|
+
def ident
|
42
|
+
@input.scan(@ident_pattern)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Looks for the existance of pattern. Returns the matching
|
46
|
+
# string on success, nil on failure, but doesn't advance the
|
47
|
+
# scan pointer.
|
48
|
+
def look(re)
|
49
|
+
@input.check(re)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Matches the given pattern and advances the scan pointer
|
53
|
+
# returning the string that matched. When the pattern doesn't
|
54
|
+
# match, nil is returned.
|
55
|
+
def match(re)
|
56
|
+
@input.scan(re)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Skips all whitespace. Moves scan pointer to next non-whitespace
|
60
|
+
# character.
|
61
|
+
def skip_white
|
62
|
+
@input.scan(/\s+/)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Skips horizontal whitespace (tabs and spaces). Moves scan
|
66
|
+
# pointer to next non-whitespace character or to the end of line.
|
67
|
+
# Returns self to allow chaining.
|
68
|
+
def hw
|
69
|
+
@input.scan(/[ \t]+/)
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module JsDuck
|
2
|
+
module Doc
|
3
|
+
|
4
|
+
# Helper in parsing the standard tag pattern with type definition
|
5
|
+
# followed by name and default value:
|
6
|
+
#
|
7
|
+
# @tag {Type} [some.name=default]
|
8
|
+
#
|
9
|
+
class StandardTagParser
|
10
|
+
# Initialized with Doc::Scanner instance
|
11
|
+
def initialize(doc_scanner)
|
12
|
+
@ds = doc_scanner
|
13
|
+
end
|
14
|
+
|
15
|
+
# Parses the standard tag pattern.
|
16
|
+
#
|
17
|
+
# Takes as parameter a configuration hash which can contain the
|
18
|
+
# following keys:
|
19
|
+
#
|
20
|
+
# - :tagname => The :tagname of the hash to return.
|
21
|
+
#
|
22
|
+
# - :type => True to parse {Type} section.
|
23
|
+
# Produces :type and :optional keys.
|
24
|
+
#
|
25
|
+
# - :name => Trye to parse [some.name=default] section.
|
26
|
+
# Produces :name, :default and :optional keys.
|
27
|
+
#
|
28
|
+
# Returns tag definition hash containing the given :tagname and a
|
29
|
+
# set of other fields depending on whether :type and :name configs
|
30
|
+
# were specified and how their matching succeeded.
|
31
|
+
#
|
32
|
+
def parse(cfg)
|
33
|
+
tag = {:tagname => cfg[:tagname]}
|
34
|
+
add_type(tag) if cfg[:type]
|
35
|
+
add_name_with_default(tag) if cfg[:name]
|
36
|
+
tag
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# matches {type} if possible and sets it on given tag hash.
|
42
|
+
# Also checks for {optionality=} in type definition.
|
43
|
+
def add_type(tag)
|
44
|
+
if hw.look(/\{/)
|
45
|
+
tdf = typedef
|
46
|
+
tag[:type] = tdf[:type]
|
47
|
+
tag[:optional] = true if tdf[:optional]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# matches {...=} and returns text inside brackets
|
52
|
+
def typedef
|
53
|
+
match(/\{/)
|
54
|
+
|
55
|
+
name = parse_balanced(/\{/, /\}/, /[^{}'"]*/)
|
56
|
+
|
57
|
+
if name =~ /=$/
|
58
|
+
name = name.chop
|
59
|
+
optional = true
|
60
|
+
else
|
61
|
+
optional = nil
|
62
|
+
end
|
63
|
+
|
64
|
+
match(/\}/)
|
65
|
+
|
66
|
+
return {:type => name, :optional => optional}
|
67
|
+
end
|
68
|
+
|
69
|
+
# matches: <ident-chain> | "[" <ident-chain> [ "=" <default-value> ] "]"
|
70
|
+
def add_name_with_default(tag)
|
71
|
+
if hw.match(/\[/)
|
72
|
+
tag[:name] = hw.ident_chain
|
73
|
+
if hw.match(/=/)
|
74
|
+
hw
|
75
|
+
tag[:default] = default_value
|
76
|
+
end
|
77
|
+
hw.match(/\]/)
|
78
|
+
tag[:optional] = true
|
79
|
+
else
|
80
|
+
tag[:name] = hw.ident_chain
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Attempts to allow balanced braces in default value.
|
85
|
+
# When the nested parsing doesn't finish at closing "]",
|
86
|
+
# roll back to beginning and simply grab anything up to closing "]".
|
87
|
+
def default_value
|
88
|
+
start_pos = @ds.input.pos
|
89
|
+
value = parse_balanced(/\[/, /\]/, /[^\[\]'"]*/)
|
90
|
+
if look(/\]/)
|
91
|
+
value
|
92
|
+
else
|
93
|
+
@ds.input.pos = start_pos
|
94
|
+
match(/[^\]]*/)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Helper method to parse a string up to a closing brace,
|
99
|
+
# balancing opening-closing braces in between.
|
100
|
+
#
|
101
|
+
# @param re_open The beginning brace regex
|
102
|
+
# @param re_close The closing brace regex
|
103
|
+
# @param re_rest Regex to match text without any braces and strings
|
104
|
+
def parse_balanced(re_open, re_close, re_rest)
|
105
|
+
result = parse_with_strings(re_rest)
|
106
|
+
while look(re_open)
|
107
|
+
result += match(re_open)
|
108
|
+
result += parse_balanced(re_open, re_close, re_rest)
|
109
|
+
result += match(re_close)
|
110
|
+
result += parse_with_strings(re_rest)
|
111
|
+
end
|
112
|
+
result
|
113
|
+
end
|
114
|
+
|
115
|
+
# Helper for parse_balanced to parse rest of the text between
|
116
|
+
# braces, taking account the strings which might occur there.
|
117
|
+
def parse_with_strings(re_rest)
|
118
|
+
result = match(re_rest)
|
119
|
+
while look(/['"]/)
|
120
|
+
result += parse_string('"') if look(/"/)
|
121
|
+
result += parse_string("'") if look(/'/)
|
122
|
+
result += match(re_rest)
|
123
|
+
end
|
124
|
+
result
|
125
|
+
end
|
126
|
+
|
127
|
+
# Parses "..." or '...' including the escape sequence \' or '\"
|
128
|
+
def parse_string(quote)
|
129
|
+
re_quote = Regexp.new(quote)
|
130
|
+
re_rest = Regexp.new("(?:[^"+quote+"\\\\]|\\\\.)*")
|
131
|
+
match(re_quote) + match(re_rest) + (match(re_quote) || "")
|
132
|
+
end
|
133
|
+
|
134
|
+
### Forward these calls to Doc::Scanner
|
135
|
+
|
136
|
+
def ident_chain
|
137
|
+
@ds.ident_chain
|
138
|
+
end
|
139
|
+
|
140
|
+
def look(re)
|
141
|
+
@ds.look(re)
|
142
|
+
end
|
143
|
+
|
144
|
+
def match(re)
|
145
|
+
@ds.match(re)
|
146
|
+
end
|
147
|
+
|
148
|
+
def hw
|
149
|
+
@ds.hw
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'jsduck/util/singleton'
|
2
|
+
require 'jsduck/logger'
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
module Doc
|
6
|
+
|
7
|
+
# Detects nested structure of subproperties.
|
8
|
+
class Subproperties
|
9
|
+
include Util::Singleton
|
10
|
+
|
11
|
+
# Given array of e.g. @param tags from Doc::Parser with names
|
12
|
+
# containing dots:
|
13
|
+
#
|
14
|
+
# {:name => "foo"},
|
15
|
+
# {:name => "foo.bar"},
|
16
|
+
# {:name => "foo.baz"},
|
17
|
+
# {:name => "zap"},
|
18
|
+
#
|
19
|
+
# Produces nested structure:
|
20
|
+
#
|
21
|
+
# {:name => "foo", :properties => [
|
22
|
+
# {:name => "bar"},
|
23
|
+
# {:name => "baz"}]},
|
24
|
+
# {:name => "zap"},
|
25
|
+
#
|
26
|
+
# Secondly it takes a position argument which is used for
|
27
|
+
# logging warnings when bogus subproperty syntax is encountered.
|
28
|
+
def nest(raw_items, pos)
|
29
|
+
# First item can't be namespaced, if it is ignore the rest.
|
30
|
+
if raw_items[0] && raw_items[0][:name] =~ /\./
|
31
|
+
return [raw_items[0]]
|
32
|
+
end
|
33
|
+
|
34
|
+
# build name-index of all items
|
35
|
+
index = {}
|
36
|
+
raw_items.each {|it| index[it[:name]] = it }
|
37
|
+
|
38
|
+
# If item name has no dots, add it directly to items array.
|
39
|
+
# Otherwise look up the parent of item and add it as the
|
40
|
+
# property of that parent.
|
41
|
+
items = []
|
42
|
+
raw_items.each do |it|
|
43
|
+
if it[:name] =~ /^(.+)\.([^.]+)$/
|
44
|
+
it[:name] = $2
|
45
|
+
parent = index[$1]
|
46
|
+
if parent
|
47
|
+
parent[:properties] = [] unless parent[:properties]
|
48
|
+
parent[:properties] << it
|
49
|
+
else
|
50
|
+
msg = "Ignoring subproperty #{$1}.#{$2}, no parent found with name '#{$1}'."
|
51
|
+
Logger.warn(:subproperty, msg, pos[:filename], pos[:linenr])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
items << it
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
return items
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|