Top Level Namespace

Includes:
Helpers::ModuleHelper

Defined Under Namespace

Modules: SketchUpYARD, YARD Classes: StubFile

Constant Summary collapse

CAMELCASE_CONSTANT =
/^([A-Z]+[a-z]+)/
MANUAL_CONSTANT_GROUPS =
{
  constants: %w{IDABORT IDCANCEL IDIGNORE IDNO IDOK IDRETRY IDYES},
  group: 'ID_MESSAGEBOX'
},
# Axes
{
  constants: %w{X_AXIS Y_AXIS Z_AXIS},
  group: 'AXES'
},
# Axes 2D
{
  constants: %w{X_AXIS_2D Y_AXIS_2D},
  group: 'AXES2D'
},
# Transformation
{
  constants: %w{IDENTITY IDENTITY_2D},
  group: 'IDENTITY'
},
# Geom::PolygonMesh
{
  constants: %w{
    AUTO_SOFTEN HIDE_BASED_ON_INDEX NO_SMOOTH_OR_HIDE SMOOTH_SOFT_EDGES
    SOFTEN_BASED_ON_INDEX},
  group: 'SOFTEN'
},
# Sketchup::Importer
# The other constants start with Import, this was odd one out.
{
  constants: %w{ImporterNotFound},
  group: 'Import'
},
# Sketchup::Http
{
  constants: %w{DELETE GET HEAD OPTIONS PATCH POST PUT},
  group: 'HTTP'
},
# Sketchup::Licensing
{
  constants: %w{EXPIRED LICENSED NOT_LICENSED TRIAL TRIAL_EXPIRED},
  group: 'EX_LICENSE'
},
# Sketchup::Model
{
  constants: %w{Make MakeTrial ProLicensed ProTrial},
  group: 'SU_LICENSE'
},
# Sketchup::RenderingOptions
# Most ROP constants start with ROPSet, with a handful of exceptions.
{
  regex: /^ROP/,
  group: 'ROP'
}
MANIFEST_FILENAME =
'coverage.manifest'.freeze
VERSION_MATCH =
/^\D+([0-9.]+)(?:\s+M(\d+))?$/

Instance Method Summary collapse

Instance Method Details

#all_objectsObject



12
13
14
# File 'lib/yard-sketchup/templates/versions/fulldoc/text/setup.rb', line 12

def all_objects
  run_verifier(Registry.all)
end

#autoload_stubs_pathObject



108
109
110
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 108

def autoload_stubs_path
  ensure_exist(File.join(stubs_path, 'autoload'))
end

#changelog_filenameObject



26
27
28
# File 'lib/yard-sketchup/templates/changelog/fulldoc/text/setup.rb', line 26

def changelog_filename
  'Changelog SU201x.log'
end

#ensure_exist(path) ⇒ Object



277
278
279
280
281
282
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 277

def ensure_exist(path)
  unless File.directory?(path)
    FileUtils.mkdir_p(path)
  end
  path
end


81
82
83
84
85
86
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 81

def file_footer(object)
  return if object.root?
  footer = StringIO.new
  footer.puts 'end'
  footer.string
end

#file_header(object) ⇒ Object



73
74
75
76
77
78
79
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 73

def file_header(object)
  header = StringIO.new
  header.puts "# Copyright:: Copyright #{Time.now.year} Trimble Inc."
  header.puts "# License:: The MIT License (MIT)"
  #header.puts "# Generated:: #{Time.now.strftime('%F %R')}"
  header.string
end

#find_all_versionsObject



17
18
19
20
21
22
23
24
25
# File 'lib/yard-sketchup/templates/versions/fulldoc/text/setup.rb', line 17

def find_all_versions
  versions = Set.new
  all_objects.each { |object|
    version_tag = object.tag(:version)
    versions << version_tag.text if version_tag
  }
  puts versions.sort.join("\n")
  exit # Avoid the YARD summary
end

#generate_autoloadObject



21
22
23
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 21

def generate_autoload
  generate_sketchup_autoload
end

#generate_changelogObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/yard-sketchup/templates/changelog/fulldoc/text/setup.rb', line 30

