Skip to content

Commit 1beae44

Browse files
committed
update
1 parent f077c64 commit 1beae44

File tree

12 files changed

+392
-46
lines changed

12 files changed

+392
-46
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ CLAUDE.md
88
# Symlinks to ignore
99
CLAUDE.md
1010
json-java21-schema/CLAUDE.md
11+
WISDOM.md
12+
13+
.vscode/

AGENTS.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,50 @@ mvn exec:java -pl json-compatibility-suite -Dexec.args="--json"
6464
./mvn-test-no-boilerplate.sh -Dtest=JsonParserTests -Djava.util.logging.ConsoleHandler.level=FINER
6565
```
6666

67+
## Python Usage (Herodoc, 3.2-safe)
68+
- Prefer `python3` with a heredoc over Perl/sed for non-trivial transforms.
69+
- Target ancient Python 3.2 syntax: no f-strings, no fancy deps.
70+
- Example pattern:
71+
72+
```bash
73+
python3 - <<'PY'
74+
import os, sys, re
75+
src = 'updates/2025-09-04/upstream/jdk.internal.util.json'
76+
dst = 'json-java21/src/main/java/jdk/sandbox/internal/util/json'
77+
def xform(text):
78+
# package
79+
text = re.sub(r'^package\s+jdk\.internal\.util\.json;', 'package jdk.sandbox.internal.util.json;', text, flags=re.M)
80+
# imports for public API
81+
text = re.sub(r'^(\s*import\s+)java\.util\.json\.', r'\1jdk.sandbox.java.util.json.', text, flags=re.M)
82+
# annotations
83+
text = re.sub(r'^\s*@(?:jdk\.internal\..*|ValueBased|StableValue).*\n', '', text, flags=re.M)
84+
return text
85+
for name in os.listdir(src):
86+
if not name.endswith('.java') or name == 'StableValue.java':
87+
continue
88+
data = open(os.path.join(src,name),'r').read()
89+
out = xform(data)
90+
target = os.path.join(dst,name)
91+
tmp = target + '.tmp'
92+
open(tmp,'w').write(out)
93+
if os.path.getsize(tmp) == 0:
94+
sys.stderr.write('Refusing to overwrite 0-byte: '+target+'\n'); sys.exit(1)
95+
os.rename(tmp, target)
96+
print('OK')
97+
PY
98+
```
99+
100+
## <IMPIMENTATION>
101+
- MUST: Follow plan → implement → verify. No silent pivots.
102+
- MUST: Stop immediately on unexpected failures and ask before changing approach.
103+
- MUST: Keep edits atomic; avoid leaving mixed partial states.
104+
- SHOULD: Propose options with trade-offs before invasive changes.
105+
- SHOULD: Prefer mechanical, reversible transforms for upstream syncs.
106+
- SHOULD: Validate non-zero outputs before overwriting files.
107+
- MAY: Add tiny shims (minimal interfaces/classes) to satisfy compile when backporting.
108+
- MUST NOT: Commit unverified mass changes; run compile/tests first.
109+
- MUST NOT: Use Perl/sed for multi-line structural edits—prefer Python 3.2 heredoc.
110+
67111
## Architecture Overview
68112

69113
### Module Structure

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonArrayImpl.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,40 @@
2929
import java.util.List;
3030
import jdk.sandbox.java.util.json.JsonArray;
3131
import jdk.sandbox.java.util.json.JsonValue;
32-
33-
34-
/// JsonArray implementation class
35-
public final class JsonArrayImpl implements JsonArray {
32+
/**
33+
* JsonArray implementation class
34+
*/
35+
public final class JsonArrayImpl implements JsonArray, JsonValueImpl {
3636

3737
private final List<JsonValue> theValues;
38+
private final int offset;
39+
private final char[] doc;
3840

3941
public JsonArrayImpl(List<JsonValue> from) {
42+
this(from, -1, null);
43+
}
44+
45+
public JsonArrayImpl(List<JsonValue> from, int o, char[] d) {
4046
theValues = from;
47+
offset = o;
48+
doc = d;
4149
}
4250

4351
@Override
4452
public List<JsonValue> values() {
4553
return Collections.unmodifiableList(theValues);
4654
}
4755

56+
@Override
57+
public char[] doc() {
58+
return doc;
59+
}
60+
61+
@Override
62+
public int offset() {
63+
return offset;
64+
}
65+
4866
@Override
4967
public String toString() {
5068
var s = new StringBuilder("[");

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonBooleanImpl.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,39 @@
2626
package jdk.sandbox.internal.util.json;
2727

2828
import jdk.sandbox.java.util.json.JsonBoolean;
29-
30-
31-
/// JsonBoolean implementation class
32-
public final class JsonBooleanImpl implements JsonBoolean {
29+
/**
30+
* JsonBoolean implementation class
31+
*/
32+
public final class JsonBooleanImpl implements JsonBoolean, JsonValueImpl {
3333

3434
private final Boolean theBoolean;
35+
private final int offset;
36+
private final char[] doc;
3537

36-
public static final JsonBooleanImpl TRUE = new JsonBooleanImpl(true);
37-
public static final JsonBooleanImpl FALSE = new JsonBooleanImpl(false);
38+
public static final JsonBooleanImpl TRUE = new JsonBooleanImpl(true, null, -1);
39+
public static final JsonBooleanImpl FALSE = new JsonBooleanImpl(false, null, -1);
3840

39-
private JsonBooleanImpl(Boolean bool) {
41+
public JsonBooleanImpl(Boolean bool, char[] doc, int offset) {
4042
theBoolean = bool;
43+
this.doc = doc;
44+
this.offset = offset;
4145
}
4246

4347
@Override
4448
public boolean value() {
4549
return theBoolean;
4650
}
4751

52+
@Override
53+
public char[] doc() {
54+
return doc;
55+
}
56+
57+
@Override
58+
public int offset() {
59+
return offset;
60+
}
61+
4862
@Override
4963
public String toString() {
5064
return String.valueOf(value());

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonNullImpl.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,32 @@
2626
package jdk.sandbox.internal.util.json;
2727

2828
import jdk.sandbox.java.util.json.JsonNull;
29+
/**
30+
* JsonNull implementation class
31+
*/
32+
public final class JsonNullImpl implements JsonNull, JsonValueImpl {
2933

34+
private final int offset;
35+
private final char[] doc;
3036

31-
/// JsonNull implementation class
32-
public final class JsonNullImpl implements JsonNull {
33-
34-
public static final JsonNullImpl NULL = new JsonNullImpl();
37+
public static final JsonNullImpl NULL = new JsonNullImpl(null, -1);
3538
private static final String VALUE = "null";
3639
private static final int HASH = VALUE.hashCode();
3740

38-
private JsonNullImpl() {}
41+
public JsonNullImpl(char[] doc, int offset) {
42+
this.doc = doc;
43+
this.offset = offset;
44+
}
45+
46+
@Override
47+
public char[] doc() {
48+
return doc;
49+
}
50+
51+
@Override
52+
public int offset() {
53+
return offset;
54+
}
3955

4056
@Override
4157
public String toString() {

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonNumberImpl.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
import java.math.BigInteger;
3030
import java.util.Locale;
3131
import jdk.sandbox.java.util.json.JsonNumber;
32-
33-
34-
/// JsonNumber implementation class
35-
public final class JsonNumberImpl implements JsonNumber {
32+
/**
33+
* JsonNumber implementation class
34+
*/
35+
public final class JsonNumberImpl implements JsonNumber, JsonValueImpl {
3636

3737
private final char[] doc;
3838
private final int startOffset;
@@ -78,7 +78,7 @@ public Number toNumber() {
7878
} else {
7979
try {
8080
return Long.parseLong(str);
81-
} catch (NumberFormatException ignored) {
81+
} catch(NumberFormatException e) {
8282
return new BigInteger(str);
8383
}
8484
}
@@ -97,6 +97,16 @@ public BigDecimal toBigDecimal() {
9797
});
9898
}
9999

100+
@Override
101+
public char[] doc() {
102+
return doc;
103+
}
104+
105+
@Override
106+
public int offset() {
107+
return startOffset;
108+
}
109+
100110
@Override
101111
public String toString() {
102112
return numString.orElseSet(

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonObjectImpl.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,40 @@
2929
import java.util.Map;
3030
import jdk.sandbox.java.util.json.JsonObject;
3131
import jdk.sandbox.java.util.json.JsonValue;
32-
33-
34-
/// JsonObject implementation class
35-
public final class JsonObjectImpl implements JsonObject {
32+
/**
33+
* JsonObject implementation class
34+
*/
35+
public final class JsonObjectImpl implements JsonObject, JsonValueImpl {
3636

3737
private final Map<String, JsonValue> theMembers;
38+
private final int offset;
39+
private final char[] doc;
3840

3941
public JsonObjectImpl(Map<String, JsonValue> map) {
42+
this(map, -1, null);
43+
}
44+
45+
public JsonObjectImpl(Map<String, JsonValue> map, int o, char[] d) {
4046
theMembers = map;
47+
offset = o;
48+
doc = d;
4149
}
4250

4351
@Override
4452
public Map<String, JsonValue> members() {
4553
return Collections.unmodifiableMap(theMembers);
4654
}
4755

56+
@Override
57+
public char[] doc() {
58+
return doc;
59+
}
60+
61+
@Override
62+
public int offset() {
63+
return offset;
64+
}
65+
4866
@Override
4967
public String toString() {
5068
var s = new StringBuilder("{");

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonParser.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
3636
import jdk.sandbox.java.util.json.JsonString;
3737
import jdk.sandbox.java.util.json.JsonValue;
3838

39-
/// Parses a JSON Document char[] into a tree of JsonValues. JsonObject and JsonArray
40-
/// nodes create their data structures which maintain the connection to children.
41-
/// JsonNumber and JsonString contain only a start and end offset, which
42-
/// are used to lazily procure their underlying value/string on demand. Singletons
43-
/// are used for JsonBoolean and JsonNull.
39+
/**
40+
* Parses a JSON Document char[] into a tree of JsonValues. JsonObject and JsonArray
41+
* nodes create their data structures which maintain the connection to children.
42+
* JsonNumber and JsonString contain only a start and end offset, which
43+
* are used to lazily procure their underlying value/string on demand. Singletons
44+
* are used for JsonBoolean and JsonNull.
45+
*/
4446
public final class JsonParser {
4547

4648
// Access to the underlying JSON contents
@@ -100,11 +102,11 @@ private JsonValue parseValue() {
100102
* See https://datatracker.ietf.org/doc/html/rfc8259#section-4
101103
*/
102104
private JsonObject parseObject() {
103-
offset++; // Walk past the '{'
105+
var startO = offset++; // Walk past the '{'
104106
skipWhitespaces();
105107
// Check for empty case
106108
if (charEquals('}')) {
107-
return new JsonObjectImpl(Map.of());
109+
return new JsonObjectImpl(Map.of(), startO, doc);
108110
}
109111
var members = new LinkedHashMap<String, JsonValue>();
110112
while (hasInput()) {
@@ -126,7 +128,7 @@ private JsonObject parseObject() {
126128
members.put(name, parseValue());
127129
// Ensure current char is either ',' or '}'
128130
if (charEquals('}')) {
129-
return new JsonObjectImpl(members);
131+
return new JsonObjectImpl(members, startO, doc);
130132
} else if (charEquals(',')) {
131133
skipWhitespaces();
132134
} else {
@@ -201,19 +203,19 @@ private String parseName() {
201203
* See https://datatracker.ietf.org/doc/html/rfc8259#section-5
202204
*/
203205
private JsonArray parseArray() {
204-
offset++; // Walk past the '['
206+
var startO = offset++; // Walk past the '['
205207
skipWhitespaces();
206208
// Check for empty case
207209
if (charEquals(']')) {
208-
return new JsonArrayImpl(List.of());
210+
return new JsonArrayImpl(List.of(), startO, doc);
209211
}
210212
var list = new ArrayList<JsonValue>();
211213
while (hasInput()) {
212214
// Get the JsonValue
213215
list.add(parseValue());
214216
// Ensure current char is either ']' or ','
215217
if (charEquals(']')) {
216-
return new JsonArrayImpl(list);
218+
return new JsonArrayImpl(list, startO, doc);
217219
} else if (!charEquals(',')) {
218220
break;
219221
}
@@ -262,7 +264,7 @@ private JsonString parseString() {
262264
private JsonBooleanImpl parseTrue() {
263265
offset++;
264266
if (charEquals('r') && charEquals('u') && charEquals('e')) {
265-
return JsonBooleanImpl.TRUE;
267+
return new JsonBooleanImpl(true, doc, offset);
266268
}
267269
throw failure(UNEXPECTED_VAL);
268270
}
@@ -271,15 +273,15 @@ private JsonBooleanImpl parseFalse() {
271273
offset++;
272274
if (charEquals('a') && charEquals('l') && charEquals('s')
273275
&& charEquals('e')) {
274-
return JsonBooleanImpl.FALSE;
276+
return new JsonBooleanImpl(false, doc, offset);
275277
}
276278
throw failure(UNEXPECTED_VAL);
277279
}
278280

279281
private JsonNullImpl parseNull() {
280282
offset++;
281283
if (charEquals('u') && charEquals('l') && charEquals('l')) {
282-
return JsonNullImpl.NULL;
284+
return new JsonNullImpl(doc, offset);
283285
}
284286
throw failure(UNEXPECTED_VAL);
285287
}
@@ -425,11 +427,15 @@ private boolean charEquals(char c) {
425427
return false;
426428
}
427429

430+
// Return the col position reflective of the current row
431+
private int col() {
432+
return offset - lineStart;
433+
}
434+
428435
private JsonParseException failure(String message) {
429436
// Non-revealing message does not produce input source String
430437
return new JsonParseException("%s. Location: row %d, col %d."
431-
.formatted(message, line, offset - lineStart),
432-
line, offset - lineStart);
438+
.formatted(message, line, col()), line, col());
433439
}
434440

435441
// Parsing error messages ----------------------

0 commit comments

Comments
 (0)