Class: NaslDoc::CLI::Comment

Inherits:
Object
  • Object
show all
Defined in:
lib/nasldoc/cli/comment.rb

Constant Summary collapse

@@tags =
[
	'anonparam',
	'category',
	'deprecated',
	'include',
	'nessus',
	'param',
	'remark',
	'return'
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node, path) ⇒ Comment

Returns a new instance of Comment.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/nasldoc/cli/comment.rb', line 78

def initialize(node, path)
	# Create common attributes.
	@name = nil
	@type = nil
	@valid = false

	# Create freeform text attributes.
	@summary = nil
	@description = nil

	# Create tag attributes.
	@anonparams = {}
	@anonparams_type = {}
	@categories = []
	@deprecated = nil
	@includes = []
	@nessus = nil
	@params = {}
	@params_type = {}
	@remarks = []
	@return = nil

	# Create export and function attributes.
	@function = nil

	# Create file attributes.
	@filename = nil
	@signed = nil

	# Create global attributes.
	@variables = []

	# Determine if this is a nasldoc comment.
	text = node.text.body;
	@valid = !Regexp.new("(^\s*\#{2,3}\s*$|#{trusted_regex})").match(text).nil?
	return unless @valid

	# Remember the type.
	unless node.next.nil?
		@type = node.next.class.name.gsub(/.*::/, '').downcase.to_sym
	else
		# The first comment in a file might not have a next node.
		@type = :file
	end

	# Store any other attributes we may need, since we're not keeping a
	# reference to the node.
	case @type
	when :export
		extract_function(node.function)
	when :file
		extract_file(node, path)
	when :function
		extract_function(node)
	when :global
		extract_global(node)
	else
		raise UnsupportedClassException, "The class #{node.next.class.name} is not supported."
	end

	# Parse the comment's text.
	parse(text)
end

Instance Attribute Details

#anonparamsObject

Tag attributes.



55
56
57
# File 'lib/nasldoc/cli/comment.rb', line 55

def anonparams
  @anonparams
end

#anonparams_typeObject

Tag attributes.



55
56
57
# File 'lib/nasldoc/cli/comment.rb', line 55

def anonparams_type
  @anonparams_type
end

#categoriesObject

Tag attributes.



55
56
57
# File 'lib/nasldoc/cli/comment.rb', line 55

def categories
  @categories
end

#deprecatedObject

Tag attributes.



55
56
57
# File 'lib/nasldoc/cli/comment.rb', line 55

def deprecated
  @deprecated
end

#descriptionObject

Freeform text attributes.



52
53
54
# File 'lib/nasldoc/cli/comment.rb', line 52

def description
  @description
end

#filenameObject

File attributes.



62
63
64
# File 'lib/nasldoc/cli/comment.rb', line 62

def filename
  @filename
end

#functionObject

Export and function attributes.



59
60
61
# File 'lib/nasldoc/cli/comment.rb', line 59

def function
  @function
end

#includesObject

Tag attributes.



55
56
57
# File 'lib/nasldoc/cli/comment.rb', line 55

def includes
  @includes
end

#nameObject (readonly)

Common attributes.



49
50
51
# File 'lib/nasldoc/cli/comment.rb', line 49

def name
  @name
end

#nessusObject

Tag attributes.



55
56
57
# File 'lib/nasldoc/cli/comment.rb', line 55

def nessus
  @nessus
end

#paramsObject

Returns the value of attribute params.



56
57
58
# File 'lib/nasldoc/cli/comment.rb', line 56

def params
  @params
end

#params_typeObject

Returns the value of attribute params_type.



56
57
58
# File 'lib/nasldoc/cli/comment.rb', line 56

def params_type
  @params_type
end

#remarksObject

Returns the value of attribute remarks.



56
57
58
# File 'lib/nasldoc/cli/comment.rb', line 56

def remarks
  @remarks
end

#returnObject

Returns the value of attribute return.



56
57
58
# File 'lib/nasldoc/cli/comment.rb', line 56

def return
  @return
end

#signedObject

File attributes.



62
63
64
# File 'lib/nasldoc/cli/comment.rb', line 62

def signed
  @signed
end

#summaryObject

Freeform text attributes.



52
53
54
# File 'lib/nasldoc/cli/comment.rb', line 52

def summary
  @summary
end

#typeObject (readonly)

Common attributes.



49
50
51
# File 'lib/nasldoc/cli/comment.rb', line 49

def type
  @type
end

#validObject (readonly)

Common attributes.



49
50
51
# File 'lib/nasldoc/cli/comment.rb', line 49

def valid
  @valid
end

#variablesObject

Global attributes.



65
66
67
# File 'lib/nasldoc/cli/comment.rb', line 65

def variables
  @variables
end

Instance Method Details

#extract_file(node, path) ⇒ Object



306
307
308
309
310
311
312
313
314
315
316
# File 'lib/nasldoc/cli/comment.rb', line 306

def extract_file(node, path)
	# Remember the filename.
	@filename = File.basename(path)

	# Name this comment for use in error messages.
	@name = "file #@filename"

	# Determine whether the filename is signed, but don't validate the
	# signature.
	@signed = !Regexp.new(trusted_regex).match(node.text.body).nil?
end

#extract_function(node) ⇒ Object



318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/nasldoc/cli/comment.rb', line 318

def extract_function(node)
	# Remember the function name.
	fn = node.next
	@function = fn.to_s
	@fn_type = fn.fn_type

	# Name this comment for use in error messages.
	@name = "function " + fn.name.name

	# Add in all named parameters, even ones that weren't annotated.
	fn.params.each { |arg| @params[arg.name] = nil }
