-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadapter.go
More file actions
135 lines (118 loc) · 3.16 KB
/
adapter.go
File metadata and controls
135 lines (118 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package adapter
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"os/exec"
"github.com/code-game-project/cge-parser/parser"
)
// ParseMetadata reads the header of the CGE file and returns the metadata fields and a new io.Reader (even present if err != nil),
// which still contains the header enabling it to be used for complete parsing.
func ParseMetadata(file io.Reader) (Metadata, io.Reader, []Diagnostic, error) {
reader := newPeekReader(file, 1024)
var metadata Metadata
diagnostics := make([]Diagnostic, 0)
err := parser.Parse(reader, &callbackSender{
CBMetadata: func(cgeVersion string) {
metadata = Metadata{
CGEVersion: cgeVersion,
}
},
CBDiagnostic: func(diagnosticType parser.DiagnosticType, message string, startLine, startCol, endLine, endCol int) {
if diagnosticType == parser.DiagnosticError {
diagnostics = append(diagnostics, Diagnostic{
Type: DiagnosticType(diagnosticType),
Message: message,
StartLine: startLine,
StartColumn: startCol,
EndLine: endLine,
EndColumn: endCol,
})
}
},
}, parser.Config{
OnlyMetadata: true,
IncludeComments: false,
SendTokens: false,
NoObjects: true,
DisableWarnings: true,
})
if len(diagnostics) > 0 && err == nil {
err = errors.New("parsing error")
}
return metadata, io.MultiReader(reader.buffer, file), diagnostics, err
}
type Config struct {
IncludeComments bool
SendTokens bool
NoObjects bool
DisableWarnings bool
}
func (c Config) toArgs() []string {
args := make([]string, 0, 2)
if c.IncludeComments {
args = append(args, "--comments")
}
if c.SendTokens {
args = append(args, "--tokens")
}
if c.NoObjects {
args = append(args, "--no-objects")
}
if c.DisableWarnings {
args = append(args, "--no-warn")
}
return args
}
type ParserResponse struct {
Metadata Metadata
Config Object
Events []Object
Commands []Object
Types []Object
Enums []Object
Tokens []Token
Diagnostics []Diagnostic
}
func ParseCGE(file io.Reader, cgeParserPath string, config Config) (ParserResponse, []error) {
cmd := exec.Command(cgeParserPath, config.toArgs()...)
cmd.Stdin = file
reader, writer := io.Pipe()
cmd.Stdout = writer
errBuf := new(bytes.Buffer)
cmd.Stderr = errBuf
err := cmd.Start()
if err != nil {
return ParserResponse{}, []error{fmt.Errorf("failed to start cge-parser: %w", err)}
}
var response ParserResponse
receiveDone := make(chan struct{})
go func() {
response, err = receiveProtobufs(reader, config)
receiveDone <- struct{}{}
}()
cmdErr := cmd.Wait()
writer.Close()
<-receiveDone
if cmdErr != nil {
if errBuf.Len() > 0 {
scanner := bufio.NewScanner(errBuf)
errs := make([]error, 0, 1)
for scanner.Scan() {
errs = append(errs, errors.New(scanner.Text()))
}
if len(errs) == 0 {
errs = append(errs, fmt.Errorf("failed to execute cge-parser"))
}
return ParserResponse{}, errs
} else {
return ParserResponse{}, []error{fmt.Errorf("failed to execute cge-parser: %w", cmdErr)}
}
}
if err != nil {
return ParserResponse{}, []error{fmt.Errorf("failed to receive data from cge-parser: %w", err)}
}
return response, nil
}