@effect/language-service 0.23.2 → 0.23.4

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/README.md CHANGED
@@ -87,7 +87,7 @@ Few options can be provided alongside the initialization of the Language Service
87
87
  "goto": true, // controls Effect goto references (default: true)
88
88
  "allowedDuplicatedPackages": [], // list of package names that has effect in peer dependencies and are allowed to be duplicated (default: [])
89
89
  "barrelImportPackages": [], // package names that should be preferred as imported from the top level barrel file (default: [])
90
- "namespaceImportPackages": [] // package names that should be preferred as imported with namespace imports e.g. ["effect"] (default: [])
90
+ "namespaceImportPackages": [] // package names that should be preferred as imported with namespace imports e.g. ["effect", "@effect/*"] (default: [])
91
91
  }
92
92
  ]
93
93
  }
package/index.js CHANGED
@@ -831,6 +831,7 @@ var dedupeWith = /* @__PURE__ */ dual(2, (self, isEquivalent) => {
831
831
  }
832
832
  return [];
833
833
  });
834
+ var dedupe = (self) => dedupeWith(self, equivalence());
834
835
 
835
836
  // src/core/Nano.ts
836
837
  function makeInternalSuccess(value) {
@@ -1029,14 +1030,43 @@ function parsePackageContentNameAndVersionFromScope(v) {
1029
1030
  if (!isString(name)) return;
1030
1031
  if (!isString(version)) return;
1031
1032
  const hasEffectInPeerDependencies = hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) && hasProperty(packageJsonContent.peerDependencies, "effect");
1033
+ const referencedPackages = Object.keys({
1034
+ ...hasProperty(packageJsonContent, "dependencies") && isObject(packageJsonContent.dependencies) ? packageJsonContent.dependencies : {},
1035
+ ...hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) ? packageJsonContent.peerDependencies : {},
1036
+ ...hasProperty(packageJsonContent, "devDependencies") && isObject(packageJsonContent.devDependencies) ? packageJsonContent.devDependencies : {}
1037
+ });
1032
1038
  return {
1033
1039
  name: name.toLowerCase(),
1034
1040
  version: version.toLowerCase(),
1035
1041
  hasEffectInPeerDependencies,
1036
1042
  contents: packageJsonContent,
1037
- packageDirectory: packageJsonScope.packageDirectory
1043
+ packageDirectory: packageJsonScope.packageDirectory,
1044
+ referencedPackages
1038
1045
  };
1039
1046
  }
