shomen-yard 0.1.0
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/.ruby +54 -0
- data/.yardopts +7 -0
- data/HISTORY.md +11 -0
- data/LICENSE.txt +28 -0
- data/README.md +7 -0
- data/bin/shomen-yard +3 -0
- data/lib/shomen-yard.rb +32 -0
- data/lib/shomen-yard/command.rb +160 -0
- data/lib/shomen-yard/generator.rb +586 -0
- data/spec/01_metadata.rdoc +24 -0
- data/spec/02_class.rdoc +63 -0
- data/spec/03_module.rdoc +59 -0
- data/spec/04_constant.rdoc +59 -0
- data/spec/05_method.rdoc +286 -0
- data/spec/10_interface_overloading.rdoc +97 -0
- data/spec/applique/ae.rb +1 -0
- data/spec/applique/shomen.rb +24 -0
- data/spec/fixture/lib/example.rb +52 -0
- metadata +102 -0
data/.ruby
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
---
|
2
|
+
source:
|
3
|
+
- meta
|
4
|
+
authors:
|
5
|
+
- name: trans
|
6
|
+
email: transfire@gmail.com
|
7
|
+
copyrights: []
|
8
|
+
requirements:
|
9
|
+
- name: yard
|
10
|
+
- name: shomen-model
|
11
|
+
- name: detroit
|
12
|
+
groups:
|
13
|
+
- build
|
14
|
+
development: true
|
15
|
+
dependencies: []
|
16
|
+
alternatives: []
|
17
|
+
conflicts: []
|
18
|
+
repositories:
|
19
|
+
- uri: git://github.com/rubyworks/shomen-yard.git
|
20
|
+
scm: git
|
21
|
+
name: upstream
|
22
|
+
resources:
|
23
|
+
- uri: http://rubyworks.github.com/shomen-yard
|
24
|
+
name: home
|
25
|
+
type: home
|
26
|
+
- uri: http://github.com/rubyworks/shomen-yard/wiki
|
27
|
+
name: docs
|
28
|
+
type: doc
|
29
|
+
- uri: http://github.com/rubyworks/shomen-yard
|
30
|
+
name: code
|
31
|
+
type: code
|
32
|
+
- uri: http://github.com/rubyworks/shomen-yard/issues
|
33
|
+
name: bugs
|
34
|
+
type: bugs
|
35
|
+
- uri: http://groups.google.com/groups/rubyworks-mailinglist
|
36
|
+
name: mail
|
37
|
+
type: mail
|
38
|
+
- uri: http://chat.us.freenode.net/rubyworks
|
39
|
+
name: chat
|
40
|
+
type: chat
|
41
|
+
extra: {}
|
42
|
+
load_path:
|
43
|
+
- lib
|
44
|
+
revision: 0
|
45
|
+
created: '2010-07-01'
|
46
|
+
summary: Shomen via YARD command line utility
|
47
|
+
title: Shomen YARD
|
48
|
+
version: 0.1.0
|
49
|
+
name: shomen-yard
|
50
|
+
description: ! 'Shomen YARD is a utiliity for generating Shomen documentation file
|
51
|
+
|
52
|
+
using YARD as a backend parser.'
|
53
|
+
organization: rubyworks
|
54
|
+
date: '2012-04-19'
|
data/.yardopts
ADDED
data/HISTORY.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Shomen Yard - Shomen Generator via Yard Documentation
|
2
|
+
(http://github.com/rubyworks/shomen)
|
3
|
+
|
4
|
+
Copyright (c) 2011 Rubyworks. All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms,
|
7
|
+
with or without modification, are permitted provided that the following
|
8
|
+
conditions are met:
|
9
|
+
|
10
|
+
1. Redistributions of source code must retain the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer.
|
12
|
+
|
13
|
+
2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
notice, this list of conditions and the following disclaimer in the
|
15
|
+
documentation and/or other materials provided with the distribution.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
18
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
20
|
+
COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
21
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
22
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
23
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
24
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
25
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
|
28
|
+
SPDX License: BSD-2-Clause
|
data/README.md
ADDED
data/bin/shomen-yard
ADDED
data/lib/shomen-yard.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Shomen
|
2
|
+
|
3
|
+
# Shomen Yard provides a utility for generating Shomen documentation
|
4
|
+
# from YARD cache.
|
5
|
+
#
|
6
|
+
module Yard
|
7
|
+
#
|
8
|
+
# Access project metadata.
|
9
|
+
#
|
10
|
+
# @return [Hash]
|
11
|
+
#
|
12
|
+
def self.metadata
|
13
|
+
@metadata ||= (
|
14
|
+
require 'yaml'
|
15
|
+
YAML.load_file(File.dirname(__FILE__) + '/shomen-yard.yml')
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# If constant missing check metadata.
|
21
|
+
#
|
22
|
+
def self.const_missing(name)
|
23
|
+
metadata[name.to_s.downcase] || super(name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'shomen-model'
|
30
|
+
require 'shomen-yard/generator'
|
31
|
+
require 'shomen-yard/command'
|
32
|
+
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Shomen
|
2
|
+
|
3
|
+
module Yard
|
4
|
+
|
5
|
+
# TODO: Instead of using command line options for shomen
|
6
|
+
# we could use environment variables. ?
|
7
|
+
|
8
|
+
# The YARD command line tool provides a utility to generate a Shomen documentation
|
9
|
+
# file using YARD's .yardoc cache.
|
10
|
+
#
|
11
|
+
# Examples:
|
12
|
+
#
|
13
|
+
# $ shomen-yard --readme README.md lib - [A-Z]*.*
|
14
|
+
#
|
15
|
+
class Command
|
16
|
+
require 'optparse'
|
17
|
+
|
18
|
+
# Public: Shortcut for `CLI.new(*argv).run`.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
def self.run(*argv)
|
22
|
+
new(*argv).run
|
23
|
+
end
|
24
|
+
|
25
|
+
# Command line options.
|
26
|
+
attr :options
|
27
|
+
|
28
|
+
# Initialize new command.
|
29
|
+
#
|
30
|
+
# argv - Command line arguments. [Array]
|
31
|
+
#
|
32
|
+
# Returns CLI instance.
|
33
|
+
def initialize(*argv)
|
34
|
+
@options = {}
|
35
|
+
|
36
|
+
parse(argv)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Public: Run command.
|
40
|
+
#
|
41
|
+
# Returns nothing.
|
42
|
+
def run
|
43
|
+
generator = Generator.new(options)
|
44
|
+
$stdout.puts generator
|
45
|
+
end
|
46
|
+
|
47
|
+
# Parse command line arguments.
|
48
|
+
#
|
49
|
+
# argv - List of command line arguments. [Array]
|
50
|
+
#
|
51
|
+
# Returns list of arguments. [Array]
|
52
|
+
#
|
53
|
+
def parse(argv)
|
54
|
+
if i = argv.index('-')
|
55
|
+
@documents = argv[i+1..-1]
|
56
|
+
argv = argv[0...i]
|
57
|
+
end
|
58
|
+
|
59
|
+
parser = OptionParser.new
|
60
|
+
|
61
|
+
parser_options(parser)
|
62
|
+
|
63
|
+
parser.parse!(argv)
|
64
|
+
|
65
|
+
if !(force? or root?)
|
66
|
+
$stderr.puts "ERROR: Not a project directory. Use --force to override."
|
67
|
+
exit -1
|
68
|
+
end
|
69
|
+
|
70
|
+
@scripts = argv
|
71
|
+
end
|
72
|
+
|
73
|
+
# Define command line options.
|
74
|
+
#
|
75
|
+
# parser - Instance of {OptionParser}.
|
76
|
+
#
|
77
|
+
# Returns nothing.
|
78
|
+
def parser_options(parser)
|
79
|
+
#parser.on('-Y', '--yard', 'use YARD for parsing') do
|
80
|
+
# options[:engine] = :yard
|
81
|
+
#end
|
82
|
+
#parser.on('-R', '--rdoc', 'use RDoc for parsing') do
|
83
|
+
# options[:engine] = :rdoc
|
84
|
+
#end
|
85
|
+
|
86
|
+
parser.on('-j', '--json', 'output JSON instead of YAML (default)') do
|
87
|
+
options[:format] = :json
|
88
|
+
end
|
89
|
+
parser.on('-y', '--yaml', 'output YAML instead of JSON') do
|
90
|
+
options[:format] = :yaml
|
91
|
+
end
|
92
|
+
|
93
|
+
parser.on('-d', '--db DIR', 'documentation store directory (deafult is `.rdoc` or `.yardoc`)') do |dir|
|
94
|
+
options[:store] = dir
|
95
|
+
end
|
96
|
+
parser.on('-c', '--use-cache', 'do not regenerate docs, use pre-existing cache') do
|
97
|
+
options[:use_cache] = true
|
98
|
+
end
|
99
|
+
|
100
|
+
parser.on('-s', '--source', 'include full source in script documentation') do
|
101
|
+
options[:source] = true
|
102
|
+
end
|
103
|
+
parser.on('-w', '--webcvs URI', 'prefix link to source code') do |uri|
|
104
|
+
options[:webcvs] = uri
|
105
|
+
end
|
106
|
+
parser.on('-r', '--readme FILE', 'which file to use as main') do |file|
|
107
|
+
options[:readme] = file
|
108
|
+
end
|
109
|
+
|
110
|
+
#parser.on('--save', 'save options for future use') do |markup|
|
111
|
+
# options[:save] = true
|
112
|
+
#end
|
113
|
+
|
114
|
+
# TODO: shouldn't this be in .yardopts?
|
115
|
+
parser.on('--markup TYPE', 'markup type used for comments (rdoc, md, tomdoc)') do |markup|
|
116
|
+
options[:markup] = markup.to_sym
|
117
|
+
end
|
118
|
+
|
119
|
+
parser.on('-F', '--force') do
|
120
|
+
$FORCE = true
|
121
|
+
end
|
122
|
+
|
123
|
+
parser.on_tail('--debug', 'run with $DEBUG set to true') do
|
124
|
+
$DEBUG = true
|
125
|
+
end
|
126
|
+
parser.on_tail('--warn', 'run with $VERBOSE set to true') do
|
127
|
+
$VERBOSE = true
|
128
|
+
end
|
129
|
+
|
130
|
+
parser.on_tail('--help', 'see this help message') do
|
131
|
+
puts parser; exit -1
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Is `$FORCE` set?
|
136
|
+
#
|
137
|
+
# Returns true or false.
|
138
|
+
def force?
|
139
|
+
!!$FORCE
|
140
|
+
end
|
141
|
+
|
142
|
+
# Is this a project directory?
|
143
|
+
#
|
144
|
+
# Returns true or false.
|
145
|
+
def root?
|
146
|
+
root = false
|
147
|
+
root = true if File.exist?('.ruby')
|
148
|
+
root = true if File.exist?('.yardoc')
|
149
|
+
root = true if File.exist?('.rdoc')
|
150
|
+
root = true if File.exist?('.git')
|
151
|
+
root = true if File.exist?('.hg')
|
152
|
+
root = true if File.exist?('_darcs')
|
153
|
+
root
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
@@ -0,0 +1,586 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Shomen
|
4
|
+
|
5
|
+
module Yard
|
6
|
+
|
7
|
+
# TODO: what about reading options from .yardopts ?
|
8
|
+
# also yard.options[:yardopts] ?
|
9
|
+
|
10
|
+
# This adapter is used to convert YARD's documentation extracted
|
11
|
+
# from a local store (`.yardoc`) to Shomen's pure-data format.
|
12
|
+
#
|
13
|
+
class Generator < Shomen::Generator
|
14
|
+
|
15
|
+
STORE = '.yardoc'
|
16
|
+
|
17
|
+
# Require YARD library.
|
18
|
+
#
|
19
|
+
# Returns nothing.
|
20
|
+
def initialize(options)
|
21
|
+
require 'yard'
|
22
|
+
|
23
|
+
@store = STORE
|
24
|
+
|
25
|
+
super(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
# The hash object that is used to store the generated
|
29
|
+
# documentation.
|
30
|
+
#
|
31
|
+
# Returns Hash of documentation table.
|
32
|
+
attr :table
|
33
|
+
|
34
|
+
# The location YARD documentation cache. The default is `.yardoc`.
|
35
|
+
#
|
36
|
+
# Returns String.
|
37
|
+
attr_accessor :store
|
38
|
+
|
39
|
+
# Use pre-existant cache instead of regenerating documentation.
|
40
|
+
attr_accessor :use_cache
|
41
|
+
|
42
|
+
# Use pre-existant cache instead of regenerating documentation.
|
43
|
+
#
|
44
|
+
# Returns true/false.
|
45
|
+
def use_cache?
|
46
|
+
@use_cache
|
47
|
+
end
|
48
|
+
|
49
|
+
# Files to be documented.
|
50
|
+
#
|
51
|
+
# Returns Array of file paths.
|
52
|
+
def files
|
53
|
+
@files ||= (
|
54
|
+
list = []
|
55
|
+
list.concat scripts
|
56
|
+
list.concat documents
|
57
|
+
list.concat(['lib', 'README*']) if list.empty?
|
58
|
+
list
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Generate with YARD as backend processor.
|
63
|
+
#
|
64
|
+
# Returns documentation table. [Hash]
|
65
|
+
def generate
|
66
|
+
preconfigure unless use_cache?
|
67
|
+
generate_table
|
68
|
+
end
|
69
|
+
|
70
|
+
# The hash object that is used to store the generated
|
71
|
+
# documentation.
|
72
|
+
#
|
73
|
+
# Returns documentation table. [Hash]
|
74
|
+
def table
|
75
|
+
@table
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Create YARD cache.
|
81
|
+
#
|
82
|
+
# Returns nothing.
|
83
|
+
def preconfigure
|
84
|
+
argv = []
|
85
|
+
argv.concat ["-q"]
|
86
|
+
argv.concat ["-n"]
|
87
|
+
argv.concat ["-b", store]
|
88
|
+
argv.concat ["--markup", markup] if markup
|
89
|
+
argv.concat ["--debug"] if $DEBUG
|
90
|
+
#argv.concat ["--no-save"] #unless save
|
91
|
+
argv.concat scripts
|
92
|
+
#argv.concat documents unless documents.empty?
|
93
|
+
|
94
|
+
# clear the registry in memory to remove any previous runs
|
95
|
+
YARD::Registry.clear
|
96
|
+
|
97
|
+
yard = YARD::CLI::Yardoc.new
|
98
|
+
$stderr.puts('yard ' + argv.join(' ')) if $DEBUG
|
99
|
+
yard.run(*argv)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Generate the shomen data structure.
|
103
|
+
#
|
104
|
+
# Returns Hash of documentation table.
|
105
|
+
def generate_table
|
106
|
+
if not File.exist?(store)
|
107
|
+
$stderr.puts "ERROR: YARD database not found -- '#{store}`."
|
108
|
+
exit -1
|
109
|
+
end
|
110
|
+
|
111
|
+
@table = {}
|
112
|
+
|
113
|
+
scripts = []
|
114
|
+
|
115
|
+
generate_metadata
|
116
|
+
|
117
|
+
@registry = YARD::Registry.load!(store)
|
118
|
+
@registry.each do |object|
|
119
|
+
case object.type
|
120
|
+
when :constant
|
121
|
+
scripts.push(object.file)
|
122
|
+
generate_constant(object)
|
123
|
+
when :class, :module
|
124
|
+
scripts.push(object.file)
|
125
|
+
generate_class(object)
|
126
|
+
# TODO: is this needed?
|
127
|
+
#object.constants.each do |c|
|
128
|
+
# generate_constant(c)
|
129
|
+
#end
|
130
|
+
when :method
|
131
|
+
scripts.push(object.file)
|
132
|
+
generate_method(object)
|
133
|
+
else
|
134
|
+
$stderr.puts "What is an #{object.type}? Ignored!"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# TODO: Are c/c++ sourse files working okay?
|
139
|
+
# TODO: Add a generator for non-ruby script (e.g. .js)?
|
140
|
+
collect_files.each do |file|
|
141
|
+
case File.extname(file)
|
142
|
+
when '.rb', '.rbx', '.c', '.cpp'
|
143
|
+
generate_script(file)
|
144
|
+
when '.rdoc', '.md', '.markdown', '.txt'
|
145
|
+
generate_document(file)
|
146
|
+
else
|
147
|
+
generate_document(file)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# TODO: Also pass parent ?
|
152
|
+
scripts.uniq.each do |file|
|
153
|
+
generate_script(file)
|
154
|
+
end
|
155
|
+
|
156
|
+
return @table
|
157
|
+
end
|
158
|
+
|
159
|
+
## Project metadata.
|
160
|
+
##
|
161
|
+
## Returns Metadata instance.
|
162
|
+
#def project_metadata
|
163
|
+
# @project_metadata ||= Shomen::Metadata.new
|
164
|
+
#end
|
165
|
+
|
166
|
+
# Collect files given list of +globs+.
|
167
|
+
#
|
168
|
+
# Returns Array of files.
|
169
|
+
def collect_files
|
170
|
+
globs = self.files
|
171
|
+
globs = globs.map{ |glob| Dir[glob] }.flatten.uniq
|
172
|
+
globs = globs.map do |glob|
|
173
|
+
if File.directory?(glob)
|
174
|
+
Dir[File.join(glob, '**/*')]
|
175
|
+
else
|
176
|
+
glob
|
177
|
+
end
|
178
|
+
end
|
179
|
+
list = globs.flatten.uniq.compact
|
180
|
+
list = list.reject{ |path| File.extname(path) == '.html' }
|
181
|
+
list = list.select{ |path| File.file?(path) }
|
182
|
+
list
|
183
|
+
end
|
184
|
+
|
185
|
+
# Generate project metadata entry.
|
186
|
+
#
|
187
|
+
# Returns Hash of metadata added to the documentation table.
|
188
|
+
def generate_metadata
|
189
|
+
metadata = Metadata.new
|
190
|
+
@table['(metadata)'] = metadata.to_h
|
191
|
+
end
|
192
|
+
|
193
|
+
# Generate a class or module structure. Note that as to whether `methods`
|
194
|
+
# also contains the accessor methods listed in `accessors` is left to
|
195
|
+
# YARD to determine.
|
196
|
+
#
|
197
|
+
# yard_class - YARD class documentation object.
|
198
|
+
#
|
199
|
+
# Returns Hash of class data that has been placed in the table
|
200
|
+
def generate_class(yard_class)
|
201
|
+
debug_msg(yard_class.path.to_s)
|
202
|
+
|
203
|
+
meths = yard_class.meths(:included=>false, :inherited=>false)
|
204
|
+
|
205
|
+
if yard_class.type == :class
|
206
|
+
model = Model::Class.new
|
207
|
+
model.superclass = yard_class.superclass ? yard_class.superclass.path : 'Object'
|
208
|
+
else
|
209
|
+
model = Model::Module.new
|
210
|
+
end
|
211
|
+
|
212
|
+
model.path = yard_class.path
|
213
|
+
model.name = yard_class.name.to_s
|
214
|
+
model.namespace = yard_class.namespace.path #full_name.split('::')[0...-1].join('::'),
|
215
|
+
model.comment = yard_class.docstring.to_s
|
216
|
+
model.format = 'rdoc' #TODO: how to determine? rdoc, markdown or plaintext ?
|
217
|
+
model.constants = yard_class.constants.map{ |x| x.path } #TODO: complete_name(x.name, c.full_name) }
|
218
|
+
model.includes = yard_class.instance_mixins.map{ |x| x.path }
|
219
|
+
model.extensions = yard_class.class_mixins.map{ |x| x.path }
|
220
|
+
model.modules = yard_class.children.select{ |x| x.type == :module }.map{ |x| x.path }
|
221
|
+
#yard_class.modules.map{ |x| complete_name(x.name, c.full_name) }
|
222
|
+
model.classes = yard_class.children.select{ |x| x.type == :class }.map{ |x| x.path }
|
223
|
+
#yard_class.classes.map{ |x| complete_name(x.name, c.full_name) }
|
224
|
+
|
225
|
+
model.methods = meths.select.map{ |m| m.path }
|
226
|
+
#model.methods = meths.select{ |m| m.scope == :instance }.map{ |m| m.path }
|
227
|
+
#model.class_methods = meths.select{ |m| m.scope == :class }.map{ |m| m.path }
|
228
|
+
|
229
|
+
model.accessors = yard_class.attributes[:class].map{ |k, rw| yard_class.path + '.' + k.to_s } +
|
230
|
+
yard_class.attributes[:instance].map{ |k, rw| yard_class.path + '#' + k.to_s }
|
231
|
+
#model.class_accessors = yard_class.attributes[:class].map{ |k, rw| yard_class.path + '.' + k.to_s }
|
232
|
+
|
233
|
+
model.files = yard_class.files.map{ |f, l| "/#{f}" } # :#{l}" }
|
234
|
+
|
235
|
+
model.tags = translate_tags(yard_class)
|
236
|
+
|
237
|
+
#@files.concat(yard_class.files.map{ |f, l| f })
|
238
|
+
|
239
|
+
@table[model.path] = model.to_h
|
240
|
+
end
|
241
|
+
|
242
|
+
=begin
|
243
|
+
# Generate a module structure.
|
244
|
+
#
|
245
|
+
def generate_module(object)
|
246
|
+
index = object.path.to_s
|
247
|
+
#meths = object.meths(:included=>false, :inherited=>false)
|
248
|
+
|
249
|
+
debug_msg(index)
|
250
|
+
|
251
|
+
data = Model::Module.new(Yard::ModuleAdapter.new(object)).to_h
|
252
|
+
|
253
|
+
#data = Shomen::Model::Module.new(
|
254
|
+
# 'name' => object.name.to_s,
|
255
|
+
# 'namespace' => object.namespace.path, #full_name.split('::')[0...-1].join('::')
|
256
|
+
# 'comment' => object.docstring.to_s,
|
257
|
+
# 'constants' => object.constants.map{ |x| x.path }, #complete_name(x.name, c.full_name) }
|
258
|
+
# 'includes' => object.instance_mixins.map{ |x| x.path },
|
259
|
+
# 'extensions' => object.class_mixins.map{ |x| x.path },
|
260
|
+
# 'modules' => object.children.select{ |x| x.type == :module }.map{ |x| x.path },
|
261
|
+
# #object.modules.map{ |x| complete_name(x.name, c.full_name) }
|
262
|
+
# 'classes' => object.children.select{ |x| x.type == :class }.map{ |x| x.path },
|
263
|
+
# #object.classes.map{ |x| complete_name(x.name, c.full_name) }
|
264
|
+
# 'methods' => meths.select{ |m| m.scope == :instance }.map{ |m| m.path },
|
265
|
+
# 'class-methods' => meths.select{ |m| m.scope == :class }.map{ |m| m.path },
|
266
|
+
# #'attributes' => meths.select{ |m| m.scope == :instance }.map{ |m| m.path },
|
267
|
+
# #'class-attributes' => meths.select{ |m| m.scope == :class }.map{ |m| m.path },
|
268
|
+
# 'files' => object.files.map{ |f, l| "/#{f}:#{l}" }
|
269
|
+
#).to_h
|
270
|
+
|
271
|
+
#@files.concat(object.files.map{ |f, l| f })
|
272
|
+
|
273
|
+
@table[index] = data
|
274
|
+
end
|
275
|
+
=end
|
276
|
+
|
277
|
+
# Generate a method structure.
|
278
|
+
#
|
279
|
+
def generate_method(yard_method)
|
280
|
+
debug_msg(yard_method.to_s)
|
281
|
+
|
282
|
+
# not sure what to do with methods with no signatures ?
|
283
|
+
if !yard_method.signature
|
284
|
+
debug_msg "no method signature -- #{yard_method.inspect}"
|
285
|
+
return
|
286
|
+
end
|
287
|
+
|
288
|
+
model = Model::Method.new
|
289
|
+
#class_model = object.scope == :instance ? Shomen::Module::Method : Shomen::Model::Function
|
290
|
+
|
291
|
+
model.path = yard_method.path
|
292
|
+
model.name = yard_method.name.to_s
|
293
|
+
model.namespace = yard_method.parent.path
|
294
|
+
model.comment = yard_method.docstring.to_s
|
295
|
+
model.format = 'rdoc' # TODO: how to determine? rdoc, markdown or plain
|
296
|
+
model.aliases = yard_method.aliases.map{ |a| a.path } #method_name(a) }
|
297
|
+
# TODO: how to get alias_for from YARD?
|
298
|
+
#model.alias_for = method_name(yard_method.alias_for)
|
299
|
+
model.singleton = (yard_method.scope == :class)
|
300
|
+
|
301
|
+
model.declarations << yard_method.scope.to_s
|
302
|
+
model.declarations << yard_method.visibility.to_s
|
303
|
+
# FIXME
|
304
|
+
#model.declarations << yard_method.attr_info
|
305
|
+
|
306
|
+
model.interfaces = []
|
307
|
+
yard_method.tags.each do |tag|
|
308
|
+
case tag
|
309
|
+
when ::YARD::Tags::OverloadTag
|
310
|
+
model.interfaces << parse_interface(tag)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
model.interfaces << parse_interface(yard_method)
|
314
|
+
|
315
|
+
model.returns = (
|
316
|
+
rtns = []
|
317
|
+
yard_method.tags(:return).each do |tag|
|
318
|
+
tag.types.to_a.each do |t|
|
319
|
+
rtns << {'type'=>t, 'comment'=>tag.text}
|
320
|
+
end
|
321
|
+
end
|
322
|
+
rtns
|
323
|
+
)
|
324
|
+
|
325
|
+
model.file = '/'+yard_method.file
|
326
|
+
model.line = yard_method.line.to_i
|
327
|
+
model.source = yard_method.source.to_s.strip
|
328
|
+
model.language = yard_method.source_type.to_s
|
329
|
+
model.dynamic = yard_method.dynamic
|
330
|
+
|
331
|
+
model.tags = translate_tags(yard_method)
|
332
|
+
|
333
|
+
@table[model.path] = model.to_h
|
334
|
+
end
|
335
|
+
|
336
|
+
# Parse a yard method's interface.
|
337
|
+
def parse_interface(yard_method)
|
338
|
+
args, block = [], {}
|
339
|
+
image, returns = yard_method.signature.split(/[=-]\>/)
|
340
|
+
image = image.strip
|
341
|
+
if i = image.index(/\)\s*\{/)
|
342
|
+
block['image'] = image[i+1..-1].strip
|
343
|
+
image = image[0..i].strip
|
344
|
+
end
|
345
|
+
image = image.sub(/^def\s*/, '')
|
346
|
+
image = image.sub(/^self\./, '')
|
347
|
+
image = image.sub('( )','()')
|
348
|
+
|
349
|
+
yard_method.parameters.each do |n,v|
|
350
|
+
n = n.to_s
|
351
|
+
case n
|
352
|
+
when /^\&/
|
353
|
+
block['name'] = n
|
354
|
+
else
|
355
|
+
args << (v ? {'name'=>n,'default'=>v} : {'name'=>n})
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
result = {}
|
360
|
+
result['signature'] = image
|
361
|
+
result['arguments'] = args
|
362
|
+
#result['parameters'] = params
|
363
|
+
result['block'] = block unless block.empty?
|
364
|
+
result['returns'] = returns.strip if returns
|
365
|
+
result
|
366
|
+
end
|
367
|
+
private :parse_interface
|
368
|
+
|
369
|
+
# Generate a constant.
|
370
|
+
#
|
371
|
+
def generate_constant(yard_constant)
|
372
|
+
debug_msg(yard_constant.path.to_s)
|
373
|
+
|
374
|
+
model = Model::Constant.new
|
375
|
+
|
376
|
+
model.path = yard_constant.path
|
377
|
+
model.name = yard_constant.name.to_s
|
378
|
+
model.namespace = yard_constant.namespace.path
|
379
|
+
model.comment = yard_constant.docstring.to_s
|
380
|
+
model.format = 'rdoc' # TODO: how to determine? rdoc, markdown or plain
|
381
|
+
model.value = yard_constant.value
|
382
|
+
model.tags = translate_tags(yard_constant)
|
383
|
+
model.files = yard_constant.files.map{|f,l| "/#{f}"} # or "#{f}:#{l}" ?
|
384
|
+
|
385
|
+
@table[model.path] = model.to_h
|
386
|
+
end
|
387
|
+
|
388
|
+
# Generate a file.
|
389
|
+
#
|
390
|
+
def generate_document(yard_document)
|
391
|
+
debug_msg(yard_document)
|
392
|
+
|
393
|
+
model = Model::Document.new
|
394
|
+
|
395
|
+
# FIXME: make absolute
|
396
|
+
absolute_path = yard_document.to_s
|
397
|
+
|
398
|
+
model.path = yard_document.to_s
|
399
|
+
model.name = File.basename(absolute_path)
|
400
|
+
model.mtime = File.ctime(absolute_path)
|
401
|
+
model.ctime = File.mtime(absolute_path)
|
402
|
+
model.text = File.read(absolute_path)
|
403
|
+
model.format = mime_type(absolute_path)
|
404
|
+
|
405
|
+
webcvs = project_metadata['webcvs'] || webcvs
|
406
|
+
if webcvs
|
407
|
+
model.uri = File.join(webcvs, model.path)
|
408
|
+
end
|
409
|
+
|
410
|
+
@table['/'+model.path] = model.to_h
|
411
|
+
end
|
412
|
+
|
413
|
+
# Generate a script entry.
|
414
|
+
#
|
415
|
+
def generate_script(yard_script)
|
416
|
+
debug_msg(yard_script)
|
417
|
+
|
418
|
+
model = Model::Script.new
|
419
|
+
|
420
|
+
# FIXME: make absolute
|
421
|
+
absolute_path = yard_script.to_s
|
422
|
+
|
423
|
+
model.path = yard_script.to_s
|
424
|
+
model.name = File.basename(absolute_path)
|
425
|
+
model.ctime = File.ctime(absolute_path)
|
426
|
+
model.mtime = File.mtime(absolute_path)
|
427
|
+
|
428
|
+
if source?
|
429
|
+
model.source = File.read(absolute_path) #file.comment
|
430
|
+
model.language = mime_type(absolute_path)
|
431
|
+
end
|
432
|
+
|
433
|
+
webcvs = project_metadata['webcvs'] || webcvs
|
434
|
+
if webcvs
|
435
|
+
model.uri = File.join(webcvs, model.path)
|
436
|
+
model.language = mime_type(absolute_path)
|
437
|
+
end
|
438
|
+
|
439
|
+
# model.header = ""
|
440
|
+
# model.footer = ""
|
441
|
+
# model.requires =
|
442
|
+
# model.constants =
|
443
|
+
# model.modules =
|
444
|
+
# model.classes =
|
445
|
+
# model.methods =
|
446
|
+
# model.class_methods =
|
447
|
+
|
448
|
+
@table['/'+model.path] = model.to_h
|
449
|
+
|
450
|
+
#table[index] = Shomen::Model::Script.new(
|
451
|
+
# "name" => File.basename(object),
|
452
|
+
# "path" => object,
|
453
|
+
# #"loadpath" => "lib",
|
454
|
+
# "mtime" => File.mtime(object),
|
455
|
+
# "header" => "",
|
456
|
+
# "footer" => "",
|
457
|
+
# # "requires" : ["fileutils"],
|
458
|
+
# # "constants" : ["MusicStore::CONFIG_DIRECTORY"],
|
459
|
+
# # "modules" : ["MusicStore", "MusicStore::MusicMixin"],
|
460
|
+
# # "classes" : ["MusicStore::Song"],
|
461
|
+
# # "functions" : ["MusicStore.config_directory"],
|
462
|
+
# # "methods" : ["MusicStore::MusicMixin#play", "MusicStore::MusicMixin#artist"]
|
463
|
+
# "source" => File.read(object)
|
464
|
+
#).to_h
|
465
|
+
|
466
|
+
@table['/'+model.path] = model.to_h
|
467
|
+
end
|
468
|
+
|
469
|
+
# Output progress information if debugging is enabled
|
470
|
+
#
|
471
|
+
def debug_msg(msg)
|
472
|
+
return unless $DEBUG
|
473
|
+
case msg[-1,1]
|
474
|
+
when '.' then tab = "= "
|
475
|
+
when ':' then tab = "== "
|
476
|
+
else tab = "* "
|
477
|
+
end
|
478
|
+
$stderr.puts(tab + msg)
|
479
|
+
end
|
480
|
+
|
481
|
+
# Given a file return offical mime-type basic on file extension.
|
482
|
+
#
|
483
|
+
# FIXME: official mime types?
|
484
|
+
def mime_type(path)
|
485
|
+
case File.extname(path)
|
486
|
+
when '.rb', '.rbx' then 'text/x-ruby'
|
487
|
+
when '.c' then 'text/c-source' # x-c-code
|
488
|
+
when '.js' then 'text/ecmascript'
|
489
|
+
when '.rdoc' then 'text/rdoc'
|
490
|
+
when '.md', '.markdown' then 'text/markdown'
|
491
|
+
else 'text/plain'
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
# Convert YARD Tags to simple Hash.
|
496
|
+
#
|
497
|
+
# TODO: Remove param tags?
|
498
|
+
def translate_tags(yard_object)
|
499
|
+
tags = {}
|
500
|
+
yard_object.tags.each do |tag|
|
501
|
+
next if tag.tag_name == 'return'
|
502
|
+
tags[tag.tag_name] = tag.text
|
503
|
+
end
|
504
|
+
return tags
|
505
|
+
end
|
506
|
+
|
507
|
+
end
|
508
|
+
|
509
|
+
end
|
510
|
+
|
511
|
+
end
|
512
|
+
|
513
|
+
|
514
|
+
|
515
|
+
|
516
|
+
|
517
|
+
|
518
|
+
|
519
|
+
|
520
|
+
|
521
|
+
|
522
|
+
|
523
|
+
|
524
|
+
|
525
|
+
|
526
|
+
|
527
|
+
|
528
|
+
=begin
|
529
|
+
# Generate a method structure.
|
530
|
+
#
|
531
|
+
def generate_attribute(object)
|
532
|
+
index = "#{object.path}"
|
533
|
+
|
534
|
+
debug_msg(index)
|
535
|
+
|
536
|
+
data = Model::Method.new(Yard::MethodAdapter.new(object)).to_h
|
537
|
+
|
538
|
+
##code = m.source_code_raw
|
539
|
+
##file, line = m.source_code_location
|
540
|
+
|
541
|
+
##full_name = method_name(m)
|
542
|
+
|
543
|
+
##'prettyname' => m.pretty_name,
|
544
|
+
##'type' => m.type, # class or instance
|
545
|
+
|
546
|
+
#args = []
|
547
|
+
#object.parameters.each do |var, val|
|
548
|
+
# if val
|
549
|
+
# args << { 'name' => var, 'default'=>val }
|
550
|
+
# else
|
551
|
+
# args << { 'name' => var }
|
552
|
+
# end
|
553
|
+
#end
|
554
|
+
#
|
555
|
+
#rtns = []
|
556
|
+
#object.tags(:return).each do |t|
|
557
|
+
# t.types.each do |ty|
|
558
|
+
# rtns << { 'type' => ty, 'comment' => t.text }
|
559
|
+
# end
|
560
|
+
#end
|
561
|
+
#
|
562
|
+
#table[index] = Shomen::Model::Attribute.new(
|
563
|
+
# 'name' => object.name.to_s,
|
564
|
+
# 'namespace' => object.parent.path,
|
565
|
+
# 'comment' => object.docstring.to_s,
|
566
|
+
# 'access' => object.visibility.to_s,
|
567
|
+
# 'singleton' => object.scope == :class,
|
568
|
+
# 'aliases' => object.aliases.map{ |a| a.path }, #method_name(a) },
|
569
|
+
# #'alias_for' => method_name(m.is_alias_for),
|
570
|
+
# 'interfaces' => [{'interface' => object.signature.sub('def ', ''), #m.params,
|
571
|
+
# 'arguments' => args,
|
572
|
+
# 'parameters' => []
|
573
|
+
# #'block' => m.block_params, # TODO: what is block?
|
574
|
+
# }],
|
575
|
+
# 'returns' => rtns,
|
576
|
+
# 'file' => "/#{object.file}",
|
577
|
+
# 'line' => object.line,
|
578
|
+
# 'source' => object.source,
|
579
|
+
# 'language' => object.source_type.to_s,
|
580
|
+
# 'dynamic' => object.dynamic
|
581
|
+
#).to_h
|
582
|
+
|
583
|
+
@table[index] = model.to_h
|
584
|
+
end
|
585
|
+
=end
|
586
|
+
|