@codesys/mcp-toolkit 1.5.8 → 2.0.0-alpha.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 +153 -189
- package/LICENSE +21 -21
- package/README.md +224 -107
- package/dist/actions.d.ts +28 -0
- package/dist/actions.js +98 -0
- package/dist/actions.js.map +1 -0
- package/dist/bridge/bridge.d.ts +105 -0
- package/dist/bridge/bridge.js +400 -0
- package/dist/bridge/bridge.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +196 -0
- package/dist/cli.js.map +1 -0
- package/dist/codesys/cache.d.ts +48 -0
- package/dist/codesys/cache.js +82 -0
- package/dist/codesys/cache.js.map +1 -0
- package/dist/codesys/changes.d.ts +57 -0
- package/dist/codesys/changes.js +133 -0
- package/dist/codesys/changes.js.map +1 -0
- package/dist/codesys/decl.d.ts +45 -0
- package/dist/codesys/decl.js +251 -0
- package/dist/codesys/decl.js.map +1 -0
- package/dist/codesys/devices.d.ts +34 -0
- package/dist/codesys/devices.js +82 -0
- package/dist/codesys/devices.js.map +1 -0
- package/dist/codesys/diff.d.ts +13 -0
- package/dist/codesys/diff.js +61 -0
- package/dist/codesys/diff.js.map +1 -0
- package/dist/codesys/install.d.ts +40 -0
- package/dist/codesys/install.js +144 -0
- package/dist/codesys/install.js.map +1 -0
- package/dist/codesys/library-browse.d.ts +19 -0
- package/dist/codesys/library-browse.js +57 -0
- package/dist/codesys/library-browse.js.map +1 -0
- package/dist/codesys/outline.d.ts +32 -0
- package/dist/codesys/outline.js +219 -0
- package/dist/codesys/outline.js.map +1 -0
- package/dist/codesys/simulation.d.ts +34 -0
- package/dist/codesys/simulation.js +57 -0
- package/dist/codesys/simulation.js.map +1 -0
- package/dist/codesys/st.d.ts +36 -0
- package/dist/codesys/st.js +69 -0
- package/dist/codesys/st.js.map +1 -0
- package/dist/daemon.d.ts +46 -0
- package/dist/daemon.js +173 -0
- package/dist/daemon.js.map +1 -0
- package/dist/driver.d.ts +25 -0
- package/dist/driver.js +33 -0
- package/dist/driver.js.map +1 -0
- package/dist/panel/sim-panel.html +357 -0
- package/dist/panel/viewer.html +126 -0
- package/dist/panel-types.d.ts +20 -0
- package/dist/panel-types.js +3 -0
- package/dist/panel-types.js.map +1 -0
- package/dist/panel.d.ts +27 -0
- package/dist/panel.js +208 -0
- package/dist/panel.js.map +1 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +33 -974
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +103 -0
- package/dist/tools.js +793 -0
- package/dist/tools.js.map +1 -0
- package/dist/viewer.d.ts +14 -0
- package/dist/viewer.js +125 -0
- package/dist/viewer.js.map +1 -0
- package/package.json +37 -21
- package/watcher/mcp_compat.py +147 -0
- package/watcher/mcp_ops.py +1178 -0
- package/watcher/mcp_sim.py +246 -0
- package/watcher/watcher.py +255 -0
- package/.claude/settings.local.json +0 -29
- package/CLAUDE.md +0 -26
- package/CONTRIBUTING.md +0 -72
- package/README.md.enhanced +0 -155
- package/codesys-mcp-toolkit-1.2.0.tgz +0 -0
- package/codesys-mcp-toolkit-1.2.1.tgz +0 -0
- package/codesys-mcp-toolkit-1.5.7.tgz +0 -0
- package/codesys-mcp-toolkit-1.5.8.tgz +0 -0
- package/dist/bin.js +0 -75
- package/dist/check_session_paths.js +0 -149
- package/dist/codesys_interop.js +0 -435
- package/dist/direct_session_command.js +0 -293
- package/dist/scriptLoader.js +0 -165
- package/dist/scripts/check_status.py +0 -21
- package/dist/scripts/compile_project.py +0 -65
- package/dist/scripts/create_method.py +0 -80
- package/dist/scripts/create_pou.py +0 -102
- package/dist/scripts/create_project.py +0 -116
- package/dist/scripts/create_property.py +0 -78
- package/dist/scripts/ensure_project_open.py +0 -154
- package/dist/scripts/find_object_by_path.py +0 -111
- package/dist/scripts/get_pou_code.py +0 -91
- package/dist/scripts/get_project_structure.py +0 -72
- package/dist/scripts/open_project.py +0 -25
- package/dist/scripts/save_project.py +0 -29
- package/dist/scripts/session_status.py +0 -281
- package/dist/scripts/set_pou_code.py +0 -109
- package/dist/scripts/start_session.py +0 -809
- package/dist/scripts/stop_session.py +0 -324
- package/dist/sessionManager.js +0 -798
- package/docs/configuration.md +0 -141
- package/docs/index.md +0 -26
- package/docs/installation.md +0 -84
- package/docs/session_management.md +0 -110
- package/examples/README.md +0 -78
- package/examples/sample_config.json +0 -32
- package/replacements_session_status.txt +0 -16
- package/scriptDoc.txt +0 -8679
- package/scripts/build.js +0 -25
- package/scripts/fix_fstrings.py +0 -76
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the server knows about the open project, for the workspace panel.
|
|
3
|
+
*
|
|
4
|
+
* The panel must never call CODESYS itself: the bridge runs one request at a
|
|
5
|
+
* time, so panel polling would stall the model's tool calls. Instead the
|
|
6
|
+
* tools keep this cache current as a side effect of their own calls (open,
|
|
7
|
+
* export, write, create, delete, rename, compile), and the panel reads it.
|
|
8
|
+
*/
|
|
9
|
+
import type { TreeNode } from "./st.js";
|
|
10
|
+
export interface CompileResult {
|
|
11
|
+
at: string;
|
|
12
|
+
errors: number;
|
|
13
|
+
warnings: number;
|
|
14
|
+
messages: {
|
|
15
|
+
severity: string;
|
|
16
|
+
text: string;
|
|
17
|
+
object?: string | null;
|
|
18
|
+
position?: string | null;
|
|
19
|
+
length?: number;
|
|
20
|
+
code?: string;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
export interface Focus {
|
|
24
|
+
/** Object path the model last touched. */
|
|
25
|
+
path: string;
|
|
26
|
+
action: "read" | "write" | "create" | "delete" | "rename" | "revert";
|
|
27
|
+
at: string;
|
|
28
|
+
}
|
|
29
|
+
export declare class ProjectCache {
|
|
30
|
+
project?: string;
|
|
31
|
+
nodes?: TreeNode[];
|
|
32
|
+
/** Bumped on every change, so the panel refetches only when needed. */
|
|
33
|
+
version: number;
|
|
34
|
+
compile?: CompileResult;
|
|
35
|
+
focus?: Focus;
|
|
36
|
+
reset(project?: string): void;
|
|
37
|
+
setAll(nodes: TreeNode[]): void;
|
|
38
|
+
/** Replace or add one object (and keep the order: new ones go after their parent's last child). */
|
|
39
|
+
upsert(node: TreeNode): void;
|
|
40
|
+
/** Remove an object and everything under it. */
|
|
41
|
+
remove(path: string): void;
|
|
42
|
+
rename(path: string, newName: string): void;
|
|
43
|
+
/** Something the workspace shows changed without a node change (e.g. the review baseline). */
|
|
44
|
+
bump(): void;
|
|
45
|
+
touch(path: string, action: Focus["action"]): void;
|
|
46
|
+
setCompile(c: CompileResult): void;
|
|
47
|
+
get(path: string): TreeNode | undefined;
|
|
48
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export class ProjectCache {
|
|
2
|
+
project;
|
|
3
|
+
nodes;
|
|
4
|
+
/** Bumped on every change, so the panel refetches only when needed. */
|
|
5
|
+
version = 0;
|
|
6
|
+
compile;
|
|
7
|
+
focus;
|
|
8
|
+
reset(project) {
|
|
9
|
+
this.project = project;
|
|
10
|
+
this.nodes = undefined;
|
|
11
|
+
this.compile = undefined;
|
|
12
|
+
this.focus = undefined;
|
|
13
|
+
this.version++;
|
|
14
|
+
}
|
|
15
|
+
setAll(nodes) {
|
|
16
|
+
this.nodes = nodes;
|
|
17
|
+
this.version++;
|
|
18
|
+
}
|
|
19
|
+
/** Replace or add one object (and keep the order: new ones go after their parent's last child). */
|
|
20
|
+
upsert(node) {
|
|
21
|
+
if (!this.nodes)
|
|
22
|
+
return;
|
|
23
|
+
const key = node.path.toLowerCase();
|
|
24
|
+
const i = this.nodes.findIndex((n) => n.path.toLowerCase() === key);
|
|
25
|
+
if (i >= 0)
|
|
26
|
+
this.nodes[i] = { ...this.nodes[i], ...node };
|
|
27
|
+
else {
|
|
28
|
+
const parent = node.path.includes("/") ? node.path.slice(0, node.path.lastIndexOf("/")).toLowerCase() : "";
|
|
29
|
+
let at = this.nodes.length;
|
|
30
|
+
for (let k = this.nodes.length - 1; k >= 0; k--) {
|
|
31
|
+
const p = this.nodes[k].path.toLowerCase();
|
|
32
|
+
if (p === parent || p.startsWith(parent ? parent + "/" : "")) {
|
|
33
|
+
at = k + 1;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
this.nodes.splice(at, 0, node);
|
|
38
|
+
}
|
|
39
|
+
this.version++;
|
|
40
|
+
}
|
|
41
|
+
/** Remove an object and everything under it. */
|
|
42
|
+
remove(path) {
|
|
43
|
+
if (!this.nodes)
|
|
44
|
+
return;
|
|
45
|
+
const key = path.toLowerCase();
|
|
46
|
+
this.nodes = this.nodes.filter((n) => n.path.toLowerCase() !== key && !n.path.toLowerCase().startsWith(key + "/"));
|
|
47
|
+
this.version++;
|
|
48
|
+
}
|
|
49
|
+
rename(path, newName) {
|
|
50
|
+
if (!this.nodes)
|
|
51
|
+
return;
|
|
52
|
+
const key = path.toLowerCase();
|
|
53
|
+
const parent = path.includes("/") ? path.slice(0, path.lastIndexOf("/") + 1) : "";
|
|
54
|
+
const to = parent + newName;
|
|
55
|
+
this.nodes = this.nodes.map((n) => {
|
|
56
|
+
const p = n.path.toLowerCase();
|
|
57
|
+
if (p === key)
|
|
58
|
+
return { ...n, path: to, name: newName };
|
|
59
|
+
if (p.startsWith(key + "/"))
|
|
60
|
+
return { ...n, path: to + n.path.slice(path.length) };
|
|
61
|
+
return n;
|
|
62
|
+
});
|
|
63
|
+
this.version++;
|
|
64
|
+
}
|
|
65
|
+
/** Something the workspace shows changed without a node change (e.g. the review baseline). */
|
|
66
|
+
bump() {
|
|
67
|
+
this.version++;
|
|
68
|
+
}
|
|
69
|
+
touch(path, action) {
|
|
70
|
+
this.focus = { path, action, at: new Date().toISOString() };
|
|
71
|
+
this.version++;
|
|
72
|
+
}
|
|
73
|
+
setCompile(c) {
|
|
74
|
+
this.compile = c;
|
|
75
|
+
this.version++;
|
|
76
|
+
}
|
|
77
|
+
get(path) {
|
|
78
|
+
const key = path.toLowerCase();
|
|
79
|
+
return this.nodes?.find((n) => n.path.toLowerCase() === key);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/codesys/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { TreeNode } from "./st.js";
|
|
2
|
+
export { formatDiff, lineDiff, type DiffOp } from "./diff.js";
|
|
3
|
+
export interface SnapObject {
|
|
4
|
+
path: string;
|
|
5
|
+
name: string;
|
|
6
|
+
kind: TreeNode["kind"];
|
|
7
|
+
sub?: string;
|
|
8
|
+
st?: boolean;
|
|
9
|
+
declaration?: string;
|
|
10
|
+
implementation?: string;
|
|
11
|
+
/** PLCopenXML of a graphical body (SFC, CFC, LD, FBD), to recreate it. */
|
|
12
|
+
xml?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface Checkpoint {
|
|
15
|
+
name: string;
|
|
16
|
+
at: string;
|
|
17
|
+
project: string;
|
|
18
|
+
objects: SnapObject[];
|
|
19
|
+
}
|
|
20
|
+
export declare function snapshot(nodes: TreeNode[]): SnapObject[];
|
|
21
|
+
export interface ObjectChange {
|
|
22
|
+
path: string;
|
|
23
|
+
kind: string;
|
|
24
|
+
change: "added" | "removed" | "modified";
|
|
25
|
+
decl?: {
|
|
26
|
+
plus: number;
|
|
27
|
+
minus: number;
|
|
28
|
+
};
|
|
29
|
+
impl?: {
|
|
30
|
+
plus: number;
|
|
31
|
+
minus: number;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare function diffObjects(before: SnapObject[], after: SnapObject[]): ObjectChange[];
|
|
35
|
+
export declare class ChangeStore {
|
|
36
|
+
readonly root: string;
|
|
37
|
+
/** Projects that already have a session-start checkpoint in this process. */
|
|
38
|
+
private started;
|
|
39
|
+
constructor(root: string);
|
|
40
|
+
dir(project: string): string;
|
|
41
|
+
private file;
|
|
42
|
+
save(project: string, name: string, nodes: TreeNode[]): Promise<Checkpoint>;
|
|
43
|
+
load(project: string, name: string): Promise<Checkpoint | undefined>;
|
|
44
|
+
list(project: string): Promise<{
|
|
45
|
+
name: string;
|
|
46
|
+
at: string;
|
|
47
|
+
objects: number;
|
|
48
|
+
}[]>;
|
|
49
|
+
/** Take the session-start checkpoint once per project per process. */
|
|
50
|
+
sessionStart(project: string, exportNodes: () => Promise<TreeNode[]>): Promise<boolean>;
|
|
51
|
+
/** The review baseline (what the user has accepted); falls back to session-start. */
|
|
52
|
+
review(project: string): Promise<Checkpoint | undefined>;
|
|
53
|
+
/** Accept the current state of an object and everything under it into the review baseline. */
|
|
54
|
+
accept(project: string, path: string, now: SnapObject[]): Promise<number>;
|
|
55
|
+
}
|
|
56
|
+
/** Name of the checkpoint the workspace's diffs and badges compare against. */
|
|
57
|
+
export declare const REVIEW = "review";
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change tracking for CODESYS edits: checkpoints (snapshots of every ST
|
|
3
|
+
* object's text), diffs against them, and what's needed to revert.
|
|
4
|
+
* Checkpoints live on disk per project, so they survive a server restart.
|
|
5
|
+
*/
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
9
|
+
import { basename, join } from "node:path";
|
|
10
|
+
import { countDiff as count, lineDiff } from "./diff.js";
|
|
11
|
+
export { formatDiff, lineDiff } from "./diff.js";
|
|
12
|
+
/** Object kinds whose text is tracked (folders are tracked for structure only). */
|
|
13
|
+
const TRACKED = new Set(["pou", "method", "property", "accessor", "action", "dut", "gvl", "interface", "interface_method", "folder"]);
|
|
14
|
+
export function snapshot(nodes) {
|
|
15
|
+
return nodes
|
|
16
|
+
.filter((n) => TRACKED.has(n.kind))
|
|
17
|
+
.map((n) => ({
|
|
18
|
+
path: n.path,
|
|
19
|
+
name: n.name,
|
|
20
|
+
kind: n.kind,
|
|
21
|
+
...(n.sub ? { sub: n.sub } : {}),
|
|
22
|
+
...(n.st === false ? { st: false } : {}),
|
|
23
|
+
...(n.declaration !== undefined ? { declaration: n.declaration } : {}),
|
|
24
|
+
...(n.implementation !== undefined ? { implementation: n.implementation } : {}),
|
|
25
|
+
...(n.xml !== undefined ? { xml: n.xml } : {}),
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
const norm = (s) => (s ?? "").replace(/\r\n?/g, "\n").replace(/\s+$/, "");
|
|
29
|
+
export function diffObjects(before, after) {
|
|
30
|
+
const b = new Map(before.map((o) => [o.path.toLowerCase(), o]));
|
|
31
|
+
const a = new Map(after.map((o) => [o.path.toLowerCase(), o]));
|
|
32
|
+
const out = [];
|
|
33
|
+
for (const [k, o] of a) {
|
|
34
|
+
const old = b.get(k);
|
|
35
|
+
if (!old) {
|
|
36
|
+
out.push({ path: o.path, kind: o.kind, change: "added" });
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const d = norm(old.declaration) === norm(o.declaration) ? undefined : count(lineDiff(norm(old.declaration), norm(o.declaration)));
|
|
40
|
+
const i = norm(old.implementation) === norm(o.implementation) ? undefined : count(lineDiff(norm(old.implementation), norm(o.implementation)));
|
|
41
|
+
if (d || i)
|
|
42
|
+
out.push({ path: o.path, kind: o.kind, change: "modified", ...(d ? { decl: d } : {}), ...(i ? { impl: i } : {}) });
|
|
43
|
+
}
|
|
44
|
+
for (const [k, o] of b)
|
|
45
|
+
if (!a.has(k))
|
|
46
|
+
out.push({ path: o.path, kind: o.kind, change: "removed" });
|
|
47
|
+
return out.sort((x, y) => x.path.localeCompare(y.path));
|
|
48
|
+
}
|
|
49
|
+
export class ChangeStore {
|
|
50
|
+
root;
|
|
51
|
+
/** Projects that already have a session-start checkpoint in this process. */
|
|
52
|
+
started = new Set();
|
|
53
|
+
constructor(root) {
|
|
54
|
+
this.root = root;
|
|
55
|
+
}
|
|
56
|
+
dir(project) {
|
|
57
|
+
const base = basename(project).replace(/\.project$/i, "").replace(/[^A-Za-z0-9_.-]/g, "_");
|
|
58
|
+
const h = createHash("sha256").update(project.toLowerCase()).digest("hex").slice(0, 8);
|
|
59
|
+
return join(this.root, `${base}-${h}`);
|
|
60
|
+
}
|
|
61
|
+
file(project, name) {
|
|
62
|
+
return join(this.dir(project), `${name.replace(/[^A-Za-z0-9_.-]/g, "_")}.json`);
|
|
63
|
+
}
|
|
64
|
+
async save(project, name, nodes) {
|
|
65
|
+
const cp = { name, at: new Date().toISOString(), project, objects: snapshot(nodes) };
|
|
66
|
+
await mkdir(this.dir(project), { recursive: true });
|
|
67
|
+
await writeFile(this.file(project, name), JSON.stringify(cp), "utf8");
|
|
68
|
+
return cp;
|
|
69
|
+
}
|
|
70
|
+
async load(project, name) {
|
|
71
|
+
const f = this.file(project, name);
|
|
72
|
+
if (!existsSync(f))
|
|
73
|
+
return undefined;
|
|
74
|
+
return JSON.parse(await readFile(f, "utf8"));
|
|
75
|
+
}
|
|
76
|
+
async list(project) {
|
|
77
|
+
const d = this.dir(project);
|
|
78
|
+
if (!existsSync(d))
|
|
79
|
+
return [];
|
|
80
|
+
const out = [];
|
|
81
|
+
for (const f of await readdir(d)) {
|
|
82
|
+
if (!f.endsWith(".json"))
|
|
83
|
+
continue;
|
|
84
|
+
try {
|
|
85
|
+
const cp = JSON.parse(await readFile(join(d, f), "utf8"));
|
|
86
|
+
out.push({ name: cp.name, at: cp.at, objects: cp.objects.length });
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
/* skip unreadable */
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return out.sort((x, y) => x.at.localeCompare(y.at));
|
|
93
|
+
}
|
|
94
|
+
/** Take the session-start checkpoint once per project per process. */
|
|
95
|
+
async sessionStart(project, exportNodes) {
|
|
96
|
+
const key = project.toLowerCase();
|
|
97
|
+
if (this.started.has(key))
|
|
98
|
+
return false;
|
|
99
|
+
this.started.add(key);
|
|
100
|
+
try {
|
|
101
|
+
const nodes = await exportNodes();
|
|
102
|
+
await this.save(project, "session-start", nodes);
|
|
103
|
+
// The review baseline starts as the session start; Accept moves it per object.
|
|
104
|
+
await this.save(project, REVIEW, nodes);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
this.started.delete(key);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** The review baseline (what the user has accepted); falls back to session-start. */
|
|
113
|
+
async review(project) {
|
|
114
|
+
return (await this.load(project, REVIEW)) ?? (await this.load(project, "session-start"));
|
|
115
|
+
}
|
|
116
|
+
/** Accept the current state of an object and everything under it into the review baseline. */
|
|
117
|
+
async accept(project, path, now) {
|
|
118
|
+
const cp = await this.review(project);
|
|
119
|
+
if (!cp)
|
|
120
|
+
throw new Error("No review baseline yet: open the project first.");
|
|
121
|
+
const key = path.replace(/^\/+/, "").toLowerCase();
|
|
122
|
+
const inTree = (o) => o.path.toLowerCase() === key || o.path.toLowerCase().startsWith(key + "/");
|
|
123
|
+
const kept = cp.objects.filter((o) => !inTree(o));
|
|
124
|
+
const taken = now.filter(inTree);
|
|
125
|
+
const objects = [...kept, ...taken];
|
|
126
|
+
await mkdir(this.dir(project), { recursive: true });
|
|
127
|
+
await writeFile(this.file(project, REVIEW), JSON.stringify({ ...cp, name: REVIEW, at: new Date().toISOString(), objects }), "utf8");
|
|
128
|
+
return taken.length;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Name of the checkpoint the workspace's diffs and badges compare against. */
|
|
132
|
+
export const REVIEW = "review";
|
|
133
|
+
//# sourceMappingURL=changes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/codesys/changes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tolerant parser for CODESYS ST declarations: headers (kind, name,
|
|
3
|
+
* EXTENDS / IMPLEMENTS, return type, modifiers), variable sections with
|
|
4
|
+
* names, types, initial values, AT addresses and comments, enum members and
|
|
5
|
+
* struct fields. Used for the outline and the I/O list; it never rejects
|
|
6
|
+
* input, it just extracts what it recognises.
|
|
7
|
+
*/
|
|
8
|
+
export type SectionKind = "VAR_INPUT" | "VAR_OUTPUT" | "VAR_IN_OUT" | "VAR" | "VAR_TEMP" | "VAR_STAT" | "VAR_INST" | "VAR_GLOBAL" | "VAR_EXTERNAL" | "VAR_CONFIG";
|
|
9
|
+
export interface VarDecl {
|
|
10
|
+
name: string;
|
|
11
|
+
type: string;
|
|
12
|
+
init?: string;
|
|
13
|
+
at?: string;
|
|
14
|
+
comment?: string;
|
|
15
|
+
section: SectionKind;
|
|
16
|
+
constant?: boolean;
|
|
17
|
+
retain?: boolean;
|
|
18
|
+
persistent?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface Header {
|
|
21
|
+
keyword: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
modifiers: string[];
|
|
24
|
+
extends?: string[];
|
|
25
|
+
implements?: string[];
|
|
26
|
+
returnType?: string;
|
|
27
|
+
attributes: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface ParsedDecl {
|
|
30
|
+
header: Header;
|
|
31
|
+
vars: VarDecl[];
|
|
32
|
+
/** Enum members with optional values (DUT enums). */
|
|
33
|
+
enumMembers?: {
|
|
34
|
+
name: string;
|
|
35
|
+
value?: string;
|
|
36
|
+
}[];
|
|
37
|
+
/** Base type of an enum (`(A, B) INT`) or an alias target. */
|
|
38
|
+
baseType?: string;
|
|
39
|
+
/** STRUCT / UNION fields (DUTs). */
|
|
40
|
+
fields?: VarDecl[];
|
|
41
|
+
dutKind?: "enum" | "struct" | "union" | "alias";
|
|
42
|
+
}
|
|
43
|
+
export declare function parseDeclaration(decl: string | undefined): ParsedDecl;
|
|
44
|
+
/** One-line signature, e.g. `METHOD Reset(bHard : BOOL) : BOOL`. */
|
|
45
|
+
export declare function signature(p: ParsedDecl, name?: string): string;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tolerant parser for CODESYS ST declarations: headers (kind, name,
|
|
3
|
+
* EXTENDS / IMPLEMENTS, return type, modifiers), variable sections with
|
|
4
|
+
* names, types, initial values, AT addresses and comments, enum members and
|
|
5
|
+
* struct fields. Used for the outline and the I/O list; it never rejects
|
|
6
|
+
* input, it just extracts what it recognises.
|
|
7
|
+
*/
|
|
8
|
+
const SECTION_RE = /^(VAR_INPUT|VAR_OUTPUT|VAR_IN_OUT|VAR_GLOBAL|VAR_EXTERNAL|VAR_CONFIG|VAR_TEMP|VAR_STAT|VAR_INST|VAR)\b(.*)$/i;
|
|
9
|
+
const MODIFIERS = new Set(["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "ABSTRACT", "FINAL"]);
|
|
10
|
+
/** Split text into statements ending in `;` outside brackets, strings and comments; keep the trailing line comment. */
|
|
11
|
+
function statements(text) {
|
|
12
|
+
const out = [];
|
|
13
|
+
let cur = "";
|
|
14
|
+
let depth = 0;
|
|
15
|
+
let pendingComment;
|
|
16
|
+
let i = 0;
|
|
17
|
+
const push = () => {
|
|
18
|
+
const body = cur.replace(/\s+/g, " ").trim();
|
|
19
|
+
if (body)
|
|
20
|
+
out.push({ body, ...(pendingComment ? { comment: pendingComment } : {}) });
|
|
21
|
+
cur = "";
|
|
22
|
+
pendingComment = undefined;
|
|
23
|
+
};
|
|
24
|
+
while (i < text.length) {
|
|
25
|
+
const c = text[i];
|
|
26
|
+
const two = text.slice(i, i + 2);
|
|
27
|
+
if (two === "//") {
|
|
28
|
+
const end = text.indexOf("\n", i);
|
|
29
|
+
const comment = text.slice(i + 2, end < 0 ? undefined : end).trim();
|
|
30
|
+
// A comment right after `;` on the same line belongs to the previous statement.
|
|
31
|
+
const last = out.at(-1);
|
|
32
|
+
if (!cur.trim() && last && !last.comment && comment)
|
|
33
|
+
last.comment = comment;
|
|
34
|
+
else if (comment)
|
|
35
|
+
pendingComment ??= comment;
|
|
36
|
+
i = end < 0 ? text.length : end;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (two === "(*" || two === "/*") {
|
|
40
|
+
const close = two === "(*" ? "*)" : "*/";
|
|
41
|
+
const end = text.indexOf(close, i + 2);
|
|
42
|
+
const comment = text.slice(i + 2, end < 0 ? undefined : end).trim();
|
|
43
|
+
const last = out.at(-1);
|
|
44
|
+
if (!cur.trim() && last && !last.comment && comment && !comment.includes("\n"))
|
|
45
|
+
last.comment = comment;
|
|
46
|
+
i = end < 0 ? text.length : end + 2;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (c === "{") {
|
|
50
|
+
const end = text.indexOf("}", i);
|
|
51
|
+
cur += text.slice(i, end < 0 ? undefined : end + 1);
|
|
52
|
+
i = end < 0 ? text.length : end + 1;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (c === "'" || c === '"') {
|
|
56
|
+
let j = i + 1;
|
|
57
|
+
while (j < text.length && text[j] !== c)
|
|
58
|
+
j += text[j] === "$" ? 2 : 1;
|
|
59
|
+
cur += text.slice(i, j + 1);
|
|
60
|
+
i = j + 1;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (c === "(" || c === "[")
|
|
64
|
+
depth++;
|
|
65
|
+
if (c === ")" || c === "]")
|
|
66
|
+
depth = Math.max(0, depth - 1);
|
|
67
|
+
if (c === ";" && depth === 0) {
|
|
68
|
+
push();
|
|
69
|
+
i++;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (c === "\n" && depth === 0) {
|
|
73
|
+
// Section keywords and headers have no `;`: end them at the line break.
|
|
74
|
+
const t = cur.trim();
|
|
75
|
+
// `TYPE X :` continues on the next line (the enum list or STRUCT).
|
|
76
|
+
if (/^(\{[^}]*\}\s*)*TYPE\b[^;]*:\s*$/i.test(t))
|
|
77
|
+
cur += " ";
|
|
78
|
+
else if (/^(\{[^}]*\}\s*)*(VAR\w*|END_VAR|END_STRUCT|END_UNION|END_TYPE|STRUCT|UNION|(PROGRAM|FUNCTION_BLOCK|FUNCTION|METHOD|PROPERTY|INTERFACE|TYPE)\b.*)(\s+\w+)*$/i.test(t) && !/:=/.test(t.replace(/^TYPE\b.*/i, "")))
|
|
79
|
+
push();
|
|
80
|
+
else
|
|
81
|
+
cur += " ";
|
|
82
|
+
i++;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
cur += c;
|
|
86
|
+
i++;
|
|
87
|
+
}
|
|
88
|
+
push();
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
const splitList = (s) => s
|
|
92
|
+
.split(",")
|
|
93
|
+
.map((x) => x.trim())
|
|
94
|
+
.filter(Boolean);
|
|
95
|
+
function parseHeader(stmt) {
|
|
96
|
+
const attributes = [...stmt.matchAll(/\{\s*attribute\s+'([^']+)'(?:\s*:=\s*'[^']*')?\s*\}/gi)].map((m) => m[1]);
|
|
97
|
+
const s = stmt.replace(/\{[^}]*\}/g, " ").replace(/\s+/g, " ").trim();
|
|
98
|
+
const m = /^(PROGRAM|FUNCTION_BLOCK|FUNCTION|METHOD|PROPERTY|INTERFACE|TYPE|VAR_GLOBAL|TEST_PROGRAM|TEST_FUNCTION_BLOCK)\b\s*(.*)$/i.exec(s);
|
|
99
|
+
if (!m)
|
|
100
|
+
return { keyword: "", modifiers: [], attributes };
|
|
101
|
+
const keyword = m[1].toUpperCase();
|
|
102
|
+
let rest = m[2];
|
|
103
|
+
const modifiers = [];
|
|
104
|
+
for (;;) {
|
|
105
|
+
const w = /^(\w+)\s*/.exec(rest);
|
|
106
|
+
if (w && MODIFIERS.has(w[1].toUpperCase())) {
|
|
107
|
+
modifiers.push(w[1].toUpperCase());
|
|
108
|
+
rest = rest.slice(w[0].length);
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
const h = { keyword, modifiers, attributes };
|
|
114
|
+
const name = /^([A-Za-z_]\w*)/.exec(rest);
|
|
115
|
+
if (name) {
|
|
116
|
+
h.name = name[1];
|
|
117
|
+
rest = rest.slice(name[0].length).trim();
|
|
118
|
+
}
|
|
119
|
+
const ret = /^:\s*(.+?)(?=\s+(EXTENDS|IMPLEMENTS)\b|$)/i.exec(rest);
|
|
120
|
+
if (ret && keyword !== "TYPE")
|
|
121
|
+
h.returnType = ret[1].trim();
|
|
122
|
+
const ext = /\bEXTENDS\s+(.+?)(?=\s+IMPLEMENTS\b|$)/i.exec(rest);
|
|
123
|
+
if (ext)
|
|
124
|
+
h.extends = splitList(ext[1]);
|
|
125
|
+
const imp = /\bIMPLEMENTS\s+(.+)$/i.exec(rest);
|
|
126
|
+
if (imp)
|
|
127
|
+
h.implements = splitList(imp[1]);
|
|
128
|
+
return h;
|
|
129
|
+
}
|
|
130
|
+
function parseVar(body, section, flags, comment) {
|
|
131
|
+
const s = body.replace(/\{[^}]*\}/g, " ").trim();
|
|
132
|
+
const m = /^([A-Za-z_][\w\s,]*?)(?:\s+AT\s+(%\S+))?\s*:\s*([\s\S]+)$/i.exec(s);
|
|
133
|
+
if (!m)
|
|
134
|
+
return [];
|
|
135
|
+
let type = m[3].trim();
|
|
136
|
+
let init;
|
|
137
|
+
// `:=` at top level separates type and initial value.
|
|
138
|
+
let depth = 0;
|
|
139
|
+
for (let i = 0; i < type.length - 1; i++) {
|
|
140
|
+
const c = type[i];
|
|
141
|
+
if (c === "(" || c === "[")
|
|
142
|
+
depth++;
|
|
143
|
+
else if (c === ")" || c === "]")
|
|
144
|
+
depth--;
|
|
145
|
+
else if (depth === 0 && c === ":" && type[i + 1] === "=") {
|
|
146
|
+
init = type.slice(i + 2).trim();
|
|
147
|
+
type = type.slice(0, i).trim();
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return splitList(m[1]).map((name) => ({
|
|
152
|
+
name,
|
|
153
|
+
type,
|
|
154
|
+
section,
|
|
155
|
+
...(init !== undefined ? { init } : {}),
|
|
156
|
+
...(m[2] ? { at: m[2] } : {}),
|
|
157
|
+
...(comment ? { comment } : {}),
|
|
158
|
+
...(flags.constant ? { constant: true } : {}),
|
|
159
|
+
...(flags.retain ? { retain: true } : {}),
|
|
160
|
+
...(flags.persistent ? { persistent: true } : {}),
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
export function parseDeclaration(decl) {
|
|
164
|
+
const stmts = statements(decl ?? "");
|
|
165
|
+
const result = { header: { keyword: "", modifiers: [], attributes: [] }, vars: [] };
|
|
166
|
+
let section;
|
|
167
|
+
let flags = { constant: false, retain: false, persistent: false };
|
|
168
|
+
let inStruct;
|
|
169
|
+
for (let k = 0; k < stmts.length; k++) {
|
|
170
|
+
const { body, comment } = stmts[k];
|
|
171
|
+
const plain = body.replace(/\{[^}]*\}/g, " ").trim();
|
|
172
|
+
if (!result.header.keyword) {
|
|
173
|
+
const h = parseHeader(body);
|
|
174
|
+
if (h.keyword) {
|
|
175
|
+
result.header = h;
|
|
176
|
+
if (h.keyword === "VAR_GLOBAL") {
|
|
177
|
+
section = "VAR_GLOBAL";
|
|
178
|
+
flags = { constant: /\bCONSTANT\b/i.test(body), retain: /\bRETAIN\b/i.test(body), persistent: /\bPERSISTENT\b/i.test(body) };
|
|
179
|
+
}
|
|
180
|
+
if (h.keyword === "TYPE") {
|
|
181
|
+
// TYPE Name : (A := 0, B) INT | TYPE Name : STRUCT | TYPE Name : INT
|
|
182
|
+
const t = /^TYPE\s+\w+\s*(?:EXTENDS\s+[\w.]+\s*)?:\s*([\s\S]*)$/i.exec(plain)?.[1]?.trim() ?? "";
|
|
183
|
+
if (t.startsWith("(")) {
|
|
184
|
+
const close = t.lastIndexOf(")");
|
|
185
|
+
result.dutKind = "enum";
|
|
186
|
+
result.enumMembers = splitList(t.slice(1, close)).map((x) => {
|
|
187
|
+
const [n, v] = x.split(":=").map((y) => y.trim());
|
|
188
|
+
return v !== undefined ? { name: n, value: v } : { name: n };
|
|
189
|
+
});
|
|
190
|
+
const base = t.slice(close + 1).trim();
|
|
191
|
+
if (base)
|
|
192
|
+
result.baseType = base;
|
|
193
|
+
}
|
|
194
|
+
else if (/^STRUCT\b/i.test(t)) {
|
|
195
|
+
result.dutKind = "struct";
|
|
196
|
+
inStruct = "struct";
|
|
197
|
+
result.fields = [];
|
|
198
|
+
}
|
|
199
|
+
else if (/^UNION\b/i.test(t)) {
|
|
200
|
+
result.dutKind = "union";
|
|
201
|
+
inStruct = "union";
|
|
202
|
+
result.fields = [];
|
|
203
|
+
}
|
|
204
|
+
else if (t) {
|
|
205
|
+
result.dutKind = "alias";
|
|
206
|
+
result.baseType = t;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const sec = SECTION_RE.exec(plain);
|
|
213
|
+
if (sec) {
|
|
214
|
+
section = sec[1].toUpperCase();
|
|
215
|
+
flags = { constant: /\bCONSTANT\b/i.test(sec[2]), retain: /\bRETAIN\b/i.test(sec[2]), persistent: /\bPERSISTENT\b/i.test(sec[2]) };
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (/^END_VAR\b/i.test(plain)) {
|
|
219
|
+
section = undefined;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (/^(STRUCT|UNION)\b/i.test(plain) && result.header.keyword === "TYPE") {
|
|
223
|
+
inStruct = /^STRUCT/i.test(plain) ? "struct" : "union";
|
|
224
|
+
result.dutKind ??= inStruct;
|
|
225
|
+
result.fields ??= [];
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (/^END_(STRUCT|UNION|TYPE)\b/i.test(plain)) {
|
|
229
|
+
inStruct = undefined;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (inStruct) {
|
|
233
|
+
result.fields.push(...parseVar(body, "VAR", { constant: false, retain: false, persistent: false }, comment));
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (section)
|
|
237
|
+
result.vars.push(...parseVar(body, section, flags, comment));
|
|
238
|
+
}
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
/** One-line signature, e.g. `METHOD Reset(bHard : BOOL) : BOOL`. */
|
|
242
|
+
export function signature(p, name) {
|
|
243
|
+
const h = p.header;
|
|
244
|
+
const ins = p.vars.filter((v) => v.section === "VAR_INPUT" || v.section === "VAR_IN_OUT").map((v) => `${v.section === "VAR_IN_OUT" ? "VAR_IN_OUT " : ""}${v.name} : ${v.type}`);
|
|
245
|
+
const outs = p.vars.filter((v) => v.section === "VAR_OUTPUT").map((v) => `${v.name} : ${v.type}`);
|
|
246
|
+
let s = `${name ?? h.name ?? "?"}(${ins.join(", ")}${outs.length ? `; out ${outs.join(", ")}` : ""})`;
|
|
247
|
+
if (h.returnType)
|
|
248
|
+
s += ` : ${h.returnType}`;
|
|
249
|
+
return s;
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=decl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decl.js","sourceRoot":"","sources":["../../src/codesys/decl.ts"],"names":[],"mappings":"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"}
|