Skip to content

Commit 648291e

Browse files
committed
Add JSON schema for programmers.txt
This schema defines the required data structure of the programmers.txt configuration file of Arduino boards platforms.
1 parent e688ba0 commit 648291e

File tree

31 files changed

+1401
-45
lines changed

31 files changed

+1401
-45
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/schemas/arduino-programmers-txt-definitions-schema.json",
4+
"title": "Shared definitions for the Arduino programmers.txt schemas",
5+
"definitions": {
6+
"propertiesObjects": {
7+
"programmerID": {
8+
"base": {
9+
"object": {
10+
"allOf": [
11+
{
12+
"type": "object"
13+
}
14+
]
15+
}
16+
},
17+
"permissive": {
18+
"object": {
19+
"allOf": [
20+
{
21+
"$ref": "#/definitions/propertiesObjects/programmerID/base/object"
22+
},
23+
{
24+
"properties": {
25+
"name": {
26+
"$ref": "#/definitions/propertiesObjects/programmerIDName/permissive/object"
27+
},
28+
"program.tool": {
29+
"$ref": "#/definitions/propertiesObjects/programmerIDProgramTool/permissive/object"
30+
}
31+
}
32+
},
33+
{
34+
"$ref": "#/definitions/requiredObjects/programmerID/permissive/object"
35+
}
36+
]
37+
}
38+
},
39+
"specification": {
40+
"object": {
41+
"allOf": [
42+
{
43+
"$ref": "#/definitions/propertiesObjects/programmerID/base/object"
44+
},
45+
{
46+
"properties": {
47+
"name": {
48+
"$ref": "#/definitions/propertiesObjects/programmerIDName/specification/object"
49+
},
50+
"program.tool": {
51+
"$ref": "#/definitions/propertiesObjects/programmerIDProgramTool/specification/object"
52+
}
53+
}
54+
},
55+
{
56+
"$ref": "#/definitions/requiredObjects/programmerID/specification/object"
57+
}
58+
]
59+
}
60+
},
61+
"strict": {
62+
"object": {
63+
"allOf": [
64+
{
65+
"$ref": "#/definitions/propertiesObjects/programmerID/base/object"
66+
},
67+
{
68+
"properties": {
69+
"name": {
70+
"$ref": "#/definitions/propertiesObjects/programmerIDName/strict/object"
71+
},
72+
"program.tool": {
73+
"$ref": "#/definitions/propertiesObjects/programmerIDProgramTool/strict/object"
74+
}
75+
}
76+
},
77+
{
78+
"$ref": "#/definitions/requiredObjects/programmerID/strict/object"
79+
}
80+
]
81+
}
82+
}
83+
},
84+
"programmerIDName": {
85+
"base": {
86+
"object": {
87+
"allOf": [
88+
{
89+
"type": "string"
90+
},
91+
{
92+
"minLength": 1
93+
}
94+
]
95+
}
96+
},
97+
"permissive": {
98+
"object": {
99+
"allOf": [
100+
{
101+
"$ref": "#/definitions/propertiesObjects/programmerIDName/base/object"
102+
}
103+
]
104+
}
105+
},
106+
"specification": {
107+
"object": {
108+
"allOf": [
109+
{
110+
"$ref": "#/definitions/propertiesObjects/programmerIDName/base/object"
111+
}
112+
]
113+
}
114+
},
115+
"strict": {
116+
"object": {
117+
"allOf": [
118+
{
119+
"$ref": "#/definitions/propertiesObjects/programmerIDName/base/object"
120+
}
121+
]
122+
}
123+
}
124+
},
125+
"programmerIDProgramTool": {
126+
"base": {
127+
"object": {
128+
"allOf": [
129+
{
130+
"type": "string"
131+
},
132+
{
133+
"minLength": 1
134+
}
135+
]
136+
}
137+
},
138+
"permissive": {
139+
"object": {
140+
"allOf": [
141+
{
142+
"$ref": "#/definitions/propertiesObjects/programmerIDProgramTool/base/object"
143+
}
144+
]
145+
}
146+
},
147+
"specification": {
148+
"object": {
149+
"allOf": [
150+
{
151+
"$ref": "#/definitions/propertiesObjects/programmerIDProgramTool/base/object"
152+
}
153+
]
154+
}
155+
},
156+
"strict": {
157+
"object": {
158+
"allOf": [
159+
{
160+
"$ref": "#/definitions/propertiesObjects/programmerIDProgramTool/base/object"
161+
}
162+
]
163+
}
164+
}
165+
}
166+
},
167+
"requiredObjects": {
168+
"programmerID": {
169+
"base": {
170+
"object": {
171+
"allOf": [
172+
{
173+
"required": ["name", "program.tool"]
174+
}
175+
]
176+
}
177+
},
178+
"permissive": {
179+
"object": {
180+
"allOf": [
181+
{
182+
"$ref": "#/definitions/requiredObjects/programmerID/base/object"
183+
}
184+
]
185+
}
186+
},
187+
"specification": {
188+
"object": {
189+
"allOf": [
190+
{
191+
"$ref": "#/definitions/requiredObjects/programmerID/base/object"
192+
}
193+
]
194+
}
195+
},
196+
"strict": {
197+
"object": {
198+
"allOf": [
199+
{
200+
"$ref": "#/definitions/requiredObjects/programmerID/base/object"
201+
}
202+
]
203+
}
204+
}
205+
}
206+
}
207+
}
208+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/schemas/arduino-programmers-txt-permissive-schema.json",
4+
"title": "Arduino programmers.txt JSON permissive schema",
5+
"description": "programmers.txt contains the definitions of Arduino hardware programmers. See: https://arduino.github.io/arduino-cli/latest/platform-specification/#programmerstxt",
6+
"$comment": "For information on the programmers.txt format, see https://godoc.org/github.com/arduino/go-properties-orderedmap",
7+
"type": "object",
8+
"patternProperties": {
9+
".+": {
10+
"$ref": "arduino-programmers-txt-definitions-schema.json#/definitions/propertiesObjects/programmerID/permissive/object"
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/schemas/arduino-programmers-txt-schema.json",
4+
"title": "Arduino programmers.txt JSON schema",
5+
"description": "programmers.txt contains the definitions of Arduino hardware programmers. See: https://arduino.github.io/arduino-cli/latest/platform-specification/#programmerstxt",
6+
"$comment": "For information on the programmers.txt format, see https://godoc.org/github.com/arduino/go-properties-orderedmap",
7+
"type": "object",
8+
"patternProperties": {
9+
".+": {
10+
"$ref": "arduino-programmers-txt-definitions-schema.json#/definitions/propertiesObjects/programmerID/specification/object"
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/schemas/arduino-programmers-txt-strict-schema.json",
4+
"title": "Arduino programmers.txt JSON strict schema",
5+
"description": "programmers.txt contains the definitions of Arduino hardware programmers. See: https://arduino.github.io/arduino-cli/latest/platform-specification/#programmerstxt",
6+
"$comment": "For information on the programmers.txt format, see https://godoc.org/github.com/arduino/go-properties-orderedmap",
7+
"type": "object",
8+
"patternProperties": {
9+
".+": {
10+
"$ref": "arduino-programmers-txt-definitions-schema.json#/definitions/propertiesObjects/programmerID/strict/object"
11+
}
12+
}
13+
}

internal/project/general/general.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// This file is part of arduino-lint.
2+
//
3+
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-lint.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
// Package general provides functions that apply to multiple project types.
17+
package general
18+
19+
import (
20+
"github.com/arduino/go-properties-orderedmap"
21+
)
22+
23+
/*
24+
PropertiesToFirstLevelExpandedMap converts properties.Map data structures to map[string]interface that maps between .
25+
Even though boards/properties.txt have a multi-level nested data structure, the format has the odd characteristic of
26+
allowing a key to be both an object and a string simultaneously, which is not compatible with Golang maps or JSON. So
27+
the data structure used is a map of the first level keys (necessary to accommodate the board/prograrmmer IDs) to the
28+
full remainder of the keys (rather than recursing through each key level individually), to string values.
29+
*/
30+
func PropertiesToFirstLevelExpandedMap(flatProperties *properties.Map) map[string]interface{} {
31+
propertiesInterface := make(map[string]interface{})
32+
keys := flatProperties.FirstLevelKeys()
33+
for _, key := range keys {
34+
subtreeMap := flatProperties.SubTree(key).AsMap()
35+
// This level also must be converted to map[string]interface{}.
36+
subtreeInterface := make(map[string]interface{})
37+
for subtreeKey, subtreeValue := range subtreeMap {
38+
subtreeInterface[subtreeKey] = subtreeValue
39+
}
40+
propertiesInterface[key] = subtreeInterface
41+
}
42+
43+
return propertiesInterface
44+
}
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// This file is part of arduino-lint.
2+
//
3+
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-lint.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package general
17+
18+
import (
19+
"reflect"
20+
"testing"
21+
22+
"github.com/arduino/go-properties-orderedmap"
23+
"github.com/stretchr/testify/assert"
24+
"github.com/stretchr/testify/require"
25+
)
26+
27+
func TestPropertiesToFirstLevelExpandedMap(t *testing.T) {
28+
rawProperties := []byte(`
29+
foo.bar=asdf
30+
foo.baz=zxcv
31+
bar.bat.bam=123
32+
`)
33+
propertiesInput, err := properties.LoadFromBytes(rawProperties)
34+
require.Nil(t, err)
35+
36+
expectedMapOutput := map[string]interface{}{
37+
"foo": map[string]interface{}{
38+
"bar": "asdf",
39+
"baz": "zxcv",
40+
},
41+
"bar": map[string]interface{}{
42+
"bat.bam": "123",
43+
},
44+
}
45+
46+
assert.True(t, reflect.DeepEqual(expectedMapOutput, PropertiesToFirstLevelExpandedMap(propertiesInput)))
47+
}

internal/project/platform/boardstxt/boardstxt.go

+3-19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ See: https://arduino.github.io/arduino-cli/latest/platform-specification/#boards
2020
package boardstxt
2121

2222
import (
23+
"github.com/arduino/arduino-lint/internal/project/general"
2324
"github.com/arduino/arduino-lint/internal/rule/schema"
2425
"github.com/arduino/arduino-lint/internal/rule/schema/compliancelevel"
2526
"github.com/arduino/arduino-lint/internal/rule/schema/schemadata"
@@ -49,25 +50,8 @@ func Validate(boardsTxt *properties.Map) map[compliancelevel.Type]schema.Validat
4950
schemaObject[compliancelevel.Strict] = schema.Compile("arduino-boards-txt-strict-schema.json", referencedSchemaFilenames, schemadata.Asset)
5051
}
5152

52-
/*
53-
Convert the boards.txt data from the native properties.Map type to the interface type required by the schema
54-
validation package.
55-
Even though boards.txt has a multi-level nested data structure, the format has the odd characteristic of allowing a
56-
key to be both an object and a string simultaneously, which is not compatible with Golang maps or JSON. So the data
57-
structure used is a map of the first level keys (necessary to accommodate the board IDs) to the full remainder of
58-
the keys (rather than recursing through the key levels individually), to string values.
59-
*/
60-
boardsTxtInterface := make(map[string]interface{})
61-
keys := boardsTxt.FirstLevelKeys()
62-
for _, key := range keys {
63-
subtreeMap := boardsTxt.SubTree(key).AsMap()
64-
// This level also must be converted to map[string]interface{}.
65-
subtreeInterface := make(map[string]interface{})
66-
for subtreeKey, subtreeValue := range subtreeMap {
67-
subtreeInterface[subtreeKey] = subtreeValue
68-
}
69-
boardsTxtInterface[key] = subtreeInterface
70-
}
53+
//Convert the boards.txt data from the native properties.Map type to the interface type required by the schema validation package.
54+
boardsTxtInterface := general.PropertiesToFirstLevelExpandedMap(boardsTxt)
7155

7256
validationResults[compliancelevel.Permissive] = schema.Validate(boardsTxtInterface, schemaObject[compliancelevel.Permissive])
7357
validationResults[compliancelevel.Specification] = schema.Validate(boardsTxtInterface, schemaObject[compliancelevel.Specification])

0 commit comments

Comments
 (0)