def generate_changelog
  #p (methods - Object.instance_methods).sort
  #p ARGV
  puts "Generating #{changelog_filename}..."
  output = StringIO.new
  new_objects = all_objects.sort { |a, b| a.path <=> b.path }
  new_objects.each do |object|
    #object.meths.each { |method|
      #methods << "#{method.namespace}##{method.name}"
    #}
    output.puts "Added #{object.type} #{object.path}"
  end
  changelog_path = File.join(output_path, changelog_filename)
  File.write(changelog_path, output.string)
end

#generate_class_methods(object) ⇒ Object



192
193
194
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 192

def generate_class_methods(object)
  generate_methods(object, :class, 'self.')
end

#generate_constants(object) ⇒ Object

Sort constants without grouping.



169
170
171
172
173
174
175
176
177
178
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 169

def generate_constants(object)
  output = StringIO.new
  constants = run_verifier(object.constants(object_options)).sort { |a, b|
    a.name <=> b.name
  }
  constants.each { |constant|
    output.puts "  #{constant.name} = nil # Stub value."
  }
  output.string
end

#generate_constants_grouped(object) ⇒ Object

Sorts and groups constants for easier reading.



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 141

def generate_constants_grouped(object)
  constants = run_verifier(object.constants(object_options))
  # The constants are not sorted before chunking. This is because `chunk` groups
  # consecutive items - and we want to chunk them based their relationship
  # with each other. This ensure that constants that doesn't follow the normal
  # pattern of PREFIX_SOME_NAME will still be grouped next to each other.
  groups = constants.chunk { |constant|
    group_constant(constant)
  }
  grouped_output = groups.map { |group, group_constants|
    output = StringIO.new
    # Each group itself is sorted in order to more easily scan the list.
    sorted = group_constants.sort { |a, b|
      a.name <=> b.name
    }
    sorted.each { |constant|
      output.puts "  #{constant.name} = nil # Stub value."
    }
    output.string
  }
  # Finally each group is also sorted, again to ease scanning for a particular
  # name. We simply use the first character of each group.
  grouped_output.sort { |a, b|
    a.lstrip[0] <=> b.lstrip[0]
  }.join("\n")
end

#generate_docstring(object, indent_step = 0) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 243

def generate_docstring(object, indent_step = 0)
  output = StringIO.new
  indent = '  ' * indent_step
  docstring = object.docstring
  docstring.delete_tags(:par) # Remove obsolete @par tags.
  docstring.to_raw.lines.each { |line|
    # Naive check for tags with no indent - if it is we insert an extra line
    # in order to get some space for easier reader. Doing it this way in order
    # to avoid hacking YARD too much.
    output.puts "#{indent}#" if line.start_with?('@')
    # This is the original docstring line.
    output.puts "#{indent}# #{line}"
  }
  output.string
end

#generate_instance_methods(object) ⇒ Object



196
197
198
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 196

def generate_instance_methods(object)
  generate_methods(object, :instance)
end

#generate_manifestObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/yard-sketchup/templates/coverage/fulldoc/text/setup.rb', line 23

def generate_manifest
  puts "Generating #{MANIFEST_FILENAME}..."
  methods = Set.new
  namespace_objects.each do |object|
    run_verifier(object.meths).each { |method|
      # TODO(thomthom): Currently the manifest doesn't distinguish between
      # class and instance methods. This should be addressed, but we need to
      # update TestUp to handle this first.
      methods << "#{method.namespace}.#{method.name}"
    }
  end
  manifest = methods.sort.join("\n")
  manifest_path = File.join(output_path, MANIFEST_FILENAME)
  puts manifest_path
  File.write(manifest_path, manifest)
end

#generate_method_signature(object) ⇒ Object

NOTE: This may modify the docstring of the object.



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 219

