cocoadex 1.4 → 1.5
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/bin/cdex_completion +7 -0
- data/bin/cocoadex +5 -3
- data/changelog.md +5 -0
- data/lib/cocoadex/docset_helper.rb +8 -4
- data/lib/cocoadex/extensions.rb +4 -0
- data/lib/cocoadex/keyword.rb +30 -103
- data/lib/cocoadex/model.rb +56 -0
- data/lib/cocoadex/models/callback.rb +12 -0
- data/lib/cocoadex/models/class.rb +2 -2
- data/lib/cocoadex/models/constant.rb +41 -0
- data/lib/cocoadex/models/data_type.rb +47 -0
- data/lib/cocoadex/models/element.rb +14 -1
- data/lib/cocoadex/models/entity.rb +6 -0
- data/lib/cocoadex/models/function.rb +28 -0
- data/lib/cocoadex/models/generic_ref.rb +88 -0
- data/lib/cocoadex/models/method.rb +21 -70
- data/lib/cocoadex/models/nested_node_element.rb +17 -0
- data/lib/cocoadex/models/parameter.rb +20 -0
- data/lib/cocoadex/models/property.rb +3 -18
- data/lib/cocoadex/models/result_code.rb +17 -0
- data/lib/cocoadex/models/seq_node_element.rb +53 -0
- data/lib/cocoadex/parser.rb +22 -18
- data/lib/cocoadex/serializer.rb +18 -8
- data/lib/cocoadex/tokenizer.rb +123 -0
- data/lib/cocoadex/tools/completion_helper.rb +84 -0
- data/lib/cocoadex/version.rb +1 -1
- data/lib/cocoadex.rb +12 -10
- data/lib/ext/nil.rb +3 -0
- data/lib/ext/string.rb +9 -0
- data/lib/ext/template_helpers.rb +20 -0
- data/lib/ext/xml_element.rb +10 -0
- data/readme.md +36 -8
- data/views/class.erb +35 -0
- data/views/constant.erb +10 -0
- data/views/constant_group.erb +28 -0
- data/views/data_type.erb +47 -0
- data/views/generic_ref.erb +28 -0
- data/views/method.erb +34 -0
- data/views/multiple.erb +4 -0
- data/views/property.erb +14 -0
- data/views/result_code.erb +7 -0
- metadata +50 -10
- data/bin/cocoadex_completion.sh +0 -36
- data/lib/cocoadex/templates.rb +0 -114
data/bin/cdex_completion
ADDED
data/bin/cocoadex
CHANGED
@@ -18,15 +18,15 @@ main do |query|
|
|
18
18
|
end
|
19
19
|
if options[:configure]
|
20
20
|
DocSetHelper.search_and_index
|
21
|
+
elsif options[:'generate-tags']
|
22
|
+
CompletionHelper.generate_tags!
|
21
23
|
elsif options[:'load-docset']
|
22
24
|
paths = options[:'load-docset'].map do |p|
|
23
25
|
File.expand_path(p)
|
24
26
|
end.uniq
|
25
27
|
DocSetHelper.search_and_index(paths)
|
26
28
|
elsif query
|
27
|
-
if
|
28
|
-
logger.debug "Loading index..."
|
29
|
-
Keyword.read
|
29
|
+
if Tokenizer.loaded?
|
30
30
|
Cocoadex.search(query, options[:first])
|
31
31
|
else
|
32
32
|
puts "No DocSets loaded. Run `cocodex --configure` to search for existing DocSets."
|
@@ -43,6 +43,8 @@ arg :query, :optional
|
|
43
43
|
|
44
44
|
on("--verbose","Be verbose")
|
45
45
|
|
46
|
+
on("--generate-tags","Generate a tags file from indexed docsets and exit")
|
47
|
+
|
46
48
|
on("--configure","Index all DocSets in default locations")
|
47
49
|
|
48
50
|
on("--first","Load first result when multiple matches exist")
|
data/changelog.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.5
|
4
|
+
|
5
|
+
- Searching for constants, functions, data types, callbacks, and result codes are now supported!
|
6
|
+
- Added smart completion; `Class-method`, `Class+method`, and `Class.property` can now be tab-completed
|
7
|
+
|
3
8
|
## 1.4
|
4
9
|
|
5
10
|
- Fixed parsing error on non-ASCII characters. Patch submitted by farcaller.
|
@@ -1,5 +1,7 @@
|
|
1
1
|
|
2
2
|
module Cocoadex
|
3
|
+
|
4
|
+
# Helper for finding and indexing DocSets
|
3
5
|
class DocSetHelper
|
4
6
|
|
5
7
|
ROOT_PATHS = [
|
@@ -15,7 +17,9 @@ module Cocoadex
|
|
15
17
|
|
16
18
|
def self.docset_paths
|
17
19
|
@paths ||= begin
|
18
|
-
ROOT_PATHS.map
|
20
|
+
ROOT_PATHS.map do |path|
|
21
|
+
Dir.glob(File.expand_path(path)+'/*/')
|
22
|
+
end.flatten
|
19
23
|
end
|
20
24
|
end
|
21
25
|
|
@@ -28,8 +32,8 @@ module Cocoadex
|
|
28
32
|
end
|
29
33
|
|
30
34
|
if docsets.size > 0
|
31
|
-
|
32
|
-
|
35
|
+
Tokenizer.persist
|
36
|
+
CompletionHelper.generate_tags!
|
33
37
|
write(docsets)
|
34
38
|
end
|
35
39
|
logger.info "Done! #{docsets.size} DocSet#{docsets.size == 1 ? '':'s'} indexed."
|
@@ -45,7 +49,7 @@ module Cocoadex
|
|
45
49
|
|
46
50
|
def self.write docsets
|
47
51
|
@docsets = docsets
|
48
|
-
Serializer.
|
52
|
+
Serializer.write_array(data_path, docsets, :overwrite)
|
49
53
|
end
|
50
54
|
end
|
51
55
|
end
|
data/lib/cocoadex/keyword.rb
CHANGED
@@ -11,41 +11,45 @@ module Cocoadex
|
|
11
11
|
CLASS_PROP_DELIM = '.'
|
12
12
|
SCOPE_CHARS = [CLASS_PROP_DELIM,CLASS_METHOD_DELIM,INST_METHOD_DELIM]
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
# Search the cache for matching text
|
15
|
+
def self.find text
|
16
|
+
logger.debug "Searching tokens for #{text}"
|
17
|
+
if scope = Keyword.get_scope(text)
|
18
|
+
class_name, term = text.split(scope)
|
19
|
+
find_with_scope(scope, class_name, term)
|
20
|
+
else
|
21
|
+
keys = Tokenizer.fuzzy_match(text)
|
22
|
+
keys.map {|k| k.to_element }
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
|
-
|
19
|
-
|
20
|
-
Cocoadex.config_file("data/store.blob")
|
26
|
+
def self.get_scope text
|
27
|
+
SCOPE_CHARS.detect {|c| text.include? c}
|
21
28
|
end
|
22
29
|
|
23
|
-
def
|
24
|
-
|
30
|
+
def initialize term, type, docset, url
|
31
|
+
@term, @type, @docset, @url = term, type, docset, url
|
25
32
|
end
|
26
33
|
|
27
|
-
|
28
|
-
|
29
|
-
if scope = SCOPE_CHARS.detect {|c| text.include? c }
|
30
|
-
class_name, term = text.split(scope)
|
31
|
-
logger.debug "Searching scope: #{scope}, #{class_name}, #{term}"
|
32
|
-
find_with_scope scope, class_name, term
|
33
|
-
else
|
34
|
-
logger.debug "Searching Keyword datastore (#{datastore.size}): #{text}"
|
35
|
-
keys = datastore.select {|k| k.term.start_with? text }
|
36
|
-
logger.debug "#{keys.size} keys found"
|
37
|
-
if key = keys.detect {|k| k.term == text }
|
38
|
-
keys = [key]
|
39
|
-
logger.debug "Exact match!"
|
40
|
-
end
|
41
|
-
untokenize(keys)
|
42
|
-
end
|
34
|
+
def to_element
|
35
|
+
Tokenizer.untokenize([self]).first
|
43
36
|
end
|
44
37
|
|
38
|
+
def inspect
|
39
|
+
"<Keyword:#{type} @term=\"#{term}\">"
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
"#{type} => #{term}"
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
45
48
|
# Find matches for term within a given class
|
46
49
|
def self.find_with_scope scope, class_name, term
|
47
|
-
if class_key =
|
48
|
-
|
50
|
+
if class_key = Tokenizer.match(class_name)
|
51
|
+
return [] unless class_key.type == :class
|
52
|
+
klass = class_key.to_element
|
49
53
|
list = case scope
|
50
54
|
when CLASS_PROP_DELIM
|
51
55
|
klass.methods + klass.properties
|
@@ -59,82 +63,5 @@ module Cocoadex
|
|
59
63
|
[]
|
60
64
|
end
|
61
65
|
end
|
62
|
-
|
63
|
-
# Are any docsets loaded into the cache?
|
64
|
-
def self.loaded?
|
65
|
-
File.exists? data_path
|
66
|
-
end
|
67
|
-
|
68
|
-
# Read a serialized cache file into an Array
|
69
|
-
def self.read
|
70
|
-
@store = Serializer.read(data_path)
|
71
|
-
logger.debug "Loaded #{datastore.size} tokens"
|
72
|
-
end
|
73
|
-
|
74
|
-
# Write a cache Array as a serialized file
|
75
|
-
def self.write style
|
76
|
-
Serializer.write(data_path, datastore, style)
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.tags
|
80
|
-
@tags ||= begin
|
81
|
-
if File.exists? tags_path
|
82
|
-
IO.read(tags_path).split('\n')
|
83
|
-
else
|
84
|
-
[]
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Build a tags file from existing kewords
|
90
|
-
def self.generate_tags!
|
91
|
-
text = datastore.map {|k| k.term }.join('\n')
|
92
|
-
Serializer.write_text tags_path, text
|
93
|
-
end
|
94
|
-
|
95
|
-
# Create Cocoadex model objects for Keyword references
|
96
|
-
def self.untokenize keys
|
97
|
-
keys.map do |key|
|
98
|
-
case key.type
|
99
|
-
when :class
|
100
|
-
Cocoadex::Class.new(key.url)
|
101
|
-
when :method, :property
|
102
|
-
if class_key = datastore.detect {|k| k.id == key.fk}
|
103
|
-
klass = Cocoadex::Class.new(class_key.url)
|
104
|
-
logger.debug "Searching #{key.type} list of #{klass.name}"
|
105
|
-
list = key.type == :method ? klass.methods : klass.properties
|
106
|
-
list.detect {|m| m.name == key.term}
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Find all searchable keywords in a class and add to cache
|
113
|
-
def self.tokenize_class docset, path, id
|
114
|
-
klass = Cocoadex::Class.new(path)
|
115
|
-
class_key = Keyword.new(klass.name, :class, docset, path)
|
116
|
-
class_key.id = id
|
117
|
-
datastore << class_key
|
118
|
-
|
119
|
-
{:method => klass.methods, :property => klass.properties}.each do |type,list|
|
120
|
-
list.each do |item|
|
121
|
-
item_key = Keyword.new(item.name, type, docset, path)
|
122
|
-
item_key.fk = id
|
123
|
-
datastore << item_key
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def initialize term, type, docset, url
|
129
|
-
@term, @type, @docset, @url = term, type, docset, url
|
130
|
-
end
|
131
|
-
|
132
|
-
def inspect
|
133
|
-
"<Keyword#{type} @term=#{term}>"
|
134
|
-
end
|
135
|
-
|
136
|
-
def to_s
|
137
|
-
"#{type} => #{term}"
|
138
|
-
end
|
139
66
|
end
|
140
|
-
end
|
67
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'cocoadex/models/docset'
|
2
|
+
require 'cocoadex/models/element'
|
3
|
+
require 'cocoadex/models/seq_node_element'
|
4
|
+
require 'cocoadex/models/nested_node_element'
|
5
|
+
require 'cocoadex/models/entity'
|
6
|
+
require 'cocoadex/models/constant'
|
7
|
+
require 'cocoadex/models/parameter'
|
8
|
+
require 'cocoadex/models/function'
|
9
|
+
require 'cocoadex/models/callback'
|
10
|
+
require 'cocoadex/models/result_code'
|
11
|
+
require 'cocoadex/models/data_type'
|
12
|
+
require 'cocoadex/models/generic_ref'
|
13
|
+
require 'cocoadex/models/method'
|
14
|
+
require 'cocoadex/models/property'
|
15
|
+
require 'cocoadex/models/class'
|
16
|
+
|
17
|
+
# Class Structure -------------
|
18
|
+
#
|
19
|
+
# DocSet
|
20
|
+
# Element
|
21
|
+
# Entity
|
22
|
+
# Class
|
23
|
+
# GenericRef
|
24
|
+
# NestedNodeElement
|
25
|
+
# Method
|
26
|
+
# Property
|
27
|
+
# SequentialNodeElement
|
28
|
+
# Callback
|
29
|
+
# ConstantGroup
|
30
|
+
# DataType
|
31
|
+
# Function
|
32
|
+
# Constant
|
33
|
+
# Parameter
|
34
|
+
# ResultCode
|
35
|
+
#
|
36
|
+
# Relationship Tree -----------
|
37
|
+
# Class
|
38
|
+
# Method
|
39
|
+
# Parameter
|
40
|
+
# Property
|
41
|
+
#
|
42
|
+
# GenericRef
|
43
|
+
# Callback
|
44
|
+
# Parameter
|
45
|
+
# ConstantGroup
|
46
|
+
# Constant
|
47
|
+
# DataType
|
48
|
+
# Parameter
|
49
|
+
# Function
|
50
|
+
# Parameter
|
51
|
+
#
|
52
|
+
#
|
53
|
+
module Cocoadex
|
54
|
+
class Model
|
55
|
+
end
|
56
|
+
end
|
@@ -4,7 +4,7 @@ require 'set'
|
|
4
4
|
module Cocoadex
|
5
5
|
# A model of a Cocoa API class or protocol
|
6
6
|
class Class < Entity
|
7
|
-
|
7
|
+
TEMPLATE_NAME=:class
|
8
8
|
|
9
9
|
attr_reader :description, :overview
|
10
10
|
|
@@ -48,7 +48,7 @@ module Cocoadex
|
|
48
48
|
@parents = doc.css("div.zSharedSpecBoxHeadList").first.css('a').map {|node| node.text}
|
49
49
|
|
50
50
|
parse_properties(doc)
|
51
|
-
parse_tasks(doc)
|
51
|
+
# parse_tasks(doc)
|
52
52
|
parse_methods(doc)
|
53
53
|
end
|
54
54
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module Cocoadex
|
3
|
+
class ConstantGroup < SequentialNodeElement
|
4
|
+
TEMPLATE_NAME=:constant_group
|
5
|
+
|
6
|
+
attr_reader :abstract, :declaration,
|
7
|
+
:discussion, :declared_in
|
8
|
+
|
9
|
+
def constants
|
10
|
+
@constants ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle_node node
|
14
|
+
if node.classes.include? "termdef"
|
15
|
+
node.css("dt").each do |field_title_node|
|
16
|
+
source = "#{@origin} > #{@name}"
|
17
|
+
field_name = field_title_node.css("code").text
|
18
|
+
description = field_title_node.next.css("p").map {|p| p.text}.join("\n")
|
19
|
+
constants << Constant.new(source,field_name, description)
|
20
|
+
end
|
21
|
+
elsif node.name == "p" and node.classes.empty?
|
22
|
+
@abstract = node.text
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Constant < Element
|
28
|
+
TEMPLATE_NAME=:constant
|
29
|
+
|
30
|
+
attr_reader :description
|
31
|
+
|
32
|
+
def initialize origin, name, description
|
33
|
+
@origin = origin
|
34
|
+
@name, @description = name, description
|
35
|
+
end
|
36
|
+
|
37
|
+
def origin
|
38
|
+
@origin
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
module Cocoadex
|
3
|
+
|
4
|
+
class DataType < SequentialNodeElement
|
5
|
+
TEMPLATE_NAME=:data_type
|
6
|
+
|
7
|
+
class Field < Parameter;end
|
8
|
+
|
9
|
+
attr_reader :abstract, :declaration, :declared_in,
|
10
|
+
:discussion, :availability, :considerations
|
11
|
+
attr_accessor :next_termdef
|
12
|
+
|
13
|
+
def fields
|
14
|
+
@fields ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def constants
|
18
|
+
@constants ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def origin
|
22
|
+
@origin
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_node node
|
26
|
+
if ["Fields","Constants"].include? node.text
|
27
|
+
next_termdef = node.text
|
28
|
+
elsif node.classes.include? "termdef" and not next_termdef.nil?
|
29
|
+
if list = termdef_to_properties(next_termdef)
|
30
|
+
node.css("dt").each do |field_title_node|
|
31
|
+
field_name = field_title_node.css("code").text
|
32
|
+
description = field_title_node.next.text
|
33
|
+
list << Field.new(field_name, description)
|
34
|
+
end
|
35
|
+
next_termdef = ""
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def termdef_to_properties termdef
|
41
|
+
case termdef
|
42
|
+
when "Fields" then fields
|
43
|
+
when "Constants" then constants
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -12,7 +12,9 @@ module Cocoadex
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def print
|
15
|
-
|
15
|
+
template_name = self.class.const_get("TEMPLATE_NAME")
|
16
|
+
path = Cocoadex.view_path(template_name)
|
17
|
+
template = IO.read(path, :mode => 'rb')
|
16
18
|
ERB.new(template, nil, '<>').result(binding)
|
17
19
|
end
|
18
20
|
|
@@ -27,5 +29,16 @@ module Cocoadex
|
|
27
29
|
def type
|
28
30
|
raise "#{self.class}#type is not defined"
|
29
31
|
end
|
32
|
+
|
33
|
+
def parse_parameters node
|
34
|
+
node.css("dt").each do |param|
|
35
|
+
name_nodes = param.css("em")
|
36
|
+
if name_nodes.size > 0
|
37
|
+
name = param.css("em").first.text
|
38
|
+
description = param.next.css("p").first.text
|
39
|
+
parameters << Parameter.new(name, description)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
30
43
|
end
|
31
44
|
end
|
@@ -2,8 +2,10 @@ module Cocoadex
|
|
2
2
|
# A top level element, roughly equivalent to one
|
3
3
|
# page of documentation
|
4
4
|
class Entity < Element
|
5
|
+
attr_reader :path
|
5
6
|
|
6
7
|
def initialize path
|
8
|
+
@path = path
|
7
9
|
text = clean(IO.read(path, :mode => 'rb'))
|
8
10
|
document = Nokogiri::HTML(text)
|
9
11
|
parse(document)
|
@@ -18,5 +20,9 @@ module Cocoadex
|
|
18
20
|
def strip text
|
19
21
|
text.gsub("  ","")
|
20
22
|
end
|
23
|
+
|
24
|
+
def section_by_title doc, title
|
25
|
+
doc.css("section").to_a.detect {|s| s.css("h2.jump").text == title }
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Cocoadex
|
3
|
+
class Function < SequentialNodeElement
|
4
|
+
attr_reader :abstract, :declaration, :declared_in,
|
5
|
+
:availability, :return_value
|
6
|
+
TEMPLATE_NAME=:method
|
7
|
+
|
8
|
+
def parameters
|
9
|
+
@parameters ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def discussion
|
13
|
+
""
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_node node
|
17
|
+
if node.classes.include? "parameters"
|
18
|
+
parse_parameters(node)
|
19
|
+
else
|
20
|
+
logger.debug("Unhandled function property: #{node.classes} => #{node.text}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def type
|
25
|
+
"Function"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
module Cocoadex
|
3
|
+
# A non-class reference document containing functions,
|
4
|
+
# constants, callbacks, result codes, and data types
|
5
|
+
class GenericRef < Entity
|
6
|
+
attr_reader :specs, :data_types, :overview,
|
7
|
+
:result_codes, :const_groups, :functions,
|
8
|
+
:callbacks
|
9
|
+
TEMPLATE_NAME=:generic_ref
|
10
|
+
|
11
|
+
def parse doc
|
12
|
+
@name = doc.title.sub("Reference","").strip
|
13
|
+
@specs = {}
|
14
|
+
|
15
|
+
parse_specbox(doc)
|
16
|
+
parse_overview(doc)
|
17
|
+
parse_data_types(doc)
|
18
|
+
parse_result_codes(doc)
|
19
|
+
parse_constants(doc)
|
20
|
+
parse_functions(doc)
|
21
|
+
parse_callbacks(doc)
|
22
|
+
end
|
23
|
+
|
24
|
+
def constants
|
25
|
+
@const_groups.map {|g| g.constants}.flatten
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_overview doc
|
29
|
+
if section = section_by_title(doc, "Overview")
|
30
|
+
@overview = section.text.sub("Overview","")
|
31
|
+
else
|
32
|
+
@overview = ""
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_specbox doc
|
37
|
+
specbox = doc.css(".specbox")
|
38
|
+
return if specbox.to_a.empty?
|
39
|
+
specbox.first.css("tr").each do |row|
|
40
|
+
title = row.css("td").first.css("strong").text
|
41
|
+
value = row.css("td").to_a[1].text.strip
|
42
|
+
@specs[title] = value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_callbacks doc
|
47
|
+
@callbacks = []
|
48
|
+
parse_section(doc, @callbacks, "Callbacks", Callback)
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_functions doc
|
52
|
+
@functions = []
|
53
|
+
parse_section(doc, @functions, "Functions", Function)
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_data_types doc
|
57
|
+
@data_types = []
|
58
|
+
parse_section(doc, @data_types, "Data Types", DataType)
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_constants doc
|
62
|
+
@const_groups = []
|
63
|
+
parse_section(doc, @const_groups, "Constants",ConstantGroup)
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_section doc, list, title, klass
|
67
|
+
if section = section_by_title(doc, title)
|
68
|
+
section.css("h3").each do |type_title|
|
69
|
+
list << klass.new(@name, type_title)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_result_codes doc
|
75
|
+
@result_codes = []
|
76
|
+
if section = section_by_title(doc, "Result Codes")
|
77
|
+
table = section.css("table").first
|
78
|
+
table.css("tr").each do |row|
|
79
|
+
if cells = row.css("td") and cells.size > 0
|
80
|
+
value = cells[1].text
|
81
|
+
description = cells[2].css("p").map {|p| p.text}.join("\n\n")
|
82
|
+
@result_codes << ResultCode.new(@name, cells.first.text, value, description)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -1,81 +1,32 @@
|
|
1
1
|
|
2
2
|
module Cocoadex
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
TEMPLATE=Cocoadex::Templates::METHOD_DESCRIPTION
|
3
|
+
# A model of a method in a Cocoa class
|
4
|
+
class Method < NestedNodeElement
|
5
|
+
TEMPLATE_NAME=:method
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
attr_reader :abstract, :declaration, :discussion,
|
8
|
+
:declared_in, :availability, :parameters,
|
9
|
+
:return_value, :scope, :parent
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
attr_reader :name, :description
|
16
|
-
|
17
|
-
def initialize name, description
|
18
|
-
@name, @description = name, description
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_s
|
22
|
-
"#{name} - #{description}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def <=> other
|
26
|
-
name <=> other.name if other.respond_to? :name
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def parameters
|
31
|
-
@parameters ||= []
|
32
|
-
end
|
33
|
-
|
34
|
-
def initialize parent_class, type, node
|
35
|
-
@parent = parent_class
|
36
|
-
@scope = type
|
37
|
-
@name = node.css("h3.#{type}Method").first.text
|
38
|
-
logger.debug("parsing #{@type} method #{@name}")
|
39
|
-
|
40
|
-
@abstract = node.css(".abstract").first.text
|
41
|
-
@declaration = node.css(".declaration").first.text
|
42
|
-
|
43
|
-
decl_nodes = node.css(".declaredIn code.HeaderFile")
|
44
|
-
@declared_in = decl_nodes.first.text if decl_nodes.size > 0
|
45
|
-
|
46
|
-
discussion_node = node.css(".discussion > p")
|
47
|
-
@discussion = discussion_node.first.text if discussion_node.length > 0
|
48
|
-
|
49
|
-
return_nodes = node.css(".return_value p")
|
50
|
-
@return_value = return_nodes.first.text if return_nodes.size > 0
|
51
|
-
|
52
|
-
ava_nodes = node.css(".availability > ul > li")
|
53
|
-
@availability = ava_nodes.first.text if ava_nodes.size > 0
|
11
|
+
def parameters
|
12
|
+
@parameters ||= []
|
13
|
+
end
|
54
14
|
|
55
|
-
|
56
|
-
|
15
|
+
def initialize parent_class, type, node
|
16
|
+
@parent = parent_class
|
17
|
+
@scope = type
|
18
|
+
@name = node.css("h3.#{type}Method").first.text
|
57
19
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
parameters.first.css("dt").each do |param|
|
62
|
-
name_nodes = param.css("em")
|
63
|
-
if name_nodes.size > 0
|
64
|
-
name = param.css("em").first.text
|
65
|
-
description = param.next.css("p").first.text
|
66
|
-
@parameters << Parameter.new(name, description)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
20
|
+
parse_properties(node)
|
21
|
+
parse_parameters(node.css(".parameters").first)
|
22
|
+
end
|
71
23
|
|
72
|
-
|
73
|
-
|
74
|
-
|
24
|
+
def type
|
25
|
+
"#{scope.to_s.capitalize} Method"
|
26
|
+
end
|
75
27
|
|
76
|
-
|
77
|
-
|
78
|
-
end
|
28
|
+
def origin
|
29
|
+
parent.to_s
|
79
30
|
end
|
80
31
|
end
|
81
32
|
end
|