Example #1
0
func (v *typeVisitor) parseMethods(iface *Interface, fields *ast.FieldList) {
	for _, field := range fields.List {
		switch typeNode := field.Type.(type) {
		case *ast.FuncType:
			if len(field.Names) != 1 {
				panic(fmt.Errorf("unexpected named fields in interface type %#v", field))
			}
			method := &Method{
				Name:      field.Names[0].String(),
				Arguments: make([]DeclPair, 0, 10),
				Results:   make([]DeclPair, 0, 10),
			}
			method.Public = ast.IsExported(method.Name)
			parseFuncType(method, typeNode)
			iface.Methods = append(iface.Methods, method)
		case *ast.Ident:
			if len(field.Names) != 0 {
				panic(fmt.Errorf("unexpected named fields in interface type %#v", field))
			}
			elementType := v.elementType(typeNode)
			rel := &Relation{Target: elementType, RelType: Extension}
			iface.Relations = append(iface.Relations, rel)
		case *ast.SelectorExpr:
			if len(field.Names) != 0 {
				panic(fmt.Errorf("unexpected named fields in interface type %#v", field))
			}
			elementType := v.elementType(typeNode)
			rel := &Relation{Target: elementType, RelType: Extension}
			iface.Relations = append(iface.Relations, rel)
		default:
			panic(fmt.Errorf("unexpected field type in interface type %#v on %+v", field, iface))
		}
	}
}
Example #2
0
func (v *methodVisitor) visitFuncDecl(node *ast.FuncDecl) {
	if node.Recv == nil {
		return
	}
	recv := node.Recv.List[0]
	typeName := elementType(recv.Type)
	class, ok := v.name2class[typeName]
	if !ok {
		// unknown method receiver
		return
	}
	method := &Method{
		Name:      node.Name.String(),
		Arguments: make([]DeclPair, 0, 10),
		Results:   make([]DeclPair, 0, 10),
	}
	method.Public = ast.IsExported(method.Name)
	parseFuncType(method, node.Type)
	class.Methods = append(class.Methods, method)
}
Example #3
0
func (v *typeVisitor) parseFields(cl *Class, prefix string, fields *ast.FieldList) {
	for _, field := range fields.List {
		multiplicity := ""
		switch fType := field.Type.(type) {
		case *ast.ArrayType:
			multiplicity = "*"
			// TODO: we should nested array struct in runtime.Memstats like:
			// type A struct { X []struct{ bool }; Y []*struct{ *A }; Z *[]struct{ []*A } }
		case *ast.StarExpr:
			if fType, ok := fType.X.(*ast.StructType); ok { // case: type A struct { X *struct{ bool } }
				if len(field.Names) == 0 { // anonymous field
					panic("anonymous struct is prohibited in go spec")
				}
				for _, name := range field.Names {
					v.parseFields(cl, prefix+name.String()+".", fType.Fields)
				}
				continue
			}
		case *ast.StructType:
			if len(field.Names) == 0 { // anonymous field
				panic("anonymous struct is prohibited in go spec")
			}
			for _, name := range field.Names {
				v.parseFields(cl, prefix+name.String()+".", fType.Fields)
			}
			continue
		}
		elementType := v.elementType(field.Type)
		switch {
		case isPrimitive(elementType) || isField(v.fieldPackages, elementType):
			f := &Field{Type: typeGoString(field.Type), Multiplicity: multiplicity}

			if len(field.Names) == 0 { // anonymous field
				f.Name = prefix + elementType
				cl.Fields = append(cl.Fields, f)
			}
			for _, name := range field.Names {
				f2 := *f
				f2.Name = prefix + name.String()
				f2.Public = ast.IsExported(f2.Name)
				cl.Fields = append(cl.Fields, &f2)
			}
		default:
			rel := &Relation{Target: elementType, Multiplicity: multiplicity}

			if len(field.Names) == 0 { // anonymous field
				if prefix == "" {
					rel.RelType = Composition
				} else {
					rel.Label = prefix + path.Ext(elementType)[1:]
					rel.RelType = Association
				}
				cl.Relations = append(cl.Relations, rel)
			}
			for _, name := range field.Names {
				rel2 := *rel
				rel2.Label = prefix + name.String()
				rel2.RelType = Association
				cl.Relations = append(cl.Relations, &rel2)
			}
		}
	}
}