1047
+ var resolveModulePattern = fn("resolveModulePattern")(
1048
+ function* (sourceFile, pattern) {
1049
+ if (pattern.indexOf("*") === -1) return [pattern.toLowerCase()];
1050
+ const ts = yield* service(TypeScriptApi);
1051
+ const packageJsonScope = parsePackageContentNameAndVersionFromScope(sourceFile);
1052
+ const referencedPackages = [];
1053
+ for (const statement of sourceFile.statements) {
1054
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
1055
+ const moduleSpecifier = statement.moduleSpecifier.text.toLowerCase();
1056
+ const packageName = moduleSpecifier.startsWith("@") ? moduleSpecifier.split("/", 2).join("/") : moduleSpecifier.split("/", 1).join("/");
1057
+ referencedPackages.push(packageName);
1058
+ }
1059
+ }
1060
+ return pipe(
1061
+ referencedPackages.concat(packageJsonScope?.referencedPackages || []),
1062
+ dedupe,
1063
+ map3((packageName) => packageName.toLowerCase()),
1064
+ filter(
1065
+ (packageName) => pattern.endsWith("*") && packageName.startsWith(pattern.toLowerCase().substring(0, pattern.length - 1))
1066
+ )
1067
+ );
1068
+ }
1069
+ );
1040
1070
  function makeGetModuleSpecifier(ts) {
1041
1071
  if (!(hasProperty(ts, "moduleSpecifiers") && hasProperty(ts.moduleSpecifiers, "getModuleSpecifier") && isFunction2(ts.moduleSpecifiers.getModuleSpecifier))) return;
1042
1072
  const _internal = ts.moduleSpecifiers.getModuleSpecifier;
@@ -2631,7 +2661,14 @@ var importFromBarrel = createDiagnostic({
2631
2661
  const ts = yield* service(TypeScriptApi);
2632
2662
  const typeChecker = yield* service(TypeCheckerApi);
2633
2663
  const program = yield* service(TypeScriptProgram);
2634
- const isImportedFromBarrelExport = (element, languageServicePluginOptions2) => {
2664
+ const packageNamesToCheck = flatten(
2665
+ yield* all(
2666
+ ...languageServicePluginOptions.namespaceImportPackages.map(
2667
+ (packageName) => resolveModulePattern(sourceFile, packageName)
2668
+ )
2669
+ )
2670
+ );
2671
+ const isImportedFromBarrelExport = (element) => {
2635
2672
  const getModuleSpecifier = makeGetModuleSpecifier(ts);
2636
2673
  const resolveExternalModuleName = makeResolveExternalModuleName(typeChecker);
2637
2674
  if (!(getModuleSpecifier && resolveExternalModuleName)) return;
@@ -2644,7 +2681,7 @@ var importFromBarrel = createDiagnostic({
2644
2681
  if (!namedBindings) return;
2645
2682
  if (!ts.isNamedImports(namedBindings)) return;
2646
2683
  const barrelModuleName = importDeclaration.moduleSpecifier.text;
2647
- if (languageServicePluginOptions2.namespaceImportPackages.indexOf(barrelModuleName.toLowerCase()) === -1) return;
2684
+ if (packageNamesToCheck.indexOf(barrelModuleName.toLowerCase()) === -1) return;
2648
2685
  const moduleSymbol = resolveExternalModuleName(importDeclaration.moduleSpecifier);
2649
2686
  if (!moduleSymbol) return;
2650
2687
  if (!moduleSymbol.exports) return;
@@ -2687,7 +2724,7 @@ var importFromBarrel = createDiagnostic({
2687
2724
  ts.forEachChild(node, appendNodeToVisit);
2688
2725
  continue;
2689
2726
  }
2690
- const result = isImportedFromBarrelExport(node, languageServicePluginOptions);
2727
+ const result = isImportedFromBarrelExport(node);
2691
2728
  if (!result) continue;
2692
2729
  const { barrelModuleName, importClause, importDeclaration, importedName, namedBindings, unbarrelledFileName } = result;
2693
2730
  report({
@@ -3496,61 +3533,73 @@ var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(functi
3496
3533
  const excludedByFileName = /* @__PURE__ */ new Map();
3497
3534
  const unbarreledModulePathByFileName = /* @__PURE__ */ new Map();
3498
3535
  const barreledModulePathByFileName = /* @__PURE__ */ new Map();
3536
+ const barreledFunctionPathByFileName = /* @__PURE__ */ new Map();
3499
3537
  const packages = [
3500
- ...languageServicePluginOptions.namespaceImportPackages.map((packageName) => ({
3501
- packageName,
3538
+ ...languageServicePluginOptions.namespaceImportPackages.map((packagePattern) => ({
3539
+ packagePattern,
3502
3540
  kind: "namespace"
3503
3541
  })),
3504
- ...languageServicePluginOptions.barrelImportPackages.map((packageName) => ({
3505
- packageName,
3542
+ ...languageServicePluginOptions.barrelImportPackages.map((packagePattern) => ({
3543
+ packagePattern,
3506
3544
  kind: "barrel"
3507
3545
  }))
3508
3546
  ];
3509
- for (const { kind, packageName } of packages) {
3510
- const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
3511
- if (barrelModule.resolvedModule) {
3512
- const barrelPath = barrelModule.resolvedModule.resolvedFileName;
3513
- const barrelSource = program.getSourceFile(barrelPath) || ts.createSourceFile(barrelPath, host.readFile(barrelPath) || "", sourceFile.languageVersion, true);
3514
- if (barrelSource) {
3515
- for (const statement of barrelSource.statements) {
3516
- if (ts.isExportDeclaration(statement)) {
3517
- const exportClause = statement.exportClause;
3518
- const moduleSpecifier = statement.moduleSpecifier;
3519
- if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
3520
- const unbarreledModulePathResolved = ts.resolveModuleName(
3521
- moduleSpecifier.text,
3522
- barrelSource.fileName,
3523
- program.getCompilerOptions(),
3524
- host
3525
- );
3526
- if (unbarreledModulePathResolved.resolvedModule) {
3527
- const unbarreledModulePath = unbarreledModulePathResolved.resolvedModule.resolvedFileName;
3528
- if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
3529
- if (kind === "namespace") {
3530
- namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
3531
- const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
3532
- existingUnbarreledModulePath.push({
3533
- fileName: unbarreledModulePath,
3534
- exportName: exportClause.name.text
3535
- });
3536
- unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
3537
- }
3538
- if (kind === "barrel") {
3539
- barreledModulePathByFileName.set(unbarreledModulePath, {
3540
- fileName: barrelSource.fileName,
3541
- exportName: exportClause.name.text,
3542
- packageName
3543
- });
3544
- }
3545
- }
3546
- if (exportClause && ts.isNamedExports(exportClause)) {
3547
- for (const element of exportClause.elements) {
3548
- if (!ts.isIdentifier(element.name)) continue;
3549
- const methodName = element.name.text;
3547
+ for (const { kind, packagePattern } of packages) {
3548
+ for (const packageName of yield* resolveModulePattern(sourceFile, packagePattern)) {
3549
+ const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
3550
+ if (barrelModule.resolvedModule) {
3551
+ const barrelPath = barrelModule.resolvedModule.resolvedFileName;
3552
+ const barrelSource = program.getSourceFile(barrelPath) || ts.createSourceFile(barrelPath, host.readFile(barrelPath) || "", sourceFile.languageVersion, true);
3553
+ if (barrelSource) {
3554
+ for (const statement of barrelSource.statements) {
3555
+ if (ts.isExportDeclaration(statement)) {
3556
+ const exportClause = statement.exportClause;
3557
+ const moduleSpecifier = statement.moduleSpecifier;
3558
+ if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
3559
+ const unbarreledModulePathResolved = ts.resolveModuleName(
3560
+ moduleSpecifier.text,
3561
+ barrelSource.fileName,
3562
+ program.getCompilerOptions(),
3563
+ host
3564
+ );
3565
+ if (unbarreledModulePathResolved.resolvedModule) {
3566
+ const unbarreledModulePath = unbarreledModulePathResolved.resolvedModule.resolvedFileName;
3567
+ if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
3550
3568
  if (kind === "namespace") {
3551
- const excludedMethods = excludedByFileName.get(methodName) || [];
3552
- excludedMethods.push(unbarreledModulePath);
3553
- excludedByFileName.set(methodName, excludedMethods);
3569
+ namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
3570
+ const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
3571
+ existingUnbarreledModulePath.push({
3572
+ fileName: unbarreledModulePath,
3573
+ exportName: exportClause.name.text
3574
+ });
3575
+ unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
3576
+ }
3577
+ if (kind === "barrel") {
3578
+ barreledModulePathByFileName.set(unbarreledModulePath, {
3579
+ fileName: barrelSource.fileName,
3580
+ exportName: exportClause.name.text,
3581
+ packageName
3582
+ });
3583
+ }
3584
+ }
3585
+ if (exportClause && ts.isNamedExports(exportClause)) {
3586
+ for (const element of exportClause.elements) {
3587
+ if (!ts.isIdentifier(element.name)) continue;
3588
+ const methodName = element.name.text;
3589
+ if (kind === "namespace") {
3590
+ const excludedMethods = excludedByFileName.get(methodName) || [];
3591
+ excludedMethods.push(unbarreledModulePath);
3592
+ excludedByFileName.set(methodName, excludedMethods);
3593
+ }
3594
+ if (kind === "barrel") {
3595
+ const previousBarreledFunctionPath = barreledFunctionPathByFileName.get(unbarreledModulePath) || [];
3596
+ previousBarreledFunctionPath.push({
3597
+ fileName: barrelSource.fileName,
3598
+ exportName: methodName,
3599
+ packageName
3600
+ });
3601
+ barreledFunctionPathByFileName.set(unbarreledModulePath, previousBarreledFunctionPath);
3602
+ }
3554
3603
  }
3555
3604
  }
3556
3605
  }
@@ -3565,7 +3614,8 @@ var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(functi
3565
3614
  getImportNamespaceByFileName: (fileName) => namespaceByFileName.get(fileName),
3566
3615
  isExcludedFromNamespaceImport: (fileName, exportName) => (excludedByFileName.get(exportName) || []).includes(fileName),
3567
3616
  getUnbarreledModulePath: (fileName, exportName) => unbarreledModulePathByFileName.get(fileName)?.find((_) => _.exportName === exportName)?.fileName,
3568
- getBarreledModulePath: (fileName) => barreledModulePathByFileName.get(fileName)
3617
+ getBarreledModulePath: (fileName) => barreledModulePathByFileName.get(fileName),
3618
+ getBarreledFunctionPath: (fileName, exportName) => barreledFunctionPathByFileName.get(fileName)?.find((_) => _.exportName === exportName)
3569
3619
  };
3570
3620
  });
3571
3621
  var appendEffectCompletionEntryData = fn("appendEffectCompletionEntryData")(
@@ -3665,7 +3715,7 @@ var getImportFromNamespaceCodeActions = fn("getImportFromNamespaceCodeActions")(
3665
3715
  }
3666
3716
  ];
3667
3717
  });
3668
- var getImportFromBarrelCodeActions = fn("getImportFromBarrelCodeActions")(function* (formatOptions, preferences, languageServiceHost, sourceFile, effectReplaceSpan, newModuleSpecifier, barrelExportName) {
3718
+ var getImportFromBarrelCodeActions = fn("getImportFromBarrelCodeActions")(function* (formatOptions, preferences, languageServiceHost, sourceFile, effectReplaceSpan, newModuleSpecifier, barrelExportName, shouldPrependExportName) {
3669
3719
  const ts = yield* service(TypeScriptApi);
3670
3720
  const formatContext = ts.formatting.getFormatContext(
3671
3721
  formatOptions || {},
@@ -3729,11 +3779,13 @@ var getImportFromBarrelCodeActions = fn("getImportFromBarrelCodeActions")(functi
3729
3779
  preferences || {}
3730
3780
  );
3731
3781
  }
3732
- changeTracker.insertText(
3733
- sourceFile,
3734
- effectReplaceSpan.start,
3735
- barrelExportName + "."
3736
- );
3782
+ if (shouldPrependExportName) {
3783
+ changeTracker.insertText(
3784
+ sourceFile,
3785
+ effectReplaceSpan.start,
3786
+ barrelExportName + "."
3787
+ );
3788
+ }
3737
3789
  }
3738
3790
  );
3739
3791
  return [
@@ -3772,16 +3824,34 @@ var postprocessCompletionEntryDetails = fn("postprocessCompletionEntryDetails")(
3772
3824
  exportName
3773
3825
  );
3774
3826
  if (isExcluded) return applicableCompletionEntryDetails;
3775
- const asBarrelImport = packagesMetadata.getBarreledModulePath(fileName);
3776
- if (asBarrelImport) {
3827
+ const asBarrelFunctionImport = packagesMetadata.getBarreledFunctionPath(fileName, exportName);
3828
+ if (asBarrelFunctionImport) {
3829
+ const codeActions = yield* getImportFromBarrelCodeActions(
3830
+ formatOptions,
3831
+ preferences,
3832
+ languageServiceHost,
3833
+ sourceFile,
3834
+ effectReplaceSpan,
3835
+ asBarrelFunctionImport.packageName,
3836
+ asBarrelFunctionImport.exportName,
3837
+ false
3838
+ );
3839
+ return {
3840
+ ...applicableCompletionEntryDetails,
3841
+ codeActions
3842
+ };
3843
+ }
3844
+ const asBarrelModuleImport = packagesMetadata.getBarreledModulePath(fileName);
3845
+ if (asBarrelModuleImport) {
3777
3846
  const codeActions = yield* getImportFromBarrelCodeActions(
3778
3847
  formatOptions,
3779
3848
  preferences,
3780
3849
  languageServiceHost,
3781
3850
  sourceFile,
3782
3851
  effectReplaceSpan,
3783
- asBarrelImport.packageName,
3784
- asBarrelImport.exportName
3852
+ asBarrelModuleImport.packageName,
3853
+ asBarrelModuleImport.exportName,
3854
+ true
3785
3855
  );
3786
3856
  return {
3787
3857
  ...applicableCompletionEntryDetails,