真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器

這篇文章主要介紹“怎么使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”,在日常操作中,相信很多人在怎么使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

作為一家“創(chuàng)意+整合+營銷”的成都網(wǎng)站建設(shè)機(jī)構(gòu),我們在業(yè)內(nèi)良好的客戶口碑。創(chuàng)新互聯(lián)公司提供從前期的網(wǎng)站品牌分析策劃、網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、創(chuàng)意表現(xiàn)、網(wǎng)頁制作、系統(tǒng)開發(fā)以及后續(xù)網(wǎng)站營銷運(yùn)營等一系列服務(wù),幫助企業(yè)打造創(chuàng)新的互聯(lián)網(wǎng)品牌經(jīng)營模式與有效的網(wǎng)絡(luò)營銷方法,創(chuàng)造更大的價(jià)值。

Spring

Spring的主要特性:
1. 控制反轉(zhuǎn)(Inversion of Control, IoC)
2. 面向容器
3. 面向切面(AspectOriented Programming, AOP)

源碼gitee地址:
https://gitee.com/ioly/learning.gooop

原文鏈接:
https://my.oschina.net/ioly

目標(biāo)

  • 參考spring boot常用注解,使用golang編寫“基于注解的靜態(tài)代碼增強(qiáng)器/生成器”

子目標(biāo)(Day 9)

  • struct解析清楚了,接著解析注解就比較容易了

    • scanner/IStructScanner.go:修復(fù)scanMethod()和scanAnnotation()的細(xì)節(jié)問題

    • scanner/IAnnotationScanner.go:注解掃描接口及默認(rèn)實(shí)現(xiàn)。注解的屬性支持雙引號(hào)和重音號(hào)字符串。

    • scanner/IAnnotationScanner_test.go:針對注解信息的單元測試

scanner/IAnnotationScanner.go

注解掃描接口及默認(rèn)實(shí)現(xiàn)。注解的屬性支持雙引號(hào)和重音號(hào)字符串。

package scanner

import (
	"errors"
	"learning/gooop/spring/autogen/common"
	"learning/gooop/spring/autogen/domain"
	"regexp"
	"strings"
)

type IAnnotationScanner interface {
	ScanAnnotations(s *domain.StructInfo)
}

type tAnnotationScanner int

func (me *tAnnotationScanner) ScanAnnotations(s *domain.StructInfo) {
	me.scanStructAnnotation(s)
	me.scanFieldAnnotation(s)
	me.scanMethodAnnotation(s)
}

func (me *tAnnotationScanner) scanStructAnnotation(s *domain.StructInfo) {
	for i := s.LineNO - 1; i >= 0; i-- {
		if !me.matchAnnotation(s, i) {
			break
		}

		code := s.CodeFile.RawLines[i]
		e, a := me.parseAnnotation(code)
		if e != nil {
			panic(e)
		}
		s.AppendAnnotation(a)
	}
}

func (me *tAnnotationScanner) scanFieldAnnotation(s *domain.StructInfo) {
	for _, fld := range s.Fields {
		for i := fld.LineNO - 1; i >= 0; i-- {
			if !me.matchAnnotation(s, i) {
				break
			}

			code := s.CodeFile.RawLines[i]
			e, a := me.parseAnnotation(code)
			if e != nil {
				panic(e)
			}
			fld.AppendAnnotation(a)
		}
	}
}

func (me *tAnnotationScanner) scanMethodAnnotation(s *domain.StructInfo) {
	for _, method := range s.Methods {
		for i := method.LineNO - 1; i >= 0; i-- {
			if !me.matchAnnotation(s, i) {
				break
			}

			code := s.CodeFile.RawLines[i]
			e, a := me.parseAnnotation(code)
			if e != nil {
				panic(e)
			}
			method.AppendAnnotation(a)
		}
	}
}

func (me *tAnnotationScanner) matchAnnotation(s *domain.StructInfo, lineNO int) bool {
	line := s.CodeFile.RawLines[lineNO]
	return gAnnotationStartRegexp.MatchString(line)
}

