github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgGoSource/kmgGoParser/type.go (about)

     1  package kmgGoParser
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/bronze1man/kmg/kmgGoSource/kmgGoReader"
     7  	"strconv"
     8  	"unicode"
     9  	"unicode/utf8"
    10  )
    11  
    12  //
    13  type FuncOrMethodDeclaration struct {
    14  	Name         string
    15  	ReceiverType Type
    16  	InParameter  []FuncParameter
    17  	OutParameter []FuncParameter
    18  }
    19  
    20  func (t *FuncOrMethodDeclaration) GetKind() Kind {
    21  	if t.ReceiverType == nil {
    22  		return Func
    23  	} else {
    24  		return Method
    25  	}
    26  }
    27  
    28  func (t *FuncOrMethodDeclaration) IsExport() bool {
    29  	runeValue, _ := utf8.DecodeRuneInString(t.Name)
    30  	return unicode.IsUpper(runeValue)
    31  }
    32  
    33  // TODO finish it.
    34  type FuncType struct {
    35  	InParameter  []FuncParameter
    36  	OutParameter []FuncParameter
    37  }
    38  
    39  func (t FuncType) GetKind() Kind {
    40  	return Func
    41  }
    42  
    43  type NamedType struct {
    44  	PackagePath string
    45  	Name        string
    46  	underType   Type //TODO 第二次扫描AST获取此信息
    47  	Pkg         *Package
    48  }
    49  
    50  func (t *NamedType) GetKind() Kind {
    51  	return Named
    52  }
    53  
    54  func (t *NamedType) GetUnderType() Type {
    55  	if t.underType == nil {
    56  		definer := t.Pkg.Program.GetNamedType(t.PackagePath, t.Name)
    57  		t.underType = definer.underType
    58  	}
    59  	return t.underType
    60  }
    61  
    62  //TODO finish it
    63  type StructType struct {
    64  	Field []StructField
    65  }
    66  
    67  func (t StructType) GetKind() Kind {
    68  	return Struct
    69  }
    70  
    71  type StructField struct {
    72  	Name             string
    73  	Elem             Type
    74  	IsAnonymousField bool
    75  	Tag              string
    76  }
    77  
    78  type MapType struct {
    79  	Key   Type
    80  	Value Type
    81  }
    82  
    83  func (t MapType) GetKind() Kind {
    84  	return Map
    85  }
    86  
    87  type StringType struct {
    88  }
    89  
    90  type InterfaceType struct {
    91  }
    92  
    93  func (t InterfaceType) GetKind() Kind {
    94  	return Interface
    95  }
    96  
    97  type PointerType struct {
    98  	Elem Type
    99  }
   100  
   101  func (t PointerType) GetKind() Kind {
   102  	return Ptr
   103  }
   104  
   105  func NewPointer(elem Type) PointerType {
   106  	return PointerType{Elem: elem}
   107  }
   108  
   109  type Type interface {
   110  	GetKind() Kind
   111  }
   112  
   113  type FuncParameter struct {
   114  	Name       string
   115  	Type       Type
   116  	IsVariadic bool //是否有3个点
   117  }
   118  
   119  type SliceType struct {
   120  	Elem Type
   121  }
   122  
   123  func (t SliceType) GetKind() Kind {
   124  	return Slice
   125  }
   126  
   127  // TODO finish it
   128  type ArrayType struct {
   129  	Size int
   130  	Elem Type
   131  }
   132  
   133  func (t ArrayType) GetKind() Kind {
   134  	return Array
   135  }
   136  
   137  type ChanType struct {
   138  	Dir  ChanDir
   139  	Elem Type
   140  }
   141  
   142  func (t ChanType) GetKind() Kind {
   143  	return Chan
   144  }
   145  
   146  // 内置的,没有package前缀的类型.
   147  type BuiltinType string
   148  
   149  func (t BuiltinType) GetKind() Kind {
   150  	return builtinTypeMap[t]
   151  }
   152  
   153  func (t BuiltinType) String() string {
   154  	return string(t)
   155  }
   156  
   157  var builtinTypeMap = map[BuiltinType]Kind{
   158  	"bool":       Bool,
   159  	"byte":       Uint8,
   160  	"complex128": Complex128,
   161  	"complex64":  Complex64,
   162  	"error":      Interface, // TODO problem?
   163  	"float32":    Float32,
   164  	"float64":    Float64,
   165  	"int":        Int,
   166  	"int8":       Int8,
   167  	"int16":      Int16,
   168  	"int32":      Int32,
   169  	"int64":      Int64,
   170  	"rune":       Int32,
   171  	"string":     String,
   172  	"uint":       Uint,
   173  	"uint8":      Uint8,
   174  	"uint16":     Uint16,
   175  	"uint32":     Uint32,
   176  	"uint64":     Uint64,
   177  	"uintptr":    Uintptr,
   178  }
   179  
   180  type Kind uint
   181  
   182  const (
   183  	Invalid Kind = iota
   184  	Bool
   185  	Int
   186  	Int8
   187  	Int16
   188  	Int32
   189  	Int64
   190  	Uint
   191  	Uint8
   192  	Uint16
   193  	Uint32
   194  	Uint64
   195  	Uintptr
   196  	Float32
   197  	Float64
   198  	Complex64
   199  	Complex128
   200  	Array
   201  	Chan
   202  	Func
   203  	Interface
   204  	Map
   205  	Ptr
   206  	Slice
   207  	String
   208  	Struct
   209  	UnsafePointer
   210  	Method
   211  	Named
   212  )
   213  
   214  func (k Kind) String() string {
   215  	if int(k) < len(kindNames) {
   216  		return kindNames[k]
   217  	}
   218  	return "kind" + strconv.Itoa(int(k))
   219  }
   220  
   221  var kindNames = []string{
   222  	Invalid:       "invalid",
   223  	Bool:          "bool",
   224  	Int:           "int",
   225  	Int8:          "int8",
   226  	Int16:         "int16",
   227  	Int32:         "int32",
   228  	Int64:         "int64",
   229  	Uint:          "uint",
   230  	Uint8:         "uint8",
   231  	Uint16:        "uint16",
   232  	Uint32:        "uint32",
   233  	Uint64:        "uint64",
   234  	Uintptr:       "uintptr",
   235  	Float32:       "float32",
   236  	Float64:       "float64",
   237  	Complex64:     "complex64",
   238  	Complex128:    "complex128",
   239  	Array:         "array",
   240  	Chan:          "chan",
   241  	Func:          "func",
   242  	Interface:     "interface",
   243  	Map:           "map",
   244  	Ptr:           "ptr",
   245  	Slice:         "slice",
   246  	String:        "string",
   247  	Struct:        "struct",
   248  	UnsafePointer: "unsafe.Pointer",
   249  	Method:        "method",
   250  	Named:         "Named",
   251  }
   252  
   253  type ChanDir int
   254  
   255  const (
   256  	RecvDir ChanDir             = 1 << iota // <-chan
   257  	SendDir                                 // chan<-
   258  	BothDir = RecvDir | SendDir             // chan
   259  )
   260  
   261  /*
   262  第一个字符可能为
   263  	letter -> identifier(单独的类型名,带package的类型的package部分)
   264  	"struct" struct类型开头
   265  	"func" func类型开头
   266  	"interface" interface类型开头
   267  	"*" 指针开头
   268  	"[" (数组,slice) 开头
   269  	"map[" map开头
   270  	"chan " chan开头
   271  	"chan<- " chan<- 开头
   272  	"<-chan" chan<- 开头
   273  */
   274  func (gofile *File) readType(r *kmgGoReader.Reader) Type {
   275  	id := readIdentifier(r)
   276  	if len(id) == 0 {
   277  		if r.IsMatchAfter([]byte("<-chan")) {
   278  			r.MustReadMatch([]byte("<-chan"))
   279  			r.ReadAllSpace()
   280  			return ChanType{
   281  				Dir:  RecvDir,
   282  				Elem: gofile.readType(r),
   283  			}
   284  		}
   285  		b := r.ReadByte()
   286  		if b == '*' {
   287  			return PointerType{
   288  				Elem: gofile.readType(r),
   289  			}
   290  		} else if b == '[' {
   291  			content := readMatchMiddleParantheses(r)
   292  			if len(content) == 1 {
   293  				return SliceType{
   294  					Elem: gofile.readType(r),
   295  				}
   296  			} else {
   297  				// 仅跳过
   298  				return ArrayType{
   299  					Elem: gofile.readType(r),
   300  				}
   301  			}
   302  		} else if b == '(' {
   303  			typ := gofile.readType(r)
   304  			r.MustReadMatch([]byte(")"))
   305  			return typ
   306  		} else {
   307  			panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
   308  		}
   309  	}
   310  	if bytes.Equal(id, []byte("struct")) {
   311  		return gofile.readStruct(r)
   312  	} else if bytes.Equal(id, []byte("interface")) {
   313  		// 仅跳过
   314  		r.ReadAllSpace()
   315  		b := r.ReadByte()
   316  		if b != '{' {
   317  			panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
   318  		}
   319  		readMatchBigParantheses(r)
   320  		return InterfaceType{}
   321  	} else if bytes.Equal(id, []byte("map")) {
   322  		b := r.ReadByte()
   323  		m := MapType{}
   324  		if b != '[' {
   325  			panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
   326  		}
   327  		m.Key = gofile.readType(r)
   328  		r.MustReadMatch([]byte("]"))
   329  		m.Value = gofile.readType(r)
   330  		return m
   331  	} else if bytes.Equal(id, []byte("func")) {
   332  		// 仅跳过
   333  		r.ReadAllSpace()
   334  		b := r.ReadByte()
   335  		if b != '(' {
   336  			panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
   337  		}
   338  		readMatchSmallParantheses(r) //跳过输入参数
   339  		r.ReadAllSpaceWithoutLineBreak()
   340  		run := r.ReadRune() //跳过输出参数
   341  		if run == '(' {
   342  			readMatchSmallParantheses(r)
   343  		} else if run == '\n' { //换行符可以标识这个函数定义结束了.
   344  			return FuncType{}
   345  		} else if unicode.IsLetter(run) || run == '[' || run == '*' || run == '<' {
   346  			r.UnreadRune() //输出参数只有一个类型
   347  			gofile.readType(r)
   348  		} else {
   349  			r.UnreadRune() //读到了其他东西,退回.
   350  		}
   351  		return FuncType{}
   352  	} else if bytes.Equal(id, []byte("chan")) {
   353  		if r.IsMatchAfter([]byte("<-")) {
   354  			r.MustReadMatch([]byte("<-"))
   355  			r.ReadAllSpace()
   356  			return ChanType{
   357  				Dir:  SendDir,
   358  				Elem: gofile.readType(r),
   359  			}
   360  		} else {
   361  			r.ReadAllSpace()
   362  			return ChanType{
   363  				Dir:  BothDir,
   364  				Elem: gofile.readType(r),
   365  			}
   366  		}
   367  	} else {
   368  		b := r.ReadByte()
   369  		if b == '.' {
   370  			pkgPath := string(id)
   371  			pkgPath, err := gofile.LookupFullPackagePath(pkgPath)
   372  			if err != nil {
   373  				fmt.Println(r.GetFileLineInfo(), err.Error()) //TODO 以目前的复杂度暂时无解.需要把所有相关的package都看一遍才能正确.
   374  			}
   375  			id2 := readIdentifier(r)
   376  			return &NamedType{
   377  				PackagePath: pkgPath,
   378  				Name:        string(id2),
   379  				Pkg:         gofile.Pkg,
   380  			}
   381  		} else {
   382  			r.UnreadByte()
   383  			name := string(id)
   384  			if builtinTypeMap[BuiltinType(name)] != Invalid {
   385  				return BuiltinType(name)
   386  			} else {
   387  				return &NamedType{
   388  					PackagePath: gofile.PackagePath,
   389  					Name:        string(id),
   390  					Pkg:         gofile.Pkg,
   391  				}
   392  			}
   393  		}
   394  	}
   395  	/*
   396  		}else if r.IsMatchAfter([]byte("struct")) { //TODO 解决struct后面必须有一个空格的问题.
   397  			r.ReadAllSpace()
   398  			b := r.ReadByte()
   399  			if b!='{' {
   400  				panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
   401  			}
   402  			readMatchBigParantheses(r)
   403  			return StructType{}
   404  		}else if r.IsMatchAfter([]byte("interface")) {
   405  			r.ReadAllSpace()
   406  			b := r.ReadByte()
   407  			if b!='{' {
   408  				panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
   409  			}
   410  			readMatchBigParantheses(r)
   411  			return InterfaceType{}
   412  		}else if r.IsMatchAfter([]byte("map[")){
   413  
   414  		}else if r.IsMatchAfter([]byte("func")){
   415  			//TODO finish it.
   416  		}
   417  	*/
   418  }
   419  
   420  func getTypeStructAnonymousName(typ Type) string {
   421  	ntyp, ok := typ.(*NamedType)
   422  	if ok {
   423  		return ntyp.Name
   424  	}
   425  	ptyp, ok := typ.(PointerType)
   426  	if ok {
   427  		return "*" + getTypeStructAnonymousName(ptyp.Elem)
   428  	}
   429  	btyp, ok := typ.(BuiltinType)
   430  	if ok {
   431  		return string(btyp)
   432  	}
   433  	panic(fmt.Errorf("[getTypeStructAnonymousName] unexpect type %T", typ))
   434  }
   435  
   436  func (gofile *File) readStruct(r *kmgGoReader.Reader) StructType {
   437  	// 仅跳过
   438  	r.ReadAllSpace()
   439  	b := r.ReadByte()
   440  	if b != '{' {
   441  		panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
   442  	}
   443  	lastReadBuf := []bytesAndType{}
   444  	var lastTag []byte
   445  	out := StructType{}
   446  	for {
   447  		r.ReadAllSpaceWithoutLineBreak()
   448  		b := r.ReadByte()
   449  		if b == '}' {
   450  			return out
   451  		} else if b == '"' || b == '\'' || b == '`' {
   452  			r.UnreadByte()
   453  			lastTag = MustReadGoString(r)
   454  		} else if b == ',' {
   455  			continue
   456  		} else if b == '\n' {
   457  			if len(lastReadBuf) == 0 {
   458  				continue
   459  			} else if len(lastReadBuf) == 1 {
   460  				typ := lastReadBuf[0].typ
   461  				name := getTypeStructAnonymousName(typ)
   462  				out.Field = append(out.Field, StructField{
   463  					Name:             name,
   464  					Elem:             typ,
   465  					IsAnonymousField: true,
   466  					Tag:              string(lastTag),
   467  				})
   468  				lastReadBuf = []bytesAndType{}
   469  			} else if len(lastReadBuf) >= 2 {
   470  				typ := lastReadBuf[len(lastReadBuf)-1].typ
   471  				for i := range lastReadBuf[:len(lastReadBuf)-1] {
   472  					out.Field = append(out.Field, StructField{
   473  						Name:             string(lastReadBuf[i].originByte),
   474  						Elem:             typ,
   475  						IsAnonymousField: false,
   476  						Tag:              string(lastTag),
   477  					})
   478  				}
   479  				lastReadBuf = []bytesAndType{}
   480  			}
   481  		} else {
   482  			r.UnreadByte()
   483  			startPos := r.Pos()
   484  			typ := gofile.readType(r)
   485  			lastReadBuf = append(lastReadBuf, bytesAndType{
   486  				originByte: r.BufToCurrent(startPos),
   487  				typ:        typ,
   488  			})
   489  		}
   490  	}
   491  }
   492  
   493  type bytesAndType struct {
   494  	originByte []byte
   495  	typ        Type
   496  }