@effect/language-service 0.22.2 → 0.22.3

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 (3) hide show
  1. package/index.js +122 -111
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -3494,6 +3494,7 @@ var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(functi
3494
3494
  const namespaceByFileName = /* @__PURE__ */ new Map();
3495
3495
  const excludedByFileName = /* @__PURE__ */ new Map();
3496
3496
  const unbarreledModulePathByFileName = /* @__PURE__ */ new Map();
3497
+ const barreledModulePathByFileName = /* @__PURE__ */ new Map();
3497
3498
  for (const packageName of languageServicePluginOptions.namespaceImportPackages) {
3498
3499
  const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
3499
3500
  if (barrelModule.resolvedModule) {
@@ -3516,8 +3517,15 @@ var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(functi
3516
3517
  if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
3517
3518
  namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
3518
3519
  const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
3519
- existingUnbarreledModulePath.push([exportClause.name.text, unbarreledModulePath]);
3520
+ existingUnbarreledModulePath.push({
3521
+ fileName: unbarreledModulePath,
3522
+ exportName: exportClause.name.text
3523
+ });
3520
3524
  unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
3525
+ barreledModulePathByFileName.set(unbarreledModulePath, {
3526
+ fileName: barrelSource.fileName,
3527
+ exportName: exportClause.name.text
3528
+ });
3521
3529
  }
3522
3530
  if (exportClause && ts.isNamedExports(exportClause)) {
3523
3531
  for (const element of exportClause.elements) {
@@ -3538,48 +3546,26 @@ var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(functi
3538
3546
  return {
3539
3547
  getImportNamespaceByFileName: (fileName) => namespaceByFileName.get(fileName),
3540
3548
  isExcludedFromNamespaceImport: (fileName, exportName) => (excludedByFileName.get(exportName) || []).includes(fileName),
3541
- getUnbarreledModulePath: (fileName, exportName) => unbarreledModulePathByFileName.get(fileName)?.find(([name]) => name === exportName)?.[1]
3549
+ getUnbarreledModulePath: (fileName, exportName) => unbarreledModulePathByFileName.get(fileName)?.find((_) => _.exportName === exportName)?.fileName,
3550
+ getBarreledModulePath: (fileName) => barreledModulePathByFileName.get(fileName)
3542
3551
  };
3543
3552
  });
3544
- var appendEffectCompletionEntryData = fn("collectNamespaceImports")(
3545
- function* (sourceFile, applicableCompletions) {
3553
+ var appendEffectCompletionEntryData = fn("appendEffectCompletionEntryData")(
3554
+ function* (_sourceFile, applicableCompletions) {
3546
3555
  const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
3547
3556
  if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletions;
3548
- const packagesMetadata = importablePackagesMetadataCache.get(sourceFile.fileName) || (yield* makeImportablePackagesMetadata(sourceFile));
3549
- importablePackagesMetadataCache.set(sourceFile.fileName, packagesMetadata);
3550
3557
  if (applicableCompletions) {
3551
3558
  return {
3552
3559
  ...applicableCompletions,
3553
- entries: applicableCompletions.entries.map((entry) => {
3554
- if (entry.data && entry.data.fileName && !entry.insertText && !entry.filterText && entry.data.exportName && entry.data.moduleSpecifier) {
3555
- const isExcluded = packagesMetadata.isExcludedFromNamespaceImport(
3556
- entry.data.fileName,
3557
- entry.data.exportName
3558
- );
3559
- if (isExcluded) return entry;
3560
- const unbarreledModulePath = packagesMetadata.getUnbarreledModulePath(
3561
- entry.data.fileName,
3562
- entry.data.exportName
3563
- );
3564
- const namespaceName = packagesMetadata.getImportNamespaceByFileName(
3565
- unbarreledModulePath || entry.data.fileName
3566
- );
3567
- if (namespaceName) {
3568
- return {
3569
- ...entry,
3570
- // insertText: unbarreledModulePath ? namespaceName : namespaceName + "." + entry.name,
3571
- // filterText: entry.name,
3572
- data: {
3573
- ...entry.data,
3574
- effectNamespaceName: namespaceName,
3575
- effectUnbarreledModulePath: unbarreledModulePath || "",
3576
- effectReplaceSpan: entry.replacementSpan || applicableCompletions.optionalReplacementSpan
3577
- }
3578
- };
3560
+ entries: applicableCompletions.entries.map(
3561
+ (entry) => entry.data ? {
3562
+ ...entry,
3563
+ data: {
3564
+ ...entry.data,
3565
+ effectReplaceSpan: entry.replacementSpan || applicableCompletions.optionalReplacementSpan
3579
3566
  }
3580
- }
3581
- return entry;
3582
- })
3567
+ } : entry
3568
+ )
3583
3569
  };
3584
3570
  }
3585
3571
  return applicableCompletions;
@@ -3589,92 +3575,117 @@ var postprocessCompletionEntryDetails = fn("postprocessCompletionEntryDetails")(
3589
3575
  function* (sourceFile, data, applicableCompletionEntryDetails, formatOptions, preferences, languageServiceHost) {
3590
3576
  const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
3591
3577
  if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletionEntryDetails;
3578
+ const isAutoImportOnlyCodeActions = fn("isAutoImportOnlyCodeActions")(
3579
+ function* (codeActions, exportName2) {
3580
+ if (!codeActions) return;
3581
+ if (codeActions.length !== 1) return;
3582
+ const action = codeActions[0];
3583
+ const changes2 = action.changes;
3584
+ if (changes2.length !== 1) return;
3585
+ const fileTextChanges = action.changes[0];
3586
+ if (fileTextChanges.fileName !== sourceFile.fileName) return;
3587
+ const textChanges = fileTextChanges.textChanges;
3588
+ if (textChanges.length !== 1) return;
3589
+ const change = textChanges[0];
3590
+ if (change.newText.trim().toLowerCase().startsWith("import") && change.newText.indexOf(exportName2) > -1) {
3591
+ return {
3592
+ type: "create"
3593
+ };
3594
+ }
3595
+ if (change.newText.indexOf(exportName2) > -1) {
3596
+ const ancestorNodes = yield* getAncestorNodesInRange(sourceFile, {
3597
+ pos: change.span.start,
3598
+ end: change.span.start
3599
+ });
3600
+ const importNodes = ancestorNodes.filter((node) => ts.isImportDeclaration(node));
3601
+ if (importNodes.length > 0) {
3602
+ return {
3603
+ type: "update"
3604
+ };
3605
+ }
3606
+ }
3607
+ }
3608
+ );
3592
3609
  const ts = yield* service(TypeScriptApi);
3593
3610
  const program = yield* service(TypeScriptProgram);
3594
3611
  const getModuleSpecifier = makeGetModuleSpecifier(ts);
3595
3612
  if (!getModuleSpecifier) return applicableCompletionEntryDetails;
3596
3613
  if (!applicableCompletionEntryDetails) return applicableCompletionEntryDetails;
3597
3614
  if (!data) return applicableCompletionEntryDetails;
3598
- if (!("effectNamespaceName" in data && "effectUnbarreledModulePath" in data && "effectReplaceSpan" in data)) {
3599
- return applicableCompletionEntryDetails;
3600
- }
3615
+ const { exportName, fileName, moduleSpecifier } = data;
3616
+ if (!fileName) return applicableCompletionEntryDetails;
3617
+ if (!exportName) return applicableCompletionEntryDetails;
3618
+ if (!moduleSpecifier) return applicableCompletionEntryDetails;
3619
+ if (!("effectReplaceSpan" in data)) return applicableCompletionEntryDetails;
3601
3620
  const effectReplaceSpan = data.effectReplaceSpan;
3602
- const codeActions = applicableCompletionEntryDetails.codeActions;
3603
- if (codeActions && codeActions.length === 1) {
3604
- const action = codeActions[0];
3605
- if (action.changes.length === 1) {
3606
- const fileTextChanges = action.changes[0];
3607
- if (fileTextChanges.fileName === sourceFile.fileName && fileTextChanges.textChanges.length === 1) {
3608
- const change = fileTextChanges.textChanges[0];
3609
- let hasImportActions = false;
3610
- if (change.newText.trim().toLowerCase().startsWith("import") && change.newText.indexOf(data.exportName) > -1) {
3611
- hasImportActions = true;
3612
- }
3613
- if (!hasImportActions && change.newText.indexOf(data.exportName) > -1) {
3614
- const ancestorNodes = yield* getAncestorNodesInRange(sourceFile, {
3615
- pos: change.span.start,
3616
- end: change.span.start
3617
- });
3618
- const importNodes = ancestorNodes.filter((node) => ts.isImportDeclaration(node));
3619
- hasImportActions = importNodes.length > 0;
3620
- }
3621
- if (!hasImportActions) return applicableCompletionEntryDetails;
3622
- const formatContext = ts.formatting.getFormatContext(
3623
- formatOptions || {},
3624
- languageServiceHost
3625
- );
3626
- const changes = ts.textChanges.ChangeTracker.with(
3627
- {
3628
- formatContext,
3629
- host: languageServiceHost,
3630
- preferences: preferences || {}
3631
- },
3632
- (changeTracker) => {
3633
- const isBarrelRedirect = String(data.effectUnbarreledModulePath).length > 0;
3634
- const moduleSpecifier = isBarrelRedirect ? getModuleSpecifier(
3635
- program.getCompilerOptions(),
3636
- sourceFile,
3637
- sourceFile.fileName,
3638
- String(data.effectUnbarreledModulePath),
3639
- program
3640
- ) : String(data.moduleSpecifier);
3641
- ts.insertImports(
3642
- changeTracker,
3643
- sourceFile,
3644
- ts.factory.createImportDeclaration(
3645
- void 0,
3646
- ts.factory.createImportClause(
3647
- false,
3648
- void 0,
3649
- ts.factory.createNamespaceImport(ts.factory.createIdentifier(String(data.effectNamespaceName)))
3650
- ),
3651
- ts.factory.createStringLiteral(moduleSpecifier)
3652
- ),
3653
- true,
3654
- preferences || {}
3655
- );
3656
- if (!isBarrelRedirect) {
3657
- changeTracker.insertText(
3658
- sourceFile,
3659
- effectReplaceSpan.start,
3660
- String(data.effectNamespaceName) + "."
3661
- );
3662
- }
3663
- }
3621
+ const result = yield* isAutoImportOnlyCodeActions(applicableCompletionEntryDetails.codeActions, exportName);
3622
+ if (!result) return applicableCompletionEntryDetails;
3623
+ const packagesMetadata = importablePackagesMetadataCache.get(sourceFile.fileName) || (yield* makeImportablePackagesMetadata(sourceFile));
3624
+ importablePackagesMetadataCache.set(sourceFile.fileName, packagesMetadata);
3625
+ const formatContext = ts.formatting.getFormatContext(
3626
+ formatOptions || {},
3627
+ languageServiceHost
3628
+ );
3629
+ const isExcluded = packagesMetadata.isExcludedFromNamespaceImport(
3630
+ fileName,
3631
+ exportName
3632
+ );
3633
+ if (isExcluded) return applicableCompletionEntryDetails;
3634
+ const effectUnbarreledModulePath = packagesMetadata.getUnbarreledModulePath(
3635
+ fileName,
3636
+ exportName
3637
+ );
3638
+ const effectNamespaceName = packagesMetadata.getImportNamespaceByFileName(
3639
+ effectUnbarreledModulePath || fileName
3640
+ );
3641
+ if (!effectNamespaceName) return applicableCompletionEntryDetails;
3642
+ const newModuleSpecifier = effectUnbarreledModulePath ? getModuleSpecifier(
3643
+ program.getCompilerOptions(),
3644
+ sourceFile,
3645
+ sourceFile.fileName,
3646
+ String(effectUnbarreledModulePath || fileName),
3647
+ program
3648
+ ) : moduleSpecifier;
3649
+ const changes = ts.textChanges.ChangeTracker.with(
3650
+ {
3651
+ formatContext,
3652
+ host: languageServiceHost,
3653
+ preferences: preferences || {}
3654
+ },
3655
+ (changeTracker) => {
3656
+ ts.insertImports(
3657
+ changeTracker,
3658
+ sourceFile,
3659
+ ts.factory.createImportDeclaration(
3660
+ void 0,
3661
+ ts.factory.createImportClause(
3662
+ false,
3663
+ void 0,
3664
+ ts.factory.createNamespaceImport(ts.factory.createIdentifier(effectNamespaceName))
3665
+ ),
3666
+ ts.factory.createStringLiteral(newModuleSpecifier)
3667
+ ),
3668
+ true,
3669
+ preferences || {}
3670
+ );
3671
+ if (!effectUnbarreledModulePath) {
3672
+ changeTracker.insertText(
3673
+ sourceFile,
3674
+ effectReplaceSpan.start,
3675
+ effectNamespaceName + "."
3664
3676
  );
3665
- return {
3666
- ...applicableCompletionEntryDetails,
3667
- codeActions: [
3668
- {
3669
- description: "Import * as " + data.effectNamespaceName + " from " + data.effectUnbarreledModulePath,
3670
- changes
3671
- }
3672
- ]
3673
- };
3674
3677
  }
3675
3678
  }
3676
- }
3677
- return applicableCompletionEntryDetails;
3679
+ );
3680
+ return {
3681
+ ...applicableCompletionEntryDetails,
3682
+ codeActions: [
3683
+ {
3684
+ description: "Import * as " + effectNamespaceName + " from " + newModuleSpecifier,
3685
+ changes
3686
+ }
3687
+ ]
3688
+ };
3678
3689
  }
3679
3690
  );
3680
3691