def generate_method_signature(object)
  signature = "#{object.name}"
  # If there is a single overload then use that as the parameter list. Many of
  # the SketchUp Ruby API methods will have this as it was safer to add an
  # @overload tag instead of renaming the function argument names.
  overloads = object.docstring.tags(:overload)
  if overloads.size == 1
    overload = overloads.first
    parameters = overload.parameters
    # Move the tags from the @overload tag to the root of the docstring. No need
    # for a single overload tag - it's unexpected when reading the source.
    object.docstring.add_tag(*overload.tags)
    object.docstring.delete_tags(:overload)
  else
    parameters = object.parameters
  end
  # Compile the signature for the arguments and default values.
  params = parameters.map { |param|
    param.last.nil? ? param.first : param.join(' = ')
  }.join(', ')
  signature << "(#{params})" unless params.empty?
  signature
end

#generate_methods(object, scope, prefix = '') ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 200

def generate_methods(object, scope, prefix = '')
  methods = sort_methods(object, scope)
  signatures = methods.map { |method|
    output = StringIO.new
    # Cannot use `methods.signature` here as it would return the C/C++ function
    # signature. Must generate one from the YARD data.
    signature = generate_method_signature(method)
    # NOTE: We must call `generate_docstring` after `generate_method_signature`
    # because `generate_method_signature` will also clean up docstrings with
    # a single @overload tag.
    output.puts generate_docstring(method, 1)
    output.puts "  def #{prefix}#{signature}"
    output.puts "  end"
    output.string
  }
  signatures.join("\n")
end

#generate_mixins(object, scope) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 180

def generate_mixins(object, scope)
  output = StringIO.new
  mixin_type = (scope == :class) ? 'extend' : 'include'
  mixins = run_verifier(object.mixins(scope)).sort { |a, b|
    a.path <=> b.path
  }
  mixins.each { |mixin|
    output.puts "  #{mixin_type} #{mixin.path}"
  }
  output.string
end

#generate_module_stubs(object) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 55

def generate_module_stubs(object)
  filename = stub_filename(object)
  ensure_exist(File.dirname(filename))
  StubFile.open(filename, 'w') { |file|
    file.puts file_header(object)
    file.puts
    file.puts namespace_definition(object)
    print_section(file, 'Extends', generate_mixins(object, :class))
    print_section(file, 'Includes', generate_mixins(object, :instance))
    print_section(file, 'Constants', generate_constants_grouped(object))
    print_section(file, 'Class Methods', generate_class_methods(object))
    print_section(file, 'Instance Methods', generate_instance_methods(object))
    file.puts
    file.puts file_footer(object)
  }
  #trim_trailing_white_space(filename)
end

#generate_object_types_listObject

Custom search list grouping the classes in the API into similar groups. TODO(thomthom): This file is just a stub.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/yard-sketchup/templates/default/fulldoc/html/setup.rb', line 8

def generate_object_types_list
   #@items = options.objects if options.objects
   @items = [
      "App Level Classes",
      "Entity Classes",
      "Collection Classes",
      "Geom Classes",
      "UI Classes",
      "Observer Classes",
      "Core Ruby Classes"
   ]
   @list_title = "Object Index"
   @list_type = "object_types"

   # optional: the specified stylesheet class
   # when not specified it will default to the value of @list_type
   @list_class = "class"

   # Generate the full list html file with named feature_list.html
   # @note this file must be match the name of the type
   asset(url_for_list(@list_type), erb(:full_list))
end

#generate_sketchup_autoloadObject



25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 25

def generate_sketchup_autoload
  base = Pathname.new(autoload_stubs_path)
  autoload_file = File.join(autoload_stubs_path, 'sketchup.rb')
  File.open(autoload_file, 'w') { |file|
    pattern = File.join(sketchup_stubs_path, '**/*.rb')
    Dir.glob(pattern) { |filename|
      pathname = Pathname.new(filename)
      relative = pathname.relative_path_from(base)
      file.puts "require '#{relative.to_s}'"
    }
  }
end

#generate_stubsObject



38
39
40
41
42
43
44
45
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 38

def generate_stubs
  puts "Generating stubs..."
  generate_module_stubs(Registry.root)
  namespace_objects.each do |object|
    generate_module_stubs(object)
  end
  generate_autoload
end

#group_constant(constant) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 124

