@effect/language-service 0.22.0 → 0.22.2
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 +1 -0
- package/index.js +1118 -1075
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +73 -65
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -729,6 +729,7 @@ var getOrElse = /* @__PURE__ */ dual(2, (self, onLeft) => isLeft2(self) ? onLeft
|
|
|
729
729
|
|
|
730
730
|
// node_modules/.pnpm/effect@3.16.5/node_modules/effect/dist/esm/Order.js
|
|
731
731
|
var make2 = (compare) => (self, that) => self === that ? 0 : compare(self, that);
|
|
732
|
+
var string2 = /* @__PURE__ */ make2((self, that) => self < that ? -1 : 1);
|
|
732
733
|
|
|
733
734
|
// node_modules/.pnpm/effect@3.16.5/node_modules/effect/dist/esm/Option.js
|
|
734
735
|
var none2 = () => none;
|
|
@@ -832,29 +833,11 @@ var dedupeWith = /* @__PURE__ */ dual(2, (self, isEquivalent) => {
|
|
|
832
833
|
});
|
|
833
834
|
|
|
834
835
|
// src/core/Nano.ts
|
|
835
|
-
var NanoInternalSuccessProto = {
|
|
836
|
-
_tag: "Right"
|
|
837
|
-
};
|
|
838
836
|
function makeInternalSuccess(value) {
|
|
839
|
-
|
|
840
|
-
result.value = value;
|
|
841
|
-
return result;
|
|
842
|
-
}
|
|
843
|
-
var NanoInternalFailureProto = {
|
|
844
|
-
_tag: "Left"
|
|
845
|
-
};
|
|
846
|
-
function makeInternalFailure(value) {
|
|
847
|
-
const result = Object.create(NanoInternalFailureProto);
|
|
848
|
-
result.value = value;
|
|
849
|
-
return result;
|
|
837
|
+
return { _tag: "Right", value };
|
|
850
838
|
}
|
|
851
|
-
var NanoInternalDefectProto = {
|
|
852
|
-
_tag: "Defect"
|
|
853
|
-
};
|
|
854
839
|
function makeInternalDefect(value) {
|
|
855
|
-
|
|
856
|
-
result.value = value;
|
|
857
|
-
return result;
|
|
840
|
+
return { _tag: "Defect", value };
|
|
858
841
|
}
|
|
859
842
|
var NanoDefectException = class {
|
|
860
843
|
constructor(message) {
|
|
@@ -869,17 +852,14 @@ var NanoTag = class {
|
|
|
869
852
|
};
|
|
870
853
|
var Tag = (identifier) => new NanoTag(identifier);
|
|
871
854
|
var contextEmpty = { value: {} };
|
|
872
|
-
var Proto = {
|
|
873
|
-
run: () => {
|
|
874
|
-
},
|
|
875
|
-
[Symbol.iterator]() {
|
|
876
|
-
return new SingleShotGen(new YieldWrap(this));
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
855
|
function make3(run2) {
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
856
|
+
const nano = {
|
|
857
|
+
run: run2,
|
|
858
|
+
[Symbol.iterator]() {
|
|
859
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
return nano;
|
|
883
863
|
}
|
|
884
864
|
var unsafeRun = (fa) => {
|
|
885
865
|
const program = provideService(internalNanoCache, {})(fa);
|
|
@@ -900,9 +880,33 @@ var run = (fa) => {
|
|
|
900
880
|
return left2(new NanoDefectException(e));
|
|
901
881
|
}
|
|
902
882
|
};
|
|
903
|
-
var succeed = (value) =>
|
|
904
|
-
|
|
905
|
-
|
|
883
|
+
var succeed = (value) => {
|
|
884
|
+
const nano = {
|
|
885
|
+
run: () => ({ _tag: "Right", value }),
|
|
886
|
+
[Symbol.iterator]() {
|
|
887
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
return nano;
|
|
891
|
+
};
|
|
892
|
+
var fail = (value) => {
|
|
893
|
+
const nano = {
|
|
894
|
+
run: () => ({ _tag: "Left", value }),
|
|
895
|
+
[Symbol.iterator]() {
|
|
896
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
return nano;
|
|
900
|
+
};
|
|
901
|
+
var sync = (value) => {
|
|
902
|
+
const nano = {
|
|
903
|
+
run: () => ({ _tag: "Right", value: value() }),
|
|
904
|
+
[Symbol.iterator]() {
|
|
905
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
return nano;
|
|
909
|
+
};
|
|
906
910
|
var flatMap2 = dual(2, (fa, f) => make3((ctx) => {
|
|
907
911
|
const result = fa.run(ctx);
|
|
908
912
|
if (result._tag !== "Right") return result;
|
|
@@ -995,8 +999,9 @@ function cachedBy(fa, key, lookupKey) {
|
|
|
995
999
|
cacheObj[key] = cache;
|
|
996
1000
|
}
|
|
997
1001
|
const lookup = lookupKey(...args);
|
|
998
|
-
|
|
999
|
-
|
|
1002
|
+
const cached2 = cache.get(lookup);
|
|
1003
|
+
if (cached2 !== void 0) {
|
|
1004
|
+
return cached2;
|
|
1000
1005
|
}
|
|
1001
1006
|
const result = fa(...args).run(ctx);
|
|
1002
1007
|
cache.set(lookup, result);
|
|
@@ -1728,122 +1733,347 @@ var effectDataClasses = createCompletion({
|
|
|
1728
1733
|
})
|
|
1729
1734
|
});
|
|
1730
1735
|
|
|
1731
|
-
// src/
|
|
1732
|
-
var
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
const
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
)
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
replacementSpan,
|
|
1771
|
-
isSnippet: true
|
|
1772
|
-
}, {
|
|
1773
|
-
name: `TaggedRequest<${name}>`,
|
|
1774
|
-
kind: ts.ScriptElementKind.constElement,
|
|
1775
|
-
insertText: `${schemaIdentifier}.TaggedRequest<${name}>("${name}")("${name}", {${"${0}"}}){}`,
|
|
1776
|
-
replacementSpan,
|
|
1777
|
-
isSnippet: true
|
|
1778
|
-
}];
|
|
1779
|
-
})
|
|
1780
|
-
});
|
|
1736
|
+
// src/diagnostics/duplicatePackage.ts
|
|
1737
|
+
var checkedPackagesCache = /* @__PURE__ */ new Map();
|
|
1738
|
+
var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
1739
|
+
var duplicatePackage = createDiagnostic({
|
|
1740
|
+
name: "duplicatePackage",
|
|
1741
|
+
code: 6,
|
|
1742
|
+
severity: "warning",
|
|
1743
|
+
apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
1744
|
+
const program = yield* service(TypeScriptProgram);
|
|
1745
|
+
const options = yield* service(LanguageServicePluginOptions);
|
|
1746
|
+
if (sourceFile.statements.length < 1) return;
|
|
1747
|
+
let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
|
|
1748
|
+
const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
|
|
1749
|
+
const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
|
|
1750
|
+
if (newResolvedModuleSize !== oldResolvedSize) {
|
|
1751
|
+
const seenPackages = /* @__PURE__ */ new Set();
|
|
1752
|
+
resolvedPackages = {};
|
|
1753
|
+
program.getSourceFiles().map((_) => {
|
|
1754
|
+
const packageInfo = parsePackageContentNameAndVersionFromScope(_);
|
|
1755
|
+
if (!packageInfo) return;
|
|
1756
|
+
const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
|
|
1757
|
+
if (seenPackages.has(packageNameAndVersion)) return;
|
|
1758
|
+
seenPackages.add(packageNameAndVersion);
|
|
1759
|
+
if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
|
|
1760
|
+
if (options.allowedDuplicatedPackages.indexOf(packageInfo.name) > -1) return;
|
|
1761
|
+
resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
|
|
1762
|
+
resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.packageDirectory;
|
|
1763
|
+
});
|
|
1764
|
+
checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
|
|
1765
|
+
programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
|
|
1766
|
+
}
|
|
1767
|
+
for (const packageName of Object.keys(resolvedPackages)) {
|
|
1768
|
+
if (Object.keys(resolvedPackages[packageName]).length > 1) {
|
|
1769
|
+
const versions = Object.keys(resolvedPackages[packageName]);
|
|
1770
|
+
report({
|
|
1771
|
+
node: sourceFile.statements[0],
|
|
1772
|
+
messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
|
|
1773
|
+
Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
|
|
1774
|
+
If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
1781
1775
|
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
const maybeInfos = yield* option(
|
|
1788
|
-
parseDataForExtendsClassCompletion(sourceFile, position)
|
|
1789
|
-
);
|
|
1790
|
-
if (isNone2(maybeInfos)) return [];
|
|
1791
|
-
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
1792
|
-
const effectName = yield* option(
|
|
1793
|
-
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
1794
|
-
sourceFile,
|
|
1795
|
-
"effect",
|
|
1796
|
-
"Effect"
|
|
1797
|
-
)
|
|
1798
|
-
);
|
|
1799
|
-
const effectIdentifier = match(effectName, {
|
|
1800
|
-
onNone: () => "Effect",
|
|
1801
|
-
onSome: (_) => _.text
|
|
1802
|
-
});
|
|
1803
|
-
if (effectIdentifier !== accessedObject.text) return [];
|
|
1804
|
-
const name = className.text;
|
|
1805
|
-
return [{
|
|
1806
|
-
name: `Service<${name}>`,
|
|
1807
|
-
kind: ts.ScriptElementKind.constElement,
|
|
1808
|
-
insertText: `${effectIdentifier}.Service<${name}>()("${name}", {${"${0}"}}){}`,
|
|
1809
|
-
replacementSpan,
|
|
1810
|
-
isSnippet: true
|
|
1811
|
-
}];
|
|
1776
|
+
${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
|
|
1777
|
+
fixes: []
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1812
1781
|
})
|
|
1813
1782
|
});
|
|
1814
1783
|
|
|
1815
|
-
// src/core/
|
|
1816
|
-
var
|
|
1817
|
-
var
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
const
|
|
1827
|
-
|
|
1828
|
-
|
|
1784
|
+
// src/core/TypeCheckerApi.ts
|
|
1785
|
+
var TypeCheckerApi = Tag("TypeChecker");
|
|
1786
|
+
var TypeCheckerApiCache = Tag("TypeCheckerApiCache");
|
|
1787
|
+
function makeTypeCheckerApiCache() {
|
|
1788
|
+
return {
|
|
1789
|
+
expectedAndRealType: /* @__PURE__ */ new WeakMap()
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
var deterministicTypeOrder = gen(function* () {
|
|
1793
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
1794
|
+
return make2((a, b) => {
|
|
1795
|
+
const aName = typeChecker.typeToString(a);
|
|
1796
|
+
const bName = typeChecker.typeToString(b);
|
|
1797
|
+
if (aName < bName) return -1;
|
|
1798
|
+
if (aName > bName) return 1;
|
|
1799
|
+
return 0;
|
|
1800
|
+
});
|
|
1801
|
+
});
|
|
1802
|
+
var getMissingTypeEntriesInTargetType = fn(
|
|
1803
|
+
"TypeCheckerApi.getMissingTypeEntriesInTargetType"
|
|
1804
|
+
)(
|
|
1805
|
+
function* (realType, expectedType) {
|
|
1806
|
+
if (realType === expectedType) return [];
|
|
1807
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
1808
|
+
const result = [];
|
|
1809
|
+
let toTest = [realType];
|
|
1810
|
+
while (toTest.length > 0) {
|
|
1811
|
+
const type = toTest.pop();
|
|
1812
|
+
if (!type) return result;
|
|
1813
|
+
if (type.isUnion()) {
|
|
1814
|
+
toTest = toTest.concat(type.types);
|
|
1815
|
+
} else {
|
|
1816
|
+
const assignable = typeChecker.isTypeAssignableTo(type, expectedType);
|
|
1817
|
+
if (!assignable) {
|
|
1818
|
+
result.push(type);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1829
1821
|
}
|
|
1830
|
-
return
|
|
1822
|
+
return result;
|
|
1831
1823
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1824
|
+
);
|
|
1825
|
+
var CannotFindAncestorConvertibleDeclarationError = class {
|
|
1826
|
+
constructor(node) {
|
|
1827
|
+
this.node = node;
|
|
1828
|
+
}
|
|
1829
|
+
_tag = "@effect/language-service/CannotFindAncestorConvertibleDeclarationError";
|
|
1830
|
+
};
|
|
1831
|
+
var getAncestorConvertibleDeclaration = fn(
|
|
1832
|
+
"TypeCheckerApi.getAncestorConvertibleDeclaration"
|
|
1833
|
+
)(function* (node) {
|
|
1834
|
+
const ts = yield* service(TypeScriptApi);
|
|
1835
|
+
let current = node;
|
|
1836
|
+
while (current) {
|
|
1837
|
+
if (ts.isFunctionDeclaration(current) || ts.isFunctionExpression(current) || ts.isArrowFunction(current) || ts.isMethodDeclaration(current)) {
|
|
1838
|
+
return current;
|
|
1836
1839
|
}
|
|
1837
|
-
|
|
1840
|
+
current = current.parent;
|
|
1838
1841
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1842
|
+
return yield* fail(new CannotFindAncestorConvertibleDeclarationError(node));
|
|
1843
|
+
});
|
|
1844
|
+
var CannotInferReturnTypeFromEmptyBody = class {
|
|
1845
|
+
constructor(declaration) {
|
|
1846
|
+
this.declaration = declaration;
|
|
1847
|
+
}
|
|
1848
|
+
_tag = "@effect/language-service/CannotInferReturnTypeFromEmptyBody";
|
|
1849
|
+
};
|
|
1850
|
+
var CannotInferReturnType = class {
|
|
1851
|
+
constructor(declaration) {
|
|
1852
|
+
this.declaration = declaration;
|
|
1853
|
+
}
|
|
1854
|
+
_tag = "@effect/language-service/CannotInferReturnType";
|
|
1855
|
+
};
|
|
1856
|
+
var getInferredReturnType = fn("TypeCheckerApi.getInferredReturnType")(function* (declaration) {
|
|
1857
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
1858
|
+
if (!declaration.body) {
|
|
1859
|
+
return yield* fail(
|
|
1860
|
+
new CannotInferReturnTypeFromEmptyBody(declaration)
|
|
1861
|
+
);
|
|
1862
|
+
}
|
|
1863
|
+
let returnType;
|
|
1864
|
+
if (typeChecker.isImplementationOfOverload(declaration)) {
|
|
1865
|
+
const signatures = typeChecker.getTypeAtLocation(declaration).getCallSignatures();
|
|
1866
|
+
if (signatures.length > 1) {
|
|
1867
|
+
returnType = typeChecker.getUnionType(
|
|
1868
|
+
signatures.map((s) => s.getReturnType()).filter((_) => !!_)
|
|
1869
|
+
);
|
|
1843
1870
|
}
|
|
1844
|
-
return succeed(signatures[0].getReturnType());
|
|
1845
1871
|
}
|
|
1846
|
-
|
|
1872
|
+
if (!returnType) {
|
|
1873
|
+
const signature = typeChecker.getSignatureFromDeclaration(declaration);
|
|
1874
|
+
if (signature) {
|
|
1875
|
+
const typePredicate = typeChecker.getTypePredicateOfSignature(signature);
|
|
1876
|
+
if (typePredicate && typePredicate.type) {
|
|
1877
|
+
return typePredicate.type;
|
|
1878
|
+
} else {
|
|
1879
|
+
returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
if (!returnType) {
|
|
1884
|
+
return yield* fail(
|
|
1885
|
+
new CannotInferReturnType(declaration)
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
return returnType;
|
|
1889
|
+
});
|
|
1890
|
+
var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (sourceFile) {
|
|
1891
|
+
const cache = yield* service(TypeCheckerApiCache);
|
|
1892
|
+
const resultCached = cache.expectedAndRealType.get(sourceFile);
|
|
1893
|
+
if (resultCached) return resultCached;
|
|
1894
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
1895
|
+
const ts = yield* service(TypeScriptApi);
|
|
1896
|
+
const result = [];
|
|
1897
|
+
const nodeToVisit = [sourceFile];
|
|
1898
|
+
const appendNodeToVisit = (node) => {
|
|
1899
|
+
nodeToVisit.push(node);
|
|
1900
|
+
return void 0;
|
|
1901
|
+
};
|
|
1902
|
+
while (nodeToVisit.length > 0) {
|
|
1903
|
+
const node = nodeToVisit.shift();
|
|
1904
|
+
if (ts.isVariableDeclaration(node) && node.initializer) {
|
|
1905
|
+
const expectedType = typeChecker.getTypeAtLocation(node.name);
|
|
1906
|
+
const realType = typeChecker.getTypeAtLocation(node.initializer);
|
|
1907
|
+
result.push([node.name, expectedType, node.initializer, realType]);
|
|
1908
|
+
appendNodeToVisit(node.initializer);
|
|
1909
|
+
continue;
|
|
1910
|
+
} else if (ts.isCallExpression(node)) {
|
|
1911
|
+
const resolvedSignature = typeChecker.getResolvedSignature(node);
|
|
1912
|
+
if (resolvedSignature) {
|
|
1913
|
+
resolvedSignature.getParameters().map((parameter, index) => {
|
|
1914
|
+
const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
|
|
1915
|
+
const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
|
|
1916
|
+
result.push([
|
|
1917
|
+
node.arguments[index],
|
|
1918
|
+
expectedType,
|
|
1919
|
+
node.arguments[index],
|
|
1920
|
+
realType
|
|
1921
|
+
]);
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
1925
|
+
continue;
|
|
1926
|
+
} else if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
1927
|
+
const parent = node.parent;
|
|
1928
|
+
if (ts.isObjectLiteralElement(parent)) {
|
|
1929
|
+
if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
|
|
1930
|
+
const type = typeChecker.getContextualType(parent.parent);
|
|
1931
|
+
if (type) {
|
|
1932
|
+
const symbol3 = typeChecker.getPropertyOfType(type, node.text);
|
|
1933
|
+
if (symbol3) {
|
|
1934
|
+
const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
|
|
1935
|
+
const realType = typeChecker.getTypeAtLocation(node);
|
|
1936
|
+
result.push([node, expectedType, node, realType]);
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
1942
|
+
continue;
|
|
1943
|
+
} else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
1944
|
+
const expectedType = typeChecker.getTypeAtLocation(node.left);
|
|
1945
|
+
const realType = typeChecker.getTypeAtLocation(node.right);
|
|
1946
|
+
result.push([node.left, expectedType, node.right, realType]);
|
|
1947
|
+
appendNodeToVisit(node.right);
|
|
1948
|
+
continue;
|
|
1949
|
+
} else if (ts.isReturnStatement(node) && node.expression) {
|
|
1950
|
+
const parentDeclaration = yield* option(getAncestorConvertibleDeclaration(node));
|
|
1951
|
+
if (isSome2(parentDeclaration)) {
|
|
1952
|
+
const expectedType = yield* option(getInferredReturnType(parentDeclaration.value));
|
|
1953
|
+
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
1954
|
+
if (isSome2(expectedType)) {
|
|
1955
|
+
result.push([node, expectedType.value, node, realType]);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
1959
|
+
continue;
|
|
1960
|
+
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length === 0 && ts.isExpression(node.body)) {
|
|
1961
|
+
const body = node.body;
|
|
1962
|
+
const expectedType = typeChecker.getContextualType(body);
|
|
1963
|
+
const realType = typeChecker.getTypeAtLocation(body);
|
|
1964
|
+
if (expectedType) {
|
|
1965
|
+
result.push([body, expectedType, body, realType]);
|
|
1966
|
+
}
|
|
1967
|
+
ts.forEachChild(body, appendNodeToVisit);
|
|
1968
|
+
continue;
|
|
1969
|
+
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length > 0 && ts.isExpression(node.body)) {
|
|
1970
|
+
const body = node.body;
|
|
1971
|
+
const expectedType = yield* option(getInferredReturnType(node));
|
|
1972
|
+
const realType = typeChecker.getTypeAtLocation(body);
|
|
1973
|
+
if (isSome2(expectedType)) {
|
|
1974
|
+
result.push([body, expectedType.value, body, realType]);
|
|
1975
|
+
}
|
|
1976
|
+
ts.forEachChild(body, appendNodeToVisit);
|
|
1977
|
+
continue;
|
|
1978
|
+
} else if (ts.isSatisfiesExpression(node)) {
|
|
1979
|
+
const expectedType = typeChecker.getTypeAtLocation(node.type);
|
|
1980
|
+
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
1981
|
+
result.push([node.expression, expectedType, node.expression, realType]);
|
|
1982
|
+
appendNodeToVisit(node.expression);
|
|
1983
|
+
continue;
|
|
1984
|
+
}
|
|
1985
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
1986
|
+
}
|
|
1987
|
+
cache.expectedAndRealType.set(sourceFile, result);
|
|
1988
|
+
return result;
|
|
1989
|
+
});
|
|
1990
|
+
var appendToUniqueTypesMap = fn(
|
|
1991
|
+
"TypeCheckerApi.appendToUniqueTypesMap"
|
|
1992
|
+
)(
|
|
1993
|
+
function* (memory, initialType, excludeNever) {
|
|
1994
|
+
const ts = yield* service(TypeScriptApi);
|
|
1995
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
1996
|
+
const newIndexes = /* @__PURE__ */ new Set();
|
|
1997
|
+
const knownIndexes = /* @__PURE__ */ new Set();
|
|
1998
|
+
let toTest = [initialType];
|
|
1999
|
+
while (toTest.length > 0) {
|
|
2000
|
+
const type = toTest.pop();
|
|
2001
|
+
if (!type) break;
|
|
2002
|
+
if (excludeNever && type.flags & ts.TypeFlags.Never) {
|
|
2003
|
+
continue;
|
|
2004
|
+
}
|
|
2005
|
+
if (type.isUnion()) {
|
|
2006
|
+
toTest = toTest.concat(type.types);
|
|
2007
|
+
} else {
|
|
2008
|
+
const foundMatch = [];
|
|
2009
|
+
for (const [typeId, knownType] of memory.entries()) {
|
|
2010
|
+
const areSame = typeChecker.isTypeAssignableTo(knownType, type) && typeChecker.isTypeAssignableTo(type, knownType);
|
|
2011
|
+
if (areSame) {
|
|
2012
|
+
foundMatch.push(typeId);
|
|
2013
|
+
break;
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
if (foundMatch.length === 0) {
|
|
2017
|
+
const newId = "t" + (memory.size + 1);
|
|
2018
|
+
memory.set(newId, type);
|
|
2019
|
+
newIndexes.add(newId);
|
|
2020
|
+
} else {
|
|
2021
|
+
knownIndexes.add(foundMatch[0]);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
return {
|
|
2026
|
+
newIndexes,
|
|
2027
|
+
knownIndexes,
|
|
2028
|
+
allIndexes: pipe(
|
|
2029
|
+
fromIterable(newIndexes),
|
|
2030
|
+
appendAll(fromIterable(knownIndexes))
|
|
2031
|
+
)
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
);
|
|
2035
|
+
function makeResolveExternalModuleName(typeChecker) {
|
|
2036
|
+
if (!(hasProperty(typeChecker, "resolveExternalModuleName") && isFunction(typeChecker.resolveExternalModuleName))) {
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
const _internal = typeChecker.resolveExternalModuleName;
|
|
2040
|
+
return (moduleSpecifier) => {
|
|
2041
|
+
return _internal(moduleSpecifier);
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
// src/core/TypeParser.ts
|
|
2046
|
+
var TypeParser = Tag("@effect/language-service/TypeParser");
|
|
2047
|
+
var TypeParserIssue = class _TypeParserIssue {
|
|
2048
|
+
_tag = "@effect/language-service/TypeParserIssue";
|
|
2049
|
+
static issue = fail(new _TypeParserIssue());
|
|
2050
|
+
};
|
|
2051
|
+
function make4(ts, typeChecker) {
|
|
2052
|
+
function typeParserIssue(_message, _type, _node) {
|
|
2053
|
+
return TypeParserIssue.issue;
|
|
2054
|
+
}
|
|
2055
|
+
function covariantTypeArgument(type) {
|
|
2056
|
+
const signatures = type.getCallSignatures();
|
|
2057
|
+
if (signatures.length !== 1) {
|
|
2058
|
+
return typeParserIssue("Covariant type has no call signature", type);
|
|
2059
|
+
}
|
|
2060
|
+
return succeed(signatures[0].getReturnType());
|
|
2061
|
+
}
|
|
2062
|
+
function contravariantTypeArgument(type) {
|
|
2063
|
+
const signatures = type.getCallSignatures();
|
|
2064
|
+
if (signatures.length !== 1) {
|
|
2065
|
+
return typeParserIssue("Contravariant type has no call signature", type);
|
|
2066
|
+
}
|
|
2067
|
+
return succeed(signatures[0].getTypeParameterAtPosition(0));
|
|
2068
|
+
}
|
|
2069
|
+
function invariantTypeArgument(type) {
|
|
2070
|
+
const signatures = type.getCallSignatures();
|
|
2071
|
+
if (signatures.length !== 1) {
|
|
2072
|
+
return typeParserIssue("Invariant type has no call signature", type);
|
|
2073
|
+
}
|
|
2074
|
+
return succeed(signatures[0].getReturnType());
|
|
2075
|
+
}
|
|
2076
|
+
const pipeableType = cachedBy(
|
|
1847
2077
|
function(type, atLocation) {
|
|
1848
2078
|
const pipeSymbol = typeChecker.getPropertyOfType(type, "pipe");
|
|
1849
2079
|
if (!pipeSymbol) {
|
|
@@ -2297,641 +2527,14 @@ function make4(ts, typeChecker) {
|
|
|
2297
2527
|
};
|
|
2298
2528
|
}
|
|
2299
2529
|
|
|
2300
|
-
// src/
|
|
2301
|
-
var
|
|
2302
|
-
name: "
|
|
2303
|
-
|
|
2530
|
+
// src/diagnostics/floatingEffect.ts
|
|
2531
|
+
var floatingEffect = createDiagnostic({
|
|
2532
|
+
name: "floatingEffect",
|
|
2533
|
+
code: 3,
|
|
2534
|
+
severity: "error",
|
|
2535
|
+
apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
|
|
2304
2536
|
const ts = yield* service(TypeScriptApi);
|
|
2305
|
-
const
|
|
2306
|
-
const maybeInfos = yield* option(
|
|
2307
|
-
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
2308
|
-
);
|
|
2309
|
-
if (isNone2(maybeInfos)) return [];
|
|
2310
|
-
const { accessedObject } = maybeInfos.value;
|
|
2311
|
-
const isEffectModule = yield* option(typeParser.importedEffectModule(accessedObject));
|
|
2312
|
-
if (isNone2(isEffectModule)) return [];
|
|
2313
|
-
const span = ts.createTextSpan(
|
|
2314
|
-
accessedObject.end + 1,
|
|
2315
|
-
Math.max(0, position - accessedObject.end - 1)
|
|
2316
|
-
);
|
|
2317
|
-
const maybeFnName = pipe(
|
|
2318
|
-
yield* getAncestorNodesInRange(sourceFile, toTextRange(accessedObject.pos)),
|
|
2319
|
-
filter(ts.isVariableDeclaration),
|
|
2320
|
-
map3((_) => _.name && ts.isIdentifier(_.name) ? _.name.text : ""),
|
|
2321
|
-
filter((_) => _.length > 0),
|
|
2322
|
-
head,
|
|
2323
|
-
map2((name) => [
|
|
2324
|
-
{
|
|
2325
|
-
name: `fn("${name}")`,
|
|
2326
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2327
|
-
insertText: `fn("${name}")(function*(${"${1}"}){${"${0}"}})`,
|
|
2328
|
-
replacementSpan: span,
|
|
2329
|
-
isSnippet: true
|
|
2330
|
-
}
|
|
2331
|
-
]),
|
|
2332
|
-
getOrElse2(() => [])
|
|
2333
|
-
);
|
|
2334
|
-
return maybeFnName.concat([{
|
|
2335
|
-
name: `fn(function*(){})`,
|
|
2336
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2337
|
-
insertText: `fn(function*(${"${1}"}){${"${0}"}})`,
|
|
2338
|
-
replacementSpan: span,
|
|
2339
|
-
isSnippet: true
|
|
2340
|
-
}, {
|
|
2341
|
-
name: `fnUntraced(function*(){})`,
|
|
2342
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2343
|
-
insertText: `fnUntraced(function*(${"${1}"}){${"${0}"}})`,
|
|
2344
|
-
replacementSpan: span,
|
|
2345
|
-
isSnippet: true
|
|
2346
|
-
}]);
|
|
2347
|
-
})
|
|
2348
|
-
});
|
|
2349
|
-
|
|
2350
|
-
// src/core/TypeCheckerApi.ts
|
|
2351
|
-
var TypeCheckerApi = Tag("TypeChecker");
|
|
2352
|
-
var TypeCheckerApiCache = Tag("TypeCheckerApiCache");
|
|
2353
|
-
function makeTypeCheckerApiCache() {
|
|
2354
|
-
return {
|
|
2355
|
-
expectedAndRealType: /* @__PURE__ */ new WeakMap()
|
|
2356
|
-
};
|
|
2357
|
-
}
|
|
2358
|
-
var deterministicTypeOrder = gen(function* () {
|
|
2359
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2360
|
-
return make2((a, b) => {
|
|
2361
|
-
const aName = typeChecker.typeToString(a);
|
|
2362
|
-
const bName = typeChecker.typeToString(b);
|
|
2363
|
-
if (aName < bName) return -1;
|
|
2364
|
-
if (aName > bName) return 1;
|
|
2365
|
-
return 0;
|
|
2366
|
-
});
|
|
2367
|
-
});
|
|
2368
|
-
var getMissingTypeEntriesInTargetType = fn(
|
|
2369
|
-
"TypeCheckerApi.getMissingTypeEntriesInTargetType"
|
|
2370
|
-
)(
|
|
2371
|
-
function* (realType, expectedType) {
|
|
2372
|
-
if (realType === expectedType) return [];
|
|
2373
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2374
|
-
const result = [];
|
|
2375
|
-
let toTest = [realType];
|
|
2376
|
-
while (toTest.length > 0) {
|
|
2377
|
-
const type = toTest.pop();
|
|
2378
|
-
if (!type) return result;
|
|
2379
|
-
if (type.isUnion()) {
|
|
2380
|
-
toTest = toTest.concat(type.types);
|
|
2381
|
-
} else {
|
|
2382
|
-
const assignable = typeChecker.isTypeAssignableTo(type, expectedType);
|
|
2383
|
-
if (!assignable) {
|
|
2384
|
-
result.push(type);
|
|
2385
|
-
}
|
|
2386
|
-
}
|
|
2387
|
-
}
|
|
2388
|
-
return result;
|
|
2389
|
-
}
|
|
2390
|
-
);
|
|
2391
|
-
var CannotFindAncestorConvertibleDeclarationError = class {
|
|
2392
|
-
constructor(node) {
|
|
2393
|
-
this.node = node;
|
|
2394
|
-
}
|
|
2395
|
-
_tag = "@effect/language-service/CannotFindAncestorConvertibleDeclarationError";
|
|
2396
|
-
};
|
|
2397
|
-
var getAncestorConvertibleDeclaration = fn(
|
|
2398
|
-
"TypeCheckerApi.getAncestorConvertibleDeclaration"
|
|
2399
|
-
)(function* (node) {
|
|
2400
|
-
const ts = yield* service(TypeScriptApi);
|
|
2401
|
-
let current = node;
|
|
2402
|
-
while (current) {
|
|
2403
|
-
if (ts.isFunctionDeclaration(current) || ts.isFunctionExpression(current) || ts.isArrowFunction(current) || ts.isMethodDeclaration(current)) {
|
|
2404
|
-
return current;
|
|
2405
|
-
}
|
|
2406
|
-
current = current.parent;
|
|
2407
|
-
}
|
|
2408
|
-
return yield* fail(new CannotFindAncestorConvertibleDeclarationError(node));
|
|
2409
|
-
});
|
|
2410
|
-
var CannotInferReturnTypeFromEmptyBody = class {
|
|
2411
|
-
constructor(declaration) {
|
|
2412
|
-
this.declaration = declaration;
|
|
2413
|
-
}
|
|
2414
|
-
_tag = "@effect/language-service/CannotInferReturnTypeFromEmptyBody";
|
|
2415
|
-
};
|
|
2416
|
-
var CannotInferReturnType = class {
|
|
2417
|
-
constructor(declaration) {
|
|
2418
|
-
this.declaration = declaration;
|
|
2419
|
-
}
|
|
2420
|
-
_tag = "@effect/language-service/CannotInferReturnType";
|
|
2421
|
-
};
|
|
2422
|
-
var getInferredReturnType = fn("TypeCheckerApi.getInferredReturnType")(function* (declaration) {
|
|
2423
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2424
|
-
if (!declaration.body) {
|
|
2425
|
-
return yield* fail(
|
|
2426
|
-
new CannotInferReturnTypeFromEmptyBody(declaration)
|
|
2427
|
-
);
|
|
2428
|
-
}
|
|
2429
|
-
let returnType;
|
|
2430
|
-
if (typeChecker.isImplementationOfOverload(declaration)) {
|
|
2431
|
-
const signatures = typeChecker.getTypeAtLocation(declaration).getCallSignatures();
|
|
2432
|
-
if (signatures.length > 1) {
|
|
2433
|
-
returnType = typeChecker.getUnionType(
|
|
2434
|
-
signatures.map((s) => s.getReturnType()).filter((_) => !!_)
|
|
2435
|
-
);
|
|
2436
|
-
}
|
|
2437
|
-
}
|
|
2438
|
-
if (!returnType) {
|
|
2439
|
-
const signature = typeChecker.getSignatureFromDeclaration(declaration);
|
|
2440
|
-
if (signature) {
|
|
2441
|
-
const typePredicate = typeChecker.getTypePredicateOfSignature(signature);
|
|
2442
|
-
if (typePredicate && typePredicate.type) {
|
|
2443
|
-
return typePredicate.type;
|
|
2444
|
-
} else {
|
|
2445
|
-
returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
2446
|
-
}
|
|
2447
|
-
}
|
|
2448
|
-
}
|
|
2449
|
-
if (!returnType) {
|
|
2450
|
-
return yield* fail(
|
|
2451
|
-
new CannotInferReturnType(declaration)
|
|
2452
|
-
);
|
|
2453
|
-
}
|
|
2454
|
-
return returnType;
|
|
2455
|
-
});
|
|
2456
|
-
var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (sourceFile) {
|
|
2457
|
-
const cache = yield* service(TypeCheckerApiCache);
|
|
2458
|
-
const resultCached = cache.expectedAndRealType.get(sourceFile);
|
|
2459
|
-
if (resultCached) return resultCached;
|
|
2460
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2461
|
-
const ts = yield* service(TypeScriptApi);
|
|
2462
|
-
const result = [];
|
|
2463
|
-
const nodeToVisit = [sourceFile];
|
|
2464
|
-
const appendNodeToVisit = (node) => {
|
|
2465
|
-
nodeToVisit.push(node);
|
|
2466
|
-
return void 0;
|
|
2467
|
-
};
|
|
2468
|
-
while (nodeToVisit.length > 0) {
|
|
2469
|
-
const node = nodeToVisit.shift();
|
|
2470
|
-
if (ts.isVariableDeclaration(node) && node.initializer) {
|
|
2471
|
-
const expectedType = typeChecker.getTypeAtLocation(node.name);
|
|
2472
|
-
const realType = typeChecker.getTypeAtLocation(node.initializer);
|
|
2473
|
-
result.push([node.name, expectedType, node.initializer, realType]);
|
|
2474
|
-
appendNodeToVisit(node.initializer);
|
|
2475
|
-
continue;
|
|
2476
|
-
} else if (ts.isCallExpression(node)) {
|
|
2477
|
-
const resolvedSignature = typeChecker.getResolvedSignature(node);
|
|
2478
|
-
if (resolvedSignature) {
|
|
2479
|
-
resolvedSignature.getParameters().map((parameter, index) => {
|
|
2480
|
-
const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
|
|
2481
|
-
const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
|
|
2482
|
-
result.push([
|
|
2483
|
-
node.arguments[index],
|
|
2484
|
-
expectedType,
|
|
2485
|
-
node.arguments[index],
|
|
2486
|
-
realType
|
|
2487
|
-
]);
|
|
2488
|
-
});
|
|
2489
|
-
}
|
|
2490
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2491
|
-
continue;
|
|
2492
|
-
} else if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
2493
|
-
const parent = node.parent;
|
|
2494
|
-
if (ts.isObjectLiteralElement(parent)) {
|
|
2495
|
-
if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
|
|
2496
|
-
const type = typeChecker.getContextualType(parent.parent);
|
|
2497
|
-
if (type) {
|
|
2498
|
-
const symbol3 = typeChecker.getPropertyOfType(type, node.text);
|
|
2499
|
-
if (symbol3) {
|
|
2500
|
-
const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
|
|
2501
|
-
const realType = typeChecker.getTypeAtLocation(node);
|
|
2502
|
-
result.push([node, expectedType, node, realType]);
|
|
2503
|
-
}
|
|
2504
|
-
}
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2508
|
-
continue;
|
|
2509
|
-
} else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
2510
|
-
const expectedType = typeChecker.getTypeAtLocation(node.left);
|
|
2511
|
-
const realType = typeChecker.getTypeAtLocation(node.right);
|
|
2512
|
-
result.push([node.left, expectedType, node.right, realType]);
|
|
2513
|
-
appendNodeToVisit(node.right);
|
|
2514
|
-
continue;
|
|
2515
|
-
} else if (ts.isReturnStatement(node) && node.expression) {
|
|
2516
|
-
const parentDeclaration = yield* option(getAncestorConvertibleDeclaration(node));
|
|
2517
|
-
if (isSome2(parentDeclaration)) {
|
|
2518
|
-
const expectedType = yield* option(getInferredReturnType(parentDeclaration.value));
|
|
2519
|
-
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2520
|
-
if (isSome2(expectedType)) {
|
|
2521
|
-
result.push([node, expectedType.value, node, realType]);
|
|
2522
|
-
}
|
|
2523
|
-
}
|
|
2524
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2525
|
-
continue;
|
|
2526
|
-
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length === 0 && ts.isExpression(node.body)) {
|
|
2527
|
-
const body = node.body;
|
|
2528
|
-
const expectedType = typeChecker.getContextualType(body);
|
|
2529
|
-
const realType = typeChecker.getTypeAtLocation(body);
|
|
2530
|
-
if (expectedType) {
|
|
2531
|
-
result.push([body, expectedType, body, realType]);
|
|
2532
|
-
}
|
|
2533
|
-
ts.forEachChild(body, appendNodeToVisit);
|
|
2534
|
-
continue;
|
|
2535
|
-
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length > 0 && ts.isExpression(node.body)) {
|
|
2536
|
-
const body = node.body;
|
|
2537
|
-
const expectedType = yield* option(getInferredReturnType(node));
|
|
2538
|
-
const realType = typeChecker.getTypeAtLocation(body);
|
|
2539
|
-
if (isSome2(expectedType)) {
|
|
2540
|
-
result.push([body, expectedType.value, body, realType]);
|
|
2541
|
-
}
|
|
2542
|
-
ts.forEachChild(body, appendNodeToVisit);
|
|
2543
|
-
continue;
|
|
2544
|
-
} else if (ts.isSatisfiesExpression(node)) {
|
|
2545
|
-
const expectedType = typeChecker.getTypeAtLocation(node.type);
|
|
2546
|
-
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2547
|
-
result.push([node.expression, expectedType, node.expression, realType]);
|
|
2548
|
-
appendNodeToVisit(node.expression);
|
|
2549
|
-
continue;
|
|
2550
|
-
}
|
|
2551
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2552
|
-
}
|
|
2553
|
-
cache.expectedAndRealType.set(sourceFile, result);
|
|
2554
|
-
return result;
|
|
2555
|
-
});
|
|
2556
|
-
var appendToUniqueTypesMap = fn(
|
|
2557
|
-
"TypeCheckerApi.appendToUniqueTypesMap"
|
|
2558
|
-
)(
|
|
2559
|
-
function* (memory, initialType, excludeNever) {
|
|
2560
|
-
const ts = yield* service(TypeScriptApi);
|
|
2561
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2562
|
-
const newIndexes = /* @__PURE__ */ new Set();
|
|
2563
|
-
const knownIndexes = /* @__PURE__ */ new Set();
|
|
2564
|
-
let toTest = [initialType];
|
|
2565
|
-
while (toTest.length > 0) {
|
|
2566
|
-
const type = toTest.pop();
|
|
2567
|
-
if (!type) break;
|
|
2568
|
-
if (excludeNever && type.flags & ts.TypeFlags.Never) {
|
|
2569
|
-
continue;
|
|
2570
|
-
}
|
|
2571
|
-
if (type.isUnion()) {
|
|
2572
|
-
toTest = toTest.concat(type.types);
|
|
2573
|
-
} else {
|
|
2574
|
-
const foundMatch = [];
|
|
2575
|
-
for (const [typeId, knownType] of memory.entries()) {
|
|
2576
|
-
const areSame = typeChecker.isTypeAssignableTo(knownType, type) && typeChecker.isTypeAssignableTo(type, knownType);
|
|
2577
|
-
if (areSame) {
|
|
2578
|
-
foundMatch.push(typeId);
|
|
2579
|
-
break;
|
|
2580
|
-
}
|
|
2581
|
-
}
|
|
2582
|
-
if (foundMatch.length === 0) {
|
|
2583
|
-
const newId = "t" + (memory.size + 1);
|
|
2584
|
-
memory.set(newId, type);
|
|
2585
|
-
newIndexes.add(newId);
|
|
2586
|
-
} else {
|
|
2587
|
-
knownIndexes.add(foundMatch[0]);
|
|
2588
|
-
}
|
|
2589
|
-
}
|
|
2590
|
-
}
|
|
2591
|
-
return {
|
|
2592
|
-
newIndexes,
|
|
2593
|
-
knownIndexes,
|
|
2594
|
-
allIndexes: pipe(
|
|
2595
|
-
fromIterable(newIndexes),
|
|
2596
|
-
appendAll(fromIterable(knownIndexes))
|
|
2597
|
-
)
|
|
2598
|
-
};
|
|
2599
|
-
}
|
|
2600
|
-
);
|
|
2601
|
-
function makeResolveExternalModuleName(typeChecker) {
|
|
2602
|
-
if (!(hasProperty(typeChecker, "resolveExternalModuleName") && isFunction(typeChecker.resolveExternalModuleName))) {
|
|
2603
|
-
return;
|
|
2604
|
-
}
|
|
2605
|
-
const _internal = typeChecker.resolveExternalModuleName;
|
|
2606
|
-
return (moduleSpecifier) => {
|
|
2607
|
-
return _internal(moduleSpecifier);
|
|
2608
|
-
};
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
|
-
// src/completions/genFunctionStar.ts
|
|
2612
|
-
var genFunctionStar = createCompletion({
|
|
2613
|
-
name: "genFunctionStar",
|
|
2614
|
-
apply: fn("genFunctionStar")(function* (sourceFile, position) {
|
|
2615
|
-
const ts = yield* service(TypeScriptApi);
|
|
2616
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2617
|
-
const maybeInfos = yield* option(
|
|
2618
|
-
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
2619
|
-
);
|
|
2620
|
-
if (isNone2(maybeInfos)) return [];
|
|
2621
|
-
const { accessedObject } = maybeInfos.value;
|
|
2622
|
-
const type = typeChecker.getTypeAtLocation(accessedObject);
|
|
2623
|
-
const genMemberSymbol = type.getProperty("gen");
|
|
2624
|
-
if (!genMemberSymbol) return [];
|
|
2625
|
-
const genType = typeChecker.getTypeOfSymbolAtLocation(genMemberSymbol, accessedObject);
|
|
2626
|
-
if (genType.getCallSignatures().length === 0) return [];
|
|
2627
|
-
const span = ts.createTextSpan(
|
|
2628
|
-
accessedObject.end + 1,
|
|
2629
|
-
Math.max(0, position - accessedObject.end - 1)
|
|
2630
|
-
);
|
|
2631
|
-
return [{
|
|
2632
|
-
name: `gen(function*(){})`,
|
|
2633
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2634
|
-
insertText: `gen(function*(){${"${0}"}})`,
|
|
2635
|
-
replacementSpan: span,
|
|
2636
|
-
isSnippet: true
|
|
2637
|
-
}];
|
|
2638
|
-
})
|
|
2639
|
-
});
|
|
2640
|
-
|
|
2641
|
-
// src/completions/rpcMakeClasses.ts
|
|
2642
|
-
var rpcMakeClasses = createCompletion({
|
|
2643
|
-
name: "rpcMakeClasses",
|
|
2644
|
-
apply: fn("rpcMakeClasses")(function* (sourceFile, position) {
|
|
2645
|
-
const ts = yield* service(TypeScriptApi);
|
|
2646
|
-
const maybeInfos = yield* option(
|
|
2647
|
-
parseDataForExtendsClassCompletion(sourceFile, position)
|
|
2648
|
-
);
|
|
2649
|
-
if (isNone2(maybeInfos)) return [];
|
|
2650
|
-
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
2651
|
-
const rpcName = yield* option(
|
|
2652
|
-
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
2653
|
-
sourceFile,
|
|
2654
|
-
"@effect/rpc",
|
|
2655
|
-
"Rpc"
|
|
2656
|
-
)
|
|
2657
|
-
);
|
|
2658
|
-
const rpcIdentifier = match(rpcName, {
|
|
2659
|
-
onNone: () => "Rpc",
|
|
2660
|
-
onSome: (_) => _.text
|
|
2661
|
-
});
|
|
2662
|
-
if (rpcIdentifier !== accessedObject.text) return [];
|
|
2663
|
-
const name = className.text;
|
|
2664
|
-
return [{
|
|
2665
|
-
name: `make("${name}")`,
|
|
2666
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2667
|
-
insertText: `${rpcIdentifier}.make("${name}", {${"${0}"}}) {}`,
|
|
2668
|
-
replacementSpan,
|
|
2669
|
-
isSnippet: true
|
|
2670
|
-
}];
|
|
2671
|
-
})
|
|
2672
|
-
});
|
|
2673
|
-
|
|
2674
|
-
// src/completions.ts
|
|
2675
|
-
var completions = [
|
|
2676
|
-
effectSchemaSelfInClasses,
|
|
2677
|
-
effectSelfInClasses,
|
|
2678
|
-
contextSelfInClasses,
|
|
2679
|
-
rpcMakeClasses,
|
|
2680
|
-
genFunctionStar,
|
|
2681
|
-
fnFunctionStar,
|
|
2682
|
-
effectDataClasses
|
|
2683
|
-
];
|
|
2684
|
-
|
|
2685
|
-
// src/completions/middlewareNamespaceImports.ts
|
|
2686
|
-
var importablePackagesMetadataCache = /* @__PURE__ */ new Map();
|
|
2687
|
-
var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(function* (sourceFile) {
|
|
2688
|
-
const ts = yield* service(TypeScriptApi);
|
|
2689
|
-
const program = yield* service(TypeScriptProgram);
|
|
2690
|
-
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
2691
|
-
const host = program;
|
|
2692
|
-
const namespaceByFileName = /* @__PURE__ */ new Map();
|
|
2693
|
-
const excludedByFileName = /* @__PURE__ */ new Map();
|
|
2694
|
-
const unbarreledModulePathByFileName = /* @__PURE__ */ new Map();
|
|
2695
|
-
for (const packageName of languageServicePluginOptions.namespaceImportPackages) {
|
|
2696
|
-
const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
|
|
2697
|
-
if (barrelModule.resolvedModule) {
|
|
2698
|
-
const barrelPath = barrelModule.resolvedModule.resolvedFileName;
|
|
2699
|
-
const barrelSource = program.getSourceFile(barrelPath) || ts.createSourceFile(barrelPath, host.readFile(barrelPath) || "", sourceFile.languageVersion, true);
|
|
2700
|
-
if (barrelSource) {
|
|
2701
|
-
for (const statement of barrelSource.statements) {
|
|
2702
|
-
if (ts.isExportDeclaration(statement)) {
|
|
2703
|
-
const exportClause = statement.exportClause;
|
|
2704
|
-
const moduleSpecifier = statement.moduleSpecifier;
|
|
2705
|
-
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
2706
|
-
const unbarreledModulePathResolved = ts.resolveModuleName(
|
|
2707
|
-
moduleSpecifier.text,
|
|
2708
|
-
barrelSource.fileName,
|
|
2709
|
-
program.getCompilerOptions(),
|
|
2710
|
-
host
|
|
2711
|
-
);
|
|
2712
|
-
if (unbarreledModulePathResolved.resolvedModule) {
|
|
2713
|
-
const unbarreledModulePath = unbarreledModulePathResolved.resolvedModule.resolvedFileName;
|
|
2714
|
-
if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
|
|
2715
|
-
namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
|
|
2716
|
-
const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
|
|
2717
|
-
existingUnbarreledModulePath.push([exportClause.name.text, unbarreledModulePath]);
|
|
2718
|
-
unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
|
|
2719
|
-
}
|
|
2720
|
-
if (exportClause && ts.isNamedExports(exportClause)) {
|
|
2721
|
-
for (const element of exportClause.elements) {
|
|
2722
|
-
if (!ts.isIdentifier(element.name)) continue;
|
|
2723
|
-
const methodName = element.name.text;
|
|
2724
|
-
const excludedMethods = excludedByFileName.get(methodName) || [];
|
|
2725
|
-
excludedMethods.push(unbarreledModulePath);
|
|
2726
|
-
excludedByFileName.set(methodName, excludedMethods);
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
}
|
|
2732
|
-
}
|
|
2733
|
-
}
|
|
2734
|
-
}
|
|
2735
|
-
}
|
|
2736
|
-
return {
|
|
2737
|
-
getImportNamespaceByFileName: (fileName) => namespaceByFileName.get(fileName),
|
|
2738
|
-
isExcludedFromNamespaceImport: (fileName, exportName) => (excludedByFileName.get(exportName) || []).includes(fileName),
|
|
2739
|
-
getUnbarreledModulePath: (fileName, exportName) => unbarreledModulePathByFileName.get(fileName)?.find(([name]) => name === exportName)?.[1]
|
|
2740
|
-
};
|
|
2741
|
-
});
|
|
2742
|
-
var appendEffectCompletionEntryData = fn("collectNamespaceImports")(
|
|
2743
|
-
function* (sourceFile, applicableCompletions) {
|
|
2744
|
-
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
2745
|
-
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletions;
|
|
2746
|
-
const packagesMetadata = importablePackagesMetadataCache.get(sourceFile.fileName) || (yield* makeImportablePackagesMetadata(sourceFile));
|
|
2747
|
-
importablePackagesMetadataCache.set(sourceFile.fileName, packagesMetadata);
|
|
2748
|
-
if (applicableCompletions) {
|
|
2749
|
-
return {
|
|
2750
|
-
...applicableCompletions,
|
|
2751
|
-
entries: applicableCompletions.entries.map((entry) => {
|
|
2752
|
-
if (entry.data && entry.data.fileName && !entry.insertText && !entry.filterText && entry.data.exportName && entry.data.moduleSpecifier) {
|
|
2753
|
-
const isExcluded = packagesMetadata.isExcludedFromNamespaceImport(
|
|
2754
|
-
entry.data.fileName,
|
|
2755
|
-
entry.data.exportName
|
|
2756
|
-
);
|
|
2757
|
-
if (isExcluded) return entry;
|
|
2758
|
-
const unbarreledModulePath = packagesMetadata.getUnbarreledModulePath(
|
|
2759
|
-
entry.data.fileName,
|
|
2760
|
-
entry.data.exportName
|
|
2761
|
-
);
|
|
2762
|
-
const namespaceName = packagesMetadata.getImportNamespaceByFileName(
|
|
2763
|
-
unbarreledModulePath || entry.data.fileName
|
|
2764
|
-
);
|
|
2765
|
-
if (namespaceName) {
|
|
2766
|
-
return {
|
|
2767
|
-
...entry,
|
|
2768
|
-
// insertText: unbarreledModulePath ? namespaceName : namespaceName + "." + entry.name,
|
|
2769
|
-
// filterText: entry.name,
|
|
2770
|
-
data: {
|
|
2771
|
-
...entry.data,
|
|
2772
|
-
effectNamespaceName: namespaceName,
|
|
2773
|
-
effectUnbarreledModulePath: unbarreledModulePath || "",
|
|
2774
|
-
effectReplaceSpan: entry.replacementSpan || applicableCompletions.optionalReplacementSpan
|
|
2775
|
-
}
|
|
2776
|
-
};
|
|
2777
|
-
}
|
|
2778
|
-
}
|
|
2779
|
-
return entry;
|
|
2780
|
-
})
|
|
2781
|
-
};
|
|
2782
|
-
}
|
|
2783
|
-
return applicableCompletions;
|
|
2784
|
-
}
|
|
2785
|
-
);
|
|
2786
|
-
var postprocessCompletionEntryDetails = fn("postprocessCompletionEntryDetails")(
|
|
2787
|
-
function* (sourceFile, data, applicableCompletionEntryDetails, formatOptions, preferences, languageServiceHost) {
|
|
2788
|
-
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
2789
|
-
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletionEntryDetails;
|
|
2790
|
-
const ts = yield* service(TypeScriptApi);
|
|
2791
|
-
const program = yield* service(TypeScriptProgram);
|
|
2792
|
-
const getModuleSpecifier = makeGetModuleSpecifier(ts);
|
|
2793
|
-
if (!getModuleSpecifier) return applicableCompletionEntryDetails;
|
|
2794
|
-
if (!applicableCompletionEntryDetails) return applicableCompletionEntryDetails;
|
|
2795
|
-
if (!data) return applicableCompletionEntryDetails;
|
|
2796
|
-
if (!("effectNamespaceName" in data && "effectUnbarreledModulePath" in data && "effectReplaceSpan" in data)) {
|
|
2797
|
-
return applicableCompletionEntryDetails;
|
|
2798
|
-
}
|
|
2799
|
-
const effectReplaceSpan = data.effectReplaceSpan;
|
|
2800
|
-
const codeActions = applicableCompletionEntryDetails.codeActions;
|
|
2801
|
-
if (codeActions && codeActions.length === 1) {
|
|
2802
|
-
const action = codeActions[0];
|
|
2803
|
-
if (action.changes.length === 1) {
|
|
2804
|
-
const fileTextChanges = action.changes[0];
|
|
2805
|
-
if (fileTextChanges.fileName === sourceFile.fileName && fileTextChanges.textChanges.length === 1) {
|
|
2806
|
-
const change = fileTextChanges.textChanges[0];
|
|
2807
|
-
let hasImportActions = false;
|
|
2808
|
-
if (change.newText.trim().toLowerCase().startsWith("import") && change.newText.indexOf(data.exportName) > -1) {
|
|
2809
|
-
hasImportActions = true;
|
|
2810
|
-
}
|
|
2811
|
-
if (!hasImportActions && change.newText.indexOf(data.exportName) > -1) {
|
|
2812
|
-
const ancestorNodes = yield* getAncestorNodesInRange(sourceFile, {
|
|
2813
|
-
pos: change.span.start,
|
|
2814
|
-
end: change.span.start
|
|
2815
|
-
});
|
|
2816
|
-
const importNodes = ancestorNodes.filter((node) => ts.isImportDeclaration(node));
|
|
2817
|
-
hasImportActions = importNodes.length > 0;
|
|
2818
|
-
}
|
|
2819
|
-
if (!hasImportActions) return applicableCompletionEntryDetails;
|
|
2820
|
-
const formatContext = ts.formatting.getFormatContext(
|
|
2821
|
-
formatOptions || {},
|
|
2822
|
-
languageServiceHost
|
|
2823
|
-
);
|
|
2824
|
-
const changes = ts.textChanges.ChangeTracker.with(
|
|
2825
|
-
{
|
|
2826
|
-
formatContext,
|
|
2827
|
-
host: languageServiceHost,
|
|
2828
|
-
preferences: preferences || {}
|
|
2829
|
-
},
|
|
2830
|
-
(changeTracker) => {
|
|
2831
|
-
const isBarrelRedirect = String(data.effectUnbarreledModulePath).length > 0;
|
|
2832
|
-
const moduleSpecifier = isBarrelRedirect ? getModuleSpecifier(
|
|
2833
|
-
program.getCompilerOptions(),
|
|
2834
|
-
sourceFile,
|
|
2835
|
-
sourceFile.fileName,
|
|
2836
|
-
String(data.effectUnbarreledModulePath),
|
|
2837
|
-
program
|
|
2838
|
-
) : String(data.moduleSpecifier);
|
|
2839
|
-
ts.insertImports(
|
|
2840
|
-
changeTracker,
|
|
2841
|
-
sourceFile,
|
|
2842
|
-
ts.factory.createImportDeclaration(
|
|
2843
|
-
void 0,
|
|
2844
|
-
ts.factory.createImportClause(
|
|
2845
|
-
false,
|
|
2846
|
-
void 0,
|
|
2847
|
-
ts.factory.createNamespaceImport(ts.factory.createIdentifier(String(data.effectNamespaceName)))
|
|
2848
|
-
),
|
|
2849
|
-
ts.factory.createStringLiteral(moduleSpecifier)
|
|
2850
|
-
),
|
|
2851
|
-
true,
|
|
2852
|
-
preferences || {}
|
|
2853
|
-
);
|
|
2854
|
-
if (!isBarrelRedirect) {
|
|
2855
|
-
changeTracker.insertText(
|
|
2856
|
-
sourceFile,
|
|
2857
|
-
effectReplaceSpan.start,
|
|
2858
|
-
String(data.effectNamespaceName) + "."
|
|
2859
|
-
);
|
|
2860
|
-
}
|
|
2861
|
-
}
|
|
2862
|
-
);
|
|
2863
|
-
return {
|
|
2864
|
-
...applicableCompletionEntryDetails,
|
|
2865
|
-
codeActions: [
|
|
2866
|
-
{
|
|
2867
|
-
description: "Import * as " + data.effectNamespaceName + " from " + data.effectUnbarreledModulePath,
|
|
2868
|
-
changes
|
|
2869
|
-
}
|
|
2870
|
-
]
|
|
2871
|
-
};
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
}
|
|
2875
|
-
return applicableCompletionEntryDetails;
|
|
2876
|
-
}
|
|
2877
|
-
);
|
|
2878
|
-
|
|
2879
|
-
// src/diagnostics/duplicatePackage.ts
|
|
2880
|
-
var checkedPackagesCache = /* @__PURE__ */ new Map();
|
|
2881
|
-
var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
2882
|
-
var duplicatePackage = createDiagnostic({
|
|
2883
|
-
name: "duplicatePackage",
|
|
2884
|
-
code: 6,
|
|
2885
|
-
severity: "warning",
|
|
2886
|
-
apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
2887
|
-
const program = yield* service(TypeScriptProgram);
|
|
2888
|
-
const options = yield* service(LanguageServicePluginOptions);
|
|
2889
|
-
if (sourceFile.statements.length < 1) return;
|
|
2890
|
-
let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
|
|
2891
|
-
const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
|
|
2892
|
-
const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
|
|
2893
|
-
if (newResolvedModuleSize !== oldResolvedSize) {
|
|
2894
|
-
const seenPackages = /* @__PURE__ */ new Set();
|
|
2895
|
-
resolvedPackages = {};
|
|
2896
|
-
program.getSourceFiles().map((_) => {
|
|
2897
|
-
const packageInfo = parsePackageContentNameAndVersionFromScope(_);
|
|
2898
|
-
if (!packageInfo) return;
|
|
2899
|
-
const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
|
|
2900
|
-
if (seenPackages.has(packageNameAndVersion)) return;
|
|
2901
|
-
seenPackages.add(packageNameAndVersion);
|
|
2902
|
-
if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
|
|
2903
|
-
if (options.allowedDuplicatedPackages.indexOf(packageInfo.name) > -1) return;
|
|
2904
|
-
resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
|
|
2905
|
-
resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.packageDirectory;
|
|
2906
|
-
});
|
|
2907
|
-
checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
|
|
2908
|
-
programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
|
|
2909
|
-
}
|
|
2910
|
-
for (const packageName of Object.keys(resolvedPackages)) {
|
|
2911
|
-
if (Object.keys(resolvedPackages[packageName]).length > 1) {
|
|
2912
|
-
const versions = Object.keys(resolvedPackages[packageName]);
|
|
2913
|
-
report({
|
|
2914
|
-
node: sourceFile.statements[0],
|
|
2915
|
-
messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
|
|
2916
|
-
Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
|
|
2917
|
-
If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
2918
|
-
|
|
2919
|
-
${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
|
|
2920
|
-
fixes: []
|
|
2921
|
-
});
|
|
2922
|
-
}
|
|
2923
|
-
}
|
|
2924
|
-
})
|
|
2925
|
-
});
|
|
2926
|
-
|
|
2927
|
-
// src/diagnostics/floatingEffect.ts
|
|
2928
|
-
var floatingEffect = createDiagnostic({
|
|
2929
|
-
name: "floatingEffect",
|
|
2930
|
-
code: 3,
|
|
2931
|
-
severity: "error",
|
|
2932
|
-
apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
|
|
2933
|
-
const ts = yield* service(TypeScriptApi);
|
|
2934
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2537
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2935
2538
|
const typeParser = yield* service(TypeParser);
|
|
2936
2539
|
function isFloatingExpression(node) {
|
|
2937
2540
|
if (!ts.isExpressionStatement(node)) return false;
|
|
@@ -3259,22 +2862,24 @@ var missingEffectContext = createDiagnostic({
|
|
|
3259
2862
|
const sortTypes = sort(typeOrder);
|
|
3260
2863
|
const entries = yield* expectedAndRealType(sourceFile);
|
|
3261
2864
|
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
expectedType,
|
|
3266
|
-
valueNode,
|
|
3267
|
-
realType
|
|
3268
|
-
),
|
|
3269
|
-
orElse2(() => succeed([]))
|
|
3270
|
-
);
|
|
3271
|
-
if (missingContext.length > 0) {
|
|
3272
|
-
report(
|
|
3273
|
-
{
|
|
2865
|
+
if (expectedType !== realType) {
|
|
2866
|
+
yield* pipe(
|
|
2867
|
+
checkForMissingContextTypes(
|
|
3274
2868
|
node,
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
2869
|
+
expectedType,
|
|
2870
|
+
valueNode,
|
|
2871
|
+
realType
|
|
2872
|
+
),
|
|
2873
|
+
map4(
|
|
2874
|
+
(missingTypes) => missingTypes.length > 0 ? report(
|
|
2875
|
+
{
|
|
2876
|
+
node,
|
|
2877
|
+
messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
|
|
2878
|
+
fixes: []
|
|
2879
|
+
}
|
|
2880
|
+
) : void 0
|
|
2881
|
+
),
|
|
2882
|
+
ignore
|
|
3278
2883
|
);
|
|
3279
2884
|
}
|
|
3280
2885
|
}
|
|
@@ -3305,36 +2910,284 @@ var missingEffectError = createDiagnostic({
|
|
|
3305
2910
|
const sortTypes = sort(typeOrder);
|
|
3306
2911
|
const entries = yield* expectedAndRealType(sourceFile);
|
|
3307
2912
|
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
3308
|
-
|
|
3309
|
-
|
|
2913
|
+
if (expectedType !== realType) {
|
|
2914
|
+
yield* pipe(
|
|
2915
|
+
checkForMissingErrorTypes(
|
|
2916
|
+
node,
|
|
2917
|
+
expectedType,
|
|
2918
|
+
valueNode,
|
|
2919
|
+
realType
|
|
2920
|
+
),
|
|
2921
|
+
map4(
|
|
2922
|
+
(missingTypes) => missingTypes.length > 0 ? report(
|
|
2923
|
+
{
|
|
2924
|
+
node,
|
|
2925
|
+
messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect errors.`,
|
|
2926
|
+
fixes: []
|
|
2927
|
+
}
|
|
2928
|
+
) : void 0
|
|
2929
|
+
),
|
|
2930
|
+
ignore
|
|
2931
|
+
);
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
})
|
|
2935
|
+
});
|
|
2936
|
+
|
|
2937
|
+
// src/diagnostics/missingReturnYieldStar.ts
|
|
2938
|
+
var missingReturnYieldStar = createDiagnostic({
|
|
2939
|
+
name: "missingReturnYieldStar",
|
|
2940
|
+
code: 7,
|
|
2941
|
+
severity: "error",
|
|
2942
|
+
apply: fn("missingReturnYieldStar.apply")(function* (sourceFile, report) {
|
|
2943
|
+
const ts = yield* service(TypeScriptApi);
|
|
2944
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2945
|
+
const typeParser = yield* service(TypeParser);
|
|
2946
|
+
const nodeToVisit = [];
|
|
2947
|
+
const appendNodeToVisit = (node) => {
|
|
2948
|
+
nodeToVisit.push(node);
|
|
2949
|
+
return void 0;
|
|
2950
|
+
};
|
|
2951
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
2952
|
+
while (nodeToVisit.length > 0) {
|
|
2953
|
+
const node = nodeToVisit.shift();
|
|
2954
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
2955
|
+
if (ts.isYieldExpression(node) && node.expression && node.asteriskToken) {
|
|
2956
|
+
const type = typeChecker.getTypeAtLocation(node.expression);
|
|
2957
|
+
const maybeEffect = yield* option(typeParser.effectType(type, node.expression));
|
|
2958
|
+
if (isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never) {
|
|
2959
|
+
const generatorFunctionOrReturnStatement = ts.findAncestor(
|
|
2960
|
+
node,
|
|
2961
|
+
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_) || ts.isReturnStatement(_)
|
|
2962
|
+
);
|
|
2963
|
+
if (generatorFunctionOrReturnStatement && !ts.isReturnStatement(generatorFunctionOrReturnStatement)) {
|
|
2964
|
+
if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.parent) {
|
|
2965
|
+
const effectGenNode = generatorFunctionOrReturnStatement.parent;
|
|
2966
|
+
const effectGenLike = yield* pipe(
|
|
2967
|
+
typeParser.effectGen(effectGenNode),
|
|
2968
|
+
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
2969
|
+
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
2970
|
+
option
|
|
2971
|
+
);
|
|
2972
|
+
if (isSome2(effectGenLike)) {
|
|
2973
|
+
const fix = node.expression ? [{
|
|
2974
|
+
fixName: "missingReturnYieldStar_fix",
|
|
2975
|
+
description: "Add return statement",
|
|
2976
|
+
apply: gen(function* () {
|
|
2977
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
2978
|
+
changeTracker.replaceNode(
|
|
2979
|
+
sourceFile,
|
|
2980
|
+
node,
|
|
2981
|
+
ts.factory.createReturnStatement(
|
|
2982
|
+
node
|
|
2983
|
+
)
|
|
2984
|
+
);
|
|
2985
|
+
})
|
|
2986
|
+
}] : [];
|
|
2987
|
+
report({
|
|
2988
|
+
node,
|
|
2989
|
+
messageText: `Yielded Effect never succeeds, so it is best to use a 'return yield*' instead.`,
|
|
2990
|
+
fixes: fix
|
|
2991
|
+
});
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
})
|
|
2999
|
+
});
|
|
3000
|
+
|
|
3001
|
+
// src/diagnostics/missingStarInYieldEffectGen.ts
|
|
3002
|
+
var missingStarInYieldEffectGen = createDiagnostic({
|
|
3003
|
+
name: "missingStarInYieldEffectGen",
|
|
3004
|
+
code: 4,
|
|
3005
|
+
severity: "error",
|
|
3006
|
+
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
3007
|
+
const ts = yield* service(TypeScriptApi);
|
|
3008
|
+
const typeParser = yield* service(TypeParser);
|
|
3009
|
+
const brokenGenerators = /* @__PURE__ */ new Set();
|
|
3010
|
+
const brokenYields = /* @__PURE__ */ new Set();
|
|
3011
|
+
const nodeToVisit = [];
|
|
3012
|
+
const appendNodeToVisit = (node) => {
|
|
3013
|
+
nodeToVisit.push(node);
|
|
3014
|
+
return void 0;
|
|
3015
|
+
};
|
|
3016
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3017
|
+
while (nodeToVisit.length > 0) {
|
|
3018
|
+
const node = nodeToVisit.shift();
|
|
3019
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
3020
|
+
if (ts.isYieldExpression(node) && node.expression && node.asteriskToken === void 0) {
|
|
3021
|
+
const functionStarNode = ts.findAncestor(
|
|
3310
3022
|
node,
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3023
|
+
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_)
|
|
3024
|
+
);
|
|
3025
|
+
if (functionStarNode && functionStarNode.parent) {
|
|
3026
|
+
const effectGenNode = functionStarNode.parent;
|
|
3027
|
+
yield* pipe(
|
|
3028
|
+
typeParser.effectGen(effectGenNode),
|
|
3029
|
+
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3030
|
+
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
3031
|
+
map4(({ functionStar }) => {
|
|
3032
|
+
if (functionStar) {
|
|
3033
|
+
brokenGenerators.add(functionStar);
|
|
3034
|
+
}
|
|
3035
|
+
brokenYields.add(node);
|
|
3036
|
+
}),
|
|
3037
|
+
ignore
|
|
3038
|
+
);
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
brokenGenerators.forEach(
|
|
3043
|
+
(node) => report({
|
|
3044
|
+
node,
|
|
3045
|
+
messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
|
|
3046
|
+
fixes: []
|
|
3047
|
+
})
|
|
3048
|
+
);
|
|
3049
|
+
brokenYields.forEach((node) => {
|
|
3050
|
+
const fix = node.expression ? [{
|
|
3051
|
+
fixName: "missingStarInYieldEffectGen_fix",
|
|
3052
|
+
description: "Replace yield with yield*",
|
|
3053
|
+
apply: gen(function* () {
|
|
3054
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
3055
|
+
changeTracker.replaceNode(
|
|
3056
|
+
sourceFile,
|
|
3320
3057
|
node,
|
|
3321
|
-
|
|
3322
|
-
|
|
3058
|
+
ts.factory.createYieldExpression(
|
|
3059
|
+
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
3060
|
+
node.expression
|
|
3061
|
+
)
|
|
3062
|
+
);
|
|
3063
|
+
})
|
|
3064
|
+
}] : [];
|
|
3065
|
+
report({
|
|
3066
|
+
node,
|
|
3067
|
+
messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
|
|
3068
|
+
fixes: fix
|
|
3069
|
+
});
|
|
3070
|
+
});
|
|
3071
|
+
})
|
|
3072
|
+
});
|
|
3073
|
+
|
|
3074
|
+
// src/diagnostics/returnEffectInGen.ts
|
|
3075
|
+
var returnEffectInGen = createDiagnostic({
|
|
3076
|
+
name: "returnEffectInGen",
|
|
3077
|
+
code: 11,
|
|
3078
|
+
severity: "suggestion",
|
|
3079
|
+
apply: fn("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
3080
|
+
const ts = yield* service(TypeScriptApi);
|
|
3081
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3082
|
+
const typeParser = yield* service(TypeParser);
|
|
3083
|
+
const nodeToVisit = [];
|
|
3084
|
+
const appendNodeToVisit = (node) => {
|
|
3085
|
+
nodeToVisit.push(node);
|
|
3086
|
+
return void 0;
|
|
3087
|
+
};
|
|
3088
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3089
|
+
while (nodeToVisit.length > 0) {
|
|
3090
|
+
const node = nodeToVisit.shift();
|
|
3091
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
3092
|
+
if (ts.isReturnStatement(node) && node.expression) {
|
|
3093
|
+
if (ts.isYieldExpression(node.expression)) continue;
|
|
3094
|
+
const generatorOrRegularFunction = ts.findAncestor(
|
|
3095
|
+
node,
|
|
3096
|
+
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_) || ts.isArrowFunction(_) || ts.isGetAccessor(_)
|
|
3097
|
+
);
|
|
3098
|
+
if (!(generatorOrRegularFunction && "asteriskToken" in generatorOrRegularFunction && generatorOrRegularFunction.asteriskToken)) continue;
|
|
3099
|
+
const type = typeChecker.getTypeAtLocation(node.expression);
|
|
3100
|
+
const maybeEffect = yield* option(typeParser.strictEffectType(type, node.expression));
|
|
3101
|
+
if (isSome2(maybeEffect)) {
|
|
3102
|
+
if (generatorOrRegularFunction && generatorOrRegularFunction.parent) {
|
|
3103
|
+
const effectGenNode = generatorOrRegularFunction.parent;
|
|
3104
|
+
yield* pipe(
|
|
3105
|
+
typeParser.effectGen(effectGenNode),
|
|
3106
|
+
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3107
|
+
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
3108
|
+
map4(() => {
|
|
3109
|
+
const fix = node.expression ? [{
|
|
3110
|
+
fixName: "returnEffectInGen_fix",
|
|
3111
|
+
description: "Add yield* statement",
|
|
3112
|
+
apply: gen(function* () {
|
|
3113
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
3114
|
+
changeTracker.replaceNode(
|
|
3115
|
+
sourceFile,
|
|
3116
|
+
node.expression,
|
|
3117
|
+
ts.factory.createYieldExpression(
|
|
3118
|
+
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
3119
|
+
node.expression
|
|
3120
|
+
)
|
|
3121
|
+
);
|
|
3122
|
+
})
|
|
3123
|
+
}] : [];
|
|
3124
|
+
report({
|
|
3125
|
+
node,
|
|
3126
|
+
messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>.
|
|
3127
|
+
Maybe you wanted to return yield* instead?
|
|
3128
|
+
Nested Effect-able types may be intended if you plan to later manually flatten or unwrap this Effect, if so you can safely disable this diagnostic for this line through quickfixes.`,
|
|
3129
|
+
fixes: fix
|
|
3130
|
+
});
|
|
3131
|
+
}),
|
|
3132
|
+
ignore
|
|
3133
|
+
);
|
|
3323
3134
|
}
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
})
|
|
3139
|
+
});
|
|
3140
|
+
|
|
3141
|
+
// src/diagnostics/unnecessaryEffectGen.ts
|
|
3142
|
+
var unnecessaryEffectGen = createDiagnostic({
|
|
3143
|
+
name: "unnecessaryEffectGen",
|
|
3144
|
+
code: 5,
|
|
3145
|
+
severity: "suggestion",
|
|
3146
|
+
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
|
|
3147
|
+
const ts = yield* service(TypeScriptApi);
|
|
3148
|
+
const typeParser = yield* service(TypeParser);
|
|
3149
|
+
const nodeToVisit = [];
|
|
3150
|
+
const appendNodeToVisit = (node) => {
|
|
3151
|
+
nodeToVisit.push(node);
|
|
3152
|
+
return void 0;
|
|
3153
|
+
};
|
|
3154
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3155
|
+
while (nodeToVisit.length > 0) {
|
|
3156
|
+
const node = nodeToVisit.shift();
|
|
3157
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
3158
|
+
if (ts.isCallExpression(node)) {
|
|
3159
|
+
yield* pipe(
|
|
3160
|
+
typeParser.unnecessaryEffectGen(node),
|
|
3161
|
+
map4(
|
|
3162
|
+
({ replacementNode }) => report({
|
|
3163
|
+
node,
|
|
3164
|
+
messageText: `This Effect.gen contains a single return statement.`,
|
|
3165
|
+
fixes: [{
|
|
3166
|
+
fixName: "unnecessaryEffectGen_fix",
|
|
3167
|
+
description: "Remove the Effect.gen, and keep the body",
|
|
3168
|
+
apply: gen(function* () {
|
|
3169
|
+
const textChanges = yield* service(
|
|
3170
|
+
ChangeTracker
|
|
3171
|
+
);
|
|
3172
|
+
textChanges.replaceNode(sourceFile, node, yield* replacementNode);
|
|
3173
|
+
})
|
|
3174
|
+
}]
|
|
3175
|
+
})
|
|
3176
|
+
),
|
|
3177
|
+
ignore
|
|
3324
3178
|
);
|
|
3325
3179
|
}
|
|
3326
3180
|
}
|
|
3327
3181
|
})
|
|
3328
3182
|
});
|
|
3329
3183
|
|
|
3330
|
-
// src/diagnostics/
|
|
3331
|
-
var
|
|
3332
|
-
name: "
|
|
3333
|
-
code:
|
|
3334
|
-
severity: "
|
|
3335
|
-
apply: fn("
|
|
3184
|
+
// src/diagnostics/unnecessaryPipe.ts
|
|
3185
|
+
var unnecessaryPipe = createDiagnostic({
|
|
3186
|
+
name: "unnecessaryPipe",
|
|
3187
|
+
code: 9,
|
|
3188
|
+
severity: "suggestion",
|
|
3189
|
+
apply: fn("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
3336
3190
|
const ts = yield* service(TypeScriptApi);
|
|
3337
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
3338
3191
|
const typeParser = yield* service(TypeParser);
|
|
3339
3192
|
const nodeToVisit = [];
|
|
3340
3193
|
const appendNodeToVisit = (node) => {
|
|
@@ -3345,295 +3198,485 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
3345
3198
|
while (nodeToVisit.length > 0) {
|
|
3346
3199
|
const node = nodeToVisit.shift();
|
|
3347
3200
|
ts.forEachChild(node, appendNodeToVisit);
|
|
3348
|
-
if (ts.
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
const effectGenLike = yield* pipe(
|
|
3360
|
-
typeParser.effectGen(effectGenNode),
|
|
3361
|
-
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3362
|
-
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
3363
|
-
option
|
|
3364
|
-
);
|
|
3365
|
-
if (isSome2(effectGenLike)) {
|
|
3366
|
-
const fix = node.expression ? [{
|
|
3367
|
-
fixName: "missingReturnYieldStar_fix",
|
|
3368
|
-
description: "Add return statement",
|
|
3201
|
+
if (ts.isCallExpression(node)) {
|
|
3202
|
+
yield* pipe(
|
|
3203
|
+
typeParser.pipeCall(node),
|
|
3204
|
+
map4(({ args, subject }) => {
|
|
3205
|
+
if (args.length === 0) {
|
|
3206
|
+
report({
|
|
3207
|
+
node,
|
|
3208
|
+
messageText: `This pipe call contains no arguments.`,
|
|
3209
|
+
fixes: [{
|
|
3210
|
+
fixName: "unnecessaryPipe_fix",
|
|
3211
|
+
description: "Remove the pipe call",
|
|
3369
3212
|
apply: gen(function* () {
|
|
3370
|
-
const
|
|
3371
|
-
|
|
3372
|
-
sourceFile,
|
|
3373
|
-
node,
|
|
3374
|
-
ts.factory.createReturnStatement(
|
|
3375
|
-
node
|
|
3376
|
-
)
|
|
3213
|
+
const textChanges = yield* service(
|
|
3214
|
+
ChangeTracker
|
|
3377
3215
|
);
|
|
3216
|
+
textChanges.replaceNode(sourceFile, node, subject);
|
|
3378
3217
|
})
|
|
3379
|
-
}]
|
|
3380
|
-
|
|
3381
|
-
node,
|
|
3382
|
-
messageText: `Yielded Effect never succeeds, so it is best to use a 'return yield*' instead.`,
|
|
3383
|
-
fixes: fix
|
|
3384
|
-
});
|
|
3385
|
-
}
|
|
3218
|
+
}]
|
|
3219
|
+
});
|
|
3386
3220
|
}
|
|
3387
|
-
}
|
|
3221
|
+
}),
|
|
3222
|
+
ignore
|
|
3223
|
+
);
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
})
|
|
3227
|
+
});
|
|
3228
|
+
|
|
3229
|
+
// src/diagnostics.ts
|
|
3230
|
+
var diagnostics = [
|
|
3231
|
+
duplicatePackage,
|
|
3232
|
+
missingEffectContext,
|
|
3233
|
+
missingEffectError,
|
|
3234
|
+
floatingEffect,
|
|
3235
|
+
missingStarInYieldEffectGen,
|
|
3236
|
+
unnecessaryEffectGen,
|
|
3237
|
+
missingReturnYieldStar,
|
|
3238
|
+
leakingRequirements,
|
|
3239
|
+
unnecessaryPipe,
|
|
3240
|
+
genericEffectServices,
|
|
3241
|
+
returnEffectInGen,
|
|
3242
|
+
importFromBarrel
|
|
3243
|
+
];
|
|
3244
|
+
|
|
3245
|
+
// src/completions/effectDiagnosticsComment.ts
|
|
3246
|
+
var effectDiagnosticsComment = createCompletion({
|
|
3247
|
+
name: "effectDiagnosticsComment",
|
|
3248
|
+
apply: fn("effectDiagnosticsComment")(function* (sourceFile, position) {
|
|
3249
|
+
const ts = yield* service(TypeScriptApi);
|
|
3250
|
+
const sourceText = sourceFile.text;
|
|
3251
|
+
const match2 = /(\/\/|\/\*(?:\*?))\s*(@)\s*$/id.exec(sourceText.substring(0, position));
|
|
3252
|
+
if (match2 && match2.indices) {
|
|
3253
|
+
const lastIndex = match2.indices[2][0];
|
|
3254
|
+
const replacementSpan = {
|
|
3255
|
+
start: lastIndex,
|
|
3256
|
+
length: Math.max(0, position - lastIndex)
|
|
3257
|
+
};
|
|
3258
|
+
const allDiagnostics = sort(Object.values(diagnostics).map((diagnostic) => diagnostic.name), string2).join(",");
|
|
3259
|
+
const disableSnippet = "${1|" + allDiagnostics + "|}:${2|off,warning,error,message,suggestion|}$0";
|
|
3260
|
+
return [{
|
|
3261
|
+
name: `@effect-diagnostics`,
|
|
3262
|
+
kind: ts.ScriptElementKind.string,
|
|
3263
|
+
insertText: "@effect-diagnostics " + disableSnippet,
|
|
3264
|
+
isSnippet: true,
|
|
3265
|
+
replacementSpan
|
|
3266
|
+
}, {
|
|
3267
|
+
name: `@effect-diagnostics-next-line`,
|
|
3268
|
+
kind: ts.ScriptElementKind.string,
|
|
3269
|
+
insertText: "@effect-diagnostics-next-line " + disableSnippet,
|
|
3270
|
+
isSnippet: true,
|
|
3271
|
+
replacementSpan
|
|
3272
|
+
}];
|
|
3273
|
+
}
|
|
3274
|
+
return [];
|
|
3275
|
+
})
|
|
3276
|
+
});
|
|
3277
|
+
|
|
3278
|
+
// src/completions/effectSchemaSelfInClasses.ts
|
|
3279
|
+
var effectSchemaSelfInClasses = createCompletion({
|
|
3280
|
+
name: "effectSchemaSelfInClasses",
|
|
3281
|
+
apply: fn("effectSchemaSelfInClasses")(function* (sourceFile, position) {
|
|
3282
|
+
const ts = yield* service(TypeScriptApi);
|
|
3283
|
+
const maybeInfos = yield* option(
|
|
3284
|
+
parseDataForExtendsClassCompletion(sourceFile, position)
|
|
3285
|
+
);
|
|
3286
|
+
if (isNone2(maybeInfos)) return [];
|
|
3287
|
+
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
3288
|
+
const effectSchemaName = yield* option(
|
|
3289
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
3290
|
+
sourceFile,
|
|
3291
|
+
"effect",
|
|
3292
|
+
"Schema"
|
|
3293
|
+
)
|
|
3294
|
+
);
|
|
3295
|
+
const schemaIdentifier = match(effectSchemaName, {
|
|
3296
|
+
onNone: () => "Schema",
|
|
3297
|
+
onSome: (_) => _.text
|
|
3298
|
+
});
|
|
3299
|
+
if (schemaIdentifier !== accessedObject.text) return [];
|
|
3300
|
+
const name = className.text;
|
|
3301
|
+
return [{
|
|
3302
|
+
name: `Class<${name}>`,
|
|
3303
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3304
|
+
insertText: `${schemaIdentifier}.Class<${name}>("${name}")({${"${0}"}}){}`,
|
|
3305
|
+
replacementSpan,
|
|
3306
|
+
isSnippet: true
|
|
3307
|
+
}, {
|
|
3308
|
+
name: `TaggedError<${name}>`,
|
|
3309
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3310
|
+
insertText: `${schemaIdentifier}.TaggedError<${name}>("${name}")("${name}", {${"${0}"}}){}`,
|
|
3311
|
+
replacementSpan,
|
|
3312
|
+
isSnippet: true
|
|
3313
|
+
}, {
|
|
3314
|
+
name: `TaggedClass<${name}>`,
|
|
3315
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3316
|
+
insertText: `${schemaIdentifier}.TaggedClass<${name}>("${name}")("${name}", {${"${0}"}}){}`,
|
|
3317
|
+
replacementSpan,
|
|
3318
|
+
isSnippet: true
|
|
3319
|
+
}, {
|
|
3320
|
+
name: `TaggedRequest<${name}>`,
|
|
3321
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3322
|
+
insertText: `${schemaIdentifier}.TaggedRequest<${name}>("${name}")("${name}", {${"${0}"}}){}`,
|
|
3323
|
+
replacementSpan,
|
|
3324
|
+
isSnippet: true
|
|
3325
|
+
}];
|
|
3326
|
+
})
|
|
3327
|
+
});
|
|
3328
|
+
|
|
3329
|
+
// src/completions/effectSelfInClasses.ts
|
|
3330
|
+
var effectSelfInClasses = createCompletion({
|
|
3331
|
+
name: "effectSelfInClasses",
|
|
3332
|
+
apply: fn("effectSelfInClasses")(function* (sourceFile, position) {
|
|
3333
|
+
const ts = yield* service(TypeScriptApi);
|
|
3334
|
+
const maybeInfos = yield* option(
|
|
3335
|
+
parseDataForExtendsClassCompletion(sourceFile, position)
|
|
3336
|
+
);
|
|
3337
|
+
if (isNone2(maybeInfos)) return [];
|
|
3338
|
+
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
3339
|
+
const effectName = yield* option(
|
|
3340
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
3341
|
+
sourceFile,
|
|
3342
|
+
"effect",
|
|
3343
|
+
"Effect"
|
|
3344
|
+
)
|
|
3345
|
+
);
|
|
3346
|
+
const effectIdentifier = match(effectName, {
|
|
3347
|
+
onNone: () => "Effect",
|
|
3348
|
+
onSome: (_) => _.text
|
|
3349
|
+
});
|
|
3350
|
+
if (effectIdentifier !== accessedObject.text) return [];
|
|
3351
|
+
const name = className.text;
|
|
3352
|
+
return [{
|
|
3353
|
+
name: `Service<${name}>`,
|
|
3354
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3355
|
+
insertText: `${effectIdentifier}.Service<${name}>()("${name}", {${"${0}"}}){}`,
|
|
3356
|
+
replacementSpan,
|
|
3357
|
+
isSnippet: true
|
|
3358
|
+
}];
|
|
3359
|
+
})
|
|
3360
|
+
});
|
|
3361
|
+
|
|
3362
|
+
// src/completions/fnFunctionStar.ts
|
|
3363
|
+
var fnFunctionStar = createCompletion({
|
|
3364
|
+
name: "fnFunctionStar",
|
|
3365
|
+
apply: fn("fnFunctionStar")(function* (sourceFile, position) {
|
|
3366
|
+
const ts = yield* service(TypeScriptApi);
|
|
3367
|
+
const typeParser = yield* service(TypeParser);
|
|
3368
|
+
const maybeInfos = yield* option(
|
|
3369
|
+
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
3370
|
+
);
|
|
3371
|
+
if (isNone2(maybeInfos)) return [];
|
|
3372
|
+
const { accessedObject } = maybeInfos.value;
|
|
3373
|
+
const isEffectModule = yield* option(typeParser.importedEffectModule(accessedObject));
|
|
3374
|
+
if (isNone2(isEffectModule)) return [];
|
|
3375
|
+
const span = ts.createTextSpan(
|
|
3376
|
+
accessedObject.end + 1,
|
|
3377
|
+
Math.max(0, position - accessedObject.end - 1)
|
|
3378
|
+
);
|
|
3379
|
+
const maybeFnName = pipe(
|
|
3380
|
+
yield* getAncestorNodesInRange(sourceFile, toTextRange(accessedObject.pos)),
|
|
3381
|
+
filter(ts.isVariableDeclaration),
|
|
3382
|
+
map3((_) => _.name && ts.isIdentifier(_.name) ? _.name.text : ""),
|
|
3383
|
+
filter((_) => _.length > 0),
|
|
3384
|
+
head,
|
|
3385
|
+
map2((name) => [
|
|
3386
|
+
{
|
|
3387
|
+
name: `fn("${name}")`,
|
|
3388
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3389
|
+
insertText: `fn("${name}")(function*(${"${1}"}){${"${0}"}})`,
|
|
3390
|
+
replacementSpan: span,
|
|
3391
|
+
isSnippet: true
|
|
3388
3392
|
}
|
|
3389
|
-
|
|
3390
|
-
|
|
3393
|
+
]),
|
|
3394
|
+
getOrElse2(() => [])
|
|
3395
|
+
);
|
|
3396
|
+
return maybeFnName.concat([{
|
|
3397
|
+
name: `fn(function*(){})`,
|
|
3398
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3399
|
+
insertText: `fn(function*(${"${1}"}){${"${0}"}})`,
|
|
3400
|
+
replacementSpan: span,
|
|
3401
|
+
isSnippet: true
|
|
3402
|
+
}, {
|
|
3403
|
+
name: `fnUntraced(function*(){})`,
|
|
3404
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3405
|
+
insertText: `fnUntraced(function*(${"${1}"}){${"${0}"}})`,
|
|
3406
|
+
replacementSpan: span,
|
|
3407
|
+
isSnippet: true
|
|
3408
|
+
}]);
|
|
3391
3409
|
})
|
|
3392
3410
|
});
|
|
3393
3411
|
|
|
3394
|
-
// src/
|
|
3395
|
-
var
|
|
3396
|
-
name: "
|
|
3397
|
-
|
|
3398
|
-
severity: "error",
|
|
3399
|
-
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
3412
|
+
// src/completions/genFunctionStar.ts
|
|
3413
|
+
var genFunctionStar = createCompletion({
|
|
3414
|
+
name: "genFunctionStar",
|
|
3415
|
+
apply: fn("genFunctionStar")(function* (sourceFile, position) {
|
|
3400
3416
|
const ts = yield* service(TypeScriptApi);
|
|
3401
|
-
const
|
|
3402
|
-
const
|
|
3403
|
-
|
|
3404
|
-
const nodeToVisit = [];
|
|
3405
|
-
const appendNodeToVisit = (node) => {
|
|
3406
|
-
nodeToVisit.push(node);
|
|
3407
|
-
return void 0;
|
|
3408
|
-
};
|
|
3409
|
-
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3410
|
-
while (nodeToVisit.length > 0) {
|
|
3411
|
-
const node = nodeToVisit.shift();
|
|
3412
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
3413
|
-
if (ts.isYieldExpression(node) && node.expression && node.asteriskToken === void 0) {
|
|
3414
|
-
const functionStarNode = ts.findAncestor(
|
|
3415
|
-
node,
|
|
3416
|
-
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_)
|
|
3417
|
-
);
|
|
3418
|
-
if (functionStarNode && functionStarNode.parent) {
|
|
3419
|
-
const effectGenNode = functionStarNode.parent;
|
|
3420
|
-
yield* pipe(
|
|
3421
|
-
typeParser.effectGen(effectGenNode),
|
|
3422
|
-
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3423
|
-
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
3424
|
-
map4(({ functionStar }) => {
|
|
3425
|
-
if (functionStar) {
|
|
3426
|
-
brokenGenerators.add(functionStar);
|
|
3427
|
-
}
|
|
3428
|
-
brokenYields.add(node);
|
|
3429
|
-
}),
|
|
3430
|
-
ignore
|
|
3431
|
-
);
|
|
3432
|
-
}
|
|
3433
|
-
}
|
|
3434
|
-
}
|
|
3435
|
-
brokenGenerators.forEach(
|
|
3436
|
-
(node) => report({
|
|
3437
|
-
node,
|
|
3438
|
-
messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
|
|
3439
|
-
fixes: []
|
|
3440
|
-
})
|
|
3417
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3418
|
+
const maybeInfos = yield* option(
|
|
3419
|
+
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
3441
3420
|
);
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
|
|
3461
|
-
fixes: fix
|
|
3462
|
-
});
|
|
3463
|
-
});
|
|
3421
|
+
if (isNone2(maybeInfos)) return [];
|
|
3422
|
+
const { accessedObject } = maybeInfos.value;
|
|
3423
|
+
const type = typeChecker.getTypeAtLocation(accessedObject);
|
|
3424
|
+
const genMemberSymbol = type.getProperty("gen");
|
|
3425
|
+
if (!genMemberSymbol) return [];
|
|
3426
|
+
const genType = typeChecker.getTypeOfSymbolAtLocation(genMemberSymbol, accessedObject);
|
|
3427
|
+
if (genType.getCallSignatures().length === 0) return [];
|
|
3428
|
+
const span = ts.createTextSpan(
|
|
3429
|
+
accessedObject.end + 1,
|
|
3430
|
+
Math.max(0, position - accessedObject.end - 1)
|
|
3431
|
+
);
|
|
3432
|
+
return [{
|
|
3433
|
+
name: `gen(function*(){})`,
|
|
3434
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3435
|
+
insertText: `gen(function*(){${"${0}"}})`,
|
|
3436
|
+
replacementSpan: span,
|
|
3437
|
+
isSnippet: true
|
|
3438
|
+
}];
|
|
3464
3439
|
})
|
|
3465
3440
|
});
|
|
3466
3441
|
|
|
3467
|
-
// src/
|
|
3468
|
-
var
|
|
3469
|
-
name: "
|
|
3470
|
-
|
|
3471
|
-
severity: "suggestion",
|
|
3472
|
-
apply: fn("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
3442
|
+
// src/completions/rpcMakeClasses.ts
|
|
3443
|
+
var rpcMakeClasses = createCompletion({
|
|
3444
|
+
name: "rpcMakeClasses",
|
|
3445
|
+
apply: fn("rpcMakeClasses")(function* (sourceFile, position) {
|
|
3473
3446
|
const ts = yield* service(TypeScriptApi);
|
|
3474
|
-
const
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3447
|
+
const maybeInfos = yield* option(
|
|
3448
|
+
parseDataForExtendsClassCompletion(sourceFile, position)
|
|
3449
|
+
);
|
|
3450
|
+
if (isNone2(maybeInfos)) return [];
|
|
3451
|
+
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
3452
|
+
const rpcName = yield* option(
|
|
3453
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
3454
|
+
sourceFile,
|
|
3455
|
+
"@effect/rpc",
|
|
3456
|
+
"Rpc"
|
|
3457
|
+
)
|
|
3458
|
+
);
|
|
3459
|
+
const rpcIdentifier = match(rpcName, {
|
|
3460
|
+
onNone: () => "Rpc",
|
|
3461
|
+
onSome: (_) => _.text
|
|
3462
|
+
});
|
|
3463
|
+
if (rpcIdentifier !== accessedObject.text) return [];
|
|
3464
|
+
const name = className.text;
|
|
3465
|
+
return [{
|
|
3466
|
+
name: `make("${name}")`,
|
|
3467
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3468
|
+
insertText: `${rpcIdentifier}.make("${name}", {${"${0}"}}) {}`,
|
|
3469
|
+
replacementSpan,
|
|
3470
|
+
isSnippet: true
|
|
3471
|
+
}];
|
|
3472
|
+
})
|
|
3473
|
+
});
|
|
3474
|
+
|
|
3475
|
+
// src/completions.ts
|
|
3476
|
+
var completions = [
|
|
3477
|
+
effectSchemaSelfInClasses,
|
|
3478
|
+
effectSelfInClasses,
|
|
3479
|
+
contextSelfInClasses,
|
|
3480
|
+
rpcMakeClasses,
|
|
3481
|
+
genFunctionStar,
|
|
3482
|
+
fnFunctionStar,
|
|
3483
|
+
effectDataClasses,
|
|
3484
|
+
effectDiagnosticsComment
|
|
3485
|
+
];
|
|
3486
|
+
|
|
3487
|
+
// src/completions/middlewareNamespaceImports.ts
|
|
3488
|
+
var importablePackagesMetadataCache = /* @__PURE__ */ new Map();
|
|
3489
|
+
var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(function* (sourceFile) {
|
|
3490
|
+
const ts = yield* service(TypeScriptApi);
|
|
3491
|
+
const program = yield* service(TypeScriptProgram);
|
|
3492
|
+
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
3493
|
+
const host = program;
|
|
3494
|
+
const namespaceByFileName = /* @__PURE__ */ new Map();
|
|
3495
|
+
const excludedByFileName = /* @__PURE__ */ new Map();
|
|
3496
|
+
const unbarreledModulePathByFileName = /* @__PURE__ */ new Map();
|
|
3497
|
+
for (const packageName of languageServicePluginOptions.namespaceImportPackages) {
|
|
3498
|
+
const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
|
|
3499
|
+
if (barrelModule.resolvedModule) {
|
|
3500
|
+
const barrelPath = barrelModule.resolvedModule.resolvedFileName;
|
|
3501
|
+
const barrelSource = program.getSourceFile(barrelPath) || ts.createSourceFile(barrelPath, host.readFile(barrelPath) || "", sourceFile.languageVersion, true);
|
|
3502
|
+
if (barrelSource) {
|
|
3503
|
+
for (const statement of barrelSource.statements) {
|
|
3504
|
+
if (ts.isExportDeclaration(statement)) {
|
|
3505
|
+
const exportClause = statement.exportClause;
|
|
3506
|
+
const moduleSpecifier = statement.moduleSpecifier;
|
|
3507
|
+
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
3508
|
+
const unbarreledModulePathResolved = ts.resolveModuleName(
|
|
3509
|
+
moduleSpecifier.text,
|
|
3510
|
+
barrelSource.fileName,
|
|
3511
|
+
program.getCompilerOptions(),
|
|
3512
|
+
host
|
|
3513
|
+
);
|
|
3514
|
+
if (unbarreledModulePathResolved.resolvedModule) {
|
|
3515
|
+
const unbarreledModulePath = unbarreledModulePathResolved.resolvedModule.resolvedFileName;
|
|
3516
|
+
if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
|
|
3517
|
+
namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
|
|
3518
|
+
const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
|
|
3519
|
+
existingUnbarreledModulePath.push([exportClause.name.text, unbarreledModulePath]);
|
|
3520
|
+
unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
|
|
3521
|
+
}
|
|
3522
|
+
if (exportClause && ts.isNamedExports(exportClause)) {
|
|
3523
|
+
for (const element of exportClause.elements) {
|
|
3524
|
+
if (!ts.isIdentifier(element.name)) continue;
|
|
3525
|
+
const methodName = element.name.text;
|
|
3526
|
+
const excludedMethods = excludedByFileName.get(methodName) || [];
|
|
3527
|
+
excludedMethods.push(unbarreledModulePath);
|
|
3528
|
+
excludedByFileName.set(methodName, excludedMethods);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3527
3533
|
}
|
|
3528
3534
|
}
|
|
3529
3535
|
}
|
|
3530
3536
|
}
|
|
3531
|
-
}
|
|
3537
|
+
}
|
|
3538
|
+
return {
|
|
3539
|
+
getImportNamespaceByFileName: (fileName) => namespaceByFileName.get(fileName),
|
|
3540
|
+
isExcludedFromNamespaceImport: (fileName, exportName) => (excludedByFileName.get(exportName) || []).includes(fileName),
|
|
3541
|
+
getUnbarreledModulePath: (fileName, exportName) => unbarreledModulePathByFileName.get(fileName)?.find(([name]) => name === exportName)?.[1]
|
|
3542
|
+
};
|
|
3532
3543
|
});
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
}
|
|
3567
|
-
}
|
|
3568
|
-
}
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
)
|
|
3572
|
-
}
|
|
3544
|
+
var appendEffectCompletionEntryData = fn("collectNamespaceImports")(
|
|
3545
|
+
function* (sourceFile, applicableCompletions) {
|
|
3546
|
+
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
3547
|
+
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletions;
|
|
3548
|
+
const packagesMetadata = importablePackagesMetadataCache.get(sourceFile.fileName) || (yield* makeImportablePackagesMetadata(sourceFile));
|
|
3549
|
+
importablePackagesMetadataCache.set(sourceFile.fileName, packagesMetadata);
|
|
3550
|
+
if (applicableCompletions) {
|
|
3551
|
+
return {
|
|
3552
|
+
...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
|
+
};
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
return entry;
|
|
3582
|
+
})
|
|
3583
|
+
};
|
|
3573
3584
|
}
|
|
3574
|
-
|
|
3575
|
-
}
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
severity: "suggestion",
|
|
3582
|
-
apply: fn("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
3585
|
+
return applicableCompletions;
|
|
3586
|
+
}
|
|
3587
|
+
);
|
|
3588
|
+
var postprocessCompletionEntryDetails = fn("postprocessCompletionEntryDetails")(
|
|
3589
|
+
function* (sourceFile, data, applicableCompletionEntryDetails, formatOptions, preferences, languageServiceHost) {
|
|
3590
|
+
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
3591
|
+
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletionEntryDetails;
|
|
3583
3592
|
const ts = yield* service(TypeScriptApi);
|
|
3584
|
-
const
|
|
3585
|
-
const
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3593
|
+
const program = yield* service(TypeScriptProgram);
|
|
3594
|
+
const getModuleSpecifier = makeGetModuleSpecifier(ts);
|
|
3595
|
+
if (!getModuleSpecifier) return applicableCompletionEntryDetails;
|
|
3596
|
+
if (!applicableCompletionEntryDetails) return applicableCompletionEntryDetails;
|
|
3597
|
+
if (!data) return applicableCompletionEntryDetails;
|
|
3598
|
+
if (!("effectNamespaceName" in data && "effectUnbarreledModulePath" in data && "effectReplaceSpan" in data)) {
|
|
3599
|
+
return applicableCompletionEntryDetails;
|
|
3600
|
+
}
|
|
3601
|
+
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
|
+
}
|
|
3613
3663
|
}
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3664
|
+
);
|
|
3665
|
+
return {
|
|
3666
|
+
...applicableCompletionEntryDetails,
|
|
3667
|
+
codeActions: [
|
|
3668
|
+
{
|
|
3669
|
+
description: "Import * as " + data.effectNamespaceName + " from " + data.effectUnbarreledModulePath,
|
|
3670
|
+
changes
|
|
3671
|
+
}
|
|
3672
|
+
]
|
|
3673
|
+
};
|
|
3674
|
+
}
|
|
3617
3675
|
}
|
|
3618
3676
|
}
|
|
3619
|
-
|
|
3620
|
-
}
|
|
3621
|
-
|
|
3622
|
-
// src/diagnostics.ts
|
|
3623
|
-
var diagnostics = [
|
|
3624
|
-
duplicatePackage,
|
|
3625
|
-
missingEffectContext,
|
|
3626
|
-
missingEffectError,
|
|
3627
|
-
floatingEffect,
|
|
3628
|
-
missingStarInYieldEffectGen,
|
|
3629
|
-
unnecessaryEffectGen,
|
|
3630
|
-
missingReturnYieldStar,
|
|
3631
|
-
leakingRequirements,
|
|
3632
|
-
unnecessaryPipe,
|
|
3633
|
-
genericEffectServices,
|
|
3634
|
-
returnEffectInGen,
|
|
3635
|
-
importFromBarrel
|
|
3636
|
-
];
|
|
3677
|
+
return applicableCompletionEntryDetails;
|
|
3678
|
+
}
|
|
3679
|
+
);
|
|
3637
3680
|
|
|
3638
3681
|
// src/goto/effectRpcDefinition.ts
|
|
3639
3682
|
function effectRpcDefinition(applicableGotoDefinition, sourceFile, position) {
|