@effect/language-service 0.23.3 → 0.23.5

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,12 +2681,14 @@ 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;
2651
2688
  const sourceFile2 = importDeclaration.getSourceFile();
2652
2689
  const nodeForSymbol = element.propertyName || element.name;
2690
+ const aliasSymbol = element.name || element.propertyName;
2691
+ const aliasedName = aliasSymbol.text;
2653
2692
  if (!ts.isIdentifier(nodeForSymbol)) return;
2654
2693
  const importedName = nodeForSymbol.text;
2655
2694
  const reexportedSymbol = moduleSymbol.exports.get(ts.escapeLeadingUnderscores(importedName));
@@ -2672,7 +2711,15 @@ var importFromBarrel = createDiagnostic({
2672
2711
  program
2673
2712
  );
2674
2713
  if (unbarrelledFileName.toLowerCase().indexOf(barrelModuleName.toLowerCase() + "/") === -1) return;
2675
- return { unbarrelledFileName, importedName, barrelModuleName, importClause, namedBindings, importDeclaration };
2714
+ return {
2715
+ unbarrelledFileName,
2716
+ importedName,
2717
+ barrelModuleName,
2718
+ importClause,
2719
+ namedBindings,
2720
+ importDeclaration,
2721
+ aliasedName
2722
+ };
2676
2723
  };
2677
2724
  const nodeToVisit = [];
