def compile_method(self, method): signature = util.StringBuilder() for annotation in method.annotations: formatter.output_annotation(annotation, signature) formatter.output_modifiers(method.modifiers, signature) signature.append(' ') if method.type_parameters: formatter.output_type_params(method.type_parameters, signature) signature.append(' ') formatter.output_type(method.return_type, signature) signature.append(' ') signature.append(method.name) signature.append('(') formatter.output_list(formatter.output_formal_param, method.parameters, signature, ', ') signature.append(')') if method.throws: signature.append(' throws ') formatter.output_list(formatter.output_exception, method.throws, signature, ', ') doc = self.__output_doc(method) directive = util.Directive('java:method', signature.build()) directive.add_content(doc) return directive
def compile_constructor(self, constructor): signature = util.StringBuilder() for annotation in constructor.annotations: formatter.output_annotation(annotation, signature) formatter.output_modifiers(constructor.modifiers, signature) signature.append(' ') if constructor.type_parameters: formatter.output_type_params(constructor.type_parameters, signature) signature.append(' ') signature.append(constructor.name) signature.append('(') formatter.output_list(formatter.output_formal_param, constructor.parameters, signature, ', ') signature.append(')') if constructor.throws: signature.append(' throws ') formatter.output_list(formatter.output_exception, constructor.throws, signature, ', ') doc = self.__output_doc(constructor) directive = util.Directive('java:constructor', signature.build()) directive.add_content(doc) return directive
def compile(self, ast): """ Compile autodocs for the given Java syntax tree. Documents will be returned documenting each separate type. """ documents = {} imports = util.StringBuilder() for imp in ast.imports: if imp.static or imp.wildcard: continue package_parts = [] cls_parts = [] for part in imp.path.split('.'): if cls_parts or part[0].isupper(): cls_parts.append(part) else: package_parts.append(part) # If the import's final part wasn't capitalized, # append it to the class parts anyway so sphinx doesn't complain. if cls_parts == []: cls_parts.append(package_parts.pop()) package = '.'.join(package_parts) cls = '.'.join(cls_parts) imports.append( util.Directive('java:import', package + ' ' + cls).build()) import_block = imports.build() if not ast.package: raise ValueError('File must have package declaration') package = ast.package.name type_declarations = [] for path, node in ast.filter(javalang.tree.TypeDeclaration): if not self.filter(node): continue classes = [ n.name for n in path if isinstance(n, javalang.tree.TypeDeclaration) ] classes.append(node.name) name = '.'.join(classes) type_declarations.append((package, name, node)) for package, name, declaration in type_declarations: full_name = package + '.' + name document = self.compile_type_document(import_block, package, name, declaration) documents[full_name] = (package, name, document.build()) return documents
def compile_type(self, declaration): signature = util.StringBuilder() formatter.output_declaration(declaration, signature) doc = self.__output_doc(declaration) directive = util.Directive('java:type', signature.build()) directive.add_content(doc) return directive
def compile_enum_constant(self, enum, constant): signature = util.StringBuilder() for annotation in constant.annotations: formatter.output_annotation(annotation, signature) # All enum constants are public, static, and final signature.append('public static final ') signature.append(enum) signature.append(' ') signature.append(constant.name) doc = self.__output_doc(constant) directive = util.Directive('java:field', signature.build()) directive.add_content(doc) return directive
def compile_field(self, field): signature = util.StringBuilder() for annotation in field.annotations: formatter.output_annotation(annotation, signature) formatter.output_modifiers(field.modifiers, signature) signature.append(' ') formatter.output_type(field.type, signature) signature.append(' ') signature.append(field.declarators[0].name) doc = self.__output_doc(field) directive = util.Directive('java:field', signature.build()) directive.add_content(doc) return directive
def write_toc(packages, opts): doc = util.Document() doc.add_heading(opts.toc_title, '=') toc = util.Directive('toctree') toc.add_option('maxdepth', '2') doc.add_object(toc) packages = list(packages) packages.sort() for package in packages: toc.add_content(package.replace('.', '/') + '/package-index\n') filename = 'packages.' + opts.suffix fullpath = os.path.join(opts.destdir, filename) if os.path.exists(fullpath) and not (opts.force or opts.update): sys.stderr.write(fullpath + ' already exists. Use -f to overwrite.\n') sys.exit(1) f = open(fullpath, 'w') f.write(doc.build()) f.close()
def compile_type_document(self, imports_block, package, name, declaration): """ Compile a complete document, documenting a type and its members """ outer_type = name.rpartition('.')[0] document = util.Document() document.add(imports_block) document.add_heading(name, '=') method_summary = util.StringBuilder() document.add_object(method_summary) package_dir = util.Directive('java:package', package) package_dir.add_option('noindex') document.add_object(package_dir) # Add type-level documentation type_dir = self.compile_type(declaration) if outer_type: type_dir.add_option('outertype', outer_type) document.add_object(type_dir) if isinstance(declaration, javalang.tree.EnumDeclaration): enum_constants = list(declaration.body.constants) enum_constants.sort(key=lambda c: c.name) document.add_heading('Enum Constants') for enum_constant in enum_constants: if self.member_headers: document.add_heading(enum_constant.name, '^') c = self.compile_enum_constant(name, enum_constant) c.add_option('outertype', name) document.add_object(c) fields = list(filter(self.filter, declaration.fields)) if fields: document.add_heading('Fields', '-') fields.sort(key=lambda f: f.declarators[0].name) for field in fields: if self.member_headers: document.add_heading(field.declarators[0].name, '^') f = self.compile_field(field) f.add_option('outertype', name) document.add_object(f) constructors = list(filter(self.filter, declaration.constructors)) if constructors: document.add_heading('Constructors', '-') constructors.sort(key=lambda c: c.name) for constructor in constructors: if self.member_headers: document.add_heading(constructor.name, '^') c = self.compile_constructor(constructor) c.add_option('outertype', name) document.add_object(c) methods = list(filter(self.filter, declaration.methods)) if methods: document.add_heading('Methods', '-') methods.sort(key=lambda m: m.name) for method in methods: if self.member_headers: document.add_heading(method.name, '^') m = self.compile_method(method) m.add_option('outertype', name) document.add_object(m) return document
def write_documents(documents, sources, opts): package_contents = dict() # Write individual documents for fullname, (package, name, document) in documents.items(): package_path = package.replace('.', os.sep) filebasename = name.replace('.', '-') filename = filebasename + '.' + opts.suffix dirpath = os.path.join(opts.destdir, package_path) fullpath = os.path.join(dirpath, filename) if not os.path.exists(dirpath): os.makedirs(dirpath) elif os.path.exists(fullpath) and not (opts.force or opts.update): sys.stderr.write(fullpath + ' already exists. Use -f to overwrite.\n') sys.exit(1) # Add to package indexes package_contents.setdefault(package, list()).append(filebasename) if opts.update and os.path.exists(fullpath): # If the destination file is newer than the source file than skip # writing it out source_mod_time = os.stat(sources[fullname]).st_mtime dest_mod_time = os.stat(fullpath).st_mtime if source_mod_time < dest_mod_time: continue f = open(fullpath, 'w') f.write(document) f.close() # Write package-index for each package for package, index in package_contents.items(): doc = util.Document() doc.add_heading(package, '=') doc.add_object(util.Directive('java:package', package)) toc = util.Directive('toctree') toc.add_option('maxdepth', '1') doc.add_object(toc) index.sort() for filebasename in index: toc.add_content(filebasename + '\n') package_path = package.replace('.', os.sep) filename = 'package-index.' + opts.suffix dirpath = os.path.join(opts.destdir, package_path) fullpath = os.path.join(dirpath, filename) if not os.path.exists(dirpath): os.makedirs(dirpath) elif os.path.exists(fullpath) and not (opts.force or opts.update): sys.stderr.write(fullpath + ' already exists. Use -f to overwrite.\n') sys.exit(1) f = open(fullpath, 'w') f.write(doc.build()) f.close()