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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"sort"
)
// Model contains the parsed version of the spec
type Model struct {
Version Metadata `json:"metaData"`
Requests []*Request `json:"requests"`
Notifications []*Notification `json:"notifications"`
Structures []*Structure `json:"structures"`
Enumerations []*Enumeration `json:"enumerations"`
TypeAliases []*TypeAlias `json:"typeAliases"`
Line int `json:"line"`
}
// Metadata is information about the version of the spec
type Metadata struct {
Version string `json:"version"`
Line int `json:"line"`
}
// A Request is the parsed version of an LSP request
type Request struct {
Documentation string `json:"documentation"`
ErrorData *Type `json:"errorData"`
Direction string `json:"messageDirection"`
Method string `json:"method"`
Params *Type `json:"params"`
PartialResult *Type `json:"partialResult"`
Proposed bool `json:"proposed"`
RegistrationMethod string `json:"registrationMethod"`
RegistrationOptions *Type `json:"registrationOptions"`
Result *Type `json:"result"`
Since string `json:"since"`
Line int `json:"line"`
}
// A Notificatin is the parsed version of an LSP notification
type Notification struct {
Documentation string `json:"documentation"`
Direction string `json:"messageDirection"`
Method string `json:"method"`
Params *Type `json:"params"`
Proposed bool `json:"proposed"`
RegistrationMethod string `json:"registrationMethod"`
RegistrationOptions *Type `json:"registrationOptions"`
Since string `json:"since"`
Line int `json:"line"`
}
// A Structure is the parsed version of an LSP structure from the spec
type Structure struct {
Documentation string `json:"documentation"`
Extends []*Type `json:"extends"`
Mixins []*Type `json:"mixins"`
Name string `json:"name"`
Properties []NameType `json:"properties"`
Proposed bool `json:"proposed"`
Since string `json:"since"`
Line int `json:"line"`
}
// An enumeration is the parsed version of an LSP enumeration from the spec
type Enumeration struct {
Documentation string `json:"documentation"`
Name string `json:"name"`
Proposed bool `json:"proposed"`
Since string `json:"since"`
SupportsCustomValues bool `json:"supportsCustomValues"`
Type *Type `json:"type"`
Values []NameValue `json:"values"`
Line int `json:"line"`
}
// A TypeAlias is the parsed version of an LSP type alias from the spec
type TypeAlias struct {
Documentation string `json:"documentation"`
Deprecated string `json:"deprecated"`
Name string `json:"name"`
Proposed bool `json:"proposed"`
Since string `json:"since"`
Type *Type `json:"type"`
Line int `json:"line"`
}
// A NameValue describes an enumeration constant
type NameValue struct {
Documentation string `json:"documentation"`
Name string `json:"name"`
Proposed bool `json:"proposed"`
Since string `json:"since"`
Value any `json:"value"` // number or string
Line int `json:"line"`
}
// A Type is the parsed version of an LSP type from the spec,
// or a Type the code constructs
type Type struct {
Kind string `json:"kind"` // -- which kind goes with which field --
Items []*Type `json:"items"` // "and", "or", "tuple"
Element *Type `json:"element"` // "array"
Name string `json:"name"` // "base", "reference"
Key *Type `json:"key"` // "map"
Value any `json:"value"` // "map", "stringLiteral", "literal"
Line int `json:"line"` // JSON source line
}
// ParsedLiteral is Type.Value when Type.Kind is "literal"
type ParseLiteral struct {
Properties `json:"properties"`
}
// A NameType represents the name and type of a structure element
type NameType struct {
Name string `json:"name"`
Type *Type `json:"type"`
Optional bool `json:"optional"`
Documentation string `json:"documentation"`
Deprecated string `json:"deprecated"`
Since string `json:"since"`
Proposed bool `json:"proposed"`
Line int `json:"line"`
}
// Properties are the collection of structure fields
type Properties []NameType
// addLineNumbers adds a "line" field to each object in the JSON.
func addLineNumbers(buf []byte) []byte {
var ans []byte
// In the specification .json file, the delimiter '{' is
// always followed by a newline. There are other {s embedded in strings.
// json.Token does not return \n, or :, or , so using it would
// require parsing the json to reconstruct the missing information.
for linecnt, i := 1, 0; i < len(buf); i++ {
ans = append(ans, buf[i])
switch buf[i] {
case '{':
if buf[i+1] == '\n' {
ans = append(ans, fmt.Sprintf(`"line": %d, `, linecnt)...)
// warning: this would fail if the spec file had
// `"value": {\n}`, but it does not, as comma is a separator.
}
case '\n':
linecnt++
}
}
return ans
}
type sortedMap[T any] map[string]T
func (s sortedMap[T]) keys() []string {
var keys []string
for k := range s {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
|