@macroforge/typescript-plugin 0.1.17 → 0.1.18

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAqDrD,iBAAS,IAAI,CAAC,OAAO,EAAE;IAAE,UAAU,EAAE,OAAO,EAAE,CAAA;CAAE;mBACxB,EAAE,CAAC,MAAM,CAAC,gBAAgB;EAsnDjD;AAED,SAAS,IAAI,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAoOrD,iBAAS,IAAI,CAAC,OAAO,EAAE;IAAE,UAAU,EAAE,OAAO,EAAE,CAAA;CAAE;mBACxB,EAAE,CAAC,MAAM,CAAC,gBAAgB;EAgoDjD;AAED,SAAS,IAAI,CAAC"}
package/dist/index.js CHANGED
@@ -5,6 +5,150 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  const macroforge_1 = require("macroforge");
6
6
  const path_1 = __importDefault(require("path"));
7
7
  const fs_1 = __importDefault(require("fs"));
8
+ // Macro manifest cache for hover info
9
+ let macroManifestCache = null;
10
+ function getMacroManifest() {
11
+ if (macroManifestCache)
12
+ return macroManifestCache;
13
+ try {
14
+ const manifest = (0, macroforge_1.__macroforgeGetManifest)();
15
+ macroManifestCache = {
16
+ macros: new Map(manifest.macros.map(m => [m.name.toLowerCase(), m])),
17
+ decorators: new Map(manifest.decorators.map(d => [d.export.toLowerCase(), d])),
18
+ };
19
+ return macroManifestCache;
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ /**
26
+ * Find macro name at position in @derive(...) comment
27
+ */
28
+ function findDeriveAtPosition(text, position) {
29
+ const derivePattern = /@derive\s*\(\s*([^)]+)\s*\)/gi;
30
+ let match;
31
+ while ((match = derivePattern.exec(text)) !== null) {
32
+ const deriveStart = match.index;
33
+ const deriveEnd = deriveStart + match[0].length;
34
+ if (position >= deriveStart && position <= deriveEnd) {
35
+ const argsStart = text.indexOf("(", deriveStart) + 1;
36
+ const argsEnd = text.indexOf(")", argsStart);
37
+ const argsContent = text.substring(argsStart, argsEnd);
38
+ let currentPos = argsStart;
39
+ const macroNames = argsContent.split(",");
40
+ for (const rawName of macroNames) {
41
+ const trimmedName = rawName.trim();
42
+ const nameStartInArgs = rawName.indexOf(trimmedName);
43
+ const nameStart = currentPos + nameStartInArgs;
44
+ const nameEnd = nameStart + trimmedName.length;
45
+ if (position >= nameStart && position <= nameEnd) {
46
+ return { macroName: trimmedName, start: nameStart, end: nameEnd };
47
+ }
48
+ currentPos += rawName.length + 1;
49
+ }
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ /**
55
+ * Find decorator at position like @serde or @debug
56
+ */
57
+ function findDecoratorAtPosition(text, position) {
58
+ const decoratorPattern = /@([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
59
+ let match;
60
+ while ((match = decoratorPattern.exec(text)) !== null) {
61
+ const atSign = match.index;
62
+ const nameStart = atSign + 1;
63
+ const nameEnd = nameStart + match[1].length;
64
+ if (position >= atSign && position <= nameEnd) {
65
+ // Skip @derive in JSDoc comments - let findDeriveAtPosition handle those
66
+ if (match[1].toLowerCase() === "derive") {
67
+ const beforeMatch = text.substring(0, atSign);
68
+ const lastCommentStart = beforeMatch.lastIndexOf("/**");
69
+ const lastCommentEnd = beforeMatch.lastIndexOf("*/");
70
+ if (lastCommentStart > lastCommentEnd) {
71
+ continue;
72
+ }
73
+ }
74
+ return { name: match[1], start: atSign, end: nameEnd };
75
+ }
76
+ }
77
+ return null;
78
+ }
79
+ /**
80
+ * Get macro hover info at position
81
+ * Returns QuickInfo if hovering on a macro or decorator, null otherwise
82
+ */
83
+ function getMacroHoverInfo(text, position, tsModule) {
84
+ const manifest = getMacroManifest();
85
+ if (!manifest)
86
+ return null;
87
+ // Check for @derive(MacroName) in JSDoc comments
88
+ const deriveMatch = findDeriveAtPosition(text, position);
89
+ if (deriveMatch) {
90
+ const macroInfo = manifest.macros.get(deriveMatch.macroName.toLowerCase());
91
+ if (macroInfo) {
92
+ return {
93
+ kind: tsModule.ScriptElementKind.functionElement,
94
+ kindModifiers: "",
95
+ textSpan: {
96
+ start: deriveMatch.start,
97
+ length: deriveMatch.end - deriveMatch.start,
98
+ },
99
+ displayParts: [
100
+ { text: "@derive(", kind: "punctuation" },
101
+ { text: macroInfo.name, kind: "functionName" },
102
+ { text: ")", kind: "punctuation" },
103
+ ],
104
+ documentation: macroInfo.description
105
+ ? [{ text: macroInfo.description, kind: "text" }]
106
+ : [],
107
+ };
108
+ }
109
+ }
110
+ // Check for @decorator patterns
111
+ const decoratorMatch = findDecoratorAtPosition(text, position);
112
+ if (decoratorMatch) {
113
+ // Check if it's a macro name
114
+ const macroInfo = manifest.macros.get(decoratorMatch.name.toLowerCase());
115
+ if (macroInfo) {
116
+ return {
117
+ kind: tsModule.ScriptElementKind.functionElement,
118
+ kindModifiers: "",
119
+ textSpan: {
120
+ start: decoratorMatch.start,
121
+ length: decoratorMatch.end - decoratorMatch.start,
122
+ },
123
+ displayParts: [
124
+ { text: "@", kind: "punctuation" },
125
+ { text: macroInfo.name, kind: "functionName" },
126
+ ],
127
+ documentation: macroInfo.description
128
+ ? [{ text: macroInfo.description, kind: "text" }]
129
+ : [],
130
+ };
131
+ }
132
+ // Check if it's a decorator
133
+ const decoratorInfo = manifest.decorators.get(decoratorMatch.name.toLowerCase());
134
+ if (decoratorInfo && decoratorInfo.docs) {
135
+ return {
136
+ kind: tsModule.ScriptElementKind.functionElement,
137
+ kindModifiers: "",
138
+ textSpan: {
139
+ start: decoratorMatch.start,
140
+ length: decoratorMatch.end - decoratorMatch.start,
141
+ },
142
+ displayParts: [
143
+ { text: "@", kind: "punctuation" },
144
+ { text: decoratorInfo.export, kind: "functionName" },
145
+ ],
146
+ documentation: [{ text: decoratorInfo.docs, kind: "text" }],
147
+ };
148
+ }
149
+ }
150
+ return null;
151
+ }
8
152
  const FILE_EXTENSIONS = [".ts", ".tsx", ".svelte"];
9
153
  function shouldProcess(fileName) {
10
154
  const lower = fileName.toLowerCase();
@@ -587,6 +731,15 @@ function init(modules) {
587
731
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
588
732
  return originalGetQuickInfoAtPosition(fileName, position);
589
733
  }
734
+ // Check for macro hover first (JSDoc @derive comments and decorators)
735
+ const snapshot = info.languageServiceHost.getScriptSnapshot(fileName);
736
+ if (snapshot) {
737
+ const text = snapshot.getText(0, snapshot.getLength());
738
+ const macroHover = getMacroHoverInfo(text, position, tsModule);
739
+ if (macroHover) {
740
+ return macroHover;
741
+ }
742
+ }
590
743
  const mapper = nativePlugin.getMapper(fileName);
591
744
  if (!mapper) {
592
745
  return originalGetQuickInfoAtPosition(fileName, position);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@macroforge/typescript-plugin",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "TypeScript language service plugin that augments classes decorated with @derive to include macro-generated methods.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  "test": "bun run build && node --test tests/**/*.test.js"
33
33
  },
34
34
  "dependencies": {
35
- "macroforge": "^0.1.17"
35
+ "macroforge": "^0.1.18"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "typescript": ">=5.0.0"