@effect/language-service 0.22.1 → 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 +1093 -1058
- package/index.js.map +1 -1
- package/package.json +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;
|
|
@@ -1732,139 +1733,364 @@ var effectDataClasses = createCompletion({
|
|
|
1732
1733
|
})
|
|
1733
1734
|
});
|
|
1734
1735
|
|
|
1735
|
-
// src/
|
|
1736
|
-
var
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
const
|
|
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
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
replacementSpan,
|
|
1775
|
-
isSnippet: true
|
|
1776
|
-
}, {
|
|
1777
|
-
name: `TaggedRequest<${name}>`,
|
|
1778
|
-
kind: ts.ScriptElementKind.constElement,
|
|
1779
|
-
insertText: `${schemaIdentifier}.TaggedRequest<${name}>("${name}")("${name}", {${"${0}"}}){}`,
|
|
1780
|
-
replacementSpan,
|
|
1781
|
-
isSnippet: true
|
|
1782
|
-
}];
|
|
1783
|
-
})
|
|
1784
|
-
});
|
|
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]))}.
|
|
1785
1775
|
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
const maybeInfos = yield* option(
|
|
1792
|
-
parseDataForExtendsClassCompletion(sourceFile, position)
|
|
1793
|
-
);
|
|
1794
|
-
if (isNone2(maybeInfos)) return [];
|
|
1795
|
-
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
1796
|
-
const effectName = yield* option(
|
|
1797
|
-
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
1798
|
-
sourceFile,
|
|
1799
|
-
"effect",
|
|
1800
|
-
"Effect"
|
|
1801
|
-
)
|
|
1802
|
-
);
|
|
1803
|
-
const effectIdentifier = match(effectName, {
|
|
1804
|
-
onNone: () => "Effect",
|
|
1805
|
-
onSome: (_) => _.text
|
|
1806
|
-
});
|
|
1807
|
-
if (effectIdentifier !== accessedObject.text) return [];
|
|
1808
|
-
const name = className.text;
|
|
1809
|
-
return [{
|
|
1810
|
-
name: `Service<${name}>`,
|
|
1811
|
-
kind: ts.ScriptElementKind.constElement,
|
|
1812
|
-
insertText: `${effectIdentifier}.Service<${name}>()("${name}", {${"${0}"}}){}`,
|
|
1813
|
-
replacementSpan,
|
|
1814
|
-
isSnippet: true
|
|
1815
|
-
}];
|
|
1776
|
+
${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
|
|
1777
|
+
fixes: []
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1816
1781
|
})
|
|
1817
1782
|
});
|
|
1818
1783
|
|
|
1819
|
-
// src/core/
|
|
1820
|
-
var
|
|
1821
|
-
var
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
const
|
|
1831
|
-
|
|
1832
|
-
|
|
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
|
+
}
|
|
1833
1821
|
}
|
|
1834
|
-
return
|
|
1822
|
+
return result;
|
|
1835
1823
|
}
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
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;
|
|
1840
1839
|
}
|
|
1841
|
-
|
|
1840
|
+
current = current.parent;
|
|
1842
1841
|
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
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
|
+
);
|
|
1847
1870
|
}
|
|
1848
|
-
return succeed(signatures[0].getReturnType());
|
|
1849
1871
|
}
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
if (signatures.length === 0) {
|
|
1859
|
-
return typeParserIssue("'pipe' property is not callable", type, atLocation);
|
|
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);
|
|
1860
1880
|
}
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
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(
|
|
2077
|
+
function(type, atLocation) {
|
|
2078
|
+
const pipeSymbol = typeChecker.getPropertyOfType(type, "pipe");
|
|
2079
|
+
if (!pipeSymbol) {
|
|
2080
|
+
return typeParserIssue("Type has no 'pipe' property", type, atLocation);
|
|
2081
|
+
}
|
|
2082
|
+
const pipeType = typeChecker.getTypeOfSymbolAtLocation(pipeSymbol, atLocation);
|
|
2083
|
+
const signatures = pipeType.getCallSignatures();
|
|
2084
|
+
if (signatures.length === 0) {
|
|
2085
|
+
return typeParserIssue("'pipe' property is not callable", type, atLocation);
|
|
2086
|
+
}
|
|
2087
|
+
return succeed(type);
|
|
2088
|
+
},
|
|
2089
|
+
"TypeParser.pipeableType",
|
|
2090
|
+
(type) => type
|
|
2091
|
+
);
|
|
2092
|
+
const varianceStructCovariantType = (type, atLocation, propertyName) => {
|
|
2093
|
+
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
1868
2094
|
if (!propertySymbol) {
|
|
1869
2095
|
return typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
1870
2096
|
}
|
|
@@ -2301,641 +2527,14 @@ function make4(ts, typeChecker) {
|
|
|
2301
2527
|
};
|
|
2302
2528
|
}
|
|
2303
2529
|
|
|
2304
|
-
// src/
|
|
2305
|
-
var
|
|
2306
|
-
name: "
|
|
2307
|
-
|
|
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) {
|
|
2308
2536
|
const ts = yield* service(TypeScriptApi);
|
|
2309
|
-
const
|
|
2310
|
-
const maybeInfos = yield* option(
|
|
2311
|
-
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
2312
|
-
);
|
|
2313
|
-
if (isNone2(maybeInfos)) return [];
|
|
2314
|
-
const { accessedObject } = maybeInfos.value;
|
|
2315
|
-
const isEffectModule = yield* option(typeParser.importedEffectModule(accessedObject));
|
|
2316
|
-
if (isNone2(isEffectModule)) return [];
|
|
2317
|
-
const span = ts.createTextSpan(
|
|
2318
|
-
accessedObject.end + 1,
|
|
2319
|
-
Math.max(0, position - accessedObject.end - 1)
|
|
2320
|
-
);
|
|
2321
|
-
const maybeFnName = pipe(
|
|
2322
|
-
yield* getAncestorNodesInRange(sourceFile, toTextRange(accessedObject.pos)),
|
|
2323
|
-
filter(ts.isVariableDeclaration),
|
|
2324
|
-
map3((_) => _.name && ts.isIdentifier(_.name) ? _.name.text : ""),
|
|
2325
|
-
filter((_) => _.length > 0),
|
|
2326
|
-
head,
|
|
2327
|
-
map2((name) => [
|
|
2328
|
-
{
|
|
2329
|
-
name: `fn("${name}")`,
|
|
2330
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2331
|
-
insertText: `fn("${name}")(function*(${"${1}"}){${"${0}"}})`,
|
|
2332
|
-
replacementSpan: span,
|
|
2333
|
-
isSnippet: true
|
|
2334
|
-
}
|
|
2335
|
-
]),
|
|
2336
|
-
getOrElse2(() => [])
|
|
2337
|
-
);
|
|
2338
|
-
return maybeFnName.concat([{
|
|
2339
|
-
name: `fn(function*(){})`,
|
|
2340
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2341
|
-
insertText: `fn(function*(${"${1}"}){${"${0}"}})`,
|
|
2342
|
-
replacementSpan: span,
|
|
2343
|
-
isSnippet: true
|
|
2344
|
-
}, {
|
|
2345
|
-
name: `fnUntraced(function*(){})`,
|
|
2346
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2347
|
-
insertText: `fnUntraced(function*(${"${1}"}){${"${0}"}})`,
|
|
2348
|
-
replacementSpan: span,
|
|
2349
|
-
isSnippet: true
|
|
2350
|
-
}]);
|
|
2351
|
-
})
|
|
2352
|
-
});
|
|
2353
|
-
|
|
2354
|
-
// src/core/TypeCheckerApi.ts
|
|
2355
|
-
var TypeCheckerApi = Tag("TypeChecker");
|
|
2356
|
-
var TypeCheckerApiCache = Tag("TypeCheckerApiCache");
|
|
2357
|
-
function makeTypeCheckerApiCache() {
|
|
2358
|
-
return {
|
|
2359
|
-
expectedAndRealType: /* @__PURE__ */ new WeakMap()
|
|
2360
|
-
};
|
|
2361
|
-
}
|
|
2362
|
-
var deterministicTypeOrder = gen(function* () {
|
|
2363
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2364
|
-
return make2((a, b) => {
|
|
2365
|
-
const aName = typeChecker.typeToString(a);
|
|
2366
|
-
const bName = typeChecker.typeToString(b);
|
|
2367
|
-
if (aName < bName) return -1;
|
|
2368
|
-
if (aName > bName) return 1;
|
|
2369
|
-
return 0;
|
|
2370
|
-
});
|
|
2371
|
-
});
|
|
2372
|
-
var getMissingTypeEntriesInTargetType = fn(
|
|
2373
|
-
"TypeCheckerApi.getMissingTypeEntriesInTargetType"
|
|
2374
|
-
)(
|
|
2375
|
-
function* (realType, expectedType) {
|
|
2376
|
-
if (realType === expectedType) return [];
|
|
2377
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2378
|
-
const result = [];
|
|
2379
|
-
let toTest = [realType];
|
|
2380
|
-
while (toTest.length > 0) {
|
|
2381
|
-
const type = toTest.pop();
|
|
2382
|
-
if (!type) return result;
|
|
2383
|
-
if (type.isUnion()) {
|
|
2384
|
-
toTest = toTest.concat(type.types);
|
|
2385
|
-
} else {
|
|
2386
|
-
const assignable = typeChecker.isTypeAssignableTo(type, expectedType);
|
|
2387
|
-
if (!assignable) {
|
|
2388
|
-
result.push(type);
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
|
-
return result;
|
|
2393
|
-
}
|
|
2394
|
-
);
|
|
2395
|
-
var CannotFindAncestorConvertibleDeclarationError = class {
|
|
2396
|
-
constructor(node) {
|
|
2397
|
-
this.node = node;
|
|
2398
|
-
}
|
|
2399
|
-
_tag = "@effect/language-service/CannotFindAncestorConvertibleDeclarationError";
|
|
2400
|
-
};
|
|
2401
|
-
var getAncestorConvertibleDeclaration = fn(
|
|
2402
|
-
"TypeCheckerApi.getAncestorConvertibleDeclaration"
|
|
2403
|
-
)(function* (node) {
|
|
2404
|
-
const ts = yield* service(TypeScriptApi);
|
|
2405
|
-
let current = node;
|
|
2406
|
-
while (current) {
|
|
2407
|
-
if (ts.isFunctionDeclaration(current) || ts.isFunctionExpression(current) || ts.isArrowFunction(current) || ts.isMethodDeclaration(current)) {
|
|
2408
|
-
return current;
|
|
2409
|
-
}
|
|
2410
|
-
current = current.parent;
|
|
2411
|
-
}
|
|
2412
|
-
return yield* fail(new CannotFindAncestorConvertibleDeclarationError(node));
|
|
2413
|
-
});
|
|
2414
|
-
var CannotInferReturnTypeFromEmptyBody = class {
|
|
2415
|
-
constructor(declaration) {
|
|
2416
|
-
this.declaration = declaration;
|
|
2417
|
-
}
|
|
2418
|
-
_tag = "@effect/language-service/CannotInferReturnTypeFromEmptyBody";
|
|
2419
|
-
};
|
|
2420
|
-
var CannotInferReturnType = class {
|
|
2421
|
-
constructor(declaration) {
|
|
2422
|
-
this.declaration = declaration;
|
|
2423
|
-
}
|
|
2424
|
-
_tag = "@effect/language-service/CannotInferReturnType";
|
|
2425
|
-
};
|
|
2426
|
-
var getInferredReturnType = fn("TypeCheckerApi.getInferredReturnType")(function* (declaration) {
|
|
2427
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2428
|
-
if (!declaration.body) {
|
|
2429
|
-
return yield* fail(
|
|
2430
|
-
new CannotInferReturnTypeFromEmptyBody(declaration)
|
|
2431
|
-
);
|
|
2432
|
-
}
|
|
2433
|
-
let returnType;
|
|
2434
|
-
if (typeChecker.isImplementationOfOverload(declaration)) {
|
|
2435
|
-
const signatures = typeChecker.getTypeAtLocation(declaration).getCallSignatures();
|
|
2436
|
-
if (signatures.length > 1) {
|
|
2437
|
-
returnType = typeChecker.getUnionType(
|
|
2438
|
-
signatures.map((s) => s.getReturnType()).filter((_) => !!_)
|
|
2439
|
-
);
|
|
2440
|
-
}
|
|
2441
|
-
}
|
|
2442
|
-
if (!returnType) {
|
|
2443
|
-
const signature = typeChecker.getSignatureFromDeclaration(declaration);
|
|
2444
|
-
if (signature) {
|
|
2445
|
-
const typePredicate = typeChecker.getTypePredicateOfSignature(signature);
|
|
2446
|
-
if (typePredicate && typePredicate.type) {
|
|
2447
|
-
return typePredicate.type;
|
|
2448
|
-
} else {
|
|
2449
|
-
returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
2450
|
-
}
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
if (!returnType) {
|
|
2454
|
-
return yield* fail(
|
|
2455
|
-
new CannotInferReturnType(declaration)
|
|
2456
|
-
);
|
|
2457
|
-
}
|
|
2458
|
-
return returnType;
|
|
2459
|
-
});
|
|
2460
|
-
var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (sourceFile) {
|
|
2461
|
-
const cache = yield* service(TypeCheckerApiCache);
|
|
2462
|
-
const resultCached = cache.expectedAndRealType.get(sourceFile);
|
|
2463
|
-
if (resultCached) return resultCached;
|
|
2464
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2465
|
-
const ts = yield* service(TypeScriptApi);
|
|
2466
|
-
const result = [];
|
|
2467
|
-
const nodeToVisit = [sourceFile];
|
|
2468
|
-
const appendNodeToVisit = (node) => {
|
|
2469
|
-
nodeToVisit.push(node);
|
|
2470
|
-
return void 0;
|
|
2471
|
-
};
|
|
2472
|
-
while (nodeToVisit.length > 0) {
|
|
2473
|
-
const node = nodeToVisit.shift();
|
|
2474
|
-
if (ts.isVariableDeclaration(node) && node.initializer) {
|
|
2475
|
-
const expectedType = typeChecker.getTypeAtLocation(node.name);
|
|
2476
|
-
const realType = typeChecker.getTypeAtLocation(node.initializer);
|
|
2477
|
-
result.push([node.name, expectedType, node.initializer, realType]);
|
|
2478
|
-
appendNodeToVisit(node.initializer);
|
|
2479
|
-
continue;
|
|
2480
|
-
} else if (ts.isCallExpression(node)) {
|
|
2481
|
-
const resolvedSignature = typeChecker.getResolvedSignature(node);
|
|
2482
|
-
if (resolvedSignature) {
|
|
2483
|
-
resolvedSignature.getParameters().map((parameter, index) => {
|
|
2484
|
-
const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
|
|
2485
|
-
const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
|
|
2486
|
-
result.push([
|
|
2487
|
-
node.arguments[index],
|
|
2488
|
-
expectedType,
|
|
2489
|
-
node.arguments[index],
|
|
2490
|
-
realType
|
|
2491
|
-
]);
|
|
2492
|
-
});
|
|
2493
|
-
}
|
|
2494
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2495
|
-
continue;
|
|
2496
|
-
} else if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
2497
|
-
const parent = node.parent;
|
|
2498
|
-
if (ts.isObjectLiteralElement(parent)) {
|
|
2499
|
-
if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
|
|
2500
|
-
const type = typeChecker.getContextualType(parent.parent);
|
|
2501
|
-
if (type) {
|
|
2502
|
-
const symbol3 = typeChecker.getPropertyOfType(type, node.text);
|
|
2503
|
-
if (symbol3) {
|
|
2504
|
-
const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
|
|
2505
|
-
const realType = typeChecker.getTypeAtLocation(node);
|
|
2506
|
-
result.push([node, expectedType, node, realType]);
|
|
2507
|
-
}
|
|
2508
|
-
}
|
|
2509
|
-
}
|
|
2510
|
-
}
|
|
2511
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2512
|
-
continue;
|
|
2513
|
-
} else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
2514
|
-
const expectedType = typeChecker.getTypeAtLocation(node.left);
|
|
2515
|
-
const realType = typeChecker.getTypeAtLocation(node.right);
|
|
2516
|
-
result.push([node.left, expectedType, node.right, realType]);
|
|
2517
|
-
appendNodeToVisit(node.right);
|
|
2518
|
-
continue;
|
|
2519
|
-
} else if (ts.isReturnStatement(node) && node.expression) {
|
|
2520
|
-
const parentDeclaration = yield* option(getAncestorConvertibleDeclaration(node));
|
|
2521
|
-
if (isSome2(parentDeclaration)) {
|
|
2522
|
-
const expectedType = yield* option(getInferredReturnType(parentDeclaration.value));
|
|
2523
|
-
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2524
|
-
if (isSome2(expectedType)) {
|
|
2525
|
-
result.push([node, expectedType.value, node, realType]);
|
|
2526
|
-
}
|
|
2527
|
-
}
|
|
2528
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2529
|
-
continue;
|
|
2530
|
-
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length === 0 && ts.isExpression(node.body)) {
|
|
2531
|
-
const body = node.body;
|
|
2532
|
-
const expectedType = typeChecker.getContextualType(body);
|
|
2533
|
-
const realType = typeChecker.getTypeAtLocation(body);
|
|
2534
|
-
if (expectedType) {
|
|
2535
|
-
result.push([body, expectedType, body, realType]);
|
|
2536
|
-
}
|
|
2537
|
-
ts.forEachChild(body, appendNodeToVisit);
|
|
2538
|
-
continue;
|
|
2539
|
-
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length > 0 && ts.isExpression(node.body)) {
|
|
2540
|
-
const body = node.body;
|
|
2541
|
-
const expectedType = yield* option(getInferredReturnType(node));
|
|
2542
|
-
const realType = typeChecker.getTypeAtLocation(body);
|
|
2543
|
-
if (isSome2(expectedType)) {
|
|
2544
|
-
result.push([body, expectedType.value, body, realType]);
|
|
2545
|
-
}
|
|
2546
|
-
ts.forEachChild(body, appendNodeToVisit);
|
|
2547
|
-
continue;
|
|
2548
|
-
} else if (ts.isSatisfiesExpression(node)) {
|
|
2549
|
-
const expectedType = typeChecker.getTypeAtLocation(node.type);
|
|
2550
|
-
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2551
|
-
result.push([node.expression, expectedType, node.expression, realType]);
|
|
2552
|
-
appendNodeToVisit(node.expression);
|
|
2553
|
-
continue;
|
|
2554
|
-
}
|
|
2555
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2556
|
-
}
|
|
2557
|
-
cache.expectedAndRealType.set(sourceFile, result);
|
|
2558
|
-
return result;
|
|
2559
|
-
});
|
|
2560
|
-
var appendToUniqueTypesMap = fn(
|
|
2561
|
-
"TypeCheckerApi.appendToUniqueTypesMap"
|
|
2562
|
-
)(
|
|
2563
|
-
function* (memory, initialType, excludeNever) {
|
|
2564
|
-
const ts = yield* service(TypeScriptApi);
|
|
2565
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2566
|
-
const newIndexes = /* @__PURE__ */ new Set();
|
|
2567
|
-
const knownIndexes = /* @__PURE__ */ new Set();
|
|
2568
|
-
let toTest = [initialType];
|
|
2569
|
-
while (toTest.length > 0) {
|
|
2570
|
-
const type = toTest.pop();
|
|
2571
|
-
if (!type) break;
|
|
2572
|
-
if (excludeNever && type.flags & ts.TypeFlags.Never) {
|
|
2573
|
-
continue;
|
|
2574
|
-
}
|
|
2575
|
-
if (type.isUnion()) {
|
|
2576
|
-
toTest = toTest.concat(type.types);
|
|
2577
|
-
} else {
|
|
2578
|
-
const foundMatch = [];
|
|
2579
|
-
for (const [typeId, knownType] of memory.entries()) {
|
|
2580
|
-
const areSame = typeChecker.isTypeAssignableTo(knownType, type) && typeChecker.isTypeAssignableTo(type, knownType);
|
|
2581
|
-
if (areSame) {
|
|
2582
|
-
foundMatch.push(typeId);
|
|
2583
|
-
break;
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
if (foundMatch.length === 0) {
|
|
2587
|
-
const newId = "t" + (memory.size + 1);
|
|
2588
|
-
memory.set(newId, type);
|
|
2589
|
-
newIndexes.add(newId);
|
|
2590
|
-
} else {
|
|
2591
|
-
knownIndexes.add(foundMatch[0]);
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
}
|
|
2595
|
-
return {
|
|
2596
|
-
newIndexes,
|
|
2597
|
-
knownIndexes,
|
|
2598
|
-
allIndexes: pipe(
|
|
2599
|
-
fromIterable(newIndexes),
|
|
2600
|
-
appendAll(fromIterable(knownIndexes))
|
|
2601
|
-
)
|
|
2602
|
-
};
|
|
2603
|
-
}
|
|
2604
|
-
);
|
|
2605
|
-
function makeResolveExternalModuleName(typeChecker) {
|
|
2606
|
-
if (!(hasProperty(typeChecker, "resolveExternalModuleName") && isFunction(typeChecker.resolveExternalModuleName))) {
|
|
2607
|
-
return;
|
|
2608
|
-
}
|
|
2609
|
-
const _internal = typeChecker.resolveExternalModuleName;
|
|
2610
|
-
return (moduleSpecifier) => {
|
|
2611
|
-
return _internal(moduleSpecifier);
|
|
2612
|
-
};
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
// src/completions/genFunctionStar.ts
|
|
2616
|
-
var genFunctionStar = createCompletion({
|
|
2617
|
-
name: "genFunctionStar",
|
|
2618
|
-
apply: fn("genFunctionStar")(function* (sourceFile, position) {
|
|
2619
|
-
const ts = yield* service(TypeScriptApi);
|
|
2620
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2621
|
-
const maybeInfos = yield* option(
|
|
2622
|
-
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
2623
|
-
);
|
|
2624
|
-
if (isNone2(maybeInfos)) return [];
|
|
2625
|
-
const { accessedObject } = maybeInfos.value;
|
|
2626
|
-
const type = typeChecker.getTypeAtLocation(accessedObject);
|
|
2627
|
-
const genMemberSymbol = type.getProperty("gen");
|
|
2628
|
-
if (!genMemberSymbol) return [];
|
|
2629
|
-
const genType = typeChecker.getTypeOfSymbolAtLocation(genMemberSymbol, accessedObject);
|
|
2630
|
-
if (genType.getCallSignatures().length === 0) return [];
|
|
2631
|
-
const span = ts.createTextSpan(
|
|
2632
|
-
accessedObject.end + 1,
|
|
2633
|
-
Math.max(0, position - accessedObject.end - 1)
|
|
2634
|
-
);
|
|
2635
|
-
return [{
|
|
2636
|
-
name: `gen(function*(){})`,
|
|
2637
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2638
|
-
insertText: `gen(function*(){${"${0}"}})`,
|
|
2639
|
-
replacementSpan: span,
|
|
2640
|
-
isSnippet: true
|
|
2641
|
-
}];
|
|
2642
|
-
})
|
|
2643
|
-
});
|
|
2644
|
-
|
|
2645
|
-
// src/completions/rpcMakeClasses.ts
|
|
2646
|
-
var rpcMakeClasses = createCompletion({
|
|
2647
|
-
name: "rpcMakeClasses",
|
|
2648
|
-
apply: fn("rpcMakeClasses")(function* (sourceFile, position) {
|
|
2649
|
-
const ts = yield* service(TypeScriptApi);
|
|
2650
|
-
const maybeInfos = yield* option(
|
|
2651
|
-
parseDataForExtendsClassCompletion(sourceFile, position)
|
|
2652
|
-
);
|
|
2653
|
-
if (isNone2(maybeInfos)) return [];
|
|
2654
|
-
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
2655
|
-
const rpcName = yield* option(
|
|
2656
|
-
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
2657
|
-
sourceFile,
|
|
2658
|
-
"@effect/rpc",
|
|
2659
|
-
"Rpc"
|
|
2660
|
-
)
|
|
2661
|
-
);
|
|
2662
|
-
const rpcIdentifier = match(rpcName, {
|
|
2663
|
-
onNone: () => "Rpc",
|
|
2664
|
-
onSome: (_) => _.text
|
|
2665
|
-
});
|
|
2666
|
-
if (rpcIdentifier !== accessedObject.text) return [];
|
|
2667
|
-
const name = className.text;
|
|
2668
|
-
return [{
|
|
2669
|
-
name: `make("${name}")`,
|
|
2670
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2671
|
-
insertText: `${rpcIdentifier}.make("${name}", {${"${0}"}}) {}`,
|
|
2672
|
-
replacementSpan,
|
|
2673
|
-
isSnippet: true
|
|
2674
|
-
}];
|
|
2675
|
-
})
|
|
2676
|
-
});
|
|
2677
|
-
|
|
2678
|
-
// src/completions.ts
|
|
2679
|
-
var completions = [
|
|
2680
|
-
effectSchemaSelfInClasses,
|
|
2681
|
-
effectSelfInClasses,
|
|
2682
|
-
contextSelfInClasses,
|
|
2683
|
-
rpcMakeClasses,
|
|
2684
|
-
genFunctionStar,
|
|
2685
|
-
fnFunctionStar,
|
|
2686
|
-
effectDataClasses
|
|
2687
|
-
];
|
|
2688
|
-
|
|
2689
|
-
// src/completions/middlewareNamespaceImports.ts
|
|
2690
|
-
var importablePackagesMetadataCache = /* @__PURE__ */ new Map();
|
|
2691
|
-
var makeImportablePackagesMetadata = fn("makeImportablePackagesMetadata")(function* (sourceFile) {
|
|
2692
|
-
const ts = yield* service(TypeScriptApi);
|
|
2693
|
-
const program = yield* service(TypeScriptProgram);
|
|
2694
|
-
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
2695
|
-
const host = program;
|
|
2696
|
-
const namespaceByFileName = /* @__PURE__ */ new Map();
|
|
2697
|
-
const excludedByFileName = /* @__PURE__ */ new Map();
|
|
2698
|
-
const unbarreledModulePathByFileName = /* @__PURE__ */ new Map();
|
|
2699
|
-
for (const packageName of languageServicePluginOptions.namespaceImportPackages) {
|
|
2700
|
-
const barrelModule = ts.resolveModuleName(packageName, sourceFile.fileName, program.getCompilerOptions(), host);
|
|
2701
|
-
if (barrelModule.resolvedModule) {
|
|
2702
|
-
const barrelPath = barrelModule.resolvedModule.resolvedFileName;
|
|
2703
|
-
const barrelSource = program.getSourceFile(barrelPath) || ts.createSourceFile(barrelPath, host.readFile(barrelPath) || "", sourceFile.languageVersion, true);
|
|
2704
|
-
if (barrelSource) {
|
|
2705
|
-
for (const statement of barrelSource.statements) {
|
|
2706
|
-
if (ts.isExportDeclaration(statement)) {
|
|
2707
|
-
const exportClause = statement.exportClause;
|
|
2708
|
-
const moduleSpecifier = statement.moduleSpecifier;
|
|
2709
|
-
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
2710
|
-
const unbarreledModulePathResolved = ts.resolveModuleName(
|
|
2711
|
-
moduleSpecifier.text,
|
|
2712
|
-
barrelSource.fileName,
|
|
2713
|
-
program.getCompilerOptions(),
|
|
2714
|
-
host
|
|
2715
|
-
);
|
|
2716
|
-
if (unbarreledModulePathResolved.resolvedModule) {
|
|
2717
|
-
const unbarreledModulePath = unbarreledModulePathResolved.resolvedModule.resolvedFileName;
|
|
2718
|
-
if (exportClause && ts.isNamespaceExport(exportClause) && ts.isIdentifier(exportClause.name)) {
|
|
2719
|
-
namespaceByFileName.set(unbarreledModulePath, exportClause.name.text);
|
|
2720
|
-
const existingUnbarreledModulePath = unbarreledModulePathByFileName.get(barrelSource.fileName) || [];
|
|
2721
|
-
existingUnbarreledModulePath.push([exportClause.name.text, unbarreledModulePath]);
|
|
2722
|
-
unbarreledModulePathByFileName.set(barrelSource.fileName, existingUnbarreledModulePath);
|
|
2723
|
-
}
|
|
2724
|
-
if (exportClause && ts.isNamedExports(exportClause)) {
|
|
2725
|
-
for (const element of exportClause.elements) {
|
|
2726
|
-
if (!ts.isIdentifier(element.name)) continue;
|
|
2727
|
-
const methodName = element.name.text;
|
|
2728
|
-
const excludedMethods = excludedByFileName.get(methodName) || [];
|
|
2729
|
-
excludedMethods.push(unbarreledModulePath);
|
|
2730
|
-
excludedByFileName.set(methodName, excludedMethods);
|
|
2731
|
-
}
|
|
2732
|
-
}
|
|
2733
|
-
}
|
|
2734
|
-
}
|
|
2735
|
-
}
|
|
2736
|
-
}
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
}
|
|
2740
|
-
return {
|
|
2741
|
-
getImportNamespaceByFileName: (fileName) => namespaceByFileName.get(fileName),
|
|
2742
|
-
isExcludedFromNamespaceImport: (fileName, exportName) => (excludedByFileName.get(exportName) || []).includes(fileName),
|
|
2743
|
-
getUnbarreledModulePath: (fileName, exportName) => unbarreledModulePathByFileName.get(fileName)?.find(([name]) => name === exportName)?.[1]
|
|
2744
|
-
};
|
|
2745
|
-
});
|
|
2746
|
-
var appendEffectCompletionEntryData = fn("collectNamespaceImports")(
|
|
2747
|
-
function* (sourceFile, applicableCompletions) {
|
|
2748
|
-
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
2749
|
-
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletions;
|
|
2750
|
-
const packagesMetadata = importablePackagesMetadataCache.get(sourceFile.fileName) || (yield* makeImportablePackagesMetadata(sourceFile));
|
|
2751
|
-
importablePackagesMetadataCache.set(sourceFile.fileName, packagesMetadata);
|
|
2752
|
-
if (applicableCompletions) {
|
|
2753
|
-
return {
|
|
2754
|
-
...applicableCompletions,
|
|
2755
|
-
entries: applicableCompletions.entries.map((entry) => {
|
|
2756
|
-
if (entry.data && entry.data.fileName && !entry.insertText && !entry.filterText && entry.data.exportName && entry.data.moduleSpecifier) {
|
|
2757
|
-
const isExcluded = packagesMetadata.isExcludedFromNamespaceImport(
|
|
2758
|
-
entry.data.fileName,
|
|
2759
|
-
entry.data.exportName
|
|
2760
|
-
);
|
|
2761
|
-
if (isExcluded) return entry;
|
|
2762
|
-
const unbarreledModulePath = packagesMetadata.getUnbarreledModulePath(
|
|
2763
|
-
entry.data.fileName,
|
|
2764
|
-
entry.data.exportName
|
|
2765
|
-
);
|
|
2766
|
-
const namespaceName = packagesMetadata.getImportNamespaceByFileName(
|
|
2767
|
-
unbarreledModulePath || entry.data.fileName
|
|
2768
|
-
);
|
|
2769
|
-
if (namespaceName) {
|
|
2770
|
-
return {
|
|
2771
|
-
...entry,
|
|
2772
|
-
// insertText: unbarreledModulePath ? namespaceName : namespaceName + "." + entry.name,
|
|
2773
|
-
// filterText: entry.name,
|
|
2774
|
-
data: {
|
|
2775
|
-
...entry.data,
|
|
2776
|
-
effectNamespaceName: namespaceName,
|
|
2777
|
-
effectUnbarreledModulePath: unbarreledModulePath || "",
|
|
2778
|
-
effectReplaceSpan: entry.replacementSpan || applicableCompletions.optionalReplacementSpan
|
|
2779
|
-
}
|
|
2780
|
-
};
|
|
2781
|
-
}
|
|
2782
|
-
}
|
|
2783
|
-
return entry;
|
|
2784
|
-
})
|
|
2785
|
-
};
|
|
2786
|
-
}
|
|
2787
|
-
return applicableCompletions;
|
|
2788
|
-
}
|
|
2789
|
-
);
|
|
2790
|
-
var postprocessCompletionEntryDetails = fn("postprocessCompletionEntryDetails")(
|
|
2791
|
-
function* (sourceFile, data, applicableCompletionEntryDetails, formatOptions, preferences, languageServiceHost) {
|
|
2792
|
-
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
2793
|
-
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return applicableCompletionEntryDetails;
|
|
2794
|
-
const ts = yield* service(TypeScriptApi);
|
|
2795
|
-
const program = yield* service(TypeScriptProgram);
|
|
2796
|
-
const getModuleSpecifier = makeGetModuleSpecifier(ts);
|
|
2797
|
-
if (!getModuleSpecifier) return applicableCompletionEntryDetails;
|
|
2798
|
-
if (!applicableCompletionEntryDetails) return applicableCompletionEntryDetails;
|
|
2799
|
-
if (!data) return applicableCompletionEntryDetails;
|
|
2800
|
-
if (!("effectNamespaceName" in data && "effectUnbarreledModulePath" in data && "effectReplaceSpan" in data)) {
|
|
2801
|
-
return applicableCompletionEntryDetails;
|
|
2802
|
-
}
|
|
2803
|
-
const effectReplaceSpan = data.effectReplaceSpan;
|
|
2804
|
-
const codeActions = applicableCompletionEntryDetails.codeActions;
|
|
2805
|
-
if (codeActions && codeActions.length === 1) {
|
|
2806
|
-
const action = codeActions[0];
|
|
2807
|
-
if (action.changes.length === 1) {
|
|
2808
|
-
const fileTextChanges = action.changes[0];
|
|
2809
|
-
if (fileTextChanges.fileName === sourceFile.fileName && fileTextChanges.textChanges.length === 1) {
|
|
2810
|
-
const change = fileTextChanges.textChanges[0];
|
|
2811
|
-
let hasImportActions = false;
|
|
2812
|
-
if (change.newText.trim().toLowerCase().startsWith("import") && change.newText.indexOf(data.exportName) > -1) {
|
|
2813
|
-
hasImportActions = true;
|
|
2814
|
-
}
|
|
2815
|
-
if (!hasImportActions && change.newText.indexOf(data.exportName) > -1) {
|
|
2816
|
-
const ancestorNodes = yield* getAncestorNodesInRange(sourceFile, {
|
|
2817
|
-
pos: change.span.start,
|
|
2818
|
-
end: change.span.start
|
|
2819
|
-
});
|
|
2820
|
-
const importNodes = ancestorNodes.filter((node) => ts.isImportDeclaration(node));
|
|
2821
|
-
hasImportActions = importNodes.length > 0;
|
|
2822
|
-
}
|
|
2823
|
-
if (!hasImportActions) return applicableCompletionEntryDetails;
|
|
2824
|
-
const formatContext = ts.formatting.getFormatContext(
|
|
2825
|
-
formatOptions || {},
|
|
2826
|
-
languageServiceHost
|
|
2827
|
-
);
|
|
2828
|
-
const changes = ts.textChanges.ChangeTracker.with(
|
|
2829
|
-
{
|
|
2830
|
-
formatContext,
|
|
2831
|
-
host: languageServiceHost,
|
|
2832
|
-
preferences: preferences || {}
|
|
2833
|
-
},
|
|
2834
|
-
(changeTracker) => {
|
|
2835
|
-
const isBarrelRedirect = String(data.effectUnbarreledModulePath).length > 0;
|
|
2836
|
-
const moduleSpecifier = isBarrelRedirect ? getModuleSpecifier(
|
|
2837
|
-
program.getCompilerOptions(),
|
|
2838
|
-
sourceFile,
|
|
2839
|
-
sourceFile.fileName,
|
|
2840
|
-
String(data.effectUnbarreledModulePath),
|
|
2841
|
-
program
|
|
2842
|
-
) : String(data.moduleSpecifier);
|
|
2843
|
-
ts.insertImports(
|
|
2844
|
-
changeTracker,
|
|
2845
|
-
sourceFile,
|
|
2846
|
-
ts.factory.createImportDeclaration(
|
|
2847
|
-
void 0,
|
|
2848
|
-
ts.factory.createImportClause(
|
|
2849
|
-
false,
|
|
2850
|
-
void 0,
|
|
2851
|
-
ts.factory.createNamespaceImport(ts.factory.createIdentifier(String(data.effectNamespaceName)))
|
|
2852
|
-
),
|
|
2853
|
-
ts.factory.createStringLiteral(moduleSpecifier)
|
|
2854
|
-
),
|
|
2855
|
-
true,
|
|
2856
|
-
preferences || {}
|
|
2857
|
-
);
|
|
2858
|
-
if (!isBarrelRedirect) {
|
|
2859
|
-
changeTracker.insertText(
|
|
2860
|
-
sourceFile,
|
|
2861
|
-
effectReplaceSpan.start,
|
|
2862
|
-
String(data.effectNamespaceName) + "."
|
|
2863
|
-
);
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
|
-
);
|
|
2867
|
-
return {
|
|
2868
|
-
...applicableCompletionEntryDetails,
|
|
2869
|
-
codeActions: [
|
|
2870
|
-
{
|
|
2871
|
-
description: "Import * as " + data.effectNamespaceName + " from " + data.effectUnbarreledModulePath,
|
|
2872
|
-
changes
|
|
2873
|
-
}
|
|
2874
|
-
]
|
|
2875
|
-
};
|
|
2876
|
-
}
|
|
2877
|
-
}
|
|
2878
|
-
}
|
|
2879
|
-
return applicableCompletionEntryDetails;
|
|
2880
|
-
}
|
|
2881
|
-
);
|
|
2882
|
-
|
|
2883
|
-
// src/diagnostics/duplicatePackage.ts
|
|
2884
|
-
var checkedPackagesCache = /* @__PURE__ */ new Map();
|
|
2885
|
-
var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
2886
|
-
var duplicatePackage = createDiagnostic({
|
|
2887
|
-
name: "duplicatePackage",
|
|
2888
|
-
code: 6,
|
|
2889
|
-
severity: "warning",
|
|
2890
|
-
apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
2891
|
-
const program = yield* service(TypeScriptProgram);
|
|
2892
|
-
const options = yield* service(LanguageServicePluginOptions);
|
|
2893
|
-
if (sourceFile.statements.length < 1) return;
|
|
2894
|
-
let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
|
|
2895
|
-
const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
|
|
2896
|
-
const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
|
|
2897
|
-
if (newResolvedModuleSize !== oldResolvedSize) {
|
|
2898
|
-
const seenPackages = /* @__PURE__ */ new Set();
|
|
2899
|
-
resolvedPackages = {};
|
|
2900
|
-
program.getSourceFiles().map((_) => {
|
|
2901
|
-
const packageInfo = parsePackageContentNameAndVersionFromScope(_);
|
|
2902
|
-
if (!packageInfo) return;
|
|
2903
|
-
const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
|
|
2904
|
-
if (seenPackages.has(packageNameAndVersion)) return;
|
|
2905
|
-
seenPackages.add(packageNameAndVersion);
|
|
2906
|
-
if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
|
|
2907
|
-
if (options.allowedDuplicatedPackages.indexOf(packageInfo.name) > -1) return;
|
|
2908
|
-
resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
|
|
2909
|
-
resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.packageDirectory;
|
|
2910
|
-
});
|
|
2911
|
-
checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
|
|
2912
|
-
programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
|
|
2913
|
-
}
|
|
2914
|
-
for (const packageName of Object.keys(resolvedPackages)) {
|
|
2915
|
-
if (Object.keys(resolvedPackages[packageName]).length > 1) {
|
|
2916
|
-
const versions = Object.keys(resolvedPackages[packageName]);
|
|
2917
|
-
report({
|
|
2918
|
-
node: sourceFile.statements[0],
|
|
2919
|
-
messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
|
|
2920
|
-
Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
|
|
2921
|
-
If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
2922
|
-
|
|
2923
|
-
${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
|
|
2924
|
-
fixes: []
|
|
2925
|
-
});
|
|
2926
|
-
}
|
|
2927
|
-
}
|
|
2928
|
-
})
|
|
2929
|
-
});
|
|
2930
|
-
|
|
2931
|
-
// src/diagnostics/floatingEffect.ts
|
|
2932
|
-
var floatingEffect = createDiagnostic({
|
|
2933
|
-
name: "floatingEffect",
|
|
2934
|
-
code: 3,
|
|
2935
|
-
severity: "error",
|
|
2936
|
-
apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
|
|
2937
|
-
const ts = yield* service(TypeScriptApi);
|
|
2938
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2537
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2939
2538
|
const typeParser = yield* service(TypeParser);
|
|
2940
2539
|
function isFloatingExpression(node) {
|
|
2941
2540
|
if (!ts.isExpressionStatement(node)) return false;
|
|
@@ -3295,38 +2894,285 @@ var missingEffectError = createDiagnostic({
|
|
|
3295
2894
|
apply: fn("missingEffectError.apply")(function* (sourceFile, report) {
|
|
3296
2895
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3297
2896
|
const typeParser = yield* service(TypeParser);
|
|
3298
|
-
const typeOrder = yield* deterministicTypeOrder;
|
|
3299
|
-
const checkForMissingErrorTypes = (node, expectedType, valueNode, realType) => pipe(
|
|
3300
|
-
all(
|
|
3301
|
-
typeParser.effectType(expectedType, node),
|
|
3302
|
-
typeParser.effectType(realType, valueNode)
|
|
3303
|
-
),
|
|
3304
|
-
flatMap2(
|
|
3305
|
-
([expectedEffect, realEffect]) => getMissingTypeEntriesInTargetType(
|
|
3306
|
-
realEffect.E,
|
|
3307
|
-
expectedEffect.E
|
|
3308
|
-
)
|
|
3309
|
-
)
|
|
3310
|
-
);
|
|
3311
|
-
const sortTypes = sort(typeOrder);
|
|
3312
|
-
const entries = yield* expectedAndRealType(sourceFile);
|
|
3313
|
-
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
3314
|
-
if (expectedType !== realType) {
|
|
2897
|
+
const typeOrder = yield* deterministicTypeOrder;
|
|
2898
|
+
const checkForMissingErrorTypes = (node, expectedType, valueNode, realType) => pipe(
|
|
2899
|
+
all(
|
|
2900
|
+
typeParser.effectType(expectedType, node),
|
|
2901
|
+
typeParser.effectType(realType, valueNode)
|
|
2902
|
+
),
|
|
2903
|
+
flatMap2(
|
|
2904
|
+
([expectedEffect, realEffect]) => getMissingTypeEntriesInTargetType(
|
|
2905
|
+
realEffect.E,
|
|
2906
|
+
expectedEffect.E
|
|
2907
|
+
)
|
|
2908
|
+
)
|
|
2909
|
+
);
|
|
2910
|
+
const sortTypes = sort(typeOrder);
|
|
2911
|
+
const entries = yield* expectedAndRealType(sourceFile);
|
|
2912
|
+
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
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(
|
|
3022
|
+
node,
|
|
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,
|
|
3057
|
+
node,
|
|
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
|
+
);
|
|
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)) {
|
|
3315
3159
|
yield* pipe(
|
|
3316
|
-
|
|
3317
|
-
node,
|
|
3318
|
-
expectedType,
|
|
3319
|
-
valueNode,
|
|
3320
|
-
realType
|
|
3321
|
-
),
|
|
3160
|
+
typeParser.unnecessaryEffectGen(node),
|
|
3322
3161
|
map4(
|
|
3323
|
-
(
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
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
|
+
})
|
|
3330
3176
|
),
|
|
3331
3177
|
ignore
|
|
3332
3178
|
);
|
|
@@ -3335,14 +3181,13 @@ var missingEffectError = createDiagnostic({
|
|
|
3335
3181
|
})
|
|
3336
3182
|
});
|
|
3337
3183
|
|
|
3338
|
-
// src/diagnostics/
|
|
3339
|
-
var
|
|
3340
|
-
name: "
|
|
3341
|
-
code:
|
|
3342
|
-
severity: "
|
|
3343
|
-
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) {
|
|
3344
3190
|
const ts = yield* service(TypeScriptApi);
|
|
3345
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
3346
3191
|
const typeParser = yield* service(TypeParser);
|
|
3347
3192
|
const nodeToVisit = [];
|
|
3348
3193
|
const appendNodeToVisit = (node) => {
|
|
@@ -3353,295 +3198,485 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
3353
3198
|
while (nodeToVisit.length > 0) {
|
|
3354
3199
|
const node = nodeToVisit.shift();
|
|
3355
3200
|
ts.forEachChild(node, appendNodeToVisit);
|
|
3356
|
-
if (ts.
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
const effectGenLike = yield* pipe(
|
|
3368
|
-
typeParser.effectGen(effectGenNode),
|
|
3369
|
-
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3370
|
-
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
3371
|
-
option
|
|
3372
|
-
);
|
|
3373
|
-
if (isSome2(effectGenLike)) {
|
|
3374
|
-
const fix = node.expression ? [{
|
|
3375
|
-
fixName: "missingReturnYieldStar_fix",
|
|
3376
|
-
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",
|
|
3377
3212
|
apply: gen(function* () {
|
|
3378
|
-
const
|
|
3379
|
-
|
|
3380
|
-
sourceFile,
|
|
3381
|
-
node,
|
|
3382
|
-
ts.factory.createReturnStatement(
|
|
3383
|
-
node
|
|
3384
|
-
)
|
|
3213
|
+
const textChanges = yield* service(
|
|
3214
|
+
ChangeTracker
|
|
3385
3215
|
);
|
|
3216
|
+
textChanges.replaceNode(sourceFile, node, subject);
|
|
3386
3217
|
})
|
|
3387
|
-
}]
|
|
3388
|
-
|
|
3389
|
-
node,
|
|
3390
|
-
messageText: `Yielded Effect never succeeds, so it is best to use a 'return yield*' instead.`,
|
|
3391
|
-
fixes: fix
|
|
3392
|
-
});
|
|
3393
|
-
}
|
|
3218
|
+
}]
|
|
3219
|
+
});
|
|
3394
3220
|
}
|
|
3395
|
-
}
|
|
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
|
|
3396
3392
|
}
|
|
3397
|
-
|
|
3398
|
-
|
|
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
|
+
}]);
|
|
3399
3409
|
})
|
|
3400
3410
|
});
|
|
3401
3411
|
|
|
3402
|
-
// src/
|
|
3403
|
-
var
|
|
3404
|
-
name: "
|
|
3405
|
-
|
|
3406
|
-
severity: "error",
|
|
3407
|
-
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) {
|
|
3408
3416
|
const ts = yield* service(TypeScriptApi);
|
|
3409
|
-
const
|
|
3410
|
-
const
|
|
3411
|
-
|
|
3412
|
-
const nodeToVisit = [];
|
|
3413
|
-
const appendNodeToVisit = (node) => {
|
|
3414
|
-
nodeToVisit.push(node);
|
|
3415
|
-
return void 0;
|
|
3416
|
-
};
|
|
3417
|
-
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3418
|
-
while (nodeToVisit.length > 0) {
|
|
3419
|
-
const node = nodeToVisit.shift();
|
|
3420
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
3421
|
-
if (ts.isYieldExpression(node) && node.expression && node.asteriskToken === void 0) {
|
|
3422
|
-
const functionStarNode = ts.findAncestor(
|
|
3423
|
-
node,
|
|
3424
|
-
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_)
|
|
3425
|
-
);
|
|
3426
|
-
if (functionStarNode && functionStarNode.parent) {
|
|
3427
|
-
const effectGenNode = functionStarNode.parent;
|
|
3428
|
-
yield* pipe(
|
|
3429
|
-
typeParser.effectGen(effectGenNode),
|
|
3430
|
-
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3431
|
-
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
3432
|
-
map4(({ functionStar }) => {
|
|
3433
|
-
if (functionStar) {
|
|
3434
|
-
brokenGenerators.add(functionStar);
|
|
3435
|
-
}
|
|
3436
|
-
brokenYields.add(node);
|
|
3437
|
-
}),
|
|
3438
|
-
ignore
|
|
3439
|
-
);
|
|
3440
|
-
}
|
|
3441
|
-
}
|
|
3442
|
-
}
|
|
3443
|
-
brokenGenerators.forEach(
|
|
3444
|
-
(node) => report({
|
|
3445
|
-
node,
|
|
3446
|
-
messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
|
|
3447
|
-
fixes: []
|
|
3448
|
-
})
|
|
3417
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3418
|
+
const maybeInfos = yield* option(
|
|
3419
|
+
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
3449
3420
|
);
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
|
|
3469
|
-
fixes: fix
|
|
3470
|
-
});
|
|
3471
|
-
});
|
|
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
|
+
}];
|
|
3472
3439
|
})
|
|
3473
3440
|
});
|
|
3474
3441
|
|
|
3475
|
-
// src/
|
|
3476
|
-
var
|
|
3477
|
-
name: "
|
|
3478
|
-
|
|
3479
|
-
severity: "suggestion",
|
|
3480
|
-
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) {
|
|
3481
3446
|
const ts = yield* service(TypeScriptApi);
|
|
3482
|
-
const
|
|
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
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
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
|
+
}
|
|
3535
3533
|
}
|
|
3536
3534
|
}
|
|
3537
3535
|
}
|
|
3538
3536
|
}
|
|
3539
|
-
}
|
|
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
|
+
};
|
|
3540
3543
|
});
|
|
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
|
-
|
|
3573
|
-
|
|
3574
|
-
}
|
|
3575
|
-
}
|
|
3576
|
-
}
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
)
|
|
3580
|
-
}
|
|
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
|
+
};
|
|
3581
3584
|
}
|
|
3582
|
-
|
|
3583
|
-
}
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
severity: "suggestion",
|
|
3590
|
-
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;
|
|
3591
3592
|
const ts = yield* service(TypeScriptApi);
|
|
3592
|
-
const
|
|
3593
|
-
const
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
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
|
+
}
|
|
3621
3663
|
}
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3664
|
+
);
|
|
3665
|
+
return {
|
|
3666
|
+
...applicableCompletionEntryDetails,
|
|
3667
|
+
codeActions: [
|
|
3668
|
+
{
|
|
3669
|
+
description: "Import * as " + data.effectNamespaceName + " from " + data.effectUnbarreledModulePath,
|
|
3670
|
+
changes
|
|
3671
|
+
}
|
|
3672
|
+
]
|
|
3673
|
+
};
|
|
3674
|
+
}
|
|
3625
3675
|
}
|
|
3626
3676
|
}
|
|
3627
|
-
|
|
3628
|
-
}
|
|
3629
|
-
|
|
3630
|
-
// src/diagnostics.ts
|
|
3631
|
-
var diagnostics = [
|
|
3632
|
-
duplicatePackage,
|
|
3633
|
-
missingEffectContext,
|
|
3634
|
-
missingEffectError,
|
|
3635
|
-
floatingEffect,
|
|
3636
|
-
missingStarInYieldEffectGen,
|
|
3637
|
-
unnecessaryEffectGen,
|
|
3638
|
-
missingReturnYieldStar,
|
|
3639
|
-
leakingRequirements,
|
|
3640
|
-
unnecessaryPipe,
|
|
3641
|
-
genericEffectServices,
|
|
3642
|
-
returnEffectInGen,
|
|
3643
|
-
importFromBarrel
|
|
3644
|
-
];
|
|
3677
|
+
return applicableCompletionEntryDetails;
|
|
3678
|
+
}
|
|
3679
|
+
);
|
|
3645
3680
|
|
|
3646
3681
|
// src/goto/effectRpcDefinition.ts
|
|
3647
3682
|
function effectRpcDefinition(applicableGotoDefinition, sourceFile, position) {
|