end

#extract_global(node) ⇒ Object



331
332
333
334
335
336
337
# File 'lib/nasldoc/cli/comment.rb', line 331

def extract_global(node)
	# Remember all the variables.
	@variables = node.next.idents.map &:name

	# Name this comment for use in error messages.
	@name = "global variable(s) #{@variables.join(', ')}"
end

#parse(text) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/nasldoc/cli/comment.rb', line 142

def parse(text)
	# Remove the trusted header.
	re_sig = Regexp.new(trusted_regex)
	text.gsub!(re_sig, '');

	# strip out empty comment lines with accidental whitespace afterwards
	text.gsub!(/^#+[ \t]+$/, '');
	# Remove the comment prefixes ('#') from the text.
	text.gsub!(/^#+/, '');

	# Parse all the paragraphs of free-form text.
	parse_paragraphs(text)

	# Parse all the tags.
	parse_tags(text)
end

#parse_paragraphs(text) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/nasldoc/cli/comment.rb', line 159

def parse_paragraphs(text)
	re_none = Regexp.new(/[^[:space:]]/)
	re_tags = Regexp.new(tags_regex)

	# Collect together a list of paragraphs.
	min = 9999
	paras = []
	text.each_line('') do |para|
		# Skip if the paragraph has a line starting with a tag, or has no
		# content.
		next unless para =~ re_none
		next if para =~ re_tags
		para.rstrip!
		paras << para

		# Determine the minimum indentation across all paragraphs.
		para.each_line do |line|
			padding = line[/^ */]
			min = [min, padding.length].min

			# No point in continuing if we hit the lower bound.
			break if min == 0
		end
	end

	# Strip the minimum number of spaces from the left.
	if min > 0
		regex = Regexp.new("^ {#{min}}")
		paras.map! { |p| p.gsub(regex, '') }
	end

	# The first paragraph is the summary.
	@summary = paras.shift

	# The following paragraphs are the description.
	@description = paras
end

#parse_tags(text) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/nasldoc/cli/comment.rb', line 197

def parse_tags(text)
	re_name = Regexp.new("(<|\\[)?[_a-zA-Z0-9:]*(\\]|>)?")
	re_tags = Regexp.new(tags_regex)

	# Tags start a line which continues until the next tag or blank line.
	text.each_line('') do |para|
		# Skip if the paragraph it doesn't have a line starting with a tag.
		next if para !~ re_tags

		# Break the paragraphs into blocks, each starting with a tag.
		until para.empty?
			# Find the bounds of the block.
			beg = para.index(re_tags)
			break if beg.nil?
			fin = para.index(re_tags, beg + 1) || -1

			# Pull the block out of the paragraph.
			block = para[beg..fin]
			para = para[fin..-1]

			# Remove the tag from the block.
			tag = block[re_tags]
			block = block[tag.length..-1]
			next if block.nil?

			# Squash all spaces on the block, being mindful that if the block is
			# nil the tag is useless.
			block.gsub!(/[ \n\r\t]+/, ' ')
			next if block.nil?
			block.strip!
			next if block.nil?

			# Squash the tag and trim the '@' off for accessing the object's
			# attribute.
			tag.lstrip!
			attr = tag[1..-1]

			case tag
				when '@anonparam', '@param'
					# Parse the argument name.
					parts_str = block[re_name]
					if parts_str.nil?
						raise TagFormatException, "Failed to parse the #{tag}'s name for #@name."
					end

					parts = parts_str.split(':')

					name = parts[0]
					name = name.gsub(/[\[\]<>]/, '')

					block = block[parts_str.length..-1]

					if block.nil?
						raise TagFormatException, "Failed to parse the #{tag}'s block for #@name."
					end

					block.lstrip!

					type = nil
					if(parts.length > 1)
						  type = parts[1]
						  type = type.gsub(/[\[\]<>]/, '')
					end

					# Check for previous declarations of this name.
					if @anonparams.key?(name)
						raise DuplicateTagException, "The param '#{name}' was previously declared as an @anonparam for #@name."
					end

					if @params.key?(name) and not @params[name].nil?
						raise DuplicateTagException, "The param '#{name}' was previously declared as a @param for #@name."
					end
					hash = self.send(attr + 's')
					hash[name] = block
					
					if(!type.nil?)
					  hash1 = self.send(attr + 's_type')
					  hash1[name] = type
					end
					
				when '@category'
					unless @categories.empty?
						raise DuplicateTagException, "The #{tag} tag appears more than once for #@name."
					end

					@categories = block.split(/,/).map &:strip
				when '@deprecated', '@nessus', '@return'
					unless self.send(attr).nil?
						raise DuplicateTagException, "The #{tag} tag appears more than once for #@name."
					end

					self.send(attr + '=', block)
				when '@include', '@remark'
					self.send(attr + 's').push(block)
				else
					raise UnrecognizedTagException, "The #{tag} tag is not recognized in #@name."
			end
		end
	end
end

#tags_regexObject



298
299
300
# File 'lib/nasldoc/cli/comment.rb', line 298

def tags_regex
	"^\s*@(#{@@tags.join('|')})"
end

#trusted_regexObject



302
303
304
# File 'lib/nasldoc/cli/comment.rb', line 302

def trusted_regex
	"^#TRUSTED [[:xdigit:]]{1024}$"
end