Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tidy-layers-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/language-service": minor
---

add `redundantLayerMergeAllInProvide` to replace direct `Layer.mergeAll` arguments to `Effect.provide` with layer arrays.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ Some diagnostics are off by default or have a default severity of suggestion, bu
<tr><td><code>missedPipeableOpportunity</code></td><td>➖</td><td>🔧</td><td>Enforces the use of pipeable style for nested function calls</td><td>✓</td><td>✓</td></tr>
<tr><td><code>missingEffectServiceDependency</code></td><td>➖</td><td></td><td>Checks that Effect.Service dependencies satisfy all required layer inputs</td><td>✓</td><td></td></tr>
<tr><td><code>nestedEffectGenYield</code></td><td>➖</td><td></td><td>Warns when yielding a nested bare Effect.gen inside an existing Effect generator context</td><td>✓</td><td>✓</td></tr>
<tr><td><code>redundantLayerMergeAllInProvide</code></td><td>💡</td><td>🔧</td><td>Replaces direct Layer.mergeAll arguments to Effect.provide with an array of layers</td><td>✓</td><td>✓</td></tr>
<tr><td><code>redundantSchemaTagIdentifier</code></td><td>💡</td><td>🔧</td><td>Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest</td><td>✓</td><td>✓</td></tr>
<tr><td><code>schemaStructWithTag</code></td><td>💡</td><td>🔧</td><td>Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field</td><td>✓</td><td>✓</td></tr>
<tr><td><code>schemaUnionOfLiterals</code></td><td>➖</td><td>🔧</td><td>Simplifies Schema.Union of multiple Schema.Literal calls into single Schema.Literal</td><td>✓</td><td></td></tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ exports[`Completion effectDataClasses > effectDataClasses_directImportTaggedErro
exports[`Completion effectDiagnosticsComment > effectDiagnosticsComment.ts at 2:5 1`] = `
[
{
"insertText": "@effect-diagnostics \${1|anyUnknownInErrorContext,asyncFunction,catchAllToMapError,catchUnfailableEffect,classSelfMismatch,cryptoRandomUUID,cryptoRandomUUIDInEffect,deterministicKeys,duplicatePackage,effectDoNotation,effectFnIife,effectFnImplicitAny,effectFnOpportunity,effectGenUsesAdapter,effectInFailure,effectInVoidSuccess,effectMapFlatten,effectMapVoid,effectSucceedWithVoid,extendsNativeError,flatMapToMap,floatingEffect,genericEffectServices,globalConsole,globalConsoleInEffect,globalDate,globalDateInEffect,globalErrorInEffectCatch,globalErrorInEffectFailure,globalFetch,globalFetchInEffect,globalRandom,globalRandomInEffect,globalTimers,globalTimersInEffect,importFromBarrel,instanceOfSchema,layerMergeAllWithDependencies,lazyPromiseInEffectSync,leakingRequirements,missedPipeableOpportunity,missingEffectContext,missingEffectError,missingEffectServiceDependency,missingLayerContext,missingReturnYieldStar,missingStarInYieldEffectGen,multipleEffectProvide,nestedEffectGenYield,newPromise,nodeBuiltinImport,nonObjectEffectServiceType,outdatedApi,outdatedEffectCodegen,overriddenSchemaConstructor,preferSchemaOverJson,processEnv,processEnvInEffect,redundantSchemaTagIdentifier,returnEffectInGen,runEffectInsideEffect,schemaStructWithTag,schemaSyncInEffect,schemaUnionOfLiterals,scopeInLayerEffect,serviceNotAsClass,strictBooleanExpressions,strictEffectProvide,tryCatchInEffectGen,unknownInEffectCatch,unnecessaryArrowBlock,unnecessaryEffectGen,unnecessaryFailYieldableError,unnecessaryPipe,unnecessaryPipeChain,unsafeEffectTypeAssertion,unsupportedServiceAccessors|}:\${2|off,warning,error,message,suggestion|}$0",
"insertText": "@effect-diagnostics \${1|anyUnknownInErrorContext,asyncFunction,catchAllToMapError,catchUnfailableEffect,classSelfMismatch,cryptoRandomUUID,cryptoRandomUUIDInEffect,deterministicKeys,duplicatePackage,effectDoNotation,effectFnIife,effectFnImplicitAny,effectFnOpportunity,effectGenUsesAdapter,effectInFailure,effectInVoidSuccess,effectMapFlatten,effectMapVoid,effectSucceedWithVoid,extendsNativeError,flatMapToMap,floatingEffect,genericEffectServices,globalConsole,globalConsoleInEffect,globalDate,globalDateInEffect,globalErrorInEffectCatch,globalErrorInEffectFailure,globalFetch,globalFetchInEffect,globalRandom,globalRandomInEffect,globalTimers,globalTimersInEffect,importFromBarrel,instanceOfSchema,layerMergeAllWithDependencies,lazyPromiseInEffectSync,leakingRequirements,missedPipeableOpportunity,missingEffectContext,missingEffectError,missingEffectServiceDependency,missingLayerContext,missingReturnYieldStar,missingStarInYieldEffectGen,multipleEffectProvide,nestedEffectGenYield,newPromise,nodeBuiltinImport,nonObjectEffectServiceType,outdatedApi,outdatedEffectCodegen,overriddenSchemaConstructor,preferSchemaOverJson,processEnv,processEnvInEffect,redundantLayerMergeAllInProvide,redundantSchemaTagIdentifier,returnEffectInGen,runEffectInsideEffect,schemaStructWithTag,schemaSyncInEffect,schemaUnionOfLiterals,scopeInLayerEffect,serviceNotAsClass,strictBooleanExpressions,strictEffectProvide,tryCatchInEffectGen,unknownInEffectCatch,unnecessaryArrowBlock,unnecessaryEffectGen,unnecessaryFailYieldableError,unnecessaryPipe,unnecessaryPipeChain,unsafeEffectTypeAssertion,unsupportedServiceAccessors|}:\${2|off,warning,error,message,suggestion|}$0",
"isSnippet": true,
"kind": "string",
"name": "@effect-diagnostics",
Expand All @@ -259,7 +259,7 @@ exports[`Completion effectDiagnosticsComment > effectDiagnosticsComment.ts at 2:
"sortText": "11",
},
{
"insertText": "@effect-diagnostics-next-line \${1|anyUnknownInErrorContext,asyncFunction,catchAllToMapError,catchUnfailableEffect,classSelfMismatch,cryptoRandomUUID,cryptoRandomUUIDInEffect,deterministicKeys,duplicatePackage,effectDoNotation,effectFnIife,effectFnImplicitAny,effectFnOpportunity,effectGenUsesAdapter,effectInFailure,effectInVoidSuccess,effectMapFlatten,effectMapVoid,effectSucceedWithVoid,extendsNativeError,flatMapToMap,floatingEffect,genericEffectServices,globalConsole,globalConsoleInEffect,globalDate,globalDateInEffect,globalErrorInEffectCatch,globalErrorInEffectFailure,globalFetch,globalFetchInEffect,globalRandom,globalRandomInEffect,globalTimers,globalTimersInEffect,importFromBarrel,instanceOfSchema,layerMergeAllWithDependencies,lazyPromiseInEffectSync,leakingRequirements,missedPipeableOpportunity,missingEffectContext,missingEffectError,missingEffectServiceDependency,missingLayerContext,missingReturnYieldStar,missingStarInYieldEffectGen,multipleEffectProvide,nestedEffectGenYield,newPromise,nodeBuiltinImport,nonObjectEffectServiceType,outdatedApi,outdatedEffectCodegen,overriddenSchemaConstructor,preferSchemaOverJson,processEnv,processEnvInEffect,redundantSchemaTagIdentifier,returnEffectInGen,runEffectInsideEffect,schemaStructWithTag,schemaSyncInEffect,schemaUnionOfLiterals,scopeInLayerEffect,serviceNotAsClass,strictBooleanExpressions,strictEffectProvide,tryCatchInEffectGen,unknownInEffectCatch,unnecessaryArrowBlock,unnecessaryEffectGen,unnecessaryFailYieldableError,unnecessaryPipe,unnecessaryPipeChain,unsafeEffectTypeAssertion,unsupportedServiceAccessors|}:\${2|off,warning,error,message,suggestion|}$0",
"insertText": "@effect-diagnostics-next-line \${1|anyUnknownInErrorContext,asyncFunction,catchAllToMapError,catchUnfailableEffect,classSelfMismatch,cryptoRandomUUID,cryptoRandomUUIDInEffect,deterministicKeys,duplicatePackage,effectDoNotation,effectFnIife,effectFnImplicitAny,effectFnOpportunity,effectGenUsesAdapter,effectInFailure,effectInVoidSuccess,effectMapFlatten,effectMapVoid,effectSucceedWithVoid,extendsNativeError,flatMapToMap,floatingEffect,genericEffectServices,globalConsole,globalConsoleInEffect,globalDate,globalDateInEffect,globalErrorInEffectCatch,globalErrorInEffectFailure,globalFetch,globalFetchInEffect,globalRandom,globalRandomInEffect,globalTimers,globalTimersInEffect,importFromBarrel,instanceOfSchema,layerMergeAllWithDependencies,lazyPromiseInEffectSync,leakingRequirements,missedPipeableOpportunity,missingEffectContext,missingEffectError,missingEffectServiceDependency,missingLayerContext,missingReturnYieldStar,missingStarInYieldEffectGen,multipleEffectProvide,nestedEffectGenYield,newPromise,nodeBuiltinImport,nonObjectEffectServiceType,outdatedApi,outdatedEffectCodegen,overriddenSchemaConstructor,preferSchemaOverJson,processEnv,processEnvInEffect,redundantLayerMergeAllInProvide,redundantSchemaTagIdentifier,returnEffectInGen,runEffectInsideEffect,schemaStructWithTag,schemaSyncInEffect,schemaUnionOfLiterals,scopeInLayerEffect,serviceNotAsClass,strictBooleanExpressions,strictEffectProvide,tryCatchInEffectGen,unknownInEffectCatch,unnecessaryArrowBlock,unnecessaryEffectGen,unnecessaryFailYieldableError,unnecessaryPipe,unnecessaryPipeChain,unsafeEffectTypeAssertion,unsupportedServiceAccessors|}:\${2|off,warning,error,message,suggestion|}$0",
"isSnippet": true,
"kind": "string",
"name": "@effect-diagnostics-next-line",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
redundantLayerMergeAllInProvide_fix from 335 to 349
redundantLayerMergeAllInProvide_skipNextLine from 335 to 349
redundantLayerMergeAllInProvide_skipFile from 335 to 349
redundantLayerMergeAllInProvide_fix from 231 to 245
redundantLayerMergeAllInProvide_skipNextLine from 231 to 245
redundantLayerMergeAllInProvide_skipFile from 231 to 245
redundantLayerMergeAllInProvide_fix from 437 to 451
redundantLayerMergeAllInProvide_skipNextLine from 437 to 451
redundantLayerMergeAllInProvide_skipFile from 437 to 451
redundantLayerMergeAllInProvide_fix from 550 to 564
redundantLayerMergeAllInProvide_skipNextLine from 550 to 564
redundantLayerMergeAllInProvide_skipFile from 550 to 564
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Layer.mergeAll
9:17 - 9:31 | 2 | `Effect.provide` accepts an array of Layers directly, so this `Layer.mergeAll` call is redundant. effect(redundantLayerMergeAllInProvide)

Layer.mergeAll
14:2 - 14:16 | 2 | `Effect.provide` accepts an array of Layers directly, so this `Layer.mergeAll` call is redundant. effect(redundantLayerMergeAllInProvide)

Layer.mergeAll
18:17 - 18:31 | 2 | `Effect.provide` accepts an array of Layers directly, so this `Layer.mergeAll` call is redundant. effect(redundantLayerMergeAllInProvide)

Layer.mergeAll
22:17 - 22:31 | 2 | `Effect.provide` accepts an array of Layers directly, so this `Layer.mergeAll` call is redundant. effect(redundantLayerMergeAllInProvide)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// code fix redundantLayerMergeAllInProvide_fix output for range 231 - 245
import { Effect, Layer } from "effect"

const first = Layer.empty
const second = Layer.empty
const third = Layer.empty
const layers = [first, second] as const

export const shouldReportPipeable = Effect.void.pipe(
Effect.provide([first, second])
)

export const shouldReportDataFirst = Effect.provide(
Effect.void,
Layer.mergeAll(first, second)
)

export const shouldReportSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...[first, second]))
)

export const shouldReportTupleSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...layers))
)

export const shouldNotReportTransformed = Effect.void.pipe(
Effect.provide(
Layer.mergeAll(first, second).pipe(Layer.provide(third))
)
)

const combined = Layer.mergeAll(first, second)

export const shouldNotReportPrecomposed = Effect.void.pipe(
Effect.provide(combined)
)

class Dependency extends Effect.Service<Dependency>()("Dependency", {
succeed: {}
}) {}
class Consumer extends Effect.Service<Consumer>()("Consumer", {
effect: Effect.as(Dependency, {})
}) {}

export const shouldNotReportWithDependencies = Effect.void.pipe(
Effect.provide(Layer.mergeAll(Dependency.Default, Consumer.Default))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// code fix redundantLayerMergeAllInProvide_fix output for range 335 - 349
import { Effect, Layer } from "effect"

const first = Layer.empty
const second = Layer.empty
const third = Layer.empty
const layers = [first, second] as const

export const shouldReportPipeable = Effect.void.pipe(
Effect.provide(Layer.mergeAll(first, second))
)

export const shouldReportDataFirst = Effect.provide(
Effect.void,
[first, second]
)

export const shouldReportSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...[first, second]))
)

export const shouldReportTupleSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...layers))
)

export const shouldNotReportTransformed = Effect.void.pipe(
Effect.provide(
Layer.mergeAll(first, second).pipe(Layer.provide(third))
)
)

const combined = Layer.mergeAll(first, second)

export const shouldNotReportPrecomposed = Effect.void.pipe(
Effect.provide(combined)
)

class Dependency extends Effect.Service<Dependency>()("Dependency", {
succeed: {}
}) {}
class Consumer extends Effect.Service<Consumer>()("Consumer", {
effect: Effect.as(Dependency, {})
}) {}

export const shouldNotReportWithDependencies = Effect.void.pipe(
Effect.provide(Layer.mergeAll(Dependency.Default, Consumer.Default))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// code fix redundantLayerMergeAllInProvide_fix output for range 437 - 451
import { Effect, Layer } from "effect"

const first = Layer.empty
const second = Layer.empty
const third = Layer.empty
const layers = [first, second] as const

export const shouldReportPipeable = Effect.void.pipe(
Effect.provide(Layer.mergeAll(first, second))
)

export const shouldReportDataFirst = Effect.provide(
Effect.void,
Layer.mergeAll(first, second)
)

export const shouldReportSpread = Effect.void.pipe(
Effect.provide([first, second])
)

export const shouldReportTupleSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...layers))
)

export const shouldNotReportTransformed = Effect.void.pipe(
Effect.provide(
Layer.mergeAll(first, second).pipe(Layer.provide(third))
)
)

const combined = Layer.mergeAll(first, second)

export const shouldNotReportPrecomposed = Effect.void.pipe(
Effect.provide(combined)
)

class Dependency extends Effect.Service<Dependency>()("Dependency", {
succeed: {}
}) {}
class Consumer extends Effect.Service<Consumer>()("Consumer", {
effect: Effect.as(Dependency, {})
}) {}

export const shouldNotReportWithDependencies = Effect.void.pipe(
Effect.provide(Layer.mergeAll(Dependency.Default, Consumer.Default))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// code fix redundantLayerMergeAllInProvide_fix output for range 550 - 564
import { Effect, Layer } from "effect"

const first = Layer.empty
const second = Layer.empty
const third = Layer.empty
const layers = [first, second] as const

export const shouldReportPipeable = Effect.void.pipe(
Effect.provide(Layer.mergeAll(first, second))
)

export const shouldReportDataFirst = Effect.provide(
Effect.void,
Layer.mergeAll(first, second)
)

export const shouldReportSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...[first, second]))
)

export const shouldReportTupleSpread = Effect.void.pipe(
Effect.provide(layers)
)

export const shouldNotReportTransformed = Effect.void.pipe(
Effect.provide(
Layer.mergeAll(first, second).pipe(Layer.provide(third))
)
)

const combined = Layer.mergeAll(first, second)

export const shouldNotReportPrecomposed = Effect.void.pipe(
Effect.provide(combined)
)

class Dependency extends Effect.Service<Dependency>()("Dependency", {
succeed: {}
}) {}
class Consumer extends Effect.Service<Consumer>()("Consumer", {
effect: Effect.as(Dependency, {})
}) {}

export const shouldNotReportWithDependencies = Effect.void.pipe(
Effect.provide(Layer.mergeAll(Dependency.Default, Consumer.Default))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Effect, Layer } from "effect"

const first = Layer.empty
const second = Layer.empty
const third = Layer.empty
const layers = [first, second] as const

export const shouldReportPipeable = Effect.void.pipe(
Effect.provide(Layer.mergeAll(first, second))
)

export const shouldReportDataFirst = Effect.provide(
Effect.void,
Layer.mergeAll(first, second)
)

export const shouldReportSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...[first, second]))
)

export const shouldReportTupleSpread = Effect.void.pipe(
Effect.provide(Layer.mergeAll(...layers))
)

export const shouldNotReportTransformed = Effect.void.pipe(
Effect.provide(
Layer.mergeAll(first, second).pipe(Layer.provide(third))
)
)

const combined = Layer.mergeAll(first, second)

export const shouldNotReportPrecomposed = Effect.void.pipe(
Effect.provide(combined)
)

class Dependency extends Effect.Service<Dependency>()("Dependency", {
succeed: {}
}) {}
class Consumer extends Effect.Service<Consumer>()("Consumer", {
effect: Effect.as(Dependency, {})
}) {}

export const shouldNotReportWithDependencies = Effect.void.pipe(
Effect.provide(Layer.mergeAll(Dependency.Default, Consumer.Default))
)
Loading