func (me *tAnnotationScanner) parseAnnotation(line string) (error, *domain.AnnotationInfo) {
	ss := gAnnotationStartRegexp.FindStringSubmatch(line)
	if len(ss) <= 0 {
		return nil, nil
	}
	a := domain.NewAnnotationInfo()

	// name
	declare := ss[0]
	a.Name = ss[1]

	// properties
	t := line[len(declare):]
	for {
		// space*
		b1, s1 := common.Tokens.MatchSpaces(t)
		if b1 {
			t = t[len(s1):]
		}

		// key
		b2, s2 := common.Tokens.MatchIdentifier(t)
		if !b2 {
			break
		}
		t = t[len(s2):]

		// =
		b31, s31 := common.Tokens.MatchSpaces(t)
		if b31 {
			t = t[len(s31):]
		}
		b32 := common.Tokens.MatchString(t, "=")
		if !b32 {
			return errors.New("expecting ="), nil
		} else {
			t = t[1:]
		}
		b33, s33 := common.Tokens.MatchSpaces(t)
		if b33 {
			t = t[len(s33):]
		}

		// value
		b4, s4, i4 := me.parsePropertyValue(t)
		if !b4 {
			return errors.New("expecting attribute value"), nil
		} else {
			t = t[i4:]
			a.AppendAttribute(s2, s4)
		}
	}

	return nil, a
}

func (me *tAnnotationScanner) parsePropertyValue(s string) (bool, string, int) {
	// quoted string by ""
	b2, s2 := common.Tokens.MatchRegexp(s, `^"((\\")|[^"])*"`)
	if b2 {
		return true, me.removeDoubleQuote(s2), len(s2)
	}

	// quoted string by ``
	b3, s3 := common.Tokens.MatchRegexp(s, "^`[^`]+`")
	if b3 {
		return true, s3[1 : len(s3)-1], len(s3)
	}

	// simple string
	b4, s4 := common.Tokens.MatchRegexp(s, `^\S+`)
	if b4 {
		return true, s4, len(s4)
	}

	return false, "", 0
}

func (me *tAnnotationScanner) removeDoubleQuote(s string) string {
	s = s[1 : len(s)-1]
	arrSpecialChars := [][]string{
		{`\r`, "\r"},
		{`\n`, "\n"},
		{`\t`, "\t"},
		{`\"`, "\""},
		{`\\`, "\\"},
		{`\v`, "\v"},
	}

	for _, it := range arrSpecialChars {
		s = strings.ReplaceAll(s, it[0], it[1])
	}
	return s
}

var gAnnotationStartRegexp = regexp.MustCompile(`^//\s*@(\w+)\s*`)

var DefaultAnnotationScanner = new(tAnnotationScanner)

scanner/IAnnotationScanner_test.go

針對注解信息的單元測試

package scanner

import (
	"encoding/json"
	"learning/gooop/spring/autogen/domain"
	"strings"
	"testing"
)

func Test_AnnotationScanner(t *testing.T) {
	code := `
// @RestController path=/order scope=singleton
type StructInfo struct {
	LineNO      int
	Name        string
	CodeFile    *CodeFileInfo
	Fields      []*FieldInfo
	Methods     []*MethodInfo
	Annotations []*AnnotationInfo
}

func NewStructInfo() *StructInfo {
	it := new(StructInfo)
	it.Fields = []*FieldInfo{}
	it.Methods = []*MethodInfo{}
	it.Annotations = []*AnnotationInfo{}
	return it
}

// @GetMapping path=/AppendField
func (me *StructInfo) AppendField(lineNO int, name string, dataType string) error {
	fld := NewFieldInfo()
	fld.Struct = me
	fld.LineNO = lineNO
	fld.Name = name
	fld.DataType = dataType
	me.Fields = append(me.Fields, fld)
	return nil
}

// @GetMapping path="/AppendMethod"
func (me *StructInfo) AppendMethod(method *MethodInfo) (error, string) {
	me.Methods = append(me.Methods, method)
	return nil, ""
}

// @PostMapping path=/AppendAnnotation
func (me *StructInfo) AppendAnnotation(ant *AnnotationInfo) (e error, s string) {
	me.Annotations = append(me.Annotations, ant)
	return nil, ""
}`
	file := domain.NewCodeFileInfo()
	file.CleanLines = strings.Split(code, "\n")
	file.RawLines = file.CleanLines

	DefaultStructScanner.ScanStruct(file)
	for _, it := range file.Structs {
		DefaultAnnotationScanner.ScanAnnotations(it)
		j, e := json.MarshalIndent(it, "", "  ")
		if e != nil {
			t.Fatal(e)
		}
		t.Log(string(j))
	}
}

測試輸出

API server listening at: [::]:41281
=== RUN   Test_AnnotationScanner
    IAnnotationScanner_test.go:63: {
          "LineNO": 2,
          "Name": "StructInfo",
          "Fields": [
            {
              "LineNO": 3,
              "Name": "LineNO",
              "DataType": "int",
              "Annotations": []
            },
            {
              "LineNO": 4,
              "Name": "Name",
              "DataType": "string",
              "Annotations": []
            },
            {
              "LineNO": 5,
              "Name": "CodeFile",
              "DataType": "*CodeFileInfo",
              "Annotations": []
            },
            {
              "LineNO": 6,
              "Name": "Fields",
              "DataType": "[]*FieldInfo",
              "Annotations": []
            },
            {
              "LineNO": 7,
              "Name": "Methods",
              "DataType": "[]*MethodInfo",
              "Annotations": []
            },
            {
              "LineNO": 8,
              "Name": "Annotations",
              "DataType": "[]*AnnotationInfo",
              "Annotations": []
            }
          ],
          "Methods": [
            {
              "LineNO": 20,
              "Name": "AppendField",
              "Arguments": [
                {
                  "Name": "lineNO",
                  "DataType": "int"
                },
                {
                  "Name": "name",
                  "DataType": "string"
                },
                {
                  "Name": "dataType",
                  "DataType": "string"
                }
              ],
              "Annotations": [
                {
                  "Name": "GetMapping",
                  "Attributes": [
                    {
                      "Key": "path",
                      "Value": "/AppendField"
                    }
                  ]
                }
              ],
              "Returns": [
                {
                  "Name": "",
                  "DataType": "error"
                }
              ]
            },
            {
              "LineNO": 31,
              "Name": "AppendMethod",
              "Arguments": [
                {
                  "Name": "method",
                  "DataType": "*MethodInfo"
                }
              ],
              "Annotations": [
                {
                  "Name": "GetMapping",
                  "Attributes": [
                    {
                      "Key": "path",
                      "Value": "/AppendMethod"
                    }
                  ]
                }
              ],
              "Returns": [
                {
                  "Name": "",
                  "DataType": "error"
                },
                {
                  "Name": "",
                  "DataType": "string"
                }
              ]
            },
            {
              "LineNO": 37,
              "Name": "AppendAnnotation",
              "Arguments": [
                {
                  "Name": "ant",
                  "DataType": "*AnnotationInfo"
                }
              ],
              "Annotations": [
                {
                  "Name": "PostMapping",
                  "Attributes": [
                    {
                      "Key": "path",
                      "Value": "/AppendAnnotation"
                    }
                  ]
                }
              ],
              "Returns": [
                {
                  "Name": "e",
                  "DataType": "error"
                }
              ]
            }
          ],
          "Annotations": [
            {
              "Name": "RestController",
              "Attributes": [
                {
                  "Key": "path",
                  "Value": "/order"
                },
                {
                  "Key": "scope",
                  "Value": "singleton"
                }
              ]
            }
          ]
        }
--- PASS: Test_AnnotationScanner (0.01s)
PASS

Debugger finished with exit code 0

到此,關(guān)于“怎么使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!


當(dāng)前標(biāo)題:怎么使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器
瀏覽路徑:http://weahome.cn/article/podjgp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部