2678
2725
  const appendNodeToVisit = (node) => {
@@ -2687,16 +2734,23 @@ var importFromBarrel = createDiagnostic({
2687
2734
  ts.forEachChild(node, appendNodeToVisit);
2688
2735
  continue;
2689
2736
  }
2690
- const result = isImportedFromBarrelExport(node, languageServicePluginOptions);
2737
+ const result = isImportedFromBarrelExport(node);
2691
2738
  if (!result) continue;
2692
- const { barrelModuleName, importClause, importDeclaration, importedName, namedBindings, unbarrelledFileName } = result;
2739
+ const {
2740
+ aliasedName,
2741
+ barrelModuleName,
2742
+ importClause,
2743
+ importDeclaration,
2744
+ namedBindings,
2745
+ unbarrelledFileName
2746
+ } = result;
2693
2747
  report({
2694
2748
  node,
2695
2749
  messageText: `Importing from barrel module ${barrelModuleName} is not allowed.`,
2696
2750
  fixes: [
2697
2751
  {
2698
2752
  fixName: "replaceWithUnbarrelledImport",
2699
- description: `Import * as ${importedName} from ${unbarrelledFileName}`,
2753
+ description: `Import * as ${aliasedName} from ${unbarrelledFileName}`,
2700
2754
  apply: gen(function* () {
2701
2755
  const changeTracker = yield* service(ChangeTracker);
2702
2756
  const newImport = ts.factory.createImportDeclaration(
@@ -2704,7 +2758,7 @@ var importFromBarrel = createDiagnostic({
2704
2758
  ts.factory.createImportClause(
2705
2759
  importClause.isTypeOnly || node.isTypeOnly,
2706
2760
  void 0,
2707
- ts.factory.createNamespaceImport(ts.factory.createIdentifier(importedName))
2761
+ ts.factory.createNamespaceImport(ts.factory.createIdentifier(aliasedName))
2708
2762
  ),
2709
2763
  ts.factory.createStringLiteral(unbarrelledFileName)
2710
2764
  );
@@ -3498,69 +3552,71 @@ var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(functi
3498
3552
  const barreledModulePathByFileName = /* @__PURE__ */ new Map();
3499
3553
  const barreledFunctionPathByFileName = /* @__PURE__ */ new Map();
3500
3554
  const packages = [
3501
- ...languageServicePluginOptions.namespaceImportPackages.map((packageName) => ({
3502
- packageName,
3555
+ ...languageServicePluginOptions.namespaceImportPackages.map((packagePattern) => ({
3556
+ packagePattern,
3503
3557
  kind: "namespace"
3504
3558
  })),
3505
- ...languageServicePluginOptions.barrelImportPackages.map((packageName) => ({
3506
- packageName,
3559
+ ...languageServicePluginOptions.barrelImportPackages.map((packagePattern) => ({
3560
+ packagePattern,
3507
3561
  kind: "barrel"
3508
3562
  }))
3509
3563
  ];
3510
- for (const { kind, packageName } of packages) {
3511
- const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
3512
- if (barrelModule.resolvedModule) {
3513
- const barrelPath = barrelModule.resolvedModule.resolvedFileName;
3514
- const barrelSource = program.getSourceFile(barrelPath) || ts.createSourceFile(barrelPath, host.readFile(barrelPath) || "", sourceFile.languageVersion, true);
3515
- if (barrelSource) {
3516
- for (const statement of barrelSource.statements) {
3517
- if (ts.isExportDeclaration(statement)) {
3518
- const exportClause = statement.exportClause;
3519
- const moduleSpecifier = statement.moduleSpecifier;
3520
- if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
3521
- const unbarreledModulePathResolved = ts.resolveModuleName(
3522
- moduleSpecifier.text,
3523
- barrelSource.fileName,
3524
- program.getCompilerOptions(),
3525
- host
3526
- );
3527
- if (unbarreledModulePathResolved.resolvedModule) {
3528
- const unbarreledModulePath = unbarreledModulePathResolved.resolvedModule.resolvedFileName;
3529
- if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
3530
- if (kind === "namespace") {
3531
- namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
3532
- const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
3533
- existingUnbarreledModulePath.push({
3534
- fileName: unbarreledModulePath,
3535
- exportName: exportClause.name.text
3536
- });
3537
- unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
3538
- }
3539
- if (kind === "barrel") {
3540
- barreledModulePathByFileName.set(unbarreledModulePath, {
3541
- fileName: barrelSource.fileName,
3542
- exportName: exportClause.name.text,
3543
- packageName
3544
- });
3545
- }
3546
- }
3547
- if (exportClause && ts.isNamedExports(exportClause)) {
3548
- for (const element of exportClause.elements) {
3549
- if (!ts.isIdentifier(element.name)) continue;
3550
- const methodName = element.name.text;
3564
+ for (const { kind, packagePattern } of packages) {
3565
+ for (const packageName of yield* resolveModulePattern(sourceFile, packagePattern)) {
3566
+ const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
3567
+ if (barrelModule.resolvedModule) {
3568
+ const barrelPath = barrelModule.resolvedModule.resolvedFileName;
3569
+ const barrelSource = program.getSourceFile(barrelPath) || ts.createSourceFile(barrelPath, host.readFile(barrelPath) || "", sourceFile.languageVersion, true);
3570
+ if (barrelSource) {
3571
+ for (const statement of barrelSource.statements) {
3572
+ if (ts.isExportDeclaration(statement)) {
3573
+ const exportClause = statement.exportClause;
3574
+ const moduleSpecifier = statement.moduleSpecifier;
3575
+ if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
3576
+ const unbarreledModulePathResolved = ts.resolveModuleName(
3577
+ moduleSpecifier.text,
3578
+ barrelSource.fileName,
3579
+ program.getCompilerOptions(),
3580
+ host
3581
+ );
3582
+ if (unbarreledModulePathResolved.resolvedModule) {
3583
+ const unbarreledModulePath = unbarreledModulePathResolved.resolvedModule.resolvedFileName;
3584
+ if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
3551
3585
  if (kind === "namespace") {
3552
- const excludedMethods = excludedByFileName.get(methodName) || [];
3553
- excludedMethods.push(unbarreledModulePath);
3554
- excludedByFileName.set(methodName, excludedMethods);
3586
+ namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
3587
+ const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
3588
+ existingUnbarreledModulePath.push({
3589
+ fileName: unbarreledModulePath,
3590
+ exportName: exportClause.name.text
3591
+ });
3592
+ unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
3555
3593
  }
3556
3594
  if (kind === "barrel") {
3557
- const previousBarreledFunctionPath = barreledFunctionPathByFileName.get(unbarreledModulePath) || [];
3558
- previousBarreledFunctionPath.push({
3595
+ barreledModulePathByFileName.set(unbarreledModulePath, {
3559
3596
  fileName: barrelSource.fileName,
3560
- exportName: methodName,
3597
+ exportName: exportClause.name.text,
3561
3598
  packageName
3562
3599
  });
3563
- barreledFunctionPathByFileName.set(unbarreledModulePath, previousBarreledFunctionPath);
3600
+ }
3601
+ }
3602
+ if (exportClause && ts.isNamedExports(exportClause)) {
3603
+ for (const element of exportClause.elements) {
3604
+ if (!ts.isIdentifier(element.name)) continue;
3605
+ const methodName = element.name.text;
3606
+ if (kind === "namespace") {
3607
+ const excludedMethods = excludedByFileName.get(methodName) || [];
3608
+ excludedMethods.push(unbarreledModulePath);
3609
+ excludedByFileName.set(methodName, excludedMethods);
3610
+ }
3611
+ if (kind === "barrel") {
3612
+ const previousBarreledFunctionPath = barreledFunctionPathByFileName.get(unbarreledModulePath) || [];
3613
+ previousBarreledFunctionPath.push({
3614
+ fileName: barrelSource.fileName,
3615
+ exportName: methodName,
3616
+ packageName
3617
+ });
3618
+ barreledFunctionPathByFileName.set(unbarreledModulePath, previousBarreledFunctionPath);
3619
+ }
3564
3620
  }
3565
3621
  }
3566
3622
  }