Skip to content
Snippets Groups Projects
Select Git revision
  • 85cc78fef2d0770d0b5a40ebfccf95426599f8b6
  • master default protected
  • classdiag
  • 13.2.1 protected
  • 13.2.0 protected
  • 13.1.2 protected
  • 13.1.1 protected
  • 13.1.0 protected
  • 13.0.1 protected
  • 13.0.0 protected
  • 10.0.1 protected
  • 10.0.0 protected
  • 7.0.0 protected
  • 6.0.4 protected
  • 6.0.2 protected
  • 6.0.1 protected
  • 6.0.0 protected
  • 5.3.0 protected
  • 5.2.8 protected
  • 5.2.5 protected
  • 5.1.2 protected
  • 5.1.0 protected
  • 5.1.1 protected
23 results

javadoc.go

Blame
  • Miklós Tóth's avatar
    Tóth Miklós Tibor authored
    85cc78fe
    History
    javadoc.go 8.08 KiB
    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"os"
    	"os/exec"
    	"path/filepath"
    	"sort"
    	"strings"
    )
    
    type annotated interface {
    	GetAnnot() []Annot
    }
    
    type InternalType struct {
    	Name          string
    	QualifiedName string
    	DocString     string
    	Annotations   []Annot
    }
    
    func (i *InternalType) GetAnnot() []Annot {
    	return i.Annotations
    }
    
    type Annot struct {
    	TypeName string
    	Elements []struct {
    		InternalType
    		Value string
    	}
    }
    
    type Params struct {
    	InternalType
    	Type InternalType
    }
    
    type Method struct {
    	InternalType
    	Parameters []*Params
    	ReturnType InternalType
    	Exceptions []struct{} // TODO
    	Modifiers  string
    }
    
    type Field struct {
    	InternalType
    	Modifiers string
    	Type      InternalType
    }
    
    type Class struct {
    	InternalType
    	Constructors []Method
    	Interfaces   []struct {
    		InternalType
    		realClass *Class
    	}
    	Superclass struct {
    		InternalType
    		realClass *Class
    	}
    	Methods   []*Method
    	Modifiers string
    	Fields    []*Field
    }
    
    func (c *Class) getMethod(name string) *Method {
    	for i, m := range c.Methods {
    		if m.Name == name {
    			return c.Methods[i]
    		}
    	}
    	return nil
    }
    
    var Javadoc = Subcommand{
    	Name: "javadoc",
    	Command: func(args []string) {
    		if len(args) > 1 {
    			fmt.Println("usage: javadoc [source location]")
    			return
    		}
    
    		if len(args) != 0 {
    			e := genJavadoc(args[0])
    			if e != nil {
    				panic(e)
    			}
    		}
    
    		classes, e := readJavadoc()
    		if e != nil {
    			panic(e)
    		}
    
    		classes = linkInheritance(classes)
    		classes = resolveDocsFromInheritance(classes)
    
    		printLatex(classes)
    	},
    	Help: "create and parse javadoc from code",
    }
    
    func genJavadoc(src string) error {
    	const path = "/tmp/javadoc"
    	e := os.MkdirAll(path, os.ModePerm)
    	if e != nil {
    		return e
    	}
    
    	p, e := filepath.Abs(src)
    	if e != nil {
    		return e
    	}
    
    	cmd := exec.Command("javadoc",
    		"-doclet", "com.raidandfade.JsonDoclet.Main",
    		"-docletpath", "/root/jsonDoclet.jar",
    		"-sourcepath", p,
    		"-private",
    		"-subpackages", "projlab")
    
    	cmd.Dir = path
    
    	b, e := cmd.CombinedOutput()
    
    	if e != nil {
    		fmt.Println(string(b))
    	}
    
    	return e
    }
    
    func readJson(fname string) (*Class, error) {
    	var c Class
    
    	b, e := ioutil.ReadFile(fname)
    	if e != nil {
    		return nil, e
    	}
    
    	e = json.Unmarshal(b, &c)
    	if e != nil {
    		return nil, e
    	}
    
    	replaceFieldType := func(field interface{}, newType string) {
    		field.(*Field).Type.Name = newType
    	}
    	replaceMethodType := func(field interface{}, newType string) {
    		field.(*Method).ReturnType.Name = newType
    	}
    	replaceMethodParamType := func(field interface{}, newType string) {
    		field.(*Params).Type.Name = newType
    	}
    	do := func(arr []annotated, replace func(field interface{}, newType string)) {
    		for i, f := range arr {
    			ann := f.GetAnnot()
    			for _, a := range ann {
    				if a.TypeName == "Docs" {
    					for _, e := range a.Elements {
    						switch e.QualifiedName {
    						case "projlab.Docs.type":
    							e.Value = strings.ReplaceAll(e.Value, "\"", "")
    							replace(arr[i], e.Value)
    						}
    					}
    				}
    			}
    		}
    	}
    
    	tmp := make([]annotated, 0, len(c.Fields))
    	for i := range tmp {
    		tmp[i] = &c.Fields[i].InternalType
    	}
    	do(tmp, replaceFieldType)
    
    	tmp = make([]annotated, 0, len(c.Methods))
    	for i := range tmp {
    		tmp[i] = &c.Methods[i].InternalType
    	}
    	do(tmp, replaceMethodType)
    
    	tmp = make([]annotated, 0)
    	for i := range c.Methods {
    		for j := range c.Methods[i].Parameters {
    			tmp = append(tmp, c.Methods[i].Parameters[j])
    		}
    	}
    	do(tmp, replaceMethodParamType)
    
    	return &c, e
    }
    
    func readJavadoc() (map[string]*Class, error) {
    	const dirname = "/tmp/javadoc/docs"
    
    	files, err := ioutil.ReadDir(dirname)
    	if err != nil {
    		return nil, err
    	}
    
    	m := make(map[string]*Class)
    
    	for _, i := range files {
    		c, e := readJson(dirname + "/" + i.Name())
    		if e != nil {
    			return nil, e
    		}
    		m[c.QualifiedName] = c
    	}
    
    	return m, nil
    }
    
    func linkInheritance(c map[string]*Class) map[string]*Class {
    	for _, v := range c {
    		for k, i := range v.Interfaces {
    			interf, ok := c[i.QualifiedName]
    			if ok {
    				v.Interfaces[k].realClass = interf
    			}
    		}
    		supclass, ok := c[v.Superclass.QualifiedName]
    		if ok {
    			v.Superclass.realClass = supclass
    		}
    	}
    	return c
    }
    
    func resolveDocsFromInheritance(c map[string]*Class) map[string]*Class {
    	for _, cl := range c {
    		// magic incoming
    		finder := func(where []*InternalType, docReplacer func(c *Class) []*InternalType) {
    			for _, m := range where {
    				if m.DocString == "" {
    					for _, repl := range docReplacer(cl) {
    						if repl != nil && repl.Name == m.Name && repl.DocString != "" {
    							m.DocString = repl.DocString
    							break
    						}
    					}
    				}
    			}
    		}
    		getSupClasses := func(c *Class) []*Class {
    			tmp := make([]*Class, 0)
    			if c.Superclass.realClass != nil {
    				tmp = append(tmp, c.Superclass.realClass)
    			}
    			for _, in := range c.Interfaces {
    				if in.realClass != nil {
    					tmp = append(tmp, in.realClass)
    				}
    			}
    			return tmp
    		}
    
    		// methods
    		{
    			tmp := make([]*InternalType, len(cl.Methods))
    			for i, m := range cl.Methods {
    				tmp[i] = &m.InternalType
    			}
    			finder(tmp, func(c *Class) []*InternalType {
    				tmp := make([]*InternalType, 0)
    				sc := getSupClasses(c)
    				for _, s := range sc {
    					for _, m := range s.Methods {
    						tmp = append(tmp, &m.InternalType)
    					}
    				}
    				return tmp
    			})
    		}
    
    		// fields
    		{
    			tmp := make([]*InternalType, len(cl.Fields))
    			for i, m := range cl.Fields {
    				tmp[i] = &m.InternalType
    			}
    			finder(tmp, func(c *Class) []*InternalType {
    				tmp := make([]*InternalType, 0)
    				sc := getSupClasses(c)
    				for _, s := range sc {
    					for _, m := range s.Fields {
    						tmp = append(tmp, &m.InternalType)
    					}
    				}
    				return tmp
    			})
    		}
    	}
    	return c
    }
    
    func printLatex(c map[string]*Class) {
    	keys := make([]string, 0, len(c))
    	for k := range c {
    		keys = append(keys, k)
    	}
    
    	sort.Slice(keys, func(i, j int) bool {
    		return keys[i] < keys[j]
    	})
    
    	for _, k := range keys {
    		class := c[k]
    		printClassDoc(class)
    	}
    }
    
    func printClassDoc(c *Class) {
    	if c.QualifiedName == "projlab.Docs" {
    		return
    	}
    
    	fmt.Printf("\\subsubsection{\\texttt{%s \\textcolor{blue}{%s}}}\n", c.Modifiers, c.Name)
    	fmt.Println("\\begin{itemize}")
    
    	if c.DocString != "" {
    		fmt.Println("\\item Felelősség:")
    		fmt.Println("\\newline")
    		fmt.Println(c.DocString)
    	}
    
    	fmt.Println("\\item Ősosztályok:")
    	fmt.Println("\\newline")
    	if c.Superclass.realClass != nil {
    		var loopy func(c *Class)
    		loopy = func(c *Class) {
    			if c.Superclass.realClass != nil {
    				loopy(c.Superclass.realClass)
    				fmt.Print(" $\\rightarrow$ ")
    			}
    			fmt.Printf("\\texttt{\\textcolor{blue}{%s}}", c.Name)
    		}
    		loopy(c)
    		fmt.Println()
    	} else {
    		fmt.Println("\\emph{Nincs ősosztály}")
    	}
    
    	if !strings.Contains(c.Modifiers, "interface") {
    
    		fmt.Println("\\item Interfészek:")
    		if len(c.Interfaces) == 0 {
    			fmt.Println("\\newline")
    			fmt.Println("\\emph{Nem valósít meg interfészeket}")
    		} else {
    			fmt.Println("\\begin{itemize}")
    			for _, i := range c.Interfaces {
    				fmt.Printf("\\item %s\n", i.Name)
    			}
    			fmt.Println("\\end{itemize}")
    		}
    
    		fmt.Println("\\item Attribútumok")
    		if len(c.Fields) == 0 {
    			fmt.Println("\\newline")
    			fmt.Println("\\emph{Nincsenek attribútumok}")
    		} else {
    			fmt.Println("\\begin{itemize}")
    			for _, attr := range c.Fields {
    				fmt.Printf(`\item \texttt{%s \textcolor{blue}{%s} %s}`, attr.Modifiers, attr.Type.Name, attr.Name)
    				if attr.DocString != "" {
    					fmt.Printf(": %s", attr.DocString)
    				}
    				fmt.Println()
    			}
    			fmt.Println("\\end{itemize}")
    		}
    
    	}
    
    	fmt.Println("\\item Metódusok")
    	if len(c.Methods) == 0 {
    		fmt.Println("\\newline")
    		fmt.Println("\\emph{Nincsenek metódusok}")
    	} else {
    		fmt.Println("\\begin{itemize}")
    		for _, meth := range c.Methods {
    			fmt.Printf(`\item \texttt{%s \textcolor{blue}{`, meth.Modifiers)
    			fmt.Printf("%s} ", meth.ReturnType.Name)
    			fmt.Printf("%s(", meth.Name)
    			for i, par := range meth.Parameters {
    				fmt.Printf("\\textcolor{blue}{%s} %s", par.Type.Name, par.Name)
    				if i != len(meth.Parameters)-1 {
    					fmt.Print(", ")
    				}
    			}
    			fmt.Print(")")
    			fmt.Printf("}")
    			if meth.DocString != "" {
    				fmt.Printf(": %s", meth.DocString)
    			}
    			fmt.Println()
    		}
    		fmt.Println("\n\\end{itemize}")
    	}
    
    	fmt.Println("\\end{itemize}")
    
    	fmt.Println()
    	fmt.Println()
    }