@neocompose/cli 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/neo.mjs +309 -16
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.0] - 2026-07-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Member access modifiers. Class and interface members now carry a required
|
|
8
|
+
`accessModifier` (`public` / `protected` / `private`); the source lowering
|
|
9
|
+
and emitter read and write the keyword, defaulting to `private` on classes
|
|
10
|
+
and `public` on interfaces when omitted, mirroring C#. The schema-commit
|
|
11
|
+
path enforces the same access rules as the web app.
|
|
12
|
+
|
|
3
13
|
## [0.5.4] - 2026-07-19
|
|
4
14
|
|
|
5
15
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -829,6 +829,7 @@ var init_document_contracts = __esm({
|
|
|
829
829
|
"isStatic",
|
|
830
830
|
"isVirtual",
|
|
831
831
|
"isAbstract",
|
|
832
|
+
"accessModifierKind",
|
|
832
833
|
"defaultValue",
|
|
833
834
|
"extendsMemberId",
|
|
834
835
|
"system",
|
|
@@ -1528,6 +1529,11 @@ function memberFromDocument(record3, members, owners, classNames, context) {
|
|
|
1528
1529
|
owner: owners.get(record3.recordId) ?? { kind: "loose" },
|
|
1529
1530
|
name: requiredString(data, "name", record3),
|
|
1530
1531
|
isStatic: booleanValue(data.isStatic, record3, "isStatic"),
|
|
1532
|
+
accessModifier: accessModifierValue(
|
|
1533
|
+
data.accessModifierKind,
|
|
1534
|
+
record3,
|
|
1535
|
+
"accessModifierKind"
|
|
1536
|
+
),
|
|
1531
1537
|
modifier,
|
|
1532
1538
|
locked: booleanValue(field("locked", false), record3, "locked"),
|
|
1533
1539
|
required: booleanValue(field("required", false), record3, "required"),
|
|
@@ -1770,7 +1776,8 @@ function memberToDocumentFields(member, baseData3) {
|
|
|
1770
1776
|
kind,
|
|
1771
1777
|
locked: member.locked,
|
|
1772
1778
|
required: member.required,
|
|
1773
|
-
isStatic: member.isStatic
|
|
1779
|
+
isStatic: member.isStatic,
|
|
1780
|
+
accessModifierKind: member.accessModifier
|
|
1774
1781
|
};
|
|
1775
1782
|
applyModifier(fields, member, baseData3);
|
|
1776
1783
|
if (member.defaultValue !== null) {
|
|
@@ -2370,6 +2377,16 @@ function optionalNumberOrNull(value, record3, path) {
|
|
|
2370
2377
|
if (value === void 0 || value === null) return null;
|
|
2371
2378
|
return requiredNumberValue(value, record3, path);
|
|
2372
2379
|
}
|
|
2380
|
+
function accessModifierValue(value, record3, path) {
|
|
2381
|
+
if (value !== "public" && value !== "protected" && value !== "private") {
|
|
2382
|
+
throw invalidDocument(
|
|
2383
|
+
record3,
|
|
2384
|
+
path,
|
|
2385
|
+
"must be public, protected, or private"
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2388
|
+
return value;
|
|
2389
|
+
}
|
|
2373
2390
|
function requiredString(value, key, record3) {
|
|
2374
2391
|
return requiredStringValue(value[key], record3, key);
|
|
2375
2392
|
}
|
|
@@ -2626,6 +2643,11 @@ function interfaceFromDocument(record3, context) {
|
|
|
2626
2643
|
);
|
|
2627
2644
|
const memberId = requiredString(member, "id", record3);
|
|
2628
2645
|
const memberSource = nestedSource(source, "interfaceMember", memberId);
|
|
2646
|
+
const accessModifier = accessModifierValue(
|
|
2647
|
+
member.accessModifierKind,
|
|
2648
|
+
record3,
|
|
2649
|
+
`members.${name}.accessModifierKind`
|
|
2650
|
+
);
|
|
2629
2651
|
if (member.kind === "property") {
|
|
2630
2652
|
return {
|
|
2631
2653
|
id: memberId,
|
|
@@ -2641,6 +2663,7 @@ function interfaceFromDocument(record3, context) {
|
|
|
2641
2663
|
record3,
|
|
2642
2664
|
`members.${name}.settable`
|
|
2643
2665
|
),
|
|
2666
|
+
accessModifier,
|
|
2644
2667
|
source: memberSource
|
|
2645
2668
|
};
|
|
2646
2669
|
}
|
|
@@ -2664,6 +2687,7 @@ function interfaceFromDocument(record3, context) {
|
|
|
2664
2687
|
record3,
|
|
2665
2688
|
`members.${name}.deferred`
|
|
2666
2689
|
),
|
|
2690
|
+
accessModifier,
|
|
2667
2691
|
source: memberSource
|
|
2668
2692
|
};
|
|
2669
2693
|
}
|
|
@@ -2683,7 +2707,8 @@ function interfaceToDocument(neoInterface) {
|
|
|
2683
2707
|
id: member.id,
|
|
2684
2708
|
kind: "property",
|
|
2685
2709
|
typeInfo: manifestTypeToDocument(member.type),
|
|
2686
|
-
settable: member.settable
|
|
2710
|
+
settable: member.settable,
|
|
2711
|
+
accessModifierKind: member.accessModifier
|
|
2687
2712
|
};
|
|
2688
2713
|
} else {
|
|
2689
2714
|
members[member.name] = {
|
|
@@ -2694,7 +2719,8 @@ function interfaceToDocument(neoInterface) {
|
|
|
2694
2719
|
name: argument2.name,
|
|
2695
2720
|
...manifestTypeToDocument(argument2.type)
|
|
2696
2721
|
})),
|
|
2697
|
-
deferred: member.deferred
|
|
2722
|
+
deferred: member.deferred,
|
|
2723
|
+
accessModifierKind: member.accessModifier
|
|
2698
2724
|
};
|
|
2699
2725
|
}
|
|
2700
2726
|
}
|
|
@@ -3480,6 +3506,9 @@ var init_language_spec = __esm({
|
|
|
3480
3506
|
"interface",
|
|
3481
3507
|
"native",
|
|
3482
3508
|
"override",
|
|
3509
|
+
"private",
|
|
3510
|
+
"protected",
|
|
3511
|
+
"public",
|
|
3483
3512
|
"return",
|
|
3484
3513
|
"sealed",
|
|
3485
3514
|
"static",
|
|
@@ -3779,6 +3808,66 @@ function createProjectIndex(project) {
|
|
|
3779
3808
|
indexesByListMemberId
|
|
3780
3809
|
};
|
|
3781
3810
|
}
|
|
3811
|
+
function memberAccessFailure(args) {
|
|
3812
|
+
const access = args.symbol.accessModifier;
|
|
3813
|
+
if (access === void 0) return null;
|
|
3814
|
+
if (access === "public") return null;
|
|
3815
|
+
const declaringTypeId = args.symbol.inheritedFrom?.typeId ?? args.owner.id;
|
|
3816
|
+
const declaringTypeName = args.symbol.inheritedFrom?.typeName ?? args.owner.name;
|
|
3817
|
+
const accessing = args.context.declaringType ?? args.context.thisClass;
|
|
3818
|
+
const accessingTypeId = accessing?.kind === "named" ? accessing.typeId : void 0;
|
|
3819
|
+
if (access === "private") {
|
|
3820
|
+
if (accessingTypeId === declaringTypeId) return null;
|
|
3821
|
+
return { kind: "private", declaringTypeName };
|
|
3822
|
+
}
|
|
3823
|
+
if (args.owner.kind === "interface") {
|
|
3824
|
+
if (accessingTypeId !== void 0 && classFamilyImplementsInterface(
|
|
3825
|
+
args.project,
|
|
3826
|
+
accessingTypeId,
|
|
3827
|
+
declaringTypeId
|
|
3828
|
+
)) {
|
|
3829
|
+
return null;
|
|
3830
|
+
}
|
|
3831
|
+
return { kind: "interfaceProtected", interfaceName: declaringTypeName };
|
|
3832
|
+
}
|
|
3833
|
+
if (accessingTypeId !== void 0 && typeExtendsInclusive(args.project, accessingTypeId, declaringTypeId)) {
|
|
3834
|
+
return null;
|
|
3835
|
+
}
|
|
3836
|
+
return { kind: "protected", declaringTypeName };
|
|
3837
|
+
}
|
|
3838
|
+
function typeExtendsInclusive(project, typeId, ancestorTypeId) {
|
|
3839
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3840
|
+
const queue = [typeId];
|
|
3841
|
+
while (queue.length > 0) {
|
|
3842
|
+
const current = queue.shift();
|
|
3843
|
+
if (current === ancestorTypeId) return true;
|
|
3844
|
+
if (visited.has(current)) continue;
|
|
3845
|
+
visited.add(current);
|
|
3846
|
+
const type = project.typeById.get(current);
|
|
3847
|
+
for (const baseTypeId of type?.baseTypeIds ?? []) queue.push(baseTypeId);
|
|
3848
|
+
}
|
|
3849
|
+
return false;
|
|
3850
|
+
}
|
|
3851
|
+
function classFamilyImplementsInterface(project, classTypeId, interfaceTypeId) {
|
|
3852
|
+
const visitedClasses = /* @__PURE__ */ new Set();
|
|
3853
|
+
const classQueue = [classTypeId];
|
|
3854
|
+
while (classQueue.length > 0) {
|
|
3855
|
+
const current = classQueue.shift();
|
|
3856
|
+
if (visitedClasses.has(current)) continue;
|
|
3857
|
+
visitedClasses.add(current);
|
|
3858
|
+
const type = project.typeById.get(current);
|
|
3859
|
+
if (type === void 0) continue;
|
|
3860
|
+
for (const interfaceId of type.interfaceTypeIds ?? []) {
|
|
3861
|
+
if (typeExtendsInclusive(project, interfaceId, interfaceTypeId)) {
|
|
3862
|
+
return true;
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
for (const baseTypeId of type.baseTypeIds ?? []) {
|
|
3866
|
+
classQueue.push(baseTypeId);
|
|
3867
|
+
}
|
|
3868
|
+
}
|
|
3869
|
+
return false;
|
|
3870
|
+
}
|
|
3782
3871
|
function withNullability(type, nullable) {
|
|
3783
3872
|
return { ...type, nullable };
|
|
3784
3873
|
}
|
|
@@ -4457,11 +4546,23 @@ function completionItemsForResolution(snapshot, resolved, word) {
|
|
|
4457
4546
|
return resolved.staticType.members.filter((member) => member.kind === "enumMember").map((member) => symbolCompletion(member, word, snapshot));
|
|
4458
4547
|
}
|
|
4459
4548
|
if (resolved.staticType) {
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
(
|
|
4464
|
-
|
|
4549
|
+
const staticType = resolved.staticType;
|
|
4550
|
+
return staticType.members.filter(
|
|
4551
|
+
(member) => member.static === true && isMemberCompletionAccessible(snapshot, staticType, member)
|
|
4552
|
+
).map((member) => symbolCompletion(member, word, snapshot));
|
|
4553
|
+
}
|
|
4554
|
+
const owner = resolved.type.kind === "named" ? snapshot.project.typeById.get(resolved.type.typeId) : void 0;
|
|
4555
|
+
return membersForType(snapshot, resolved.type).filter(
|
|
4556
|
+
(symbol) => owner === void 0 || isMemberCompletionAccessible(snapshot, owner, symbol)
|
|
4557
|
+
).map((symbol) => symbolCompletion(symbol, word, snapshot));
|
|
4558
|
+
}
|
|
4559
|
+
function isMemberCompletionAccessible(snapshot, owner, symbol) {
|
|
4560
|
+
return memberAccessFailure({
|
|
4561
|
+
project: snapshot.project,
|
|
4562
|
+
context: snapshot.context,
|
|
4563
|
+
owner,
|
|
4564
|
+
symbol
|
|
4565
|
+
}) === null;
|
|
4465
4566
|
}
|
|
4466
4567
|
function membersForType(snapshot, type) {
|
|
4467
4568
|
if (type.kind === "named") {
|
|
@@ -9808,6 +9909,7 @@ var init_strict_resolver = __esm({
|
|
|
9808
9909
|
pos
|
|
9809
9910
|
);
|
|
9810
9911
|
}
|
|
9912
|
+
this.assertMemberAccessible(staticType, member, pos);
|
|
9811
9913
|
if (member.static !== true) {
|
|
9812
9914
|
throw new CompileError(
|
|
9813
9915
|
`Member '${staticType.name}.${name}' requires an instance receiver.`,
|
|
@@ -9960,6 +10062,7 @@ var init_strict_resolver = __esm({
|
|
|
9960
10062
|
pos
|
|
9961
10063
|
);
|
|
9962
10064
|
}
|
|
10065
|
+
this.assertMemberAccessible(type, member, pos);
|
|
9963
10066
|
if (member.static === true) {
|
|
9964
10067
|
throw new CompileError(
|
|
9965
10068
|
`Static member '${type.name}.${name}' must be accessed through the type name, not an instance.`,
|
|
@@ -10281,6 +10384,7 @@ var init_strict_resolver = __esm({
|
|
|
10281
10384
|
pos
|
|
10282
10385
|
);
|
|
10283
10386
|
}
|
|
10387
|
+
this.assertMemberAccessible(staticType, member, pos);
|
|
10284
10388
|
if (member.static !== true) {
|
|
10285
10389
|
throw new CompileError(
|
|
10286
10390
|
`Member '${staticType.name}.${callee.name}' requires an instance receiver.`,
|
|
@@ -10317,6 +10421,7 @@ var init_strict_resolver = __esm({
|
|
|
10317
10421
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === callee.name
|
|
10318
10422
|
);
|
|
10319
10423
|
if (member) {
|
|
10424
|
+
if (type !== void 0) this.assertMemberAccessible(type, member, pos);
|
|
10320
10425
|
if (member.static === true) {
|
|
10321
10426
|
throw new CompileError(
|
|
10322
10427
|
`Static member '${type?.name}.${callee.name}' must be accessed through the type name, not an instance.`,
|
|
@@ -10867,6 +10972,7 @@ var init_strict_resolver = __esm({
|
|
|
10867
10972
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === memberName
|
|
10868
10973
|
);
|
|
10869
10974
|
if (!symbol2) return null;
|
|
10975
|
+
this.assertMemberAccessible(staticType, symbol2, expression.pos);
|
|
10870
10976
|
if (symbol2.static !== true) {
|
|
10871
10977
|
throw new CompileError(
|
|
10872
10978
|
`Member '${staticType.name}.${memberName}' requires an instance receiver.`,
|
|
@@ -10908,6 +11014,9 @@ var init_strict_resolver = __esm({
|
|
|
10908
11014
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === memberName
|
|
10909
11015
|
);
|
|
10910
11016
|
if (!symbol) return null;
|
|
11017
|
+
if (type !== void 0) {
|
|
11018
|
+
this.assertMemberAccessible(type, symbol, expression.pos);
|
|
11019
|
+
}
|
|
10911
11020
|
if (symbol.static === true) {
|
|
10912
11021
|
throw new CompileError(
|
|
10913
11022
|
`Static member '${type?.name}.${memberName}' must be accessed through the type name, not an instance.`,
|
|
@@ -11285,6 +11394,36 @@ var init_strict_resolver = __esm({
|
|
|
11285
11394
|
describe(type) {
|
|
11286
11395
|
return formatType(type, this.project);
|
|
11287
11396
|
}
|
|
11397
|
+
/**
|
|
11398
|
+
* Enforces C#-style member accessibility on a resolved member. Runs after
|
|
11399
|
+
* the member is found so hover/definition still resolve while the strict
|
|
11400
|
+
* compile carries the diagnostic.
|
|
11401
|
+
*/
|
|
11402
|
+
assertMemberAccessible(owner, symbol, pos) {
|
|
11403
|
+
const failure = memberAccessFailure({
|
|
11404
|
+
project: this.project,
|
|
11405
|
+
context: this.context,
|
|
11406
|
+
owner,
|
|
11407
|
+
symbol
|
|
11408
|
+
});
|
|
11409
|
+
if (failure === null) return;
|
|
11410
|
+
if (failure.kind === "private") {
|
|
11411
|
+
throw new CompileError(
|
|
11412
|
+
`'${symbol.name}' is private to ${failure.declaringTypeName}.`,
|
|
11413
|
+
pos
|
|
11414
|
+
);
|
|
11415
|
+
}
|
|
11416
|
+
if (failure.kind === "interfaceProtected") {
|
|
11417
|
+
throw new CompileError(
|
|
11418
|
+
`'${symbol.name}' is protected; through an ${failure.interfaceName} reference it is accessible only from classes that implement ${failure.interfaceName} and their derived classes.`,
|
|
11419
|
+
pos
|
|
11420
|
+
);
|
|
11421
|
+
}
|
|
11422
|
+
throw new CompileError(
|
|
11423
|
+
`'${symbol.name}' is protected; accessible only from ${failure.declaringTypeName} and derived classes.`,
|
|
11424
|
+
pos
|
|
11425
|
+
);
|
|
11426
|
+
}
|
|
11288
11427
|
symbolValue(symbol) {
|
|
11289
11428
|
if (symbol.kind === "root" || symbol.kind === "parameter" || symbol.kind === "value") {
|
|
11290
11429
|
return {
|
|
@@ -11307,6 +11446,13 @@ var init_strict_resolver = __esm({
|
|
|
11307
11446
|
if (this.context.staticMember === true && symbol.static !== true) {
|
|
11308
11447
|
return null;
|
|
11309
11448
|
}
|
|
11449
|
+
const accessFailure = memberAccessFailure({
|
|
11450
|
+
project: this.project,
|
|
11451
|
+
context: this.context,
|
|
11452
|
+
owner,
|
|
11453
|
+
symbol
|
|
11454
|
+
});
|
|
11455
|
+
if (accessFailure !== null) return null;
|
|
11310
11456
|
return { owner, symbol };
|
|
11311
11457
|
}
|
|
11312
11458
|
nextCallSite(pos) {
|
|
@@ -12355,6 +12501,14 @@ var init_parity_contract = __esm({
|
|
|
12355
12501
|
});
|
|
12356
12502
|
|
|
12357
12503
|
// ../packages/neoscript-language/src/project-source-ast.ts
|
|
12504
|
+
function isNeoSourceAccessModifier(value) {
|
|
12505
|
+
return value === "public" || value === "protected" || value === "private";
|
|
12506
|
+
}
|
|
12507
|
+
function effectiveSourceAccessModifier(modifiers, ownerKind) {
|
|
12508
|
+
const explicit = modifiers.find(isNeoSourceAccessModifier);
|
|
12509
|
+
if (explicit !== void 0) return explicit;
|
|
12510
|
+
return ownerKind === "interface" ? "public" : "private";
|
|
12511
|
+
}
|
|
12358
12512
|
var init_project_source_ast = __esm({
|
|
12359
12513
|
"../packages/neoscript-language/src/project-source-ast.ts"() {
|
|
12360
12514
|
"use strict";
|
|
@@ -12822,6 +12976,7 @@ function validateDeclarationSemantics(declarations, diagnostics) {
|
|
|
12822
12976
|
message: `Member '${member.name}' repeats the '${modifier}' modifier.`
|
|
12823
12977
|
});
|
|
12824
12978
|
}
|
|
12979
|
+
validateMemberAccessModifiers(declaration, member, diagnostics);
|
|
12825
12980
|
if (member.kind !== "function") continue;
|
|
12826
12981
|
if (declaration.kind === "interface") {
|
|
12827
12982
|
if (member.body) {
|
|
@@ -12867,6 +13022,61 @@ function validateDeclarationSemantics(declarations, diagnostics) {
|
|
|
12867
13022
|
}
|
|
12868
13023
|
}
|
|
12869
13024
|
}
|
|
13025
|
+
function validateMemberAccessModifiers(declaration, member, diagnostics) {
|
|
13026
|
+
const accessModifiers = [
|
|
13027
|
+
...new Set(member.modifiers.filter(isNeoSourceAccessModifier))
|
|
13028
|
+
];
|
|
13029
|
+
if (accessModifiers.length > 1) {
|
|
13030
|
+
diagnostics.push({
|
|
13031
|
+
range: member.nameRange,
|
|
13032
|
+
severity: "error",
|
|
13033
|
+
source: "neo-project",
|
|
13034
|
+
code: "conflicting-access-modifiers",
|
|
13035
|
+
message: `Member '${member.name}' declares more than one access modifier (${accessModifiers.join(", ")}); a member accepts at most one.`
|
|
13036
|
+
});
|
|
13037
|
+
return;
|
|
13038
|
+
}
|
|
13039
|
+
const accessModifier = accessModifiers[0];
|
|
13040
|
+
if (accessModifier === void 0) return;
|
|
13041
|
+
if (declaration.kind === "interface" && accessModifier === "private") {
|
|
13042
|
+
diagnostics.push({
|
|
13043
|
+
range: member.nameRange,
|
|
13044
|
+
severity: "error",
|
|
13045
|
+
source: "neo-project",
|
|
13046
|
+
code: "private-interface-member",
|
|
13047
|
+
message: `Interface member '${member.name}' cannot be private; private interface members are not yet supported. Use public or protected.`
|
|
13048
|
+
});
|
|
13049
|
+
return;
|
|
13050
|
+
}
|
|
13051
|
+
if (accessModifier !== "private") return;
|
|
13052
|
+
if (member.modifiers.includes("virtual")) {
|
|
13053
|
+
diagnostics.push({
|
|
13054
|
+
range: member.nameRange,
|
|
13055
|
+
severity: "error",
|
|
13056
|
+
source: "neo-project",
|
|
13057
|
+
code: "private-virtual-member",
|
|
13058
|
+
message: `Member '${member.name}' cannot be both private and virtual; a private member is never overridable.`
|
|
13059
|
+
});
|
|
13060
|
+
}
|
|
13061
|
+
if (member.modifiers.includes("abstract")) {
|
|
13062
|
+
diagnostics.push({
|
|
13063
|
+
range: member.nameRange,
|
|
13064
|
+
severity: "error",
|
|
13065
|
+
source: "neo-project",
|
|
13066
|
+
code: "private-abstract-member",
|
|
13067
|
+
message: `Member '${member.name}' cannot be both private and abstract; an abstract member exists to be implemented by descendants.`
|
|
13068
|
+
});
|
|
13069
|
+
}
|
|
13070
|
+
if (member.modifiers.includes("override")) {
|
|
13071
|
+
diagnostics.push({
|
|
13072
|
+
range: member.nameRange,
|
|
13073
|
+
severity: "error",
|
|
13074
|
+
source: "neo-project",
|
|
13075
|
+
code: "private-override-member",
|
|
13076
|
+
message: `Member '${member.name}' cannot be both private and override; an override keeps the accessibility of the member it overrides, and a private member cannot be overridden.`
|
|
13077
|
+
});
|
|
13078
|
+
}
|
|
13079
|
+
}
|
|
12870
13080
|
function isNameToken(token) {
|
|
12871
13081
|
return token !== void 0 && (token.kind === "identifier" || token.kind === "type" || token.kind === "keyword");
|
|
12872
13082
|
}
|
|
@@ -12902,12 +13112,16 @@ var init_project_source_parser = __esm({
|
|
|
12902
13112
|
"use strict";
|
|
12903
13113
|
init_lexer();
|
|
12904
13114
|
init_neoflow_graph_parser();
|
|
13115
|
+
init_project_source_ast();
|
|
12905
13116
|
init_source_text();
|
|
12906
13117
|
MODIFIERS = /* @__PURE__ */ new Set([
|
|
12907
13118
|
"abstract",
|
|
12908
13119
|
"async",
|
|
12909
13120
|
"native",
|
|
12910
13121
|
"override",
|
|
13122
|
+
"private",
|
|
13123
|
+
"protected",
|
|
13124
|
+
"public",
|
|
12911
13125
|
"sealed",
|
|
12912
13126
|
"static",
|
|
12913
13127
|
"virtual"
|
|
@@ -12945,6 +13159,14 @@ var init_project_source_parser = __esm({
|
|
|
12945
13159
|
const annotations = this.parseAnnotations();
|
|
12946
13160
|
const modifiers = this.parseModifiers();
|
|
12947
13161
|
if (this.at("class")) {
|
|
13162
|
+
const accessModifier = modifiers.find(isNeoSourceAccessModifier);
|
|
13163
|
+
if (accessModifier !== void 0) {
|
|
13164
|
+
throw this.failure(
|
|
13165
|
+
"source-class-access-modifier",
|
|
13166
|
+
`Access modifier '${accessModifier}' is valid only on class and interface member declarations, not on a class declaration.`,
|
|
13167
|
+
start
|
|
13168
|
+
);
|
|
13169
|
+
}
|
|
12948
13170
|
return this.parseClass(start, annotations, modifiers);
|
|
12949
13171
|
}
|
|
12950
13172
|
if (this.at("interface")) {
|
|
@@ -13545,6 +13767,7 @@ var init_project_schema_contract_generated = __esm({
|
|
|
13545
13767
|
"isStatic",
|
|
13546
13768
|
"isVirtual",
|
|
13547
13769
|
"isAbstract",
|
|
13770
|
+
"accessModifierKind",
|
|
13548
13771
|
"defaultValue",
|
|
13549
13772
|
"extendsMemberId",
|
|
13550
13773
|
"system",
|
|
@@ -17356,6 +17579,10 @@ function sourceMemberSymbol(member, owner, typeIds, source) {
|
|
|
17356
17579
|
type,
|
|
17357
17580
|
static: staticMember,
|
|
17358
17581
|
abstract: member.modifiers.includes("abstract"),
|
|
17582
|
+
accessModifier: effectiveSourceAccessModifier(
|
|
17583
|
+
member.modifiers,
|
|
17584
|
+
owner.declaration.kind
|
|
17585
|
+
),
|
|
17359
17586
|
location: location(owner.uri, member.range),
|
|
17360
17587
|
selectionLocation: location(owner.uri, member.nameRange)
|
|
17361
17588
|
};
|
|
@@ -17690,6 +17917,7 @@ var init_project_source_script_compiler = __esm({
|
|
|
17690
17917
|
"use strict";
|
|
17691
17918
|
init_compiler();
|
|
17692
17919
|
init_language_spec();
|
|
17920
|
+
init_project_source_ast();
|
|
17693
17921
|
init_project();
|
|
17694
17922
|
init_project_root();
|
|
17695
17923
|
init_source_text();
|
|
@@ -18246,6 +18474,7 @@ function validateMembers(environment, diagnostics) {
|
|
|
18246
18474
|
}
|
|
18247
18475
|
for (const modifier of member.modifiers) {
|
|
18248
18476
|
if (modifier === "async" && member.kind === "function") continue;
|
|
18477
|
+
if (isNeoSourceAccessModifier(modifier)) continue;
|
|
18249
18478
|
diagnose(
|
|
18250
18479
|
diagnostics,
|
|
18251
18480
|
ref.uri,
|
|
@@ -18899,6 +19128,7 @@ var init_project_source_type_checker = __esm({
|
|
|
18899
19128
|
"../packages/neoscript-language/src/project-source-type-checker.ts"() {
|
|
18900
19129
|
"use strict";
|
|
18901
19130
|
init_language_spec();
|
|
19131
|
+
init_project_source_ast();
|
|
18902
19132
|
BUILTIN_ARITY = /* @__PURE__ */ new Map([
|
|
18903
19133
|
["List", 1],
|
|
18904
19134
|
["Set", 1],
|
|
@@ -24316,6 +24546,11 @@ function assertMember2(value, path) {
|
|
|
24316
24546
|
assertMemberOwner(member.owner, `${path}.owner`);
|
|
24317
24547
|
nonEmptyString(member.name, `${path}.name`);
|
|
24318
24548
|
booleanAt(member.isStatic, `${path}.isStatic`);
|
|
24549
|
+
stringIn(
|
|
24550
|
+
member.accessModifier,
|
|
24551
|
+
/* @__PURE__ */ new Set(["public", "protected", "private"]),
|
|
24552
|
+
`${path}.accessModifier`
|
|
24553
|
+
);
|
|
24319
24554
|
stringIn(
|
|
24320
24555
|
member.modifier,
|
|
24321
24556
|
/* @__PURE__ */ new Set([
|
|
@@ -24746,12 +24981,14 @@ function assertInterfaceMember(value, path) {
|
|
|
24746
24981
|
"name",
|
|
24747
24982
|
"type",
|
|
24748
24983
|
"settable",
|
|
24984
|
+
"accessModifier",
|
|
24749
24985
|
"source"
|
|
24750
24986
|
]);
|
|
24751
24987
|
nonEmptyString(member.id, `${path}.id`);
|
|
24752
24988
|
nonEmptyString(member.name, `${path}.name`);
|
|
24753
24989
|
assertType2(member.type, `${path}.type`);
|
|
24754
24990
|
booleanAt(member.settable, `${path}.settable`);
|
|
24991
|
+
assertInterfaceMemberAccessModifier(member.accessModifier, path);
|
|
24755
24992
|
assertSourceIdentity(member.source, `${path}.source`, "interfaceMember");
|
|
24756
24993
|
return;
|
|
24757
24994
|
}
|
|
@@ -24763,16 +25000,21 @@ function assertInterfaceMember(value, path) {
|
|
|
24763
25000
|
"returnType",
|
|
24764
25001
|
"arguments",
|
|
24765
25002
|
"deferred",
|
|
25003
|
+
"accessModifier",
|
|
24766
25004
|
"source"
|
|
24767
25005
|
]);
|
|
24768
25006
|
nonEmptyString(member.id, `${path}.id`);
|
|
24769
25007
|
nonEmptyString(member.name, `${path}.name`);
|
|
24770
25008
|
assertFunctionSignature(member, path);
|
|
25009
|
+
assertInterfaceMemberAccessModifier(member.accessModifier, path);
|
|
24771
25010
|
assertSourceIdentity(member.source, `${path}.source`, "interfaceMember");
|
|
24772
25011
|
return;
|
|
24773
25012
|
}
|
|
24774
25013
|
invalid(`${path}.kind`, "must be property or function.");
|
|
24775
25014
|
}
|
|
25015
|
+
function assertInterfaceMemberAccessModifier(value, path) {
|
|
25016
|
+
stringIn(value, /* @__PURE__ */ new Set(["public", "protected"]), `${path}.accessModifier`);
|
|
25017
|
+
}
|
|
24776
25018
|
function assertEnum2(value, path) {
|
|
24777
25019
|
const neoEnum = objectAt(value, path, [
|
|
24778
25020
|
"id",
|
|
@@ -25518,6 +25760,7 @@ var init_validate = __esm({
|
|
|
25518
25760
|
"owner",
|
|
25519
25761
|
"name",
|
|
25520
25762
|
"isStatic",
|
|
25763
|
+
"accessModifier",
|
|
25521
25764
|
"modifier",
|
|
25522
25765
|
"locked",
|
|
25523
25766
|
"required",
|
|
@@ -27329,6 +27572,10 @@ function memberCommon(context, ownerClass, declaration, id2, owner, base) {
|
|
|
27329
27572
|
owner,
|
|
27330
27573
|
name: declaration.name,
|
|
27331
27574
|
isStatic: declaration.modifiers.includes("static"),
|
|
27575
|
+
// Non-class placements (collection entries, generic arguments, loose
|
|
27576
|
+
// members) have no receiver type to scope visibility to; they are
|
|
27577
|
+
// structurally public. Class schema entries apply the C# omission default.
|
|
27578
|
+
accessModifier: owner.kind === "classMember" ? effectiveSourceAccessModifier(declaration.modifiers, "class") : "public",
|
|
27332
27579
|
modifier: memberModifier2(declaration.modifiers, base?.modifier),
|
|
27333
27580
|
locked: hasAnnotation(declaration.annotations, "locked"),
|
|
27334
27581
|
required: declaration.kind === "field" ? !declaration.type.nullable : base?.required ?? false,
|
|
@@ -27546,6 +27793,10 @@ function lowerInterface(context, declaration) {
|
|
|
27546
27793
|
`${declaration.name}.${member.name}`
|
|
27547
27794
|
);
|
|
27548
27795
|
const source = sourceIdentity2(member, "interfaceMember", member.name);
|
|
27796
|
+
const accessModifier = effectiveSourceAccessModifier(
|
|
27797
|
+
member.modifiers,
|
|
27798
|
+
"interface"
|
|
27799
|
+
);
|
|
27549
27800
|
if (member.kind === "function") {
|
|
27550
27801
|
return {
|
|
27551
27802
|
id: memberId,
|
|
@@ -27559,6 +27810,7 @@ function lowerInterface(context, declaration) {
|
|
|
27559
27810
|
selectionSpan: span(parameter3)
|
|
27560
27811
|
})),
|
|
27561
27812
|
deferred: member.modifiers.includes("async"),
|
|
27813
|
+
accessModifier,
|
|
27562
27814
|
source
|
|
27563
27815
|
};
|
|
27564
27816
|
}
|
|
@@ -27568,6 +27820,7 @@ function lowerInterface(context, declaration) {
|
|
|
27568
27820
|
name: member.name,
|
|
27569
27821
|
type: lowerType(context, member.type),
|
|
27570
27822
|
settable: /\bset\s*;/.test(member.body ?? ""),
|
|
27823
|
+
accessModifier,
|
|
27571
27824
|
source
|
|
27572
27825
|
};
|
|
27573
27826
|
});
|
|
@@ -29066,11 +29319,12 @@ function emitInterface(context, value) {
|
|
|
29066
29319
|
(interfaceId) => required(context.interfaces, interfaceId, "interface").name
|
|
29067
29320
|
);
|
|
29068
29321
|
const members = value.members.map((member) => {
|
|
29322
|
+
const access = member.accessModifier === "public" ? "" : `${member.accessModifier} `;
|
|
29069
29323
|
if (member.kind === "property") {
|
|
29070
|
-
return `${id(member.id)}${renderType(context, member.type)} ${member.name} { get;${member.settable ? " set;" : ""} }`;
|
|
29324
|
+
return `${id(member.id)}${access}${renderType(context, member.type)} ${member.name} { get;${member.settable ? " set;" : ""} }`;
|
|
29071
29325
|
}
|
|
29072
29326
|
const deferred = member.deferred ? "async " : "";
|
|
29073
|
-
return `${id(member.id)}${deferred}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map(
|
|
29327
|
+
return `${id(member.id)}${access}${deferred}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map(
|
|
29074
29328
|
(argument2) => `${renderType(context, argument2.type)} ${argument2.name}`
|
|
29075
29329
|
).join(", ")});`;
|
|
29076
29330
|
});
|
|
@@ -29135,9 +29389,10 @@ ${body ? `${signature} ${body}` : abstractContract ? `${signature};` : `native $
|
|
|
29135
29389
|
${prefix}${type} ${member.name}${initializer === null ? ";" : ` = ${initializer};`}`;
|
|
29136
29390
|
}
|
|
29137
29391
|
function memberModifier3(member) {
|
|
29392
|
+
const accessPrefix = `${member.accessModifier} `;
|
|
29138
29393
|
const staticPrefix = member.isStatic ? "static " : "";
|
|
29139
29394
|
const modifier = member.modifier === "plain" ? "" : member.modifier === "abstractOverride" ? "abstract override " : member.modifier === "sealedOverride" ? "override " : `${member.modifier} `;
|
|
29140
|
-
return `${staticPrefix}${modifier}`;
|
|
29395
|
+
return `${accessPrefix}${staticPrefix}${modifier}`;
|
|
29141
29396
|
}
|
|
29142
29397
|
function renderExtendsGenericBindings(context, schemaClass2, base) {
|
|
29143
29398
|
if (base.genericParameters.length === 0) return "";
|
|
@@ -33207,6 +33462,11 @@ var init_neoscript = __esm({
|
|
|
33207
33462
|
});
|
|
33208
33463
|
|
|
33209
33464
|
// ../src/models/members/member-kinds.ts
|
|
33465
|
+
function isMemberAccessModifierKind(value) {
|
|
33466
|
+
if (value === "public") return true;
|
|
33467
|
+
if (value === "protected") return true;
|
|
33468
|
+
return value === "private";
|
|
33469
|
+
}
|
|
33210
33470
|
function isValidCallableIdentifier(value) {
|
|
33211
33471
|
if (typeof value !== "string") return false;
|
|
33212
33472
|
if (!FunctionMemberNamePattern.test(value)) return false;
|
|
@@ -33650,6 +33910,7 @@ function isMemberBase(value) {
|
|
|
33650
33910
|
if (typeof v.locked !== "boolean") return false;
|
|
33651
33911
|
if (typeof v.required !== "boolean") return false;
|
|
33652
33912
|
if (typeof v.isStatic !== "boolean") return false;
|
|
33913
|
+
if (!isMemberAccessModifierKind(v.accessModifierKind)) return false;
|
|
33653
33914
|
if (v.isVirtual !== void 0 && typeof v.isVirtual !== "boolean") {
|
|
33654
33915
|
return false;
|
|
33655
33916
|
}
|
|
@@ -33705,6 +33966,7 @@ function isMemberOverrideBase(value) {
|
|
|
33705
33966
|
if (v.locked !== void 0 && typeof v.locked !== "boolean") return false;
|
|
33706
33967
|
if (v.required !== void 0 && typeof v.required !== "boolean") return false;
|
|
33707
33968
|
if (v.isStatic !== void 0 && v.isStatic !== false) return false;
|
|
33969
|
+
if (!isMemberAccessModifierKind(v.accessModifierKind)) return false;
|
|
33708
33970
|
if (v.isVirtual !== void 0 && typeof v.isVirtual !== "boolean") {
|
|
33709
33971
|
return false;
|
|
33710
33972
|
}
|
|
@@ -34212,6 +34474,9 @@ function substituteMember(member, env, members) {
|
|
|
34212
34474
|
...binding,
|
|
34213
34475
|
name: resolved.name,
|
|
34214
34476
|
locked: resolved.locked,
|
|
34477
|
+
// Accessibility is a slot-owned declaration field — a binding member's
|
|
34478
|
+
// modifier must not change the declaring slot's visibility.
|
|
34479
|
+
accessModifierKind: resolved.accessModifierKind,
|
|
34215
34480
|
system: resolved.system ?? void 0
|
|
34216
34481
|
};
|
|
34217
34482
|
const slotId = getOptionalString(member, "id");
|
|
@@ -35518,6 +35783,7 @@ function isNeoInterfaceMember(value) {
|
|
|
35518
35783
|
if (value === null) return false;
|
|
35519
35784
|
const member = value;
|
|
35520
35785
|
if (typeof member.id !== "string" || member.id.length === 0) return false;
|
|
35786
|
+
if (!isMemberAccessModifierKind(member.accessModifierKind)) return false;
|
|
35521
35787
|
if (member.kind === "property") {
|
|
35522
35788
|
if (!isNSTypeInfo(member.typeInfo)) return false;
|
|
35523
35789
|
if (containsForbiddenMemberTypeInfo(member.typeInfo)) return false;
|
|
@@ -44882,6 +45148,29 @@ function migrateMemberStaticOwnership(data) {
|
|
|
44882
45148
|
if (Object.prototype.hasOwnProperty.call(data, "isStatic")) return data;
|
|
44883
45149
|
return { ...data, isStatic: false };
|
|
44884
45150
|
}
|
|
45151
|
+
function migrateMemberAccessModifier(data) {
|
|
45152
|
+
if (!isRecord5(data)) return data;
|
|
45153
|
+
if (Object.prototype.hasOwnProperty.call(data, "accessModifierKind")) {
|
|
45154
|
+
return data;
|
|
45155
|
+
}
|
|
45156
|
+
return { ...data, accessModifierKind: "public" };
|
|
45157
|
+
}
|
|
45158
|
+
function migrateInterfaceMemberAccessModifiers(data) {
|
|
45159
|
+
if (!isRecord5(data)) return data;
|
|
45160
|
+
const members = data.members;
|
|
45161
|
+
if (!isRecord5(members)) return data;
|
|
45162
|
+
let nextMembers = members;
|
|
45163
|
+
for (const [memberKey, member] of Object.entries(members)) {
|
|
45164
|
+
if (!isRecord5(member)) continue;
|
|
45165
|
+
if (Object.prototype.hasOwnProperty.call(member, "accessModifierKind")) {
|
|
45166
|
+
continue;
|
|
45167
|
+
}
|
|
45168
|
+
if (nextMembers === members) nextMembers = { ...members };
|
|
45169
|
+
nextMembers[memberKey] = { ...member, accessModifierKind: "public" };
|
|
45170
|
+
}
|
|
45171
|
+
if (nextMembers === members) return data;
|
|
45172
|
+
return { ...data, members: nextMembers };
|
|
45173
|
+
}
|
|
44885
45174
|
function migrateProjectRecordData(args) {
|
|
44886
45175
|
const currentVersion = CURRENT_PROJECT_RECORD_DATA_SCHEMA_VERSION[args.recordKind];
|
|
44887
45176
|
if (args.dataSchemaVersion > currentVersion) {
|
|
@@ -45065,12 +45354,12 @@ var init_project_record_migrations = __esm({
|
|
|
45065
45354
|
init_neoscript_call_receiver_migration();
|
|
45066
45355
|
CURRENT_PROJECT_RECORD_DATA_SCHEMA_VERSION = {
|
|
45067
45356
|
[ProjectRecordKind.Project]: 1,
|
|
45068
|
-
[ProjectRecordKind.Member]:
|
|
45357
|
+
[ProjectRecordKind.Member]: 5,
|
|
45069
45358
|
[ProjectRecordKind.Value]: 1,
|
|
45070
45359
|
[ProjectRecordKind.Class]: 1,
|
|
45071
45360
|
[ProjectRecordKind.InternalRecordRelation]: 1,
|
|
45072
45361
|
[ProjectRecordKind.Enum]: 4,
|
|
45073
|
-
[ProjectRecordKind.Interface]:
|
|
45362
|
+
[ProjectRecordKind.Interface]: 3,
|
|
45074
45363
|
[ProjectRecordKind.Dialogue]: 5,
|
|
45075
45364
|
[ProjectRecordKind.DialogueNode]: 4,
|
|
45076
45365
|
[ProjectRecordKind.DialogueGroup]: 4,
|
|
@@ -45088,7 +45377,8 @@ var init_project_record_migrations = __esm({
|
|
|
45088
45377
|
[ProjectRecordKind.Member]: {
|
|
45089
45378
|
1: migrateGeneralFunctionCallIR,
|
|
45090
45379
|
2: migrateMemberStaticOwnership,
|
|
45091
|
-
3: migrateExplicitCallReceiverIR
|
|
45380
|
+
3: migrateExplicitCallReceiverIR,
|
|
45381
|
+
4: migrateMemberAccessModifier
|
|
45092
45382
|
},
|
|
45093
45383
|
[ProjectRecordKind.Value]: {},
|
|
45094
45384
|
[ProjectRecordKind.Class]: {},
|
|
@@ -45096,7 +45386,9 @@ var init_project_record_migrations = __esm({
|
|
|
45096
45386
|
[ProjectRecordKind.Enum]: {
|
|
45097
45387
|
1: migrateEnumOptionKeyOrder
|
|
45098
45388
|
},
|
|
45099
|
-
[ProjectRecordKind.Interface]: {
|
|
45389
|
+
[ProjectRecordKind.Interface]: {
|
|
45390
|
+
2: migrateInterfaceMemberAccessModifiers
|
|
45391
|
+
},
|
|
45100
45392
|
[ProjectRecordKind.Dialogue]: {
|
|
45101
45393
|
1: migrateDialoguePrimaryLinkedValues,
|
|
45102
45394
|
2: migrateGeneralFunctionCallIR,
|
|
@@ -53463,7 +53755,8 @@ function constructClassValue(info, scope, ctx) {
|
|
|
53463
53755
|
classId,
|
|
53464
53756
|
locked: false,
|
|
53465
53757
|
required: true,
|
|
53466
|
-
isStatic: false
|
|
53758
|
+
isStatic: false,
|
|
53759
|
+
accessModifierKind: "public"
|
|
53467
53760
|
};
|
|
53468
53761
|
const createdValues = [];
|
|
53469
53762
|
const storageKeyDeclarations = /* @__PURE__ */ new Map();
|