diff --git a/.changeset/fair-ducks-applaud.md b/.changeset/fair-ducks-applaud.md new file mode 100644 index 00000000..cf0385ff --- /dev/null +++ b/.changeset/fair-ducks-applaud.md @@ -0,0 +1,5 @@ +--- +"@effect/language-service": patch +--- + +Update the Effect v4 beta dependencies to `4.0.0-beta.43` for the language service and v4 harness packages. diff --git a/packages/harness-effect-v4/package.json b/packages/harness-effect-v4/package.json index 2b122b54..2e9a7cf5 100644 --- a/packages/harness-effect-v4/package.json +++ b/packages/harness-effect-v4/package.json @@ -6,7 +6,7 @@ }, "dependencies": { "@standard-schema/spec": "^1.1.0", - "effect": "^4.0.0-beta.38" + "effect": "^4.0.0-beta.43" }, "devDependencies": { "@types/node": "^25.0.6" diff --git a/packages/language-service/package.json b/packages/language-service/package.json index 733e5c47..5dbad79d 100644 --- a/packages/language-service/package.json +++ b/packages/language-service/package.json @@ -43,10 +43,10 @@ "perf": "tsx test/perf.ts" }, "devDependencies": { - "@effect/platform-node": "^4.0.0-beta.38", + "@effect/platform-node": "^4.0.0-beta.43", "@types/pako": "^2.0.4", "@typescript-eslint/project-service": "^8.52.0", - "effect": "^4.0.0-beta.38", + "effect": "^4.0.0-beta.43", "pako": "^2.1.0", "ts-patch": "^3.3.0" } diff --git a/packages/language-service/src/cli/overview.ts b/packages/language-service/src/cli/overview.ts index 8ee8ab73..c143e665 100644 --- a/packages/language-service/src/cli/overview.ts +++ b/packages/language-service/src/cli/overview.ts @@ -136,6 +136,7 @@ export function collectExportedItems( // Check if it's a Context.Tag (has _Identifier and _Service variance) const contextTagResult = yield* pipe( typeParser.contextTag(type, declaration), + Nano.orElse(() => typeParser.serviceType(type, declaration)), Nano.option ) if (Option.isSome(contextTagResult)) { diff --git a/packages/language-service/src/core/TypeParser.ts b/packages/language-service/src/core/TypeParser.ts index 16c5d224..50dee22e 100644 --- a/packages/language-service/src/core/TypeParser.ts +++ b/packages/language-service/src/core/TypeParser.ts @@ -1628,40 +1628,32 @@ export function make( ([Identifier, Service]) => ({ Identifier, Service }) ) - const serviceVarianceStruct = ( - type: ts.Type, - atLocation: ts.Node - ) => - Nano.map( - Nano.all( - varianceStructInvariantType(type, atLocation, "_Identifier"), - varianceStructInvariantType(type, atLocation, "_Service") - ), - ([Identifier, Service]) => ({ Identifier, Service }) - ) - const serviceType = Nano.cachedBy( Nano.fn("TypeParser.serviceType")(function*( type: ts.Type, atLocation: ts.Node ) { + // v4 only + if (supportedEffect() !== "v4") return yield* typeParserIssue("v4 only") // should be pipeable yield* pipeableType(type, atLocation) - // get the properties to check (exclude non-property and optional properties) - const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter((_) => - _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration - ) - // early exit - if (propertiesSymbols.length === 0) { - return yield* typeParserIssue("Type has no tag variance struct", type, atLocation) + // Effect v4 beta.43 switched ServiceMap keys from nested variance markers + const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/ServiceMap/Service") + if (!typeIdSymbol) { + return yield* typeParserIssue("Type has no service key type id", type, atLocation) } - // try to put typeid first (heuristic to optimize hot path) - propertiesSymbols.sort((a, b) => ts.symbolName(b).indexOf("TypeId") - ts.symbolName(a).indexOf("TypeId")) - // has a property symbol which is a service variance struct - return yield* Nano.firstSuccessOf(propertiesSymbols.map((propertySymbol) => { - const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation) - return serviceVarianceStruct(propertyType, atLocation) - })) + const identifierSymbol = typeChecker.getPropertyOfType(type, "Identifier") + if (!identifierSymbol) { + return yield* typeParserIssue("Type has no 'Identifier' property", type, atLocation) + } + const serviceSymbol = typeChecker.getPropertyOfType(type, "Service") + if (!serviceSymbol) { + return yield* typeParserIssue("Type has no 'Service' property", type, atLocation) + } + return ({ + Identifier: typeChecker.getTypeOfSymbolAtLocation(identifierSymbol, atLocation), + Service: typeChecker.getTypeOfSymbolAtLocation(serviceSymbol, atLocation) + }) }), "TypeParser.serviceType", (type) => type @@ -1672,6 +1664,8 @@ export function make( type: ts.Type, atLocation: ts.Node ) { + // v4 only + if (supportedEffect() !== "v3") return yield* typeParserIssue("v3 only") // should be pipeable yield* pipeableType(type, atLocation) // get the properties to check (exclude non-property and optional properties) diff --git a/packages/language-service/src/diagnostics/genericEffectServices.ts b/packages/language-service/src/diagnostics/genericEffectServices.ts index 6c3ef242..c909192c 100644 --- a/packages/language-service/src/diagnostics/genericEffectServices.ts +++ b/packages/language-service/src/diagnostics/genericEffectServices.ts @@ -45,6 +45,7 @@ export const genericEffectServices = LSP.createDiagnostic({ for (const [type, reportAt] of typesToCheck) { yield* pipe( typeParser.contextTag(type, node), + Nano.orElse(() => typeParser.serviceType(type, node)), Nano.map(() => { report({ location: reportAt, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5bd55b1..c475071f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -124,8 +124,8 @@ importers: specifier: ^1.1.0 version: 1.1.0 effect: - specifier: ^4.0.0-beta.38 - version: 4.0.0-beta.38 + specifier: ^4.0.0-beta.43 + version: 4.0.0-beta.43 devDependencies: '@types/node': specifier: ^25.0.6 @@ -134,8 +134,8 @@ importers: packages/language-service: devDependencies: '@effect/platform-node': - specifier: ^4.0.0-beta.38 - version: 4.0.0-beta.38(effect@4.0.0-beta.38)(ioredis@5.10.0) + specifier: ^4.0.0-beta.43 + version: 4.0.0-beta.43(effect@4.0.0-beta.43)(ioredis@5.10.0) '@types/pako': specifier: ^2.0.4 version: 2.0.4 @@ -143,8 +143,8 @@ importers: specifier: ^8.52.0 version: 8.52.0(typescript@5.9.3) effect: - specifier: ^4.0.0-beta.38 - version: 4.0.0-beta.38 + specifier: ^4.0.0-beta.43 + version: 4.0.0-beta.43 pako: specifier: ^2.1.0 version: 2.1.0 @@ -575,29 +575,29 @@ packages: uuid: 11.1.0 dev: false - /@effect/platform-node-shared@4.0.0-beta.38(effect@4.0.0-beta.38): - resolution: {integrity: sha512-Im2lEq2k7L6MxT0IMoI4yJBwyqgWVJLv+Z0izFCHsmMHCZkaGUDXpTDwCd0ynwszn4V6PET23dyI/GfCY3EHNA==} + /@effect/platform-node-shared@4.0.0-beta.43(effect@4.0.0-beta.43): + resolution: {integrity: sha512-A9q0GEb61pYcQ06Dr6gXj1nKlDI3KHsar1sk3qb1ZY+kVSR64tBAylI8zGon23KY+NPtTUj/sEIToB7jc3Qt5w==} engines: {node: '>=18.0.0'} peerDependencies: - effect: ^4.0.0-beta.38 + effect: ^4.0.0-beta.43 dependencies: '@types/ws': 8.18.1 - effect: 4.0.0-beta.38 + effect: 4.0.0-beta.43 ws: 8.19.0 transitivePeerDependencies: - bufferutil - utf-8-validate dev: true - /@effect/platform-node@4.0.0-beta.38(effect@4.0.0-beta.38)(ioredis@5.10.0): - resolution: {integrity: sha512-uTcBIoH9rjmPbvl9axUHF5fACu/jjn4i/EbXVqych1zNw7XYjjAG3VrU7ypasAgAGvCRGUfLbfuAVrcMKaKDSg==} + /@effect/platform-node@4.0.0-beta.43(effect@4.0.0-beta.43)(ioredis@5.10.0): + resolution: {integrity: sha512-Uq6E1rjaIpjHauzjwoB2HzAg3battYt2Boy8XO50GoHiWCXKE6WapYZ0/AnaBx5v5qg2sOfqpuiLsUf9ZgxOkA==} engines: {node: '>=18.0.0'} peerDependencies: - effect: ^4.0.0-beta.38 + effect: ^4.0.0-beta.43 ioredis: ^5.7.0 dependencies: - '@effect/platform-node-shared': 4.0.0-beta.38(effect@4.0.0-beta.38) - effect: 4.0.0-beta.38 + '@effect/platform-node-shared': 4.0.0-beta.43(effect@4.0.0-beta.43) + effect: 4.0.0-beta.43 ioredis: 5.10.0 mime: 4.1.0 undici: 7.24.5 @@ -2835,8 +2835,8 @@ packages: fast-check: 3.23.2 dev: false - /effect@4.0.0-beta.38: - resolution: {integrity: sha512-4Sr5dJqfexSuH0CiXBisLavcTMmzcN0al62aTOHujBGmS6s2VA4Yg25bvvuQbCWTPXv4+zEC5zDupIGY420m1g==} + /effect@4.0.0-beta.43: + resolution: {integrity: sha512-AJYyDimIwJOn87uUz/JzmgDc5GfjxJbXvEbTvNzMa+M3Uer344bLo/O5mMRkqc1vBleA+Ygs4+dbE3QsqOkKTQ==} dependencies: '@standard-schema/spec': 1.1.0 fast-check: 4.5.3