From cb3f31877cd26ca42d6cc8757486788624ef1d89 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 12 Oct 2022 14:55:04 +0200 Subject: [PATCH 1/8] Add config for reporting transitively dead things. This is the normal behaviour: no change. When turned off, only the top dead things, and not the transitive ones, are reported. --- analysis/reanalyze/src/Common.ml | 2 +- analysis/reanalyze/src/DeadCommon.ml | 27 +++++++++++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/analysis/reanalyze/src/Common.ml b/analysis/reanalyze/src/Common.ml index e540d2cbf..e0e7e592b 100644 --- a/analysis/reanalyze/src/Common.ml +++ b/analysis/reanalyze/src/Common.ml @@ -197,7 +197,7 @@ type decl = { pos: Lexing.position; posEnd: Lexing.position; posStart: Lexing.position; - mutable resolved: bool; + mutable resolvedDead: bool option; mutable report: bool; } diff --git a/analysis/reanalyze/src/DeadCommon.ml b/analysis/reanalyze/src/DeadCommon.ml index 0f6536954..4573e30e6 100644 --- a/analysis/reanalyze/src/DeadCommon.ml +++ b/analysis/reanalyze/src/DeadCommon.ml @@ -13,6 +13,7 @@ module Config = struct let analyzeTypes = ref true let analyzeExternals = ref false let reportUnderscore = false + let reportTransitive = true let reportTypesDeadOnlyInInterface = false let recursiveDebug = false let warnOnCircularDependencies = false @@ -375,7 +376,7 @@ let addDeclaration_ ?posEnd ?posStart ~declKind ~path ~(loc : Location.t) pos; posEnd; posStart; - resolved = false; + resolvedDead = None; report = true; } in @@ -536,12 +537,21 @@ module Decl = struct | VariantCase -> (WarningDeadType, "is a variant case which is never constructed") in + let hasRefBelow () = + let refs = ValueReferences.find decl.pos in + let refIsBelow (pos : Lexing.position) = + decl.pos.pos_fname <> pos.pos_fname + || decl.pos.pos_cnum < pos.pos_cnum + && decl.posEnd.pos_cnum < pos.pos_cnum + in + refs |> PosSet.exists refIsBelow + in let shouldEmitWarning = (not insideReportedValue) - && - match decl.path with - | name :: _ when name |> Name.isUnderscore -> Config.reportUnderscore - | _ -> true + && (match decl.path with + | name :: _ when name |> Name.isUnderscore -> Config.reportUnderscore + | _ -> true) + && (Config.reportTransitive || not (hasRefBelow ())) in if shouldEmitWarning then ( decl.path @@ -563,7 +573,7 @@ let doReportDead pos = not (ProcessDeadAnnotations.isAnnotatedGenTypeOrDead pos) let rec resolveRecursiveRefs ~checkOptionalArg ~deadDeclarations ~level ~orderedFiles ~refs ~refsBeingResolved decl : bool = match decl.pos with - | _ when decl.resolved -> + | _ when decl.resolvedDead <> None -> if Config.recursiveDebug then Log_.item "recursiveDebug %s [%d] already resolved@." (decl.path |> Path.toString) @@ -609,13 +619,13 @@ let rec resolveRecursiveRefs ~checkOptionalArg ~deadDeclarations ~level ~level:(level + 1) ~orderedFiles ~refs:xRefs ~refsBeingResolved in - if not xDecl.resolved then allDepsResolved := false; + if xDecl.resolvedDead = None then allDepsResolved := false; not xDeclIsDead) in let isDead = decl |> declIsDead ~refs:newRefs in let isResolved = (not isDead) || !allDepsResolved || level = 0 in if isResolved then ( - decl.resolved <- true; + decl.resolvedDead <- Some isDead; if isDead then ( decl.path |> DeadModules.markDead @@ -691,4 +701,5 @@ let reportDead ~checkOptionalArg = let sortedDeadDeclarations = !deadDeclarations |> List.fast_sort Decl.compareForReporting in + (* XXX *) sortedDeadDeclarations |> List.iter Decl.report From a1e190ca069d3d4d8e6827770df9913b59e43249 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 12 Oct 2022 14:56:07 +0200 Subject: [PATCH 2/8] Turn off the flag for reporting transitive dead things. --- analysis/reanalyze/src/DeadCommon.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis/reanalyze/src/DeadCommon.ml b/analysis/reanalyze/src/DeadCommon.ml index 4573e30e6..612a2c50e 100644 --- a/analysis/reanalyze/src/DeadCommon.ml +++ b/analysis/reanalyze/src/DeadCommon.ml @@ -13,7 +13,7 @@ module Config = struct let analyzeTypes = ref true let analyzeExternals = ref false let reportUnderscore = false - let reportTransitive = true + let reportTransitive = false let reportTypesDeadOnlyInInterface = false let recursiveDebug = false let warnOnCircularDependencies = false From 3a24e655389fcc4ee57a248a604694c45b137e6e Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 12 Oct 2022 14:59:51 +0200 Subject: [PATCH 3/8] Comment. --- analysis/reanalyze/src/DeadCommon.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/analysis/reanalyze/src/DeadCommon.ml b/analysis/reanalyze/src/DeadCommon.ml index 612a2c50e..51d8a68c4 100644 --- a/analysis/reanalyze/src/DeadCommon.ml +++ b/analysis/reanalyze/src/DeadCommon.ml @@ -542,7 +542,8 @@ module Decl = struct let refIsBelow (pos : Lexing.position) = decl.pos.pos_fname <> pos.pos_fname || decl.pos.pos_cnum < pos.pos_cnum - && decl.posEnd.pos_cnum < pos.pos_cnum + && (* not a function defined inside a function, e.g. not a callback *) + decl.posEnd.pos_cnum < pos.pos_cnum in refs |> PosSet.exists refIsBelow in From b18b749267a733d2c8bb5d207e8acea2067d0cfd Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Tue, 18 Oct 2022 08:21:41 +0100 Subject: [PATCH 4/8] Do not report empty modules when transitive reporting is off. As the only way for a module to be dead would be for it to be empty. --- analysis/reanalyze/src/DeadCommon.ml | 14 ++++++++------ analysis/tests/src/expected/Dce.res.txt | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/analysis/reanalyze/src/DeadCommon.ml b/analysis/reanalyze/src/DeadCommon.ml index 51d8a68c4..85bb9c47c 100644 --- a/analysis/reanalyze/src/DeadCommon.ml +++ b/analysis/reanalyze/src/DeadCommon.ml @@ -406,9 +406,10 @@ let emitWarning ~decl ~message deadWarning = WriteDeadAnnotations.addLineAnnotation ~decl else None in - decl.path - |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) - |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; + if Config.reportTransitive then + decl.path + |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) + |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; Log_.warning ~loc (DeadWarning { @@ -555,9 +556,10 @@ module Decl = struct && (Config.reportTransitive || not (hasRefBelow ())) in if shouldEmitWarning then ( - decl.path - |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) - |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; + if Config.reportTransitive then + decl.path + |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) + |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; emitWarning ~decl ~message name) end diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index f50cced86..d03b3452e 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:2 +issues:0 From 6613f51f6d79044819e55e5f2b7fd39c75c76953 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 21 Oct 2022 12:32:07 +0200 Subject: [PATCH 5/8] Make transitive reports configurable. --- CHANGELOG.md | 4 + .../reanalyze/examples/deadcode/bsconfig.json | 3 +- .../examples/deadcode/expected/deadcode.txt | 496 +----------------- analysis/reanalyze/src/DeadCommon.ml | 17 +- analysis/reanalyze/src/DeadModules.ml | 2 +- analysis/reanalyze/src/Paths.ml | 9 +- analysis/reanalyze/src/RunConfig.ml | 4 + analysis/tests/src/expected/Dce.res.txt | 2 +- 8 files changed, 28 insertions(+), 509 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d505627f..181be3ec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ ## master +#### :rocket: New Feature + +- Add configuration parameter `"transitive"` under `"reanalyze"`. If set to false, analysis does not report transitively dead items. So removing the item directly reported can be done in isolation https://github.com/rescript-lang/rescript-vscode/pull/601 + #### :bug: Bug Fix - Fix issue where module paths in `-open` in `bsc-flags` such as "-open ReScriptJs.Js" were not recognized https://github.com/rescript-lang/rescript-vscode/issues/607 diff --git a/analysis/reanalyze/examples/deadcode/bsconfig.json b/analysis/reanalyze/examples/deadcode/bsconfig.json index 74e32b929..81c847b6f 100644 --- a/analysis/reanalyze/examples/deadcode/bsconfig.json +++ b/analysis/reanalyze/examples/deadcode/bsconfig.json @@ -2,7 +2,8 @@ "reanalyze": { "analysis": ["dce"], "suppress": [], - "unsuppress": [] + "unsuppress": [], + "transitive": false }, "name": "sample-typescript-app", "bsc-flags": ["-bs-super-errors -w a"], diff --git a/analysis/reanalyze/examples/deadcode/expected/deadcode.txt b/analysis/reanalyze/examples/deadcode/expected/deadcode.txt index b01a65eba..613fb959d 100644 --- a/analysis/reanalyze/examples/deadcode/expected/deadcode.txt +++ b/analysis/reanalyze/examples/deadcode/expected/deadcode.txt @@ -2663,10 +2663,6 @@ File References File "OptArg.res", line 1, characters 1-49 optional argument z of function foo is never used - Warning Dead Module - File "AutoAnnotate.res", line 0, characters 1-1 - AutoAnnotate is a dead module as all its items are dead. - Warning Dead Type File "AutoAnnotate.res", line 1, characters 16-22 variant.R is a variant case which is never constructed @@ -2709,10 +2705,6 @@ File References <-- line 15 | @dead("annotatedVariant.R4") R4(r4) - Warning Dead Module - File "BucklescriptAnnotations.res", line 0, characters 1-1 - BucklescriptAnnotations is a dead module as all its items are dead. - Warning Dead Value File "BucklescriptAnnotations.res", line 25, characters 1-71 bar is never used @@ -2731,20 +2723,12 @@ File References <-- line 8 @dead("eToplevel") let eToplevel = Etoplevel - Warning Dead Module - File "DeadMl.ml", line 1, characters 1-121 - DeadMl.QQ is a dead module as all its items are dead. - Warning Dead Value File "DeadMl.ml", line 3, characters 5-94 QQ.thisSpansSeveralLines is never used <-- line 3 x + y : int -> int -> int) [@@dead "QQ.thisSpansSeveralLines"] - Warning Dead Module - File "DeadMl.ml", line 8, characters 1-104 - DeadMl.AA is a dead module as all its items are dead. - Warning Dead Value File "DeadMl.ml", line 9, characters 3-41 AA.thisIsInInterface is never used @@ -2775,10 +2759,6 @@ File References <-- line 17 type thisIsDead = | DeadA [@dead "thisIsDead.DeadA"] | DeadB [@dead "thisIsDead.DeadB"] - Warning Dead Module - File "DeadMl.ml", line 25, characters 1-257 - DeadMl.Bs_version is a dead module as all its items are dead. - Warning Dead Value File "DeadMl.ml", line 26, characters 7-27 Bs_version.version is never used @@ -2917,10 +2897,6 @@ File References <-- line 2 @dead("fortytwo") let fortytwo = 42 - Warning Dead Module - File "DeadTest.res", line 27, characters 8-98 - DeadTest.M is a dead module as all its items are dead. - Warning Dead Value File "DeadTest.res", line 31, characters 3-35 M.thisSignatureItemIsDead is never used @@ -2951,12 +2927,6 @@ File References <-- line 77 @dead("split_map") let rec split_map = l => { - Warning Dead Value - File "DeadTest.res", line 82, characters 1-28 - rec1 is never used - <-- line 82 - @dead("rec1") let rec rec1 = () => rec2() - Warning Dead Value File "DeadTest.res", line 83, characters 1-24 rec2 is never used @@ -2969,12 +2939,6 @@ File References <-- line 85 @dead("recWithCallback") let rec recWithCallback = () => { - Warning Dead Value - File "DeadTest.res", line 90, characters 1-54 - foo is never used - <-- line 90 - @dead("foo") let rec foo = () => { - Warning Dead Value File "DeadTest.res", line 94, characters 1-22 bar is never used @@ -2987,14 +2951,6 @@ File References <-- line 96 @dead("withDefaultValue") let withDefaultValue = (~paramWithDefault=3, y) => paramWithDefault + y - Warning Dead Module - File "DeadTest.res", line 110, characters 8-414 - DeadTest.LazyDynamicallyLoadedComponent2 is a dead module as all its items are dead. - - Warning Dead Value With Side Effects - File "DeadTest.res", line 111, characters 3-143 - LazyDynamicallyLoadedComponent2.reasonResource is never used and could have side effects - Warning Dead Value File "DeadTest.res", line 114, characters 3-55 LazyDynamicallyLoadedComponent2.makeProps is never used @@ -3013,12 +2969,6 @@ File References <-- line 127 @dead("zzz") let zzz = { - Warning Dead Value - File "DeadTest.res", line 135, characters 1-16 - second is never used - <-- line 135 - @dead("second") let second = 1L - Warning Dead Value File "DeadTest.res", line 136, characters 1-36 minute is never used @@ -3047,20 +2997,12 @@ File References <-- line 175 type rc = {@dead("rc.a") a: int} - Warning Dead Module - File "DeadTestBlacklist.res", line 0, characters 1-1 - DeadTestBlacklist is a dead module as all its items are dead. - Warning Dead Value File "DeadTestBlacklist.res", line 1, characters 1-11 x is never used <-- line 1 @dead("x") let x = 34 - Warning Dead Module - File "DeadTestWithInterface.res", line 1, characters 8-55 - DeadTestWithInterface.Ext_buffer is a dead module as all its items are dead. - Warning Dead Value File "DeadTestWithInterface.res", line 2, characters 3-13 Ext_buffer.x is never used @@ -3079,12 +3021,6 @@ File References <-- line 3 | @dead("t.B") B - Warning Dead Value - File "DeadTypeTest.res", line 4, characters 1-10 - a is never used - <-- line 4 - @dead("a") let a = A - Warning Dead Type File "DeadTypeTest.res", line 10, characters 5-14 deadType.InNeither is a variant case which is never constructed @@ -3109,12 +3045,6 @@ File References <-- line 10 | @dead("deadType.InNeither") InNeither - Warning Dead Value - File "DeadValueTest.res", line 2, characters 1-18 - valueDead is never used - <-- line 2 - @dead("valueDead") let valueDead = 2 - Warning Dead Value File "DeadValueTest.res", line 4, characters 1-34 valueOnlyInImplementation is never used @@ -3139,30 +3069,12 @@ File References <-- line 61 | @dead("t.B") B - Warning Dead Module - File "ErrorHandler.res", line 0, characters 1-1 - ErrorHandler is a dead module as all its items are dead. - - Warning Dead Value - File "ErrorHandler.res", line 12, characters 1-11 - x is never used - <-- line 12 - @dead("x") let x = 42 - - Warning Dead Module - File "ErrorHandler.resi", line 0, characters 1-1 - ErrorHandler is a dead module as all its items are dead. - Warning Dead Value File "ErrorHandler.resi", line 10, characters 1-11 x is never used <-- line 10 @dead("x") let x: int - Warning Dead Module - File "EverythingLiveHere.res", line 0, characters 1-1 - EverythingLiveHere is a dead module as all its items are dead. - Warning Dead Value File "EverythingLiveHere.res", line 1, characters 1-10 x is never used @@ -3181,10 +3093,6 @@ File References <-- line 5 @dead("z") let z = 4 - Warning Dead Module - File "FirstClassModulesInterface.res", line 0, characters 1-1 - FirstClassModulesInterface is a dead module as all its items are dead. - Warning Dead Type File "FirstClassModulesInterface.res", line 2, characters 3-9 record.x is a record label never used to read a value @@ -3197,16 +3105,6 @@ File References <-- line 3 @dead("record.y") y: string, - Warning Dead Value - File "FirstClassModulesInterface.res", line 6, characters 1-27 - r is never used - <-- line 6 - @dead("r") let r = {x: 3, y: "hello"} - - Warning Dead Module - File "FirstClassModulesInterface.resi", line 0, characters 1-1 - FirstClassModulesInterface is a dead module as all its items are dead. - Warning Dead Type File "FirstClassModulesInterface.resi", line 3, characters 3-9 record.x is a record label never used to read a value @@ -3225,354 +3123,6 @@ File References <-- line 7 @dead("r") let r: record - Warning Dead Value - File "ImmutableArray.res", line 16, characters 3-42 - toArray is never used - <-- line 16 - @dead("toArray") let toArray = a => Array.copy(a->fromT) - - Warning Dead Value - File "ImmutableArray.res", line 20, characters 3-43 - length is never used - <-- line 20 - @dead("length") let length = a => Array.length(a->fromT) - - Warning Dead Value - File "ImmutableArray.res", line 22, characters 3-39 - size is never used - <-- line 22 - @dead("size") let size = a => Array.size(a->fromT) - - Warning Dead Value - File "ImmutableArray.res", line 26, characters 3-51 - getExn is never used - <-- line 26 - @dead("getExn") let getExn = (a, x) => Array.getExn(a->fromT, x) - - Warning Dead Value - File "ImmutableArray.res", line 28, characters 3-57 - getUnsafe is never used - <-- line 28 - @dead("getUnsafe") let getUnsafe = (a, x) => Array.getUnsafe(a->fromT, x) - - Warning Dead Value - File "ImmutableArray.res", line 30, characters 3-63 - getUndefined is never used - <-- line 30 - @dead("getUndefined") let getUndefined = (a, x) => Array.getUndefined(a->fromT, x) - - Warning Dead Value - File "ImmutableArray.res", line 32, characters 3-50 - shuffle is never used - <-- line 32 - @dead("shuffle") let shuffle = x => Array.shuffle(x->fromT)->toT - - Warning Dead Value - File "ImmutableArray.res", line 34, characters 3-50 - reverse is never used - <-- line 34 - @dead("reverse") let reverse = x => Array.reverse(x->fromT)->toT - - Warning Dead Value - File "ImmutableArray.res", line 36, characters 3-63 - makeUninitialized is never used - <-- line 36 - @dead("makeUninitialized") let makeUninitialized = x => Array.makeUninitialized(x)->toT - - Warning Dead Value - File "ImmutableArray.res", line 38, characters 3-75 - makeUninitializedUnsafe is never used - <-- line 38 - @dead("makeUninitializedUnsafe") let makeUninitializedUnsafe = x => Array.makeUninitializedUnsafe(x)->toT - - Warning Dead Value - File "ImmutableArray.res", line 40, characters 3-45 - make is never used - <-- line 40 - @dead("make") let make = (x, y) => Array.make(x, y)->toT - - Warning Dead Value - File "ImmutableArray.res", line 42, characters 3-47 - range is never used - <-- line 42 - @dead("range") let range = (x, y) => Array.range(x, y)->toT - - Warning Dead Value - File "ImmutableArray.res", line 44, characters 3-65 - rangeBy is never used - <-- line 44 - @dead("rangeBy") let rangeBy = (x, y, ~step) => Array.rangeBy(x, y, ~step)->toT - - Warning Dead Value - File "ImmutableArray.res", line 46, characters 3-51 - makeByU is never used - <-- line 46 - @dead("makeByU") let makeByU = (c, f) => Array.makeByU(c, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 47, characters 3-49 - makeBy is never used - <-- line 47 - @dead("makeBy") let makeBy = (c, f) => Array.makeBy(c, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 49, characters 3-71 - makeByAndShuffleU is never used - <-- line 49 - @dead("makeByAndShuffleU") let makeByAndShuffleU = (c, f) => Array.makeByAndShuffleU(c, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 50, characters 3-69 - makeByAndShuffle is never used - <-- line 50 - @dead("makeByAndShuffle") let makeByAndShuffle = (c, f) => Array.makeByAndShuffle(c, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 52, characters 3-62 - zip is never used - <-- line 52 - @dead("zip") let zip = (a1, a2) => Array.zip(fromT(a1), fromT(a2))->toTp - - Warning Dead Value - File "ImmutableArray.res", line 54, characters 3-73 - zipByU is never used - <-- line 54 - @dead("zipByU") let zipByU = (a1, a2, f) => Array.zipByU(fromT(a1), fromT(a2), f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 55, characters 3-71 - zipBy is never used - <-- line 55 - @dead("zipBy") let zipBy = (a1, a2, f) => Array.zipBy(fromT(a1), fromT(a2), f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 57, characters 3-48 - unzip is never used - <-- line 57 - @dead("unzip") let unzip = a => Array.unzip(a->fromTp)->toT2 - - Warning Dead Value - File "ImmutableArray.res", line 59, characters 3-67 - concat is never used - <-- line 59 - @dead("concat") let concat = (a1, a2) => Array.concat(a1->fromT, a2->fromT)->toT - - Warning Dead Value - File "ImmutableArray.res", line 61, characters 3-68 - concatMany is never used - <-- line 61 - @dead("concatMany") let concatMany = (a: t>) => Array.concatMany(a->fromTT)->toT - - Warning Dead Value - File "ImmutableArray.res", line 63, characters 3-78 - slice is never used - <-- line 63 - @dead("slice") let slice = (a, ~offset, ~len) => Array.slice(a->fromT, ~offset, ~len)->toT - - Warning Dead Value - File "ImmutableArray.res", line 65, characters 3-64 - sliceToEnd is never used - <-- line 65 - @dead("sliceToEnd") let sliceToEnd = (a, b) => Array.sliceToEnd(a->fromT, b)->toT - - Warning Dead Value - File "ImmutableArray.res", line 67, characters 3-44 - copy is never used - <-- line 67 - @dead("copy") let copy = a => Array.copy(a->fromT)->toT - - Warning Dead Value - File "ImmutableArray.res", line 69, characters 3-55 - forEachU is never used - <-- line 69 - @dead("forEachU") let forEachU = (a, f) => Array.forEachU(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 70, characters 3-53 - forEach is never used - <-- line 70 - @dead("forEach") let forEach = (a, f) => Array.forEach(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 72, characters 3-52 - mapU is never used - <-- line 72 - @dead("mapU") let mapU = (a, f) => Array.mapU(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 73, characters 3-50 - map is never used - <-- line 73 - @dead("map") let map = (a, f) => Array.map(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 75, characters 3-72 - keepWithIndexU is never used - <-- line 75 - @dead("keepWithIndexU") let keepWithIndexU = (a, f) => Array.keepWithIndexU(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 76, characters 3-70 - keepWithIndex is never used - <-- line 76 - @dead("keepWithIndex") let keepWithIndex = (a, f) => Array.keepWithIndex(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 78, characters 3-60 - keepMapU is never used - <-- line 78 - @dead("keepMapU") let keepMapU = (a, f) => Array.keepMapU(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 79, characters 3-58 - keepMap is never used - <-- line 79 - @dead("keepMap") let keepMap = (a, f) => Array.keepMap(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 81, characters 3-73 - forEachWithIndexU is never used - <-- line 81 - @dead("forEachWithIndexU") let forEachWithIndexU = (a, f) => Array.forEachWithIndexU(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 82, characters 3-71 - forEachWithIndex is never used - <-- line 82 - @dead("forEachWithIndex") let forEachWithIndex = (a, f) => Array.forEachWithIndex(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 84, characters 3-70 - mapWithIndexU is never used - <-- line 84 - @dead("mapWithIndexU") let mapWithIndexU = (a, f) => Array.mapWithIndexU(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 85, characters 3-68 - mapWithIndex is never used - <-- line 85 - @dead("mapWithIndex") let mapWithIndex = (a, f) => Array.mapWithIndex(a->fromT, f)->toT - - Warning Dead Value - File "ImmutableArray.res", line 87, characters 3-65 - partitionU is never used - <-- line 87 - @dead("partitionU") let partitionU = (a, f) => Array.partitionU(a->fromT, f)->toT2 - - Warning Dead Value - File "ImmutableArray.res", line 88, characters 3-63 - partition is never used - <-- line 88 - @dead("partition") let partition = (a, f) => Array.partition(a->fromT, f)->toT2 - - Warning Dead Value - File "ImmutableArray.res", line 90, characters 3-59 - reduceU is never used - <-- line 90 - @dead("reduceU") let reduceU = (a, b, f) => Array.reduceU(a->fromT, b, f) - - Warning Dead Value - File "ImmutableArray.res", line 91, characters 3-57 - reduce is never used - <-- line 91 - @dead("reduce") let reduce = (a, b, f) => Array.reduce(a->fromT, b, f) - - Warning Dead Value - File "ImmutableArray.res", line 93, characters 3-73 - reduceReverseU is never used - <-- line 93 - @dead("reduceReverseU") let reduceReverseU = (a, b, f) => Array.reduceReverseU(a->fromT, b, f) - - Warning Dead Value - File "ImmutableArray.res", line 94, characters 3-71 - reduceReverse is never used - <-- line 94 - @dead("reduceReverse") let reduceReverse = (a, b, f) => Array.reduceReverse(a->fromT, b, f) - - Warning Dead Value - File "ImmutableArray.res", line 96, characters 3-92 - reduceReverse2U is never used - <-- line 96 - @dead("reduceReverse2U") let reduceReverse2U = (a1, a2, c, f) => Array.reduceReverse2U(fromT(a1), fromT(a2), c, f) - - Warning Dead Value - File "ImmutableArray.res", line 97, characters 3-90 - reduceReverse2 is never used - <-- line 97 - @dead("reduceReverse2") let reduceReverse2 = (a1, a2, c, f) => Array.reduceReverse2(fromT(a1), fromT(a2), c, f) - - Warning Dead Value - File "ImmutableArray.res", line 99, characters 3-49 - someU is never used - <-- line 99 - @dead("someU") let someU = (a, f) => Array.someU(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 100, characters 3-47 - some is never used - <-- line 100 - @dead("some") let some = (a, f) => Array.some(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 102, characters 3-51 - everyU is never used - <-- line 102 - @dead("everyU") let everyU = (a, f) => Array.everyU(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 103, characters 3-49 - every is never used - <-- line 103 - @dead("every") let every = (a, f) => Array.every(a->fromT, f) - - Warning Dead Value - File "ImmutableArray.res", line 105, characters 3-70 - every2U is never used - <-- line 105 - @dead("every2U") let every2U = (a1, a2, f) => Array.every2U(fromT(a1), fromT(a2), f) - - Warning Dead Value - File "ImmutableArray.res", line 106, characters 3-68 - every2 is never used - <-- line 106 - @dead("every2") let every2 = (a1, a2, f) => Array.every2(fromT(a1), fromT(a2), f) - - Warning Dead Value - File "ImmutableArray.res", line 108, characters 3-68 - some2U is never used - <-- line 108 - @dead("some2U") let some2U = (a1, a2, f) => Array.some2U(fromT(a1), fromT(a2), f) - - Warning Dead Value - File "ImmutableArray.res", line 109, characters 3-66 - some2 is never used - <-- line 109 - @dead("some2") let some2 = (a1, a2, f) => Array.some2(fromT(a1), fromT(a2), f) - - Warning Dead Value - File "ImmutableArray.res", line 111, characters 3-64 - cmpU is never used - <-- line 111 - @dead("cmpU") let cmpU = (a1, a2, f) => Array.cmpU(fromT(a1), fromT(a2), f) - - Warning Dead Value - File "ImmutableArray.res", line 112, characters 3-62 - cmp is never used - <-- line 112 - @dead("cmp") let cmp = (a1, a2, f) => Array.cmp(fromT(a1), fromT(a2), f) - - Warning Dead Value - File "ImmutableArray.res", line 114, characters 3-62 - eqU is never used - <-- line 114 - @dead("eqU") let eqU = (a1, a2, f) => Array.eqU(fromT(a1), fromT(a2), f) - - Warning Dead Value - File "ImmutableArray.res", line 115, characters 3-60 - eq is never used - <-- line 115 - @dead("eq") let eq = (a1, a2, f) => Array.eq(fromT(a1), fromT(a2), f) - Warning Dead Value File "ImmutableArray.resi", line 12, characters 1-32 toArray is never used @@ -3987,30 +3537,18 @@ File References <-- line 12 @dead("make") let make = make - Warning Dead Module - File "ModuleAliases.res", line 2, characters 10-57 - ModuleAliases.Outer.Inner is a dead module as all its items are dead. - Warning Dead Type File "ModuleAliases.res", line 3, characters 20-33 Outer.Inner.innerT.inner is a record label never used to read a value <-- line 3 type innerT = {@dead("Outer.Inner.innerT.inner") inner: string} - Warning Dead Module - File "ModuleAliases.res", line 10, characters 12-62 - ModuleAliases.Outer2.Inner2.InnerNested is a dead module as all its items are dead. - Warning Dead Type File "ModuleAliases.res", line 11, characters 17-28 Outer2.Inner2.InnerNested.t.nested is a record label never used to read a value <-- line 11 type t = {@dead("Outer2.Inner2.InnerNested.t.nested") nested: int} - Warning Dead Module - File "ModuleAliases2.res", line 0, characters 1-1 - ModuleAliases2 is a dead module as all its items are dead. - Warning Dead Type File "ModuleAliases2.res", line 3, characters 3-9 record.x is a record label never used to read a value @@ -4023,20 +3561,12 @@ File References <-- line 4 @dead("record.y") y: string, - Warning Dead Module - File "ModuleAliases2.res", line 7, characters 8-131 - ModuleAliases2.Outer is a dead module as all its items are dead. - Warning Dead Type File "ModuleAliases2.res", line 9, characters 17-30 Outer.outer.outer is a record label never used to read a value <-- line 9 type outer = {@dead("Outer.outer.outer") outer: string} - Warning Dead Module - File "ModuleAliases2.res", line 11, characters 10-69 - ModuleAliases2.Outer.Inner is a dead module as all its items are dead. - Warning Dead Type File "ModuleAliases2.res", line 13, characters 19-32 Outer.Inner.inner.inner is a record label never used to read a value @@ -4049,10 +3579,6 @@ File References <-- line 21 @dead("q") let q = 42 - Warning Dead Module - File "ModuleExceptionBug.res", line 1, characters 8-53 - ModuleExceptionBug.Dep is a dead module as all its items are dead. - Warning Dead Value File "ModuleExceptionBug.res", line 2, characters 3-36 Dep.customDouble is never used @@ -4119,10 +3645,6 @@ File References <-- line 47 | @dead("Universe.variant.B") B(string) - Warning Dead Module - File "Newsyntax.res", line 0, characters 1-1 - Newsyntax is a dead module as all its items are dead. - Warning Dead Value File "Newsyntax.res", line 1, characters 1-11 x is never used @@ -4303,10 +3825,6 @@ File References <-- line 11 type toPayload = {@dead("toPayload.result") result: string} - Warning Dead Module - File "TransitiveType2.res", line 0, characters 1-1 - TransitiveType2 is a dead module as all its items are dead. - Warning Dead Value File "TransitiveType2.res", line 7, characters 1-29 convertT2 is never used @@ -4325,20 +3843,12 @@ File References <-- line 4 @dead("t3.s") s: string, - Warning Dead Module - File "TypeParams1.res", line 0, characters 1-1 - TypeParams1 is a dead module as all its items are dead. - Warning Dead Value File "TypeParams1.res", line 4, characters 1-25 exportSomething is never used <-- line 4 @dead("exportSomething") let exportSomething = 10 - Warning Dead Module - File "TypeParams2.res", line 0, characters 1-1 - TypeParams2 is a dead module as all its items are dead. - Warning Dead Type File "TypeParams2.res", line 2, characters 14-21 item.id is a record label never used to read a value @@ -4399,10 +3909,6 @@ File References <-- line 133 type someRecord = {@dead("someRecord.id") id: int} - Warning Dead Module - File "Types.res", line 161, characters 8-80 - Types.ObjectId is a dead module as all its items are dead. - Warning Dead Value File "Types.res", line 166, characters 3-12 ObjectId.x is never used @@ -4511,4 +4017,4 @@ File References <-- line 96 type variant1Object = | @dead("variant1Object.R") R(payload) - Analysis reported 334 issues (Incorrect Dead Annotation:1, Warning Dead Exception:2, Warning Dead Module:25, Warning Dead Type:89, Warning Dead Value:199, Warning Dead Value With Side Effects:2, Warning Redundant Optional Argument:5, Warning Unused Argument:11) + Analysis reported 243 issues (Incorrect Dead Annotation:1, Warning Dead Exception:2, Warning Dead Type:89, Warning Dead Value:134, Warning Dead Value With Side Effects:1, Warning Redundant Optional Argument:5, Warning Unused Argument:11) diff --git a/analysis/reanalyze/src/DeadCommon.ml b/analysis/reanalyze/src/DeadCommon.ml index 85bb9c47c..fd8486fee 100644 --- a/analysis/reanalyze/src/DeadCommon.ml +++ b/analysis/reanalyze/src/DeadCommon.ml @@ -13,7 +13,6 @@ module Config = struct let analyzeTypes = ref true let analyzeExternals = ref false let reportUnderscore = false - let reportTransitive = false let reportTypesDeadOnlyInInterface = false let recursiveDebug = false let warnOnCircularDependencies = false @@ -406,10 +405,9 @@ let emitWarning ~decl ~message deadWarning = WriteDeadAnnotations.addLineAnnotation ~decl else None in - if Config.reportTransitive then - decl.path - |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) - |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; + decl.path + |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) + |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; Log_.warning ~loc (DeadWarning { @@ -553,13 +551,12 @@ module Decl = struct && (match decl.path with | name :: _ when name |> Name.isUnderscore -> Config.reportUnderscore | _ -> true) - && (Config.reportTransitive || not (hasRefBelow ())) + && (runConfig.transitive || not (hasRefBelow ())) in if shouldEmitWarning then ( - if Config.reportTransitive then - decl.path - |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) - |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; + decl.path + |> Path.toModuleName ~isType:(decl.declKind |> DeclKind.isType) + |> DeadModules.checkModuleDead ~fileName:decl.pos.pos_fname; emitWarning ~decl ~message name) end diff --git a/analysis/reanalyze/src/DeadModules.ml b/analysis/reanalyze/src/DeadModules.ml index 9b6acb88b..054b685e1 100644 --- a/analysis/reanalyze/src/DeadModules.ml +++ b/analysis/reanalyze/src/DeadModules.ml @@ -1,4 +1,4 @@ -let active () = true +let active () = RunConfig.runConfig.transitive let table = Hashtbl.create 1 let markDead ~isType ~loc path = diff --git a/analysis/reanalyze/src/Paths.ml b/analysis/reanalyze/src/Paths.ml index b0d64694b..eea3422c9 100644 --- a/analysis/reanalyze/src/Paths.ml +++ b/analysis/reanalyze/src/Paths.ml @@ -73,6 +73,12 @@ module Config = struct (* if no "analysis" specified, default to dce *) RunConfig.dce () + let readTransitive conf = + match Json.get "transitive" conf with + | Some True -> RunConfig.transitive true + | Some False -> RunConfig.transitive false + | _ -> () + (* Read the config from bsconfig.json and apply it to runConfig and suppress and unsuppress *) let processBsconfig () = Lazy.force setReScriptProjectRoot; @@ -87,7 +93,8 @@ module Config = struct | Some conf -> readSuppress conf; readUnsuppress conf; - readAnalysis conf + readAnalysis conf; + readTransitive conf | None -> (* if no "analysis" specified, default to dce *) RunConfig.dce ())) diff --git a/analysis/reanalyze/src/RunConfig.ml b/analysis/reanalyze/src/RunConfig.ml index 71cfd450d..8e9e17319 100644 --- a/analysis/reanalyze/src/RunConfig.ml +++ b/analysis/reanalyze/src/RunConfig.ml @@ -5,6 +5,7 @@ type t = { mutable projectRoot: string; mutable suppress: string list; mutable termination: bool; + mutable transitive: bool; mutable unsuppress: string list; } @@ -16,6 +17,7 @@ let runConfig = projectRoot = ""; suppress = []; termination = false; + transitive = true; unsuppress = []; } @@ -27,3 +29,5 @@ let all () = let dce () = runConfig.dce <- true let exception_ () = runConfig.exception_ <- true let termination () = runConfig.termination <- true + +let transitive b = runConfig.transitive <- b \ No newline at end of file diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index d03b3452e..f50cced86 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:0 +issues:2 From 8a2913cc7b372b23d2b4e5d74b447cd756ef2844 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 21 Oct 2022 12:38:01 +0200 Subject: [PATCH 6/8] Restore default behaviour in tests. --- .../reanalyze/examples/deadcode/bsconfig.json | 2 +- .../examples/deadcode/expected/deadcode.txt | 496 +++++++++++++++++- 2 files changed, 496 insertions(+), 2 deletions(-) diff --git a/analysis/reanalyze/examples/deadcode/bsconfig.json b/analysis/reanalyze/examples/deadcode/bsconfig.json index 81c847b6f..a0e2baae9 100644 --- a/analysis/reanalyze/examples/deadcode/bsconfig.json +++ b/analysis/reanalyze/examples/deadcode/bsconfig.json @@ -3,7 +3,7 @@ "analysis": ["dce"], "suppress": [], "unsuppress": [], - "transitive": false + "transitive": true }, "name": "sample-typescript-app", "bsc-flags": ["-bs-super-errors -w a"], diff --git a/analysis/reanalyze/examples/deadcode/expected/deadcode.txt b/analysis/reanalyze/examples/deadcode/expected/deadcode.txt index 613fb959d..b01a65eba 100644 --- a/analysis/reanalyze/examples/deadcode/expected/deadcode.txt +++ b/analysis/reanalyze/examples/deadcode/expected/deadcode.txt @@ -2663,6 +2663,10 @@ File References File "OptArg.res", line 1, characters 1-49 optional argument z of function foo is never used + Warning Dead Module + File "AutoAnnotate.res", line 0, characters 1-1 + AutoAnnotate is a dead module as all its items are dead. + Warning Dead Type File "AutoAnnotate.res", line 1, characters 16-22 variant.R is a variant case which is never constructed @@ -2705,6 +2709,10 @@ File References <-- line 15 | @dead("annotatedVariant.R4") R4(r4) + Warning Dead Module + File "BucklescriptAnnotations.res", line 0, characters 1-1 + BucklescriptAnnotations is a dead module as all its items are dead. + Warning Dead Value File "BucklescriptAnnotations.res", line 25, characters 1-71 bar is never used @@ -2723,12 +2731,20 @@ File References <-- line 8 @dead("eToplevel") let eToplevel = Etoplevel + Warning Dead Module + File "DeadMl.ml", line 1, characters 1-121 + DeadMl.QQ is a dead module as all its items are dead. + Warning Dead Value File "DeadMl.ml", line 3, characters 5-94 QQ.thisSpansSeveralLines is never used <-- line 3 x + y : int -> int -> int) [@@dead "QQ.thisSpansSeveralLines"] + Warning Dead Module + File "DeadMl.ml", line 8, characters 1-104 + DeadMl.AA is a dead module as all its items are dead. + Warning Dead Value File "DeadMl.ml", line 9, characters 3-41 AA.thisIsInInterface is never used @@ -2759,6 +2775,10 @@ File References <-- line 17 type thisIsDead = | DeadA [@dead "thisIsDead.DeadA"] | DeadB [@dead "thisIsDead.DeadB"] + Warning Dead Module + File "DeadMl.ml", line 25, characters 1-257 + DeadMl.Bs_version is a dead module as all its items are dead. + Warning Dead Value File "DeadMl.ml", line 26, characters 7-27 Bs_version.version is never used @@ -2897,6 +2917,10 @@ File References <-- line 2 @dead("fortytwo") let fortytwo = 42 + Warning Dead Module + File "DeadTest.res", line 27, characters 8-98 + DeadTest.M is a dead module as all its items are dead. + Warning Dead Value File "DeadTest.res", line 31, characters 3-35 M.thisSignatureItemIsDead is never used @@ -2927,6 +2951,12 @@ File References <-- line 77 @dead("split_map") let rec split_map = l => { + Warning Dead Value + File "DeadTest.res", line 82, characters 1-28 + rec1 is never used + <-- line 82 + @dead("rec1") let rec rec1 = () => rec2() + Warning Dead Value File "DeadTest.res", line 83, characters 1-24 rec2 is never used @@ -2939,6 +2969,12 @@ File References <-- line 85 @dead("recWithCallback") let rec recWithCallback = () => { + Warning Dead Value + File "DeadTest.res", line 90, characters 1-54 + foo is never used + <-- line 90 + @dead("foo") let rec foo = () => { + Warning Dead Value File "DeadTest.res", line 94, characters 1-22 bar is never used @@ -2951,6 +2987,14 @@ File References <-- line 96 @dead("withDefaultValue") let withDefaultValue = (~paramWithDefault=3, y) => paramWithDefault + y + Warning Dead Module + File "DeadTest.res", line 110, characters 8-414 + DeadTest.LazyDynamicallyLoadedComponent2 is a dead module as all its items are dead. + + Warning Dead Value With Side Effects + File "DeadTest.res", line 111, characters 3-143 + LazyDynamicallyLoadedComponent2.reasonResource is never used and could have side effects + Warning Dead Value File "DeadTest.res", line 114, characters 3-55 LazyDynamicallyLoadedComponent2.makeProps is never used @@ -2969,6 +3013,12 @@ File References <-- line 127 @dead("zzz") let zzz = { + Warning Dead Value + File "DeadTest.res", line 135, characters 1-16 + second is never used + <-- line 135 + @dead("second") let second = 1L + Warning Dead Value File "DeadTest.res", line 136, characters 1-36 minute is never used @@ -2997,12 +3047,20 @@ File References <-- line 175 type rc = {@dead("rc.a") a: int} + Warning Dead Module + File "DeadTestBlacklist.res", line 0, characters 1-1 + DeadTestBlacklist is a dead module as all its items are dead. + Warning Dead Value File "DeadTestBlacklist.res", line 1, characters 1-11 x is never used <-- line 1 @dead("x") let x = 34 + Warning Dead Module + File "DeadTestWithInterface.res", line 1, characters 8-55 + DeadTestWithInterface.Ext_buffer is a dead module as all its items are dead. + Warning Dead Value File "DeadTestWithInterface.res", line 2, characters 3-13 Ext_buffer.x is never used @@ -3021,6 +3079,12 @@ File References <-- line 3 | @dead("t.B") B + Warning Dead Value + File "DeadTypeTest.res", line 4, characters 1-10 + a is never used + <-- line 4 + @dead("a") let a = A + Warning Dead Type File "DeadTypeTest.res", line 10, characters 5-14 deadType.InNeither is a variant case which is never constructed @@ -3045,6 +3109,12 @@ File References <-- line 10 | @dead("deadType.InNeither") InNeither + Warning Dead Value + File "DeadValueTest.res", line 2, characters 1-18 + valueDead is never used + <-- line 2 + @dead("valueDead") let valueDead = 2 + Warning Dead Value File "DeadValueTest.res", line 4, characters 1-34 valueOnlyInImplementation is never used @@ -3069,12 +3139,30 @@ File References <-- line 61 | @dead("t.B") B + Warning Dead Module + File "ErrorHandler.res", line 0, characters 1-1 + ErrorHandler is a dead module as all its items are dead. + + Warning Dead Value + File "ErrorHandler.res", line 12, characters 1-11 + x is never used + <-- line 12 + @dead("x") let x = 42 + + Warning Dead Module + File "ErrorHandler.resi", line 0, characters 1-1 + ErrorHandler is a dead module as all its items are dead. + Warning Dead Value File "ErrorHandler.resi", line 10, characters 1-11 x is never used <-- line 10 @dead("x") let x: int + Warning Dead Module + File "EverythingLiveHere.res", line 0, characters 1-1 + EverythingLiveHere is a dead module as all its items are dead. + Warning Dead Value File "EverythingLiveHere.res", line 1, characters 1-10 x is never used @@ -3093,6 +3181,10 @@ File References <-- line 5 @dead("z") let z = 4 + Warning Dead Module + File "FirstClassModulesInterface.res", line 0, characters 1-1 + FirstClassModulesInterface is a dead module as all its items are dead. + Warning Dead Type File "FirstClassModulesInterface.res", line 2, characters 3-9 record.x is a record label never used to read a value @@ -3105,6 +3197,16 @@ File References <-- line 3 @dead("record.y") y: string, + Warning Dead Value + File "FirstClassModulesInterface.res", line 6, characters 1-27 + r is never used + <-- line 6 + @dead("r") let r = {x: 3, y: "hello"} + + Warning Dead Module + File "FirstClassModulesInterface.resi", line 0, characters 1-1 + FirstClassModulesInterface is a dead module as all its items are dead. + Warning Dead Type File "FirstClassModulesInterface.resi", line 3, characters 3-9 record.x is a record label never used to read a value @@ -3123,6 +3225,354 @@ File References <-- line 7 @dead("r") let r: record + Warning Dead Value + File "ImmutableArray.res", line 16, characters 3-42 + toArray is never used + <-- line 16 + @dead("toArray") let toArray = a => Array.copy(a->fromT) + + Warning Dead Value + File "ImmutableArray.res", line 20, characters 3-43 + length is never used + <-- line 20 + @dead("length") let length = a => Array.length(a->fromT) + + Warning Dead Value + File "ImmutableArray.res", line 22, characters 3-39 + size is never used + <-- line 22 + @dead("size") let size = a => Array.size(a->fromT) + + Warning Dead Value + File "ImmutableArray.res", line 26, characters 3-51 + getExn is never used + <-- line 26 + @dead("getExn") let getExn = (a, x) => Array.getExn(a->fromT, x) + + Warning Dead Value + File "ImmutableArray.res", line 28, characters 3-57 + getUnsafe is never used + <-- line 28 + @dead("getUnsafe") let getUnsafe = (a, x) => Array.getUnsafe(a->fromT, x) + + Warning Dead Value + File "ImmutableArray.res", line 30, characters 3-63 + getUndefined is never used + <-- line 30 + @dead("getUndefined") let getUndefined = (a, x) => Array.getUndefined(a->fromT, x) + + Warning Dead Value + File "ImmutableArray.res", line 32, characters 3-50 + shuffle is never used + <-- line 32 + @dead("shuffle") let shuffle = x => Array.shuffle(x->fromT)->toT + + Warning Dead Value + File "ImmutableArray.res", line 34, characters 3-50 + reverse is never used + <-- line 34 + @dead("reverse") let reverse = x => Array.reverse(x->fromT)->toT + + Warning Dead Value + File "ImmutableArray.res", line 36, characters 3-63 + makeUninitialized is never used + <-- line 36 + @dead("makeUninitialized") let makeUninitialized = x => Array.makeUninitialized(x)->toT + + Warning Dead Value + File "ImmutableArray.res", line 38, characters 3-75 + makeUninitializedUnsafe is never used + <-- line 38 + @dead("makeUninitializedUnsafe") let makeUninitializedUnsafe = x => Array.makeUninitializedUnsafe(x)->toT + + Warning Dead Value + File "ImmutableArray.res", line 40, characters 3-45 + make is never used + <-- line 40 + @dead("make") let make = (x, y) => Array.make(x, y)->toT + + Warning Dead Value + File "ImmutableArray.res", line 42, characters 3-47 + range is never used + <-- line 42 + @dead("range") let range = (x, y) => Array.range(x, y)->toT + + Warning Dead Value + File "ImmutableArray.res", line 44, characters 3-65 + rangeBy is never used + <-- line 44 + @dead("rangeBy") let rangeBy = (x, y, ~step) => Array.rangeBy(x, y, ~step)->toT + + Warning Dead Value + File "ImmutableArray.res", line 46, characters 3-51 + makeByU is never used + <-- line 46 + @dead("makeByU") let makeByU = (c, f) => Array.makeByU(c, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 47, characters 3-49 + makeBy is never used + <-- line 47 + @dead("makeBy") let makeBy = (c, f) => Array.makeBy(c, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 49, characters 3-71 + makeByAndShuffleU is never used + <-- line 49 + @dead("makeByAndShuffleU") let makeByAndShuffleU = (c, f) => Array.makeByAndShuffleU(c, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 50, characters 3-69 + makeByAndShuffle is never used + <-- line 50 + @dead("makeByAndShuffle") let makeByAndShuffle = (c, f) => Array.makeByAndShuffle(c, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 52, characters 3-62 + zip is never used + <-- line 52 + @dead("zip") let zip = (a1, a2) => Array.zip(fromT(a1), fromT(a2))->toTp + + Warning Dead Value + File "ImmutableArray.res", line 54, characters 3-73 + zipByU is never used + <-- line 54 + @dead("zipByU") let zipByU = (a1, a2, f) => Array.zipByU(fromT(a1), fromT(a2), f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 55, characters 3-71 + zipBy is never used + <-- line 55 + @dead("zipBy") let zipBy = (a1, a2, f) => Array.zipBy(fromT(a1), fromT(a2), f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 57, characters 3-48 + unzip is never used + <-- line 57 + @dead("unzip") let unzip = a => Array.unzip(a->fromTp)->toT2 + + Warning Dead Value + File "ImmutableArray.res", line 59, characters 3-67 + concat is never used + <-- line 59 + @dead("concat") let concat = (a1, a2) => Array.concat(a1->fromT, a2->fromT)->toT + + Warning Dead Value + File "ImmutableArray.res", line 61, characters 3-68 + concatMany is never used + <-- line 61 + @dead("concatMany") let concatMany = (a: t>) => Array.concatMany(a->fromTT)->toT + + Warning Dead Value + File "ImmutableArray.res", line 63, characters 3-78 + slice is never used + <-- line 63 + @dead("slice") let slice = (a, ~offset, ~len) => Array.slice(a->fromT, ~offset, ~len)->toT + + Warning Dead Value + File "ImmutableArray.res", line 65, characters 3-64 + sliceToEnd is never used + <-- line 65 + @dead("sliceToEnd") let sliceToEnd = (a, b) => Array.sliceToEnd(a->fromT, b)->toT + + Warning Dead Value + File "ImmutableArray.res", line 67, characters 3-44 + copy is never used + <-- line 67 + @dead("copy") let copy = a => Array.copy(a->fromT)->toT + + Warning Dead Value + File "ImmutableArray.res", line 69, characters 3-55 + forEachU is never used + <-- line 69 + @dead("forEachU") let forEachU = (a, f) => Array.forEachU(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 70, characters 3-53 + forEach is never used + <-- line 70 + @dead("forEach") let forEach = (a, f) => Array.forEach(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 72, characters 3-52 + mapU is never used + <-- line 72 + @dead("mapU") let mapU = (a, f) => Array.mapU(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 73, characters 3-50 + map is never used + <-- line 73 + @dead("map") let map = (a, f) => Array.map(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 75, characters 3-72 + keepWithIndexU is never used + <-- line 75 + @dead("keepWithIndexU") let keepWithIndexU = (a, f) => Array.keepWithIndexU(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 76, characters 3-70 + keepWithIndex is never used + <-- line 76 + @dead("keepWithIndex") let keepWithIndex = (a, f) => Array.keepWithIndex(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 78, characters 3-60 + keepMapU is never used + <-- line 78 + @dead("keepMapU") let keepMapU = (a, f) => Array.keepMapU(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 79, characters 3-58 + keepMap is never used + <-- line 79 + @dead("keepMap") let keepMap = (a, f) => Array.keepMap(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 81, characters 3-73 + forEachWithIndexU is never used + <-- line 81 + @dead("forEachWithIndexU") let forEachWithIndexU = (a, f) => Array.forEachWithIndexU(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 82, characters 3-71 + forEachWithIndex is never used + <-- line 82 + @dead("forEachWithIndex") let forEachWithIndex = (a, f) => Array.forEachWithIndex(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 84, characters 3-70 + mapWithIndexU is never used + <-- line 84 + @dead("mapWithIndexU") let mapWithIndexU = (a, f) => Array.mapWithIndexU(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 85, characters 3-68 + mapWithIndex is never used + <-- line 85 + @dead("mapWithIndex") let mapWithIndex = (a, f) => Array.mapWithIndex(a->fromT, f)->toT + + Warning Dead Value + File "ImmutableArray.res", line 87, characters 3-65 + partitionU is never used + <-- line 87 + @dead("partitionU") let partitionU = (a, f) => Array.partitionU(a->fromT, f)->toT2 + + Warning Dead Value + File "ImmutableArray.res", line 88, characters 3-63 + partition is never used + <-- line 88 + @dead("partition") let partition = (a, f) => Array.partition(a->fromT, f)->toT2 + + Warning Dead Value + File "ImmutableArray.res", line 90, characters 3-59 + reduceU is never used + <-- line 90 + @dead("reduceU") let reduceU = (a, b, f) => Array.reduceU(a->fromT, b, f) + + Warning Dead Value + File "ImmutableArray.res", line 91, characters 3-57 + reduce is never used + <-- line 91 + @dead("reduce") let reduce = (a, b, f) => Array.reduce(a->fromT, b, f) + + Warning Dead Value + File "ImmutableArray.res", line 93, characters 3-73 + reduceReverseU is never used + <-- line 93 + @dead("reduceReverseU") let reduceReverseU = (a, b, f) => Array.reduceReverseU(a->fromT, b, f) + + Warning Dead Value + File "ImmutableArray.res", line 94, characters 3-71 + reduceReverse is never used + <-- line 94 + @dead("reduceReverse") let reduceReverse = (a, b, f) => Array.reduceReverse(a->fromT, b, f) + + Warning Dead Value + File "ImmutableArray.res", line 96, characters 3-92 + reduceReverse2U is never used + <-- line 96 + @dead("reduceReverse2U") let reduceReverse2U = (a1, a2, c, f) => Array.reduceReverse2U(fromT(a1), fromT(a2), c, f) + + Warning Dead Value + File "ImmutableArray.res", line 97, characters 3-90 + reduceReverse2 is never used + <-- line 97 + @dead("reduceReverse2") let reduceReverse2 = (a1, a2, c, f) => Array.reduceReverse2(fromT(a1), fromT(a2), c, f) + + Warning Dead Value + File "ImmutableArray.res", line 99, characters 3-49 + someU is never used + <-- line 99 + @dead("someU") let someU = (a, f) => Array.someU(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 100, characters 3-47 + some is never used + <-- line 100 + @dead("some") let some = (a, f) => Array.some(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 102, characters 3-51 + everyU is never used + <-- line 102 + @dead("everyU") let everyU = (a, f) => Array.everyU(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 103, characters 3-49 + every is never used + <-- line 103 + @dead("every") let every = (a, f) => Array.every(a->fromT, f) + + Warning Dead Value + File "ImmutableArray.res", line 105, characters 3-70 + every2U is never used + <-- line 105 + @dead("every2U") let every2U = (a1, a2, f) => Array.every2U(fromT(a1), fromT(a2), f) + + Warning Dead Value + File "ImmutableArray.res", line 106, characters 3-68 + every2 is never used + <-- line 106 + @dead("every2") let every2 = (a1, a2, f) => Array.every2(fromT(a1), fromT(a2), f) + + Warning Dead Value + File "ImmutableArray.res", line 108, characters 3-68 + some2U is never used + <-- line 108 + @dead("some2U") let some2U = (a1, a2, f) => Array.some2U(fromT(a1), fromT(a2), f) + + Warning Dead Value + File "ImmutableArray.res", line 109, characters 3-66 + some2 is never used + <-- line 109 + @dead("some2") let some2 = (a1, a2, f) => Array.some2(fromT(a1), fromT(a2), f) + + Warning Dead Value + File "ImmutableArray.res", line 111, characters 3-64 + cmpU is never used + <-- line 111 + @dead("cmpU") let cmpU = (a1, a2, f) => Array.cmpU(fromT(a1), fromT(a2), f) + + Warning Dead Value + File "ImmutableArray.res", line 112, characters 3-62 + cmp is never used + <-- line 112 + @dead("cmp") let cmp = (a1, a2, f) => Array.cmp(fromT(a1), fromT(a2), f) + + Warning Dead Value + File "ImmutableArray.res", line 114, characters 3-62 + eqU is never used + <-- line 114 + @dead("eqU") let eqU = (a1, a2, f) => Array.eqU(fromT(a1), fromT(a2), f) + + Warning Dead Value + File "ImmutableArray.res", line 115, characters 3-60 + eq is never used + <-- line 115 + @dead("eq") let eq = (a1, a2, f) => Array.eq(fromT(a1), fromT(a2), f) + Warning Dead Value File "ImmutableArray.resi", line 12, characters 1-32 toArray is never used @@ -3537,18 +3987,30 @@ File References <-- line 12 @dead("make") let make = make + Warning Dead Module + File "ModuleAliases.res", line 2, characters 10-57 + ModuleAliases.Outer.Inner is a dead module as all its items are dead. + Warning Dead Type File "ModuleAliases.res", line 3, characters 20-33 Outer.Inner.innerT.inner is a record label never used to read a value <-- line 3 type innerT = {@dead("Outer.Inner.innerT.inner") inner: string} + Warning Dead Module + File "ModuleAliases.res", line 10, characters 12-62 + ModuleAliases.Outer2.Inner2.InnerNested is a dead module as all its items are dead. + Warning Dead Type File "ModuleAliases.res", line 11, characters 17-28 Outer2.Inner2.InnerNested.t.nested is a record label never used to read a value <-- line 11 type t = {@dead("Outer2.Inner2.InnerNested.t.nested") nested: int} + Warning Dead Module + File "ModuleAliases2.res", line 0, characters 1-1 + ModuleAliases2 is a dead module as all its items are dead. + Warning Dead Type File "ModuleAliases2.res", line 3, characters 3-9 record.x is a record label never used to read a value @@ -3561,12 +4023,20 @@ File References <-- line 4 @dead("record.y") y: string, + Warning Dead Module + File "ModuleAliases2.res", line 7, characters 8-131 + ModuleAliases2.Outer is a dead module as all its items are dead. + Warning Dead Type File "ModuleAliases2.res", line 9, characters 17-30 Outer.outer.outer is a record label never used to read a value <-- line 9 type outer = {@dead("Outer.outer.outer") outer: string} + Warning Dead Module + File "ModuleAliases2.res", line 11, characters 10-69 + ModuleAliases2.Outer.Inner is a dead module as all its items are dead. + Warning Dead Type File "ModuleAliases2.res", line 13, characters 19-32 Outer.Inner.inner.inner is a record label never used to read a value @@ -3579,6 +4049,10 @@ File References <-- line 21 @dead("q") let q = 42 + Warning Dead Module + File "ModuleExceptionBug.res", line 1, characters 8-53 + ModuleExceptionBug.Dep is a dead module as all its items are dead. + Warning Dead Value File "ModuleExceptionBug.res", line 2, characters 3-36 Dep.customDouble is never used @@ -3645,6 +4119,10 @@ File References <-- line 47 | @dead("Universe.variant.B") B(string) + Warning Dead Module + File "Newsyntax.res", line 0, characters 1-1 + Newsyntax is a dead module as all its items are dead. + Warning Dead Value File "Newsyntax.res", line 1, characters 1-11 x is never used @@ -3825,6 +4303,10 @@ File References <-- line 11 type toPayload = {@dead("toPayload.result") result: string} + Warning Dead Module + File "TransitiveType2.res", line 0, characters 1-1 + TransitiveType2 is a dead module as all its items are dead. + Warning Dead Value File "TransitiveType2.res", line 7, characters 1-29 convertT2 is never used @@ -3843,12 +4325,20 @@ File References <-- line 4 @dead("t3.s") s: string, + Warning Dead Module + File "TypeParams1.res", line 0, characters 1-1 + TypeParams1 is a dead module as all its items are dead. + Warning Dead Value File "TypeParams1.res", line 4, characters 1-25 exportSomething is never used <-- line 4 @dead("exportSomething") let exportSomething = 10 + Warning Dead Module + File "TypeParams2.res", line 0, characters 1-1 + TypeParams2 is a dead module as all its items are dead. + Warning Dead Type File "TypeParams2.res", line 2, characters 14-21 item.id is a record label never used to read a value @@ -3909,6 +4399,10 @@ File References <-- line 133 type someRecord = {@dead("someRecord.id") id: int} + Warning Dead Module + File "Types.res", line 161, characters 8-80 + Types.ObjectId is a dead module as all its items are dead. + Warning Dead Value File "Types.res", line 166, characters 3-12 ObjectId.x is never used @@ -4017,4 +4511,4 @@ File References <-- line 96 type variant1Object = | @dead("variant1Object.R") R(payload) - Analysis reported 243 issues (Incorrect Dead Annotation:1, Warning Dead Exception:2, Warning Dead Type:89, Warning Dead Value:134, Warning Dead Value With Side Effects:1, Warning Redundant Optional Argument:5, Warning Unused Argument:11) + Analysis reported 334 issues (Incorrect Dead Annotation:1, Warning Dead Exception:2, Warning Dead Module:25, Warning Dead Type:89, Warning Dead Value:199, Warning Dead Value With Side Effects:2, Warning Redundant Optional Argument:5, Warning Unused Argument:11) From 4daeba551ec72b10e8f4e67f53d46c75150bbb73 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 21 Oct 2022 12:42:24 +0200 Subject: [PATCH 7/8] comment --- analysis/reanalyze/src/DeadModules.ml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/analysis/reanalyze/src/DeadModules.ml b/analysis/reanalyze/src/DeadModules.ml index 054b685e1..572748bcf 100644 --- a/analysis/reanalyze/src/DeadModules.ml +++ b/analysis/reanalyze/src/DeadModules.ml @@ -1,4 +1,7 @@ -let active () = RunConfig.runConfig.transitive +let active () = + (* When transitive reporting is off, the only dead modules would be empty modules *) + RunConfig.runConfig.transitive + let table = Hashtbl.create 1 let markDead ~isType ~loc path = From b5e1919f08e7a62c69f89fe742d2c32a428f3933 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 21 Oct 2022 12:54:37 +0200 Subject: [PATCH 8/8] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 181be3ec0..8e06c9d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,8 @@ #### :rocket: New Feature -- Add configuration parameter `"transitive"` under `"reanalyze"`. If set to false, analysis does not report transitively dead items. So removing the item directly reported can be done in isolation https://github.com/rescript-lang/rescript-vscode/pull/601 +- Add configuration parameter `"transitive"` under `"reanalyze"` is `bsconfig.json`. If set to `false`, the analysis does not report transitively dead items. So removing the reported item individually can be done in isolation. This is a more fine-grained process for guiding the user to remove dead code one item at a time. https://github.com/rescript-lang/rescript-vscode/pull/601 +This feature comes from a conversation with @jfmengels on how https://github.com/jfmengels/elm-review is designed. #### :bug: Bug Fix