@ripple-ts/typescript-plugin 0.2.188 → 0.2.190

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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/language.js +153 -87
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "TypeScript plugin for Ripple",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.2.188",
6
+ "version": "0.2.190",
7
7
  "main": "src/index.js",
8
8
  "homepage": "https://ripplejs.com",
9
9
  "repository": {
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "peerDependencies": {
25
25
  "typescript": "^5.9.2",
26
- "ripple": "0.2.188"
26
+ "ripple": "0.2.190"
27
27
  },
28
28
  "scripts": {
29
29
  "build": "tsdown",
package/src/language.js CHANGED
@@ -26,15 +26,7 @@ const { log, logWarning, logError } = createLogging('[Ripple Language]');
26
26
  function getRippleLanguagePlugin() {
27
27
  log('Creating Ripple language plugin...');
28
28
 
29
- /** @type {Map<string, string | null>} */
30
- const path2RipplePathMap = new Map();
31
- /** @type {string | null} */
32
- let packaged_path = null;
33
-
34
29
  return {
35
- /**
36
- * @param {ScriptId} fileNameOrUri
37
- */
38
30
  getLanguageId(fileNameOrUri) {
39
31
  const file_name =
40
32
  typeof fileNameOrUri === 'string'
@@ -45,19 +37,10 @@ function getRippleLanguagePlugin() {
45
37
  return 'ripple';
46
38
  }
47
39
  },
48
-
49
- /**
50
- * @param {ScriptId} fileNameOrUri
51
- * @param {string} languageId
52
- * @param {IScriptSnapshot} snapshot
53
- */
54
40
  createVirtualCode(fileNameOrUri, languageId, snapshot) {
55
41
  if (languageId === 'ripple') {
56
- const file_name =
57
- typeof fileNameOrUri === 'string'
58
- ? fileNameOrUri
59
- : fileNameOrUri.fsPath.replace(/\\/g, '/');
60
- const ripple = getRippleForFile(file_name);
42
+ const file_name = normalizeFileNameOrUri(fileNameOrUri);
43
+ const ripple = getRippleCompiler(file_name);
61
44
  if (!ripple) {
62
45
  logError(`Ripple compiler not found for file: ${file_name}`);
63
46
  return undefined;
@@ -72,12 +55,6 @@ function getRippleLanguagePlugin() {
72
55
  }
73
56
  return undefined;
74
57
  },
75
-
76
- /**
77
- * @param {ScriptId} fileNameOrUri
78
- * @param {VirtualCode} virtualCode
79
- * @param {IScriptSnapshot} snapshot
80
- */
81
58
  updateVirtualCode(fileNameOrUri, virtualCode, snapshot) {
82
59
  if (virtualCode instanceof RippleVirtualCode) {
83
60
  log('Updating existing virtual code for:', virtualCode.fileName);
@@ -106,68 +83,6 @@ function getRippleLanguagePlugin() {
106
83
  },
107
84
  },
108
85
  };
109
-
110
- /**
111
- * @param {string} normalized_file_name
112
- * @returns {RippleCompiler | undefined}
113
- */
114
- function getRippleForFile(normalized_file_name) {
115
- const compiler_path = ['node_modules', 'ripple', 'src', 'compiler', 'index.js'];
116
-
117
- const parts = normalized_file_name.split('/');
118
-
119
- // First, try to find ripple in the workspace (user's repo)
120
- for (let i = parts.length - 2; i >= 0; i--) {
121
- const dir = parts.slice(0, i + 1).join('/');
122
-
123
- if (!path2RipplePathMap.has(dir)) {
124
- const full_path = [dir, ...compiler_path].join('/');
125
- if (fs.existsSync(full_path)) {
126
- path2RipplePathMap.set(dir, full_path);
127
- log('Found ripple compiler at:', full_path);
128
- } else {
129
- path2RipplePathMap.set(dir, null);
130
- }
131
- }
132
-
133
- const ripple_path = path2RipplePathMap.get(dir);
134
- if (ripple_path) {
135
- return /** @type {RippleCompiler} */ (require(ripple_path));
136
- }
137
- }
138
-
139
- const warn_message = `Ripple compiler not found in workspace for ${normalized_file_name}. \
140
- Using packaged version`;
141
-
142
- if (packaged_path) {
143
- logWarning(`${warn_message} at ${packaged_path}`);
144
- return /** @type {RippleCompiler} */ (require(packaged_path));
145
- }
146
-
147
- // Fallback: look for the packaged version
148
- // Use node's module resolution just in case we move the package location
149
- // Start from the plugin's directory and walk up
150
- let current_dir = __dirname;
151
-
152
- while (current_dir) {
153
- const full_path = path.join(current_dir, ...compiler_path);
154
-
155
- if (fs.existsSync(full_path)) {
156
- packaged_path = full_path;
157
- logWarning(`${warn_message} at ${packaged_path}`);
158
- return /** @type {RippleCompiler} */ (require(full_path));
159
- }
160
-
161
- const parent_dir = path.dirname(current_dir);
162
- // Stop if we've reached the root
163
- if (parent_dir === current_dir) {
164
- break;
165
- }
166
- current_dir = parent_dir;
167
- }
168
-
169
- return undefined;
170
- }
171
86
  }
172
87
 
173
88
  /**
@@ -527,8 +442,159 @@ const resolveConfig = (config) => {
527
442
  };
528
443
  };
529
444
 
445
+ /** @type {Map<string, string | null>} */
446
+ const path2RipplePathMap = new Map();
447
+ /** @type {string | null} */
448
+ let packaged_dir = null;
449
+ /** @type {Map<string, string>} */
450
+ const pathToTypesCache = new Map();
451
+ /** @type {Map<string, RegExpMatchArray>} */
452
+ const typeNameMatchCache = new Map();
453
+
454
+ /**
455
+ * @param {ScriptId} fileNameOrUri
456
+ * @returns {string}
457
+ */
458
+ function normalizeFileNameOrUri(fileNameOrUri) {
459
+ return typeof fileNameOrUri === 'string'
460
+ ? fileNameOrUri
461
+ : fileNameOrUri.fsPath.replace(/\\/g, '/');
462
+ }
463
+
464
+ /**
465
+ * @param {string} normalized_file_name
466
+ * @returns {RippleCompiler | undefined}
467
+ */
468
+ function getRippleCompiler(normalized_file_name) {
469
+ const dir = getRippleDirForFile(normalized_file_name);
470
+ const ripple_path = dir ? path.join(dir, 'src', 'compiler', 'index.js') : undefined;
471
+ if (ripple_path) {
472
+ return /** @type {RippleCompiler} */ (require(ripple_path));
473
+ }
474
+ }
475
+
476
+ /**
477
+ * @param {string} normalized_file_name
478
+ * @returns {string | undefined}
479
+ */
480
+ function getRippleDirForFile(normalized_file_name) {
481
+ const ripple_src_dir = ['node_modules', 'ripple'];
482
+
483
+ const parts = normalized_file_name.split('/');
484
+
485
+ // First, try to find ripple in the workspace (user's repo)
486
+ for (let i = parts.length - 2; i >= 0; i--) {
487
+ const dir = parts.slice(0, i + 1).join('/');
488
+
489
+ if (!path2RipplePathMap.has(dir)) {
490
+ const full_path = [dir, ...ripple_src_dir].join('/');
491
+ if (fs.existsSync(full_path)) {
492
+ path2RipplePathMap.set(dir, full_path);
493
+ log('Found ripple src directory at:', full_path);
494
+ } else {
495
+ path2RipplePathMap.set(dir, null);
496
+ }
497
+ }
498
+
499
+ const src_dir = path2RipplePathMap.get(dir);
500
+ if (src_dir) {
501
+ return src_dir;
502
+ }
503
+ }
504
+
505
+ const warn_message = `Ripple src directory not found in workspace for ${normalized_file_name}. \
506
+ Using packaged version`;
507
+
508
+ if (packaged_dir) {
509
+ logWarning(`${warn_message} at ${packaged_dir}`);
510
+ return packaged_dir;
511
+ }
512
+
513
+ // Fallback: look for the packaged version
514
+ // Use node's module resolution just in case we move the package location
515
+ // Start from the plugin's directory and walk up
516
+ let current_dir = __dirname;
517
+
518
+ while (current_dir) {
519
+ const full_path = path.join(current_dir, ...ripple_src_dir);
520
+
521
+ if (fs.existsSync(full_path)) {
522
+ packaged_dir = full_path;
523
+ logWarning(`${warn_message} at ${packaged_dir}`);
524
+ return require(full_path);
525
+ }
526
+
527
+ const parent_dir = path.dirname(current_dir);
528
+ // Stop if we've reached the root
529
+ if (parent_dir === current_dir) {
530
+ break;
531
+ }
532
+ current_dir = parent_dir;
533
+ }
534
+
535
+ return undefined;
536
+ }
537
+
538
+ /**
539
+ * @param {string} typesFilePath
540
+ * @returns {string | undefined}
541
+ */
542
+ function getCachedTypeDefinitionFile(typesFilePath) {
543
+ const cached = pathToTypesCache.get(typesFilePath);
544
+ if (cached) {
545
+ return cached;
546
+ }
547
+
548
+ if (!fs.existsSync(typesFilePath)) {
549
+ logWarning(`Types file does not exist at path: ${typesFilePath}`);
550
+ return;
551
+ }
552
+
553
+ log(`Found ripple types at: ${typesFilePath}`);
554
+
555
+ // Read the file to find the class definition offset
556
+ const fileContent = fs.readFileSync(typesFilePath, 'utf8');
557
+
558
+ if (!fileContent) {
559
+ logWarning(`Failed to read content of types file at: ${typesFilePath}`);
560
+ return;
561
+ }
562
+
563
+ pathToTypesCache.set(typesFilePath, fileContent);
564
+ return fileContent;
565
+ }
566
+
567
+ /**
568
+ * @param {string} typeName
569
+ * @param {string} text
570
+ * @returns {RegExpMatchArray | undefined}
571
+ */
572
+ function getCachedTypeMatches(typeName, text) {
573
+ const cached = typeNameMatchCache.get(typeName);
574
+ if (cached) {
575
+ return cached;
576
+ }
577
+
578
+ const searchPattern = new RegExp(
579
+ `(?:export\\s+(?:declare\\s+)?|declare\\s+)(class|function)\\s+${typeName}`,
580
+ );
581
+
582
+ const match = text.match(searchPattern);
583
+
584
+ if (match && match.index !== undefined) {
585
+ typeNameMatchCache.set(typeName, match);
586
+ return match;
587
+ }
588
+
589
+ return;
590
+ }
591
+
530
592
  module.exports = {
593
+ getRippleDirForFile,
594
+ normalizeFileNameOrUri,
531
595
  getRippleLanguagePlugin,
596
+ getCachedTypeDefinitionFile,
597
+ getCachedTypeMatches,
532
598
  RippleVirtualCode,
533
599
  resolveConfig,
534
600
  };