@marko/language-server 1.0.0 → 1.0.1

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/dist/index.mjs CHANGED
@@ -1267,6 +1267,7 @@ import {
1267
1267
  import { URI as URI6 } from "vscode-uri";
1268
1268
  import * as prettier2 from "prettier";
1269
1269
  import {
1270
+ NodeType as NodeType9,
1270
1271
  ScriptLang as ScriptLang3,
1271
1272
  extractScript as extractScript2
1272
1273
  } from "@marko/language-tools";
@@ -1470,6 +1471,7 @@ function patch(ts2, scriptLang, cache, host) {
1470
1471
  var IGNORE_DIAG_REG = /^(?:Expression|Identifier|['"][^\w]['"]) expected.$/;
1471
1472
  var extractCache = /* @__PURE__ */ new Map();
1472
1473
  var snapshotCache = /* @__PURE__ */ new Map();
1474
+ var insertModuleStatementLocCache = /* @__PURE__ */ new WeakMap();
1473
1475
  var markoFileReg = /\.marko$/;
1474
1476
  var tsTriggerChars = /* @__PURE__ */ new Set([".", '"', "'", "`", "/", "@", "<", "#", " "]);
1475
1477
  var optionalModifierReg = /\boptional\b/;
@@ -1650,18 +1652,29 @@ var ScriptService = {
1650
1652
  for (const change of action.changes) {
1651
1653
  if (change.fileName !== fileName)
1652
1654
  continue;
1653
- for (const { span, newText } of change.textChanges) {
1654
- const sourceRange = /^\s*(?:import|export) /.test(newText) ? (
1655
- // Ensure import inserts are always in the program root.
1656
- // TODO: this could probably be updated to more closely reflect
1657
- // where typescript wants to put the import/export.
1658
- START_LOCATION
1659
- ) : sourceLocationAtTextSpan(extracted, span);
1660
- if (sourceRange) {
1661
- textEdits.push({
1662
- newText,
1663
- range: sourceRange
1664
- });
1655
+ for (const { span, newText: rawText } of change.textChanges) {
1656
+ let range;
1657
+ let newText = rawText;
1658
+ if (span.length === 0 && /^\s*(?:import|export) /.test(newText)) {
1659
+ const cached = insertModuleStatementLocCache.get(extracted);
1660
+ newText = newText.replace(/\n\s*$/, "\n");
1661
+ if (cached) {
1662
+ range = cached;
1663
+ } else {
1664
+ const { parsed } = getMarkoFile(doc);
1665
+ const offset = getInsertModuleStatementOffset(parsed);
1666
+ const start = parsed.positionAt(offset);
1667
+ range = {
1668
+ start,
1669
+ end: start
1670
+ };
1671
+ insertModuleStatementLocCache.set(extracted, range);
1672
+ }
1673
+ } else {
1674
+ range = sourceLocationAtTextSpan(extracted, span);
1675
+ }
1676
+ if (range) {
1677
+ textEdits.push({ newText, range });
1665
1678
  }
1666
1679
  }
1667
1680
  }
@@ -1867,6 +1880,42 @@ function processScript(doc, tsProject) {
1867
1880
  });
1868
1881
  });
1869
1882
  }
1883
+ function getInsertModuleStatementOffset(parsed) {
1884
+ const { program } = parsed;
1885
+ let firstNode;
1886
+ if (program.static.length) {
1887
+ let lastImport;
1888
+ for (const node of program.static) {
1889
+ switch (node.type) {
1890
+ case NodeType9.Export:
1891
+ return node.start;
1892
+ case NodeType9.Import:
1893
+ lastImport = node;
1894
+ break;
1895
+ }
1896
+ }
1897
+ if (lastImport) {
1898
+ return lastImport.end + 1;
1899
+ }
1900
+ firstNode = program.static[0];
1901
+ }
1902
+ if (program.body.length) {
1903
+ if (!firstNode || firstNode.start > program.body[0].start) {
1904
+ firstNode = program.body[0];
1905
+ }
1906
+ }
1907
+ if (firstNode) {
1908
+ return getOffsetAfterComments(firstNode);
1909
+ }
1910
+ return 0;
1911
+ }
1912
+ function getOffsetAfterComments(node) {
1913
+ const { comments } = node;
1914
+ if (comments) {
1915
+ return comments.at(-1).end + 1;
1916
+ }
1917
+ return Math.max(0, node.start - 1);
1918
+ }
1870
1919
  function sourceLocationAtTextSpan(extracted, { start, length }) {
1871
1920
  if (start === 0 && length === 0)
1872
1921
  return START_LOCATION;