| 1 | ; docformat = 'rst' |
|---|
| 2 | |
|---|
| 3 | ;+ |
|---|
| 4 | ; :Properties: |
|---|
| 5 | ; `file` : get, type=object |
|---|
| 6 | ; file tree object |
|---|
| 7 | ; `name` : set, get, type=string |
|---|
| 8 | ; name of the routine |
|---|
| 9 | ; `is_function` : get, set, type=boolean |
|---|
| 10 | ; 1 if a function, 0 if not |
|---|
| 11 | ; `is_method` : get, set, type=boolean |
|---|
| 12 | ; 1 if a method, 0 if not |
|---|
| 13 | ; `parameters` : get, type=object |
|---|
| 14 | ; list object of positional parameter objects for routine |
|---|
| 15 | ; `keywords` : get, type=object |
|---|
| 16 | ; list object of keyword objects for routine |
|---|
| 17 | ;- |
|---|
| 18 | |
|---|
| 19 | ;+ |
|---|
| 20 | ; Get properties. |
|---|
| 21 | ;- |
|---|
| 22 | pro doctreeroutine::getProperty, file=file, name=name, is_function=isFunction, $ |
|---|
| 23 | is_method=isMethod, parameters=parameters, $ |
|---|
| 24 | keywords=keywords |
|---|
| 25 | compile_opt strictarr |
|---|
| 26 | |
|---|
| 27 | if (arg_present(file)) then file = self.file |
|---|
| 28 | if (arg_present(name)) then name = self.name |
|---|
| 29 | if (arg_present(isFunction)) then isFunction = self.isFunction |
|---|
| 30 | if (arg_present(isMethod)) then isMethod = self.isMethod |
|---|
| 31 | if (arg_present(parameters)) then parameters = self.parameters |
|---|
| 32 | if (arg_present(keywords)) then keywords = self.keywords |
|---|
| 33 | end |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | ;+ |
|---|
| 37 | ; Set properties. |
|---|
| 38 | ;- |
|---|
| 39 | pro doctreeroutine::setProperty, name=name, $ |
|---|
| 40 | is_Function=isFunction, $ |
|---|
| 41 | is_method=isMethod, $ |
|---|
| 42 | is_obsolete=isObsolete, $ |
|---|
| 43 | is_abstract=isAbstract, $ |
|---|
| 44 | is_hidden=isHidden, $ |
|---|
| 45 | is_private=isPrivate, $ |
|---|
| 46 | comments=comments, $ |
|---|
| 47 | returns=returns, $ |
|---|
| 48 | examples=examples, $ |
|---|
| 49 | bugs=bugs, pre=pre, post=post, $ |
|---|
| 50 | customer_id=customerId, $ |
|---|
| 51 | author=author, copyright=copyright, $ |
|---|
| 52 | history=history, $ |
|---|
| 53 | version=version, $ |
|---|
| 54 | todo=todo, $ |
|---|
| 55 | restrictions=restrictions |
|---|
| 56 | compile_opt strictarr |
|---|
| 57 | |
|---|
| 58 | if (n_elements(name) gt 0) then self.name = name |
|---|
| 59 | |
|---|
| 60 | if (n_elements(isFunction) gt 0) then self.isFunction = isFunction |
|---|
| 61 | if (n_elements(isMethod) gt 0) then self.isMethod = isMethod |
|---|
| 62 | if (n_elements(isHidden) gt 0) then self.isHidden = isHidden |
|---|
| 63 | if (n_elements(isPrivate) gt 0) then self.isPrivate = isPrivate |
|---|
| 64 | if (n_elements(isObsolete) gt 0) then self.isObsolete = isObsolete |
|---|
| 65 | if (n_elements(isAbstract) gt 0) then self.isAbstract = isAbstract |
|---|
| 66 | |
|---|
| 67 | if (n_elements(comments) gt 0) then self.comments = comments |
|---|
| 68 | if (n_elements(returns) gt 0) then self.returns = returns |
|---|
| 69 | if (n_elements(examples) gt 0) then self.examples = examples |
|---|
| 70 | |
|---|
| 71 | ; "author info" attributes |
|---|
| 72 | if (n_elements(author) gt 0) then begin |
|---|
| 73 | self.hasAuthorInfo = 1B |
|---|
| 74 | self.author = author |
|---|
| 75 | endif |
|---|
| 76 | |
|---|
| 77 | if (n_elements(copyright) gt 0) then begin |
|---|
| 78 | self.hasAuthorInfo = 1B |
|---|
| 79 | self.copyright = copyright |
|---|
| 80 | endif |
|---|
| 81 | |
|---|
| 82 | if (n_elements(history) gt 0) then begin |
|---|
| 83 | self.hasAuthorInfo = 1B |
|---|
| 84 | self.history = history |
|---|
| 85 | endif |
|---|
| 86 | |
|---|
| 87 | if (n_elements(version) gt 0) then begin |
|---|
| 88 | self.hasAuthorInfo = 1B |
|---|
| 89 | self.version = version |
|---|
| 90 | endif |
|---|
| 91 | |
|---|
| 92 | ; "other" attributes |
|---|
| 93 | if (n_elements(bugs) gt 0) then begin |
|---|
| 94 | self.hasOthers = 1B |
|---|
| 95 | self.bugs = bugs |
|---|
| 96 | endif |
|---|
| 97 | |
|---|
| 98 | if (n_elements(pre) gt 0) then begin |
|---|
| 99 | self.hasOthers = 1B |
|---|
| 100 | self.pre = pre |
|---|
| 101 | endif |
|---|
| 102 | |
|---|
| 103 | if (n_elements(post) gt 0) then begin |
|---|
| 104 | self.hasOthers = 1B |
|---|
| 105 | self.post = post |
|---|
| 106 | endif |
|---|
| 107 | |
|---|
| 108 | if (n_elements(customerId) gt 0) then begin |
|---|
| 109 | self.hasOthers = 1B |
|---|
| 110 | self.customerId = customerId |
|---|
| 111 | endif |
|---|
| 112 | |
|---|
| 113 | if (n_elements(todo) gt 0) then begin |
|---|
| 114 | self.hasOthers = 1B |
|---|
| 115 | self.todo = todo |
|---|
| 116 | endif |
|---|
| 117 | |
|---|
| 118 | if (n_elements(restrictions) gt 0) then begin |
|---|
| 119 | self.hasOthers = 1B |
|---|
| 120 | self.restrictions = restrictions |
|---|
| 121 | endif |
|---|
| 122 | end |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | ;+ |
|---|
| 126 | ; Get variables for use with templates. |
|---|
| 127 | ; |
|---|
| 128 | ; :Returns: variable |
|---|
| 129 | ; :Params: |
|---|
| 130 | ; `name` : in, required, type=string |
|---|
| 131 | ; name of variable |
|---|
| 132 | ; |
|---|
| 133 | ; :Keywords: |
|---|
| 134 | ; `found` : out, optional, type=boolean |
|---|
| 135 | ; set to a named variable, returns if variable name was found |
|---|
| 136 | ;- |
|---|
| 137 | function doctreeroutine::getVariable, name, found=found |
|---|
| 138 | compile_opt strictarr |
|---|
| 139 | |
|---|
| 140 | found = 1B |
|---|
| 141 | case strlowcase(name) of |
|---|
| 142 | 'name': return, self.name |
|---|
| 143 | |
|---|
| 144 | 'is_function': return, self.isFunction |
|---|
| 145 | 'is_private': return, self.isPrivate |
|---|
| 146 | 'is_abstract': return, self.isAbstract |
|---|
| 147 | 'is_obsolete': return, self.isObsolete |
|---|
| 148 | |
|---|
| 149 | 'has_comments': return, obj_valid(self.comments) |
|---|
| 150 | 'comments': return, self.system->processComments(self.comments) |
|---|
| 151 | 'comments_first_line': begin |
|---|
| 152 | if (~obj_valid(self.comments)) then return, '' |
|---|
| 153 | |
|---|
| 154 | comments = self.system->processComments(self.comments) |
|---|
| 155 | |
|---|
| 156 | nLines = n_elements(comments) |
|---|
| 157 | line = 0 |
|---|
| 158 | while (line lt nLines) do begin |
|---|
| 159 | pos = stregex(comments[line], '\.( |$)') |
|---|
| 160 | if (pos ne -1) then break |
|---|
| 161 | line++ |
|---|
| 162 | endwhile |
|---|
| 163 | |
|---|
| 164 | if (pos eq -1) then return, comments[0:line-1] |
|---|
| 165 | if (line eq 0) then return, strmid(comments[line], 0, pos + 1) |
|---|
| 166 | |
|---|
| 167 | return, [comments[0:line-1], strmid(comments[line], 0, pos + 1)] |
|---|
| 168 | end |
|---|
| 169 | |
|---|
| 170 | 'has_returns': return, obj_valid(self.returns) |
|---|
| 171 | 'returns': return, self.system->processComments(self.returns) |
|---|
| 172 | |
|---|
| 173 | 'has_examples': return, obj_valid(self.examples) |
|---|
| 174 | 'examples': return, self.system->processComments(self.examples) |
|---|
| 175 | |
|---|
| 176 | 'has_author_info': return, self.hasAuthorInfo |
|---|
| 177 | |
|---|
| 178 | 'has_author': return, obj_valid(self.author) |
|---|
| 179 | 'author': return, self.system->processComments(self.author) |
|---|
| 180 | |
|---|
| 181 | 'has_copyright': return, obj_valid(self.copyright) |
|---|
| 182 | 'copyright': return, self.system->processComments(self.copyright) |
|---|
| 183 | |
|---|
| 184 | 'has_history': return, obj_valid(self.history) |
|---|
| 185 | 'history': return, self.system->processComments(self.history) |
|---|
| 186 | |
|---|
| 187 | 'has_version': return, obj_valid(self.version) |
|---|
| 188 | 'version': return, self.system->processComments(self.version) |
|---|
| 189 | |
|---|
| 190 | 'has_others': return, self.hasOthers |
|---|
| 191 | |
|---|
| 192 | 'has_bugs': return, obj_valid(self.bugs) |
|---|
| 193 | 'bugs': return, self.system->processComments(self.bugs) |
|---|
| 194 | |
|---|
| 195 | 'has_pre': return, obj_valid(self.pre) |
|---|
| 196 | 'pre': return, self.system->processComments(self.pre) |
|---|
| 197 | |
|---|
| 198 | 'has_post': return, obj_valid(self.post) |
|---|
| 199 | 'post': return, self.system->processComments(self.post) |
|---|
| 200 | |
|---|
| 201 | 'has_customer_id': return, obj_valid(self.customerId) |
|---|
| 202 | 'customer_id': return, self.system->processComments(self.customerId) |
|---|
| 203 | |
|---|
| 204 | 'has_todo': return, obj_valid(self.todo) |
|---|
| 205 | 'todo': return, self.system->processComments(self.todo) |
|---|
| 206 | |
|---|
| 207 | 'has_restrictions': return, obj_valid(self.restrictions) |
|---|
| 208 | 'restrictions': return, self.system->processComments(self.restrictions) |
|---|
| 209 | |
|---|
| 210 | 'n_parameters': return, self.parameters->count() |
|---|
| 211 | 'parameters': return, self.parameters->get(/all) |
|---|
| 212 | 'n_keywords': return, self.keywords->count() |
|---|
| 213 | 'keywords': return, self.keywords->get(/all) |
|---|
| 214 | else: begin |
|---|
| 215 | ; search in the system object if the variable is not found here |
|---|
| 216 | var = self.file->getVariable(name, found=found) |
|---|
| 217 | if (found) then return, var |
|---|
| 218 | |
|---|
| 219 | found = 0B |
|---|
| 220 | return, -1L |
|---|
| 221 | end |
|---|
| 222 | endcase |
|---|
| 223 | end |
|---|
| 224 | |
|---|
| 225 | |
|---|
| 226 | ;+ |
|---|
| 227 | ; Uses file hidden/private attributes, system wide user/developer level, and |
|---|
| 228 | ; the status of the containing file to determine if this routine should be |
|---|
| 229 | ; visible. |
|---|
| 230 | ; |
|---|
| 231 | ; :Returns: boolean |
|---|
| 232 | ;- |
|---|
| 233 | function doctreeroutine::isVisible |
|---|
| 234 | compile_opt strictarr |
|---|
| 235 | |
|---|
| 236 | ; each routine in a not-visible file is not visible |
|---|
| 237 | if (~self.file->isVisible()) then return, 0B |
|---|
| 238 | |
|---|
| 239 | if (self.hidden) then return, 0B |
|---|
| 240 | |
|---|
| 241 | ; if creating user-level docs and private then not visible |
|---|
| 242 | self.system->getProperty, user=user |
|---|
| 243 | if (self.private && user) then return, 0B |
|---|
| 244 | |
|---|
| 245 | return, 1B |
|---|
| 246 | end |
|---|
| 247 | |
|---|
| 248 | |
|---|
| 249 | ;+ |
|---|
| 250 | ; Add a parameter to the list of parameters for this routine. |
|---|
| 251 | ; |
|---|
| 252 | ; :Params: |
|---|
| 253 | ; `param` : in, required, type=object |
|---|
| 254 | ; argument tree object |
|---|
| 255 | ;- |
|---|
| 256 | pro doctreeroutine::addParameter, param |
|---|
| 257 | compile_opt strictarr |
|---|
| 258 | |
|---|
| 259 | param->getProperty, name=n |
|---|
| 260 | self.parameters->add, param |
|---|
| 261 | end |
|---|
| 262 | |
|---|
| 263 | |
|---|
| 264 | function doctreeroutine::getParameter, name, found=found |
|---|
| 265 | compile_opt strictarr |
|---|
| 266 | |
|---|
| 267 | found = 1B |
|---|
| 268 | for i = 0L, self.parameters->count() - 1L do begin |
|---|
| 269 | p = self.parameters->get(position=i) |
|---|
| 270 | p->getProperty, name=n |
|---|
| 271 | if (strlowcase(name) eq strlowcase(n)) then return, p |
|---|
| 272 | endfor |
|---|
| 273 | found = 0B |
|---|
| 274 | return, -1L |
|---|
| 275 | end |
|---|
| 276 | |
|---|
| 277 | |
|---|
| 278 | ;+ |
|---|
| 279 | ; Add a keyword to the list of keywords for this routine. |
|---|
| 280 | ; |
|---|
| 281 | ; :Params: |
|---|
| 282 | ; `keyword` : in, required, type=object |
|---|
| 283 | ; argument tree object |
|---|
| 284 | ;- |
|---|
| 285 | pro doctreeroutine::addKeyword, keyword |
|---|
| 286 | compile_opt strictarr |
|---|
| 287 | |
|---|
| 288 | self.keywords->add, keyword |
|---|
| 289 | end |
|---|
| 290 | |
|---|
| 291 | |
|---|
| 292 | function doctreeroutine::getKeyword, name, found=found |
|---|
| 293 | compile_opt strictarr |
|---|
| 294 | |
|---|
| 295 | found = 1B |
|---|
| 296 | for i = 0L, self.keywords->count() - 1L do begin |
|---|
| 297 | k = self.keywords->get(position=i) |
|---|
| 298 | k->getProperty, name=n |
|---|
| 299 | if (strlowcase(name) eq strlowcase(n)) then return, k |
|---|
| 300 | endfor |
|---|
| 301 | found = 0B |
|---|
| 302 | return, -1L |
|---|
| 303 | end |
|---|
| 304 | |
|---|
| 305 | |
|---|
| 306 | ;+ |
|---|
| 307 | ; Mark first and last arguments of a routine. Needs to be called after parsing |
|---|
| 308 | ; the routine, but before the output is started. |
|---|
| 309 | ;- |
|---|
| 310 | pro doctreeroutine::markArguments |
|---|
| 311 | compile_opt strictarr |
|---|
| 312 | |
|---|
| 313 | nArgs = self.parameters->count() + self.keywords->count() |
|---|
| 314 | if (nArgs le 0) then return |
|---|
| 315 | |
|---|
| 316 | arguments = objarr(nArgs) |
|---|
| 317 | |
|---|
| 318 | if (self.parameters->count() gt 0) then begin |
|---|
| 319 | arguments[0] = self.parameters->get(/all) |
|---|
| 320 | endif |
|---|
| 321 | |
|---|
| 322 | if (self.keywords->count() gt 0) then begin |
|---|
| 323 | arguments[self.parameters->count()] = self.keywords->get(/all) |
|---|
| 324 | endif |
|---|
| 325 | |
|---|
| 326 | arguments[0]->setProperty, is_first=1B |
|---|
| 327 | arguments[n_elements(arguments) - 1L]->setProperty, is_last=1B |
|---|
| 328 | end |
|---|
| 329 | |
|---|
| 330 | |
|---|
| 331 | ;+ |
|---|
| 332 | ; Free resources. |
|---|
| 333 | ;- |
|---|
| 334 | pro doctreeroutine::cleanup |
|---|
| 335 | compile_opt strictarr |
|---|
| 336 | |
|---|
| 337 | obj_destroy, [self.parameters, self.keywords, self.comments] |
|---|
| 338 | obj_destroy, [self.returns, self.bugs] |
|---|
| 339 | obj_destroy, [self.author, self.copyright, self.history, self.todo] |
|---|
| 340 | obj_destroy, [self.restrictions] |
|---|
| 341 | end |
|---|
| 342 | |
|---|
| 343 | |
|---|
| 344 | ;+ |
|---|
| 345 | ; Create a routine object. |
|---|
| 346 | ; |
|---|
| 347 | ; :Returns: |
|---|
| 348 | ; 1 for success, 0 for failure |
|---|
| 349 | ; |
|---|
| 350 | ; :Params: |
|---|
| 351 | ; `file` : in, required, type=object |
|---|
| 352 | ; file tree object |
|---|
| 353 | ;- |
|---|
| 354 | function doctreeroutine::init, file, system=system |
|---|
| 355 | compile_opt strictarr |
|---|
| 356 | |
|---|
| 357 | self.file = file |
|---|
| 358 | self.system = system |
|---|
| 359 | |
|---|
| 360 | self.parameters = obj_new('MGcoArrayList', type=11) |
|---|
| 361 | self.keywords = obj_new('MGcoArrayList', type=11) |
|---|
| 362 | |
|---|
| 363 | return, 1B |
|---|
| 364 | end |
|---|
| 365 | |
|---|
| 366 | |
|---|
| 367 | ;+ |
|---|
| 368 | ; Define instance variables for routine class. |
|---|
| 369 | ; |
|---|
| 370 | ; :Fields: |
|---|
| 371 | ; `file` file object containing this routine |
|---|
| 372 | ; `name` string name of this routine |
|---|
| 373 | ; `isFunction` true if this routine is a function |
|---|
| 374 | ; `isMethod` true if this routine is a method of a class |
|---|
| 375 | ; `parameters` list of parameter objects |
|---|
| 376 | ; `keywords` list of keyword objects |
|---|
| 377 | ; `comments` tree node hierarchy |
|---|
| 378 | ;- |
|---|
| 379 | pro doctreeroutine__define |
|---|
| 380 | compile_opt strictarr |
|---|
| 381 | |
|---|
| 382 | define = { DOCtreeRoutine, $ |
|---|
| 383 | system: obj_new(), $ |
|---|
| 384 | file: obj_new(), $ |
|---|
| 385 | |
|---|
| 386 | name: '', $ |
|---|
| 387 | isFunction: 0B, $ |
|---|
| 388 | isMethod: 0B, $ |
|---|
| 389 | isAbstract: 0B, $ |
|---|
| 390 | isObsolete: 0B, $ |
|---|
| 391 | isHidden: 0B, $ |
|---|
| 392 | isPrivate: 0B, $ |
|---|
| 393 | |
|---|
| 394 | parameters: obj_new(), $ |
|---|
| 395 | keywords: obj_new(), $ |
|---|
| 396 | |
|---|
| 397 | comments: obj_new(), $ |
|---|
| 398 | returns: obj_new(), $ |
|---|
| 399 | |
|---|
| 400 | examples: obj_new(), $ |
|---|
| 401 | |
|---|
| 402 | hasAuthorInfo: 0B, $ |
|---|
| 403 | author: obj_new(), $ |
|---|
| 404 | copyright: obj_new(), $ |
|---|
| 405 | history: obj_new(), $ |
|---|
| 406 | version: obj_new(), $ |
|---|
| 407 | |
|---|
| 408 | hasOthers: 0B, $ |
|---|
| 409 | bugs: obj_new(), $ |
|---|
| 410 | pre: obj_new(), $ |
|---|
| 411 | post: obj_new(), $ |
|---|
| 412 | customerId: obj_new(), $ |
|---|
| 413 | todo: obj_new(), $ |
|---|
| 414 | restrictions: obj_new() $ |
|---|
| 415 | } |
|---|
| 416 | end |
|---|