def group_constant(constant)
  constant_name = constant.name.to_s
  MANUAL_CONSTANT_GROUPS.each { |rule|
    if rule[:constants]
      return rule[:group] if rule[:constants].include?(constant_name)
    else
      return rule[:group] if rule[:regex].match(constant_name)
    end
  }
  if constant_name.include?('_')
    constant_name.split('_').first
  else
    constant_name[CAMELCASE_CONSTANT] || constant_name
  end
end

#initObject



8
9
10
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 8

def init
  generate_stubs
end

#javascriptsObject

TODO(thomthom): Temporarily disabled until we have time to fully implement this. def menu_lists

# Load the existing menus
super + [ { :type => 'object_types', :title => 'Object Reference', :search_title => 'Object Reference List' } ]

end



11
12
13
14
15
# File 'lib/yard-sketchup/templates/default/layout/html/setup.rb', line 11

def javascripts
  # Using the latest 1.x jQuery from CDN broke the YARD js. For now we must
  # continue to use the version shipping with the YARD template we use as base.
  %w(js/jquery.js js/app.js)
end

#javascripts_full_listObject



1
2
3
# File 'lib/yard-sketchup/templates/default/fulldoc/html/setup.rb', line 1

def javascripts_full_list
  %w(js/jquery.js js/full_list.js js/sketchup.js)
end

#namespace_definition(object) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 88

def namespace_definition(object)
  return if object.root?
  definition = "#{object.type} #{object.path}"
  if object.type == :class && object.superclass.name != :Object
    definition << " < #{object.superclass.path}"
  end
  output = StringIO.new
  output.puts generate_docstring(object)
  output.puts definition
  output.string
end

#namespace_objectsObject

NOTE: Remember to run objects outputted through ‘run_verifier` first in order to filter out items that should be excluded by command line arguments.



16
17
18
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 16

def namespace_objects
  run_verifier(Registry.all(:class, :module))
end

#object_optionsObject



269
270
271
272
273
274
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 269

def object_options
  {
    :inherited => false,
    :included => false
  }
end

#output_pathObject



100
101
102
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 100

def output_path
  options.serializer.options[:basepath] || File.join(Dir.pwd, 'stubs')
end


47
48
49
50
51
52
53
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 47

def print_section(io, title, content)
  return if content.strip.empty?
  io.puts
  io.puts "  # #{title}"
  io.puts
  io.puts content
end

#reference_listObject

See ‘class_list` in fulldoc/html.



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/yard-sketchup/templates/default/fulldoc/html/setup.rb', line 33

def reference_list
   even_odd = "odd"
   out = ""
   @items.each { |item|
      out << "<li class='#{even_odd}'>"
      out << "<a class='toggle'></a>"
      out << item
      out << "</li>"
      even_odd = (even_odd == 'even' ? 'odd' : 'even')
   }
   out
end

#sketchup_stubs_pathObject



112
113
114
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 112

def sketchup_stubs_path
  ensure_exist(File.join(stubs_path, 'SketchUp'))
end

#sort_methods(object, scope) ⇒ Object



259
260
261
262
263
264
265
266
267
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 259

def sort_methods(object, scope)
  methods = run_verifier(object.meths(object_options))
  objects = methods.select { |method|
    method.scope == scope
  }
  objects.sort { |a, b|
    a.name <=> b.name
  }
end

#sourceObject



4
5
6
# File 'lib/yard-sketchup/templates/default/method_details/setup.rb', line 4

def source 
  return 
end

#stub_filename(object) ⇒ Object



116
117
118
119
120
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 116

def stub_filename(object)
  basename = object.path.gsub('::', '/')
  basename = '_top_level' if basename.empty?
  File.join(sketchup_stubs_path, "#{basename}.rb")
end

#stubs_pathObject



104
105
106
# File 'lib/yard-sketchup/templates/stubs/fulldoc/text/setup.rb', line 104

def stubs_path
  ensure_exist(output_path)
end

#stylesheetsObject



17
18
19
# File 'lib/yard-sketchup/templates/default/layout/html/setup.rb', line 17

def stylesheets
  %w(css/style.css css/sketchup.css css/rubyapi.css)
end