cmd/gentypes: generate request, response, event ctor (#63)
The mapping from event request and response id to event and response types
can be done in generating. This makes sure that the maps stay up
to date with the spec.
Suzy Mueller authored 2 years ago
GitHub committed 2 years ago
30 | 30 | "net/http" |
31 | 31 | "os" |
32 | 32 | "strings" |
33 | "unicode" | |
33 | 34 | ) |
34 | 35 | |
35 | 36 | var ( |
423 | 424 | } |
424 | 425 | } |
425 | 426 | |
427 | func emitCtor(sb *strings.Builder, reqs, resps, events []string) { | |
428 | fmt.Fprint(sb, ` | |
429 | // Mapping of request commands and corresponding struct constructors that | |
430 | // can be passed to json.Unmarshal. | |
431 | var requestCtor = map[string]messageCtor{`) | |
432 | for _, r := range reqs { | |
433 | req := strings.TrimSuffix(firstToLower(r), "Request") | |
434 | var msg string | |
435 | if req == "initialize" { | |
436 | msg = ` | |
437 | Arguments: InitializeRequestArguments{ | |
438 | // Set the default values specified here: https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Initialize. | |
439 | LinesStartAt1: true, | |
440 | ColumnsStartAt1: true, | |
441 | PathFormat: "path", | |
442 | }, | |
443 | ` | |
444 | } | |
445 | fmt.Fprintf(sb, "\n\t\"%s\":\tfunc() Message { return &%s{%s} },", req, r, msg) | |
446 | } | |
447 | fmt.Fprint(sb, "\n}") | |
448 | ||
449 | fmt.Fprint(sb, ` | |
450 | // Mapping of response commands and corresponding struct constructors that | |
451 | // can be passed to json.Unmarshal. | |
452 | var responseCtor = map[string]messageCtor{`) | |
453 | for _, r := range resps { | |
454 | resp := strings.TrimSuffix(firstToLower(r), "Response") | |
455 | ||
456 | fmt.Fprintf(sb, "\n\t\"%s\":\tfunc() Message { return &%s{} },", resp, r) | |
457 | } | |
458 | fmt.Fprint(sb, "\n}") | |
459 | ||
460 | fmt.Fprint(sb, ` | |
461 | // Mapping of event ids and corresponding struct constructors that | |
462 | // can be passed to json.Unmarshal. | |
463 | var eventCtor = map[string]messageCtor{`) | |
464 | for _, e := range events { | |
465 | ev := strings.TrimSuffix(firstToLower(e), "Event") | |
466 | fmt.Fprintf(sb, "\n\t\"%s\":\tfunc() Message { return &%s{} },", ev, e) | |
467 | } | |
468 | fmt.Fprint(sb, "\n}\n") | |
469 | } | |
470 | ||
471 | func firstToLower(s string) string { | |
472 | r := []rune(s) | |
473 | return string(unicode.ToLower(r[0])) + string(r[1:]) | |
474 | } | |
475 | ||
426 | 476 | const preamble = `// Copyright 2020 Google LLC |
427 | 477 | // |
428 | 478 | // Licensed under the Apache License, Version 2.0 (the "License"); |
536 | 586 | log.Fatal(err) |
537 | 587 | } |
538 | 588 | |
589 | var requests, responses, events []string | |
539 | 590 | for _, typeName := range typeNames { |
540 | 591 | if _, ok := typesExcludeList[typeName]; !ok { |
541 | 592 | b.WriteString(emitToplevelType(replaceGoTypename(typeName), typeMap[typeName])) |
543 | 594 | } |
544 | 595 | |
545 | 596 | emitMethodsForType(&b, replaceGoTypename(typeName)) |
546 | } | |
597 | // Add the typename to the appropriate list. | |
598 | if strings.HasSuffix(typeName, "Request") && typeName != "Request" { | |
599 | requests = append(requests, typeName) | |
600 | } | |
601 | if strings.HasSuffix(typeName, "Response") && typeName != "Response" && typeName != "ErrorResponse" { | |
602 | responses = append(responses, typeName) | |
603 | } | |
604 | if strings.HasSuffix(typeName, "Event") && typeName != "Event" { | |
605 | events = append(events, typeName) | |
606 | } | |
607 | } | |
608 | ||
609 | // Emit the maps from id to response and event types. | |
610 | emitCtor(&b, requests, responses, events) | |
547 | 611 | |
548 | 612 | wholeFile := []byte(b.String()) |
549 | 613 | formatted, err := format.Source(wholeFile) |
72 | 72 | return nil, &DecodeProtocolMessageFieldError{r.GetSeq(), "Request", "command", r.Command} |
73 | 73 | } |
74 | 74 | |
75 | // Mapping of request commands and corresponding struct constructors that | |
76 | // can be passed to json.Unmarshal. | |
77 | var requestCtor = map[string]messageCtor{ | |
78 | "cancel": func() Message { return &CancelRequest{} }, | |
79 | "runInTerminal": func() Message { return &RunInTerminalRequest{} }, | |
80 | "initialize": func() Message { | |
81 | return &InitializeRequest{ | |
82 | Arguments: InitializeRequestArguments{ | |
83 | // Set the default values specified here: https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Initialize. | |
84 | LinesStartAt1: true, | |
85 | ColumnsStartAt1: true, | |
86 | PathFormat: "path", | |
87 | }, | |
88 | } | |
89 | }, | |
90 | "configurationDone": func() Message { return &ConfigurationDoneRequest{} }, | |
91 | "launch": func() Message { return &LaunchRequest{} }, | |
92 | "attach": func() Message { return &AttachRequest{} }, | |
93 | "restart": func() Message { return &RestartRequest{} }, | |
94 | "disconnect": func() Message { return &DisconnectRequest{} }, | |
95 | "terminate": func() Message { return &TerminateRequest{} }, | |
96 | "breakpointLocations": func() Message { return &BreakpointLocationsRequest{} }, | |
97 | "setBreakpoints": func() Message { return &SetBreakpointsRequest{} }, | |
98 | "setFunctionBreakpoints": func() Message { return &SetFunctionBreakpointsRequest{} }, | |
99 | "setExceptionBreakpoints": func() Message { return &SetExceptionBreakpointsRequest{} }, | |
100 | "dataBreakpointInfo": func() Message { return &DataBreakpointInfoRequest{} }, | |
101 | "setDataBreakpoints": func() Message { return &SetDataBreakpointsRequest{} }, | |
102 | "continue": func() Message { return &ContinueRequest{} }, | |
103 | "next": func() Message { return &NextRequest{} }, | |
104 | "stepIn": func() Message { return &StepInRequest{} }, | |
105 | "stepOut": func() Message { return &StepOutRequest{} }, | |
106 | "stepBack": func() Message { return &StepBackRequest{} }, | |
107 | "reverseContinue": func() Message { return &ReverseContinueRequest{} }, | |
108 | "restartFrame": func() Message { return &RestartFrameRequest{} }, | |
109 | "goto": func() Message { return &GotoRequest{} }, | |
110 | "pause": func() Message { return &PauseRequest{} }, | |
111 | "stackTrace": func() Message { return &StackTraceRequest{} }, | |
112 | "scopes": func() Message { return &ScopesRequest{} }, | |
113 | "variables": func() Message { return &VariablesRequest{} }, | |
114 | "setVariable": func() Message { return &SetVariableRequest{} }, | |
115 | "source": func() Message { return &SourceRequest{} }, | |
116 | "threads": func() Message { return &ThreadsRequest{} }, | |
117 | "terminateThreads": func() Message { return &TerminateThreadsRequest{} }, | |
118 | "modules": func() Message { return &ModulesRequest{} }, | |
119 | "loadedSources": func() Message { return &LoadedSourcesRequest{} }, | |
120 | "evaluate": func() Message { return &EvaluateRequest{} }, | |
121 | "setExpression": func() Message { return &SetExpressionRequest{} }, | |
122 | "stepInTargets": func() Message { return &StepInTargetsRequest{} }, | |
123 | "gotoTargets": func() Message { return &GotoTargetsRequest{} }, | |
124 | "completions": func() Message { return &CompletionsRequest{} }, | |
125 | "exceptionInfo": func() Message { return &ExceptionInfoRequest{} }, | |
126 | "readMemory": func() Message { return &ReadMemoryRequest{} }, | |
127 | "disassemble": func() Message { return &DisassembleRequest{} }, | |
128 | } | |
129 | ||
130 | 75 | // decodeResponse determines what response type in the ProtocolMessage hierarchy |
131 | 76 | // data corresponds to and uses json.Unmarshal to populate the corresponding |
132 | 77 | // struct to be returned. |
148 | 93 | return nil, &DecodeProtocolMessageFieldError{r.GetSeq(), "Response", "command", r.Command} |
149 | 94 | } |
150 | 95 | |
151 | // Mapping of response commands and corresponding struct constructors that | |
152 | // can be passed to json.Unmarshal. | |
153 | var responseCtor = map[string]messageCtor{ | |
154 | "cancel": func() Message { return &CancelResponse{} }, | |
155 | "runInTerminal": func() Message { return &RunInTerminalResponse{} }, | |
156 | "initialize": func() Message { return &InitializeResponse{} }, | |
157 | "configurationDone": func() Message { return &ConfigurationDoneResponse{} }, | |
158 | "launch": func() Message { return &LaunchResponse{} }, | |
159 | "attach": func() Message { return &AttachResponse{} }, | |
160 | "restart": func() Message { return &RestartResponse{} }, | |
161 | "disconnect": func() Message { return &DisconnectResponse{} }, | |
162 | "terminate": func() Message { return &TerminateResponse{} }, | |
163 | "breakpointLocations": func() Message { return &BreakpointLocationsResponse{} }, | |
164 | "setBreakpoints": func() Message { return &SetBreakpointsResponse{} }, | |
165 | "setFunctionBreakpoints": func() Message { return &SetFunctionBreakpointsResponse{} }, | |
166 | "setExceptionBreakpoints": func() Message { return &SetExceptionBreakpointsResponse{} }, | |
167 | "dataBreakpointInfo": func() Message { return &DataBreakpointInfoResponse{} }, | |
168 | "setDataBreakpoints": func() Message { return &SetDataBreakpointsResponse{} }, | |
169 | "continue": func() Message { return &ContinueResponse{} }, | |
170 | "next": func() Message { return &NextResponse{} }, | |
171 | "stepIn": func() Message { return &StepInResponse{} }, | |
172 | "stepOut": func() Message { return &StepOutResponse{} }, | |
173 | "stepBack": func() Message { return &StepBackResponse{} }, | |
174 | "reverseContinue": func() Message { return &ReverseContinueResponse{} }, | |
175 | "restartFrame": func() Message { return &RestartFrameResponse{} }, | |
176 | "goto": func() Message { return &GotoResponse{} }, | |
177 | "pause": func() Message { return &PauseResponse{} }, | |
178 | "stackTrace": func() Message { return &StackTraceResponse{} }, | |
179 | "scopes": func() Message { return &ScopesResponse{} }, | |
180 | "variables": func() Message { return &VariablesResponse{} }, | |
181 | "setVariable": func() Message { return &SetVariableResponse{} }, | |
182 | "source": func() Message { return &SourceResponse{} }, | |
183 | "threads": func() Message { return &ThreadsResponse{} }, | |
184 | "terminateThreads": func() Message { return &TerminateThreadsResponse{} }, | |
185 | "modules": func() Message { return &ModulesResponse{} }, | |
186 | "loadedSources": func() Message { return &LoadedSourcesResponse{} }, | |
187 | "evaluate": func() Message { return &EvaluateResponse{} }, | |
188 | "setExpression": func() Message { return &SetExpressionResponse{} }, | |
189 | "stepInTargets": func() Message { return &StepInTargetsResponse{} }, | |
190 | "gotoTargets": func() Message { return &GotoTargetsResponse{} }, | |
191 | "completions": func() Message { return &CompletionsResponse{} }, | |
192 | "exceptionInfo": func() Message { return &ExceptionInfoResponse{} }, | |
193 | "readMemory": func() Message { return &ReadMemoryResponse{} }, | |
194 | "disassemble": func() Message { return &DisassembleResponse{} }, | |
195 | } | |
196 | ||
197 | 96 | // decodeEvent determines what event type in the ProtocolMessage hierarchy |
198 | 97 | // data corresponds to and uses json.Unmarshal to populate the corresponding |
199 | 98 | // struct to be returned. |
209 | 108 | } |
210 | 109 | return nil, &DecodeProtocolMessageFieldError{e.GetSeq(), "Event", "event", e.Event} |
211 | 110 | } |
212 | ||
213 | // Mapping of event ids and corresponding struct constructors that | |
214 | // can be passed to json.Unmarshal. | |
215 | var eventCtor = map[string]messageCtor{ | |
216 | "initialized": func() Message { return &InitializedEvent{} }, | |
217 | "stopped": func() Message { return &StoppedEvent{} }, | |
218 | "continued": func() Message { return &ContinuedEvent{} }, | |
219 | "exited": func() Message { return &ExitedEvent{} }, | |
220 | "terminated": func() Message { return &TerminatedEvent{} }, | |
221 | "thread": func() Message { return &ThreadEvent{} }, | |
222 | "output": func() Message { return &OutputEvent{} }, | |
223 | "breakpoint": func() Message { return &BreakpointEvent{} }, | |
224 | "module": func() Message { return &ModuleEvent{} }, | |
225 | "loadedSource": func() Message { return &LoadedSourceEvent{} }, | |
226 | "process": func() Message { return &ProcessEvent{} }, | |
227 | "capabilities": func() Message { return &CapabilitiesEvent{} }, | |
228 | } |
1953 | 1953 | |
1954 | 1954 | // InvalidatedAreas: Logical areas that can be invalidated by the 'invalidated' event. |
1955 | 1955 | type InvalidatedAreas string |
1956 | ||
1957 | // Mapping of request commands and corresponding struct constructors that | |
1958 | // can be passed to json.Unmarshal. | |
1959 | var requestCtor = map[string]messageCtor{ | |
1960 | "cancel": func() Message { return &CancelRequest{} }, | |
1961 | "runInTerminal": func() Message { return &RunInTerminalRequest{} }, | |
1962 | "initialize": func() Message { | |
1963 | return &InitializeRequest{ | |
1964 | Arguments: InitializeRequestArguments{ | |
1965 | // Set the default values specified here: https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Initialize. | |
1966 | LinesStartAt1: true, | |
1967 | ColumnsStartAt1: true, | |
1968 | PathFormat: "path", | |
1969 | }, | |
1970 | } | |
1971 | }, | |
1972 | "configurationDone": func() Message { return &ConfigurationDoneRequest{} }, | |
1973 | "launch": func() Message { return &LaunchRequest{} }, | |
1974 | "attach": func() Message { return &AttachRequest{} }, | |
1975 | "restart": func() Message { return &RestartRequest{} }, | |
1976 | "disconnect": func() Message { return &DisconnectRequest{} }, | |
1977 | "terminate": func() Message { return &TerminateRequest{} }, | |
1978 | "breakpointLocations": func() Message { return &BreakpointLocationsRequest{} }, | |
1979 | "setBreakpoints": func() Message { return &SetBreakpointsRequest{} }, | |
1980 | "setFunctionBreakpoints": func() Message { return &SetFunctionBreakpointsRequest{} }, | |
1981 | "setExceptionBreakpoints": func() Message { return &SetExceptionBreakpointsRequest{} }, | |
1982 | "dataBreakpointInfo": func() Message { return &DataBreakpointInfoRequest{} }, | |
1983 | "setDataBreakpoints": func() Message { return &SetDataBreakpointsRequest{} }, | |
1984 | "setInstructionBreakpoints": func() Message { return &SetInstructionBreakpointsRequest{} }, | |
1985 | "continue": func() Message { return &ContinueRequest{} }, | |
1986 | "next": func() Message { return &NextRequest{} }, | |
1987 | "stepIn": func() Message { return &StepInRequest{} }, | |
1988 | "stepOut": func() Message { return &StepOutRequest{} }, | |
1989 | "stepBack": func() Message { return &StepBackRequest{} }, | |
1990 | "reverseContinue": func() Message { return &ReverseContinueRequest{} }, | |
1991 | "restartFrame": func() Message { return &RestartFrameRequest{} }, | |
1992 | "goto": func() Message { return &GotoRequest{} }, | |
1993 | "pause": func() Message { return &PauseRequest{} }, | |
1994 | "stackTrace": func() Message { return &StackTraceRequest{} }, | |
1995 | "scopes": func() Message { return &ScopesRequest{} }, | |
1996 | "variables": func() Message { return &VariablesRequest{} }, | |
1997 | "setVariable": func() Message { return &SetVariableRequest{} }, | |
1998 | "source": func() Message { return &SourceRequest{} }, | |
1999 | "threads": func() Message { return &ThreadsRequest{} }, | |
2000 | "terminateThreads": func() Message { return &TerminateThreadsRequest{} }, | |
2001 | "modules": func() Message { return &ModulesRequest{} }, | |
2002 | "loadedSources": func() Message { return &LoadedSourcesRequest{} }, | |
2003 | "evaluate": func() Message { return &EvaluateRequest{} }, | |
2004 | "setExpression": func() Message { return &SetExpressionRequest{} }, | |
2005 | "stepInTargets": func() Message { return &StepInTargetsRequest{} }, | |
2006 | "gotoTargets": func() Message { return &GotoTargetsRequest{} }, | |
2007 | "completions": func() Message { return &CompletionsRequest{} }, | |
2008 | "exceptionInfo": func() Message { return &ExceptionInfoRequest{} }, | |
2009 | "readMemory": func() Message { return &ReadMemoryRequest{} }, | |
2010 | "writeMemory": func() Message { return &WriteMemoryRequest{} }, | |
2011 | "disassemble": func() Message { return &DisassembleRequest{} }, | |
2012 | } | |
2013 | ||
2014 | // Mapping of response commands and corresponding struct constructors that | |
2015 | // can be passed to json.Unmarshal. | |
2016 | var responseCtor = map[string]messageCtor{ | |
2017 | "cancel": func() Message { return &CancelResponse{} }, | |
2018 | "runInTerminal": func() Message { return &RunInTerminalResponse{} }, | |
2019 | "initialize": func() Message { return &InitializeResponse{} }, | |
2020 | "configurationDone": func() Message { return &ConfigurationDoneResponse{} }, | |
2021 | "launch": func() Message { return &LaunchResponse{} }, | |
2022 | "attach": func() Message { return &AttachResponse{} }, | |
2023 | "restart": func() Message { return &RestartResponse{} }, | |
2024 | "disconnect": func() Message { return &DisconnectResponse{} }, | |
2025 | "terminate": func() Message { return &TerminateResponse{} }, | |
2026 | "breakpointLocations": func() Message { return &BreakpointLocationsResponse{} }, | |
2027 | "setBreakpoints": func() Message { return &SetBreakpointsResponse{} }, | |
2028 | "setFunctionBreakpoints": func() Message { return &SetFunctionBreakpointsResponse{} }, | |
2029 | "setExceptionBreakpoints": func() Message { return &SetExceptionBreakpointsResponse{} }, | |
2030 | "dataBreakpointInfo": func() Message { return &DataBreakpointInfoResponse{} }, | |
2031 | "setDataBreakpoints": func() Message { return &SetDataBreakpointsResponse{} }, | |
2032 | "setInstructionBreakpoints": func() Message { return &SetInstructionBreakpointsResponse{} }, | |
2033 | "continue": func() Message { return &ContinueResponse{} }, | |
2034 | "next": func() Message { return &NextResponse{} }, | |
2035 | "stepIn": func() Message { return &StepInResponse{} }, | |
2036 | "stepOut": func() Message { return &StepOutResponse{} }, | |
2037 | "stepBack": func() Message { return &StepBackResponse{} }, | |
2038 | "reverseContinue": func() Message { return &ReverseContinueResponse{} }, | |
2039 | "restartFrame": func() Message { return &RestartFrameResponse{} }, | |
2040 | "goto": func() Message { return &GotoResponse{} }, | |
2041 | "pause": func() Message { return &PauseResponse{} }, | |
2042 | "stackTrace": func() Message { return &StackTraceResponse{} }, | |
2043 | "scopes": func() Message { return &ScopesResponse{} }, | |
2044 | "variables": func() Message { return &VariablesResponse{} }, | |
2045 | "setVariable": func() Message { return &SetVariableResponse{} }, | |
2046 | "source": func() Message { return &SourceResponse{} }, | |
2047 | "threads": func() Message { return &ThreadsResponse{} }, | |
2048 | "terminateThreads": func() Message { return &TerminateThreadsResponse{} }, | |
2049 | "modules": func() Message { return &ModulesResponse{} }, | |
2050 | "loadedSources": func() Message { return &LoadedSourcesResponse{} }, | |
2051 | "evaluate": func() Message { return &EvaluateResponse{} }, | |
2052 | "setExpression": func() Message { return &SetExpressionResponse{} }, | |
2053 | "stepInTargets": func() Message { return &StepInTargetsResponse{} }, | |
2054 | "gotoTargets": func() Message { return &GotoTargetsResponse{} }, | |
2055 | "completions": func() Message { return &CompletionsResponse{} }, | |
2056 | "exceptionInfo": func() Message { return &ExceptionInfoResponse{} }, | |
2057 | "readMemory": func() Message { return &ReadMemoryResponse{} }, | |
2058 | "writeMemory": func() Message { return &WriteMemoryResponse{} }, | |
2059 | "disassemble": func() Message { return &DisassembleResponse{} }, | |
2060 | } | |
2061 | ||
2062 | // Mapping of event ids and corresponding struct constructors that | |
2063 | // can be passed to json.Unmarshal. | |
2064 | var eventCtor = map[string]messageCtor{ | |
2065 | "initialized": func() Message { return &InitializedEvent{} }, | |
2066 | "stopped": func() Message { return &StoppedEvent{} }, | |
2067 | "continued": func() Message { return &ContinuedEvent{} }, | |
2068 | "exited": func() Message { return &ExitedEvent{} }, | |
2069 | "terminated": func() Message { return &TerminatedEvent{} }, | |
2070 | "thread": func() Message { return &ThreadEvent{} }, | |
2071 | "output": func() Message { return &OutputEvent{} }, | |
2072 | "breakpoint": func() Message { return &BreakpointEvent{} }, | |
2073 | "module": func() Message { return &ModuleEvent{} }, | |
2074 | "loadedSource": func() Message { return &LoadedSourceEvent{} }, | |
2075 | "process": func() Message { return &ProcessEvent{} }, | |
2076 | "capabilities": func() Message { return &CapabilitiesEvent{} }, | |
2077 | "progressStart": func() Message { return &ProgressStartEvent{} }, | |
2078 | "progressUpdate": func() Message { return &ProgressUpdateEvent{} }, | |
2079 | "progressEnd": func() Message { return &ProgressEndEvent{} }, | |
2080 | "invalidated": func() Message { return &InvalidatedEvent{} }, | |
2081 | "memory": func() Message { return &MemoryEvent{} }, | |
2082 | } |