Skip to content

Commit 0a02b8b

Browse files
authored
optimize C import block handle logic (#131)
* optimize C import block handle logic Signed-off-by: Loong <[email protected]> * update comments Signed-off-by: Loong <[email protected]> * bump up Signed-off-by: Loong <[email protected]>
1 parent 666f229 commit 0a02b8b

11 files changed

+127
-37
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ By default, blank and dot sections are not used and the corresponding lines end
2323

2424
All import blocks use one TAB(`\t`) as Indent.
2525

26+
Since v0.9.0, GCI always puts C import block as the first.
27+
2628
**Note**:
2729

2830
`nolint` is hard to handle at section level, GCI will consider it as a single comment.

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"github.com/daixiang0/gci/cmd/gci"
77
)
88

9-
var version = "0.8.5"
9+
var version = "0.9.0"
1010

1111
func main() {
1212
e := gci.NewExecutor(version)

pkg/gci/gci.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func LoadFormatGoFile(file io.FileObj, cfg config.Config) (src, dist []byte, err
121121
return src, src, nil
122122
}
123123

124-
imports, headEnd, tailStart, err := parse.ParseFile(src, file.Path())
124+
imports, headEnd, tailStart, cStart, cEnd, err := parse.ParseFile(src, file.Path())
125125
if err != nil {
126126
if errors.Is(err, parse.NoImportError{}) {
127127
return src, src, nil
@@ -162,6 +162,12 @@ func LoadFormatGoFile(file io.FileObj, cfg config.Config) (src, dist []byte, err
162162
copy(tail, src[tailStart:])
163163

164164
head = append(head, utils.Linebreak)
165+
// ensure C
166+
if cStart != 0 {
167+
head = append(head, src[cStart:cEnd]...)
168+
head = append(head, utils.Linebreak)
169+
}
170+
165171
// add beginning of import block
166172
head = append(head, `import (`...)
167173
// add end of import block
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
common.cfg.yaml
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/daixiang0/gci"
7+
g "github.com/golang"
8+
)
9+
10+
// #cgo CFLAGS: -DPNG_DEBUG=1
11+
// #cgo amd64 386 CFLAGS: -DX86=1
12+
// #cgo LDFLAGS: -lpng
13+
// #include <png.h>
14+
import "C"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package main
2+
3+
// #cgo CFLAGS: -DPNG_DEBUG=1
4+
// #cgo amd64 386 CFLAGS: -DX86=1
5+
// #cgo LDFLAGS: -lpng
6+
// #include <png.h>
7+
import "C"
8+
9+
import (
10+
"fmt"
11+
12+
g "github.com/golang"
13+
14+
"github.com/daixiang0/gci"
15+
)

pkg/gci/internal/testdata/cgo-block-before-import.cfg.yaml

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
common.cfg.yaml
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
common.cfg.yaml
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/daixiang0/gci"
7+
)
8+
9+
import "C"
10+
11+
import "github.com/golang"
12+
13+
import (
14+
"github.com/daixiang0/gci"
15+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package main
2+
3+
import "C"
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/golang"
9+
10+
"github.com/daixiang0/gci"
11+
)

pkg/parse/parse.go

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -70,31 +70,36 @@ func getImports(imp *ast.ImportSpec) (start, end int, name string) {
7070
return
7171
}
7272

73-
func ParseFile(src []byte, filename string) (ImportList, int, int, error) {
73+
func ParseFile(src []byte, filename string) (ImportList, int, int, int, int, error) {
7474
fileSet := token.NewFileSet()
7575
f, err := parser.ParseFile(fileSet, filename, src, parser.ParseComments)
7676
if err != nil {
77-
return nil, 0, 0, err
77+
return nil, 0, 0, 0, 0, err
7878
}
7979

8080
if len(f.Imports) == 0 {
81-
return nil, 0, 0, NoImportError{}
81+
return nil, 0, 0, 0, 0, NoImportError{}
8282
}
8383

8484
var (
8585
// headEnd means the start of import block
8686
headEnd int
8787
// tailStart means the end + 1 of import block
8888
tailStart int
89-
data ImportList
89+
// cStart means the start of C import block
90+
cStart int
91+
// cEnd means the end of C import block
92+
cEnd int
93+
data ImportList
9094
)
9195

92-
for _, d := range f.Decls {
93-
switch d.(type) {
96+
for index, decl := range f.Decls {
97+
switch decl.(type) {
98+
// skip BadDecl and FuncDecl
9499
case *ast.GenDecl:
95-
dd := d.(*ast.GenDecl)
100+
genDecl := decl.(*ast.GenDecl)
96101

97-
if dd.Tok == token.IMPORT {
102+
if genDecl.Tok == token.IMPORT {
98103
// there are two cases, both end with linebreak:
99104
// 1.
100105
// import (
@@ -103,35 +108,58 @@ func ParseFile(src []byte, filename string) (ImportList, int, int, error) {
103108
// 2.
104109
// import "xxx"
105110
if headEnd == 0 {
106-
headEnd = int(d.Pos()) - 1
111+
headEnd = int(decl.Pos()) - 1
112+
}
113+
tailStart = int(decl.End())
114+
115+
for _, spec := range genDecl.Specs {
116+
imp := spec.(*ast.ImportSpec)
117+
// there are only one C import block
118+
// ensure C import block is the first import block
119+
if imp.Path.Value == C {
120+
/*
121+
common case:
122+
123+
// #include <png.h>
124+
import "C"
125+
126+
notice that decl.Pos() == genDecl.Pos() > genDecl.Doc.Pos()
127+
*/
128+
if genDecl.Doc != nil {
129+
cStart = int(genDecl.Doc.Pos()) - 1
130+
// if C import block is the first, update headEnd
131+
if index == 0 {
132+
headEnd = cStart
133+
}
134+
} else {
135+
/*
136+
special case:
137+
138+
import "C"
139+
*/
140+
cStart = int(decl.Pos()) - 1
141+
}
142+
143+
cEnd = int(decl.End())
144+
145+
continue
146+
}
147+
148+
start, end, name := getImports(imp)
149+
150+
data = append(data, &GciImports{
151+
Start: start,
152+
End: end,
153+
Name: name,
154+
Path: strings.Trim(imp.Path.Value, `"`),
155+
})
107156
}
108-
tailStart = int(d.End())
109-
}
110-
}
111-
}
112-
113-
for _, imp := range f.Imports {
114-
if imp.Path.Value == C {
115-
if imp.Comment != nil {
116-
headEnd = int(imp.Comment.End())
117-
} else {
118-
headEnd = int(imp.Path.End())
119157
}
120-
continue
121158
}
122-
123-
start, end, name := getImports(imp)
124-
125-
data = append(data, &GciImports{
126-
Start: start,
127-
End: end,
128-
Name: name,
129-
Path: strings.Trim(imp.Path.Value, `"`),
130-
})
131159
}
132160

133161
sort.Sort(data)
134-
return data, headEnd, tailStart, nil
162+
return data, headEnd, tailStart, cStart, cEnd, nil
135163
}
136164

137165
// IsGeneratedFileByComment reports whether the source file is generated code.

0 commit comments

Comments
 (0)