Пример #1
0
// ParseTags will create a TagMap from comments given by
// parameter
func ParseTags(commentMap ast.CommentMap) *TagMap {
	tagMap := NewTagMap()
	for _, comment := range commentMap.Comments() {
		// split comment to lines
		lines := strings.Split(comment.Text(), "\n")
		for _, line := range lines {
			// if line does not match this regexp made by Miro do not read tags from line
			if !regexp.MustCompile(`(\@\S+)(:? ([\S]+))*`).Match([]byte(line)) {
				continue
			}
			line, tagName, _ := parseValue(line)
			// if there is a tag on the line read its parameters and their values
			if len(tagName) > 0 && tagName[0] == '@' {
				tag := NewTag(tagName)
				//fmt.Println("Tag Name:", tagName)
				// while there is some input check for parameters
				for line != "" {
					var parName, parVal string
					line, parName, parVal = parseValue(line)
					if parName != "" {
						//fmt.Println("Parameter name:", parName, "Parameter value", parVal)
						tag.Set(parName, parVal)
					}
				}
				// save tag to map
				tagMap.Set(tagName, tag)
			}
		}
	}

	return tagMap
}
Пример #2
0
// ParseStruct will create a structure
// with parameters given and return it
func ParseStruct(spec *ast.TypeSpec, parent *ast.StructType, comments ast.CommentMap) *Structure {
	fMap := make(map[string]*StructField)
	for _, field := range parent.Fields.List {
		if len(field.Names) == 0 {
			continue
		}
		fMap[field.Names[0].Name] = ParseStructField(field, comments.Filter(field))
	}

	s := NewStructure(parent, spec, fMap, ParseTags(comments))

	return s
}
Пример #3
0
// ParseFileAST creates a File parse with all necessary
// structures.
func ParseFileAST(name string, tree *ast.File, commentMap ast.CommentMap) (*File, error) {
	f := NewFile(name, tree)

	for _, i := range tree.Imports {
		f.AddImport(ParseImport(i, commentMap.Filter(i)))
	}

	for _, declaration := range tree.Decls {
		switch decValue := declaration.(type) {
		// catch only generic declarations
		case *ast.GenDecl:
			for _, spec := range decValue.Specs {
				switch specValue := spec.(type) {
				case *ast.TypeSpec:
					// all cases should pass in also specValue as
					// it is the underlying spec
					switch typeValue := specValue.Type.(type) {
					case *ast.StructType:
						f.AddStruct(ParseStruct(specValue, typeValue, commentMap.Filter(declaration)))
					case *ast.InterfaceType:
						f.AddInterface(ParseInterface(specValue, typeValue, commentMap.Filter(declaration)))
					}
				case *ast.ImportSpec:
					// just ignore for now
				case *ast.ValueSpec:
					f.AddConstant(ParseConstant(specValue, commentMap.Filter(declaration)))
				default:
					fmt.Println("Generic value not recognized: ", specValue)
				}
			}
		// catch function declarations
		case *ast.FuncDecl:
			fun := ParseFunction(decValue, commentMap.Filter(declaration))
			if !fun.IsMethod() {
				// add the function to the top level map
				f.AddFunction(fun)
			} else {
				// add the function to the structure it belongs to
				if len(fun.parent.Recv.List) <= 0 {
					// TODO: no receiver defined report?
					break
				}

				// struct that should be assigned the method
				var structType *ast.StructType

				switch receiver := fun.parent.Recv.List[0].Type.(type) {
				// pointer receiver
				case *ast.StarExpr:
					structType = receiver.X.(*ast.Ident).Obj.Decl.(*ast.TypeSpec).Type.(*ast.StructType)
				// copy receiver
				case *ast.Ident:
					structType = receiver.Obj.Decl.(*ast.TypeSpec).Type.(*ast.StructType)
				}

				// search for the structures that receive the method
				// and bind it
				for _, st := range f.structures {
					if st.parent == structType {
						st.AddMethod(fun)
					}
				}
			}
		}
	}

	return f, nil
}