diff --git a/CHANGELOG.md b/CHANGELOG.md index 906757ea2..49a2af97a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ #### :nail_care: Polish - Signature Help is now considered stable, and enabled for all users. Can still be turned off in settings. +- Show whether record fields and variant constructors are deprecated when completing. https://github.com/rescript-lang/rescript-vscode/pull/731 ## 1.12.0 diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 7a62de8e6..9eee9cdab 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -108,6 +108,7 @@ let completionsForExportedConstructors ~(env : QueryEnv.t) ~prefix ~exact let () = Hashtbl.add namesUsed name () in Some (Completion.create name ~env ~docstring:c.docstring + ?deprecated:c.deprecated ~kind: (Completion.Constructor (c, t.item.decl |> Shared.declToString t.name.txt))) @@ -130,6 +131,7 @@ let completionForExportedFields ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed = let () = Hashtbl.add namesUsed name () in Some (Completion.create name ~env ~docstring:f.docstring + ?deprecated:f.deprecated ~kind: (Completion.Field (f, t.item.decl |> Shared.declToString t.name.txt))) @@ -740,7 +742,7 @@ let rec getCompletionsForContextPath ~full ~opens ~rawOpens ~allFiles ~pos ~env if Utils.checkName field.fname.txt ~prefix:fieldName ~exact then Some (Completion.create field.fname.txt ~env - ~docstring:field.docstring + ~docstring:field.docstring ?deprecated:field.deprecated ~kind: (Completion.Field ( field, @@ -1072,7 +1074,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode | InlineRecord _ -> 1 | Args args -> List.length args in - Completion.createWithSnippet + Completion.createWithSnippet ?deprecated:constructor.deprecated ~name: (constructor.cname.txt ^ printConstructorArgs numArgs ~asSnippet:false) @@ -1151,6 +1153,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode match (field.optional, mode) with | true, Pattern Destructuring -> Completion.create ("?" ^ field.fname.txt) + ?deprecated:field.deprecated ~docstring: [ field.fname.txt @@ -1161,7 +1164,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode (Field (field, TypeUtils.extractedTypeToString extractedType)) ~env | _ -> - Completion.create field.fname.txt + Completion.create field.fname.txt ?deprecated:field.deprecated ~kind: (Field (field, TypeUtils.extractedTypeToString extractedType)) ~env) @@ -1189,7 +1192,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode List.mem field.fname.txt seenFields = false) |> List.map (fun (field : field) -> Completion.create field.fname.txt ~kind:(Label "Inline record") - ~env) + ?deprecated:field.deprecated ~env) |> filterItems ~prefix | None -> if prefix = "" then diff --git a/analysis/src/ProcessCmt.ml b/analysis/src/ProcessCmt.ml index 67b910830..329af53fc 100644 --- a/analysis/src/ProcessCmt.ml +++ b/analysis/src/ProcessCmt.ml @@ -27,6 +27,7 @@ let mapRecordField {Types.ld_id; ld_type; ld_attributes} = (match ProcessAttributes.findDocAttribute ld_attributes with | None -> [] | Some docstring -> [docstring]); + deprecated = ProcessAttributes.findDeprecatedAttribute ld_attributes; } let rec forTypeSignatureItem ~(env : SharedTypes.Env.t) ~(exported : Exported.t) @@ -99,6 +100,9 @@ let rec forTypeSignatureItem ~(env : SharedTypes.Env.t) ~(exported : Exported.t) res = cd_res; typeDecl = (name, decl); docstring = attrsToDocstring cd_attributes; + deprecated = + ProcessAttributes.findDeprecatedAttribute + cd_attributes; } in let declared = @@ -200,6 +204,9 @@ let forTypeDeclaration ~env ~(exported : Exported.t) { Constructor.stamp; cname; + deprecated = + ProcessAttributes.findDeprecatedAttribute + cd_attributes; args = (match cd_args with | Cstr_tuple args -> @@ -231,6 +238,10 @@ let forTypeDeclaration ~env ~(exported : Exported.t) with | None -> [] | Some docstring -> [docstring]); + deprecated = + ProcessAttributes + .findDeprecatedAttribute + f.ld_attributes; }))); res = (match cd_res with @@ -268,6 +279,9 @@ let forTypeDeclaration ~env ~(exported : Exported.t) Res_parsetree_viewer.hasOptionalAttribute ld_attributes; docstring = attrsToDocstring ld_attributes; + deprecated = + ProcessAttributes.findDeprecatedAttribute + ld_attributes; }))); } ~name ~stamp ~env typ_attributes diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 622065cdd..c84aabf25 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -32,6 +32,7 @@ type field = { typ: Types.type_expr; optional: bool; docstring: string list; + deprecated: string option; } type constructorArgs = @@ -46,6 +47,7 @@ module Constructor = struct res: Types.type_expr option; typeDecl: string * Types.type_declaration; docstring: string list; + deprecated: string option; } end @@ -367,12 +369,12 @@ module Completion = struct detail; } - let createWithSnippet ~name ?insertText ~kind ~env ?sortText ?filterText - ?(docstring = []) () = + let createWithSnippet ~name ?insertText ~kind ~env ?sortText ?deprecated + ?filterText ?(docstring = []) () = { name; env; - deprecated = None; + deprecated; docstring; kind; sortText; diff --git a/analysis/tests/src/Completion.res b/analysis/tests/src/Completion.res index dd1e90879..9246c2bdd 100644 --- a/analysis/tests/src/Completion.res +++ b/analysis/tests/src/Completion.res @@ -425,3 +425,28 @@ let ok = Ok(true) // ok->g // ^com + +type someRecordWithDeprecatedField = { + name: string, + @deprecated + someInt: int, + @deprecated("Use 'someInt'.") + someFloat: float, +} + +let rWithDepr: someRecordWithDeprecatedField = { + name: "hej", + someInt: 12, + someFloat: 12., +} + +// Should show deprecated status +// rWithDepr.so +// ^com + +type someVariantWithDeprecated = + | @deprecated DoNotUseMe | UseMeInstead | @deprecated("Use 'UseMeInstead'") AndNotMe + +// Should show deprecated status +// let v: someVariantWithDeprecated = +// ^com diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index b36ab0940..c98e1a2c8 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1625,8 +1625,8 @@ Resolved opens 2 Completion.res Completion.res }] Complete src/Completion.res 405:22 -posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->428:0] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->423:17], ...[428:0->428:0]) +posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->453:0] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->423:17], ...[428:0->453:0]) posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->423:17] Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->405:19], ...[405:21->423:17]) posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:21->423:17] @@ -1759,3 +1759,54 @@ Resolved opens 2 Completion.res Completion.res "documentation": {"kind": "markdown", "value": "\n `getWithDefault(res, defaultValue)`: If `res` is `Ok(n)`, returns `n`,\n otherwise `default`\n\n ```res example\n Belt.Result.getWithDefault(Ok(42), 0) == 42\n\n Belt.Result.getWithDefault(Error(\"Invalid Data\"), 0) == 0\n ```\n"} }] +Complete src/Completion.res 443:15 +posCursor:[443:15] posNoWhite:[443:14] Found expr:[443:3->443:15] +Pexp_field [443:3->443:12] so:[443:13->443:15] +Completable: Cpath Value[rWithDepr].so +Raw opens: 2 Shadow.B.place holder ... Shadow.A.place holder +Resolved opens 2 Completion.res Completion.res +[{ + "label": "someInt", + "kind": 5, + "tags": [1], + "detail": "someInt: int\n\ntype someRecordWithDeprecatedField = {\n name: string,\n someInt: int,\n someFloat: float,\n}", + "documentation": {"kind": "markdown", "value": "Deprecated: \n\n"} + }, { + "label": "someFloat", + "kind": 5, + "tags": [1], + "detail": "someFloat: float\n\ntype someRecordWithDeprecatedField = {\n name: string,\n someInt: int,\n someFloat: float,\n}", + "documentation": {"kind": "markdown", "value": "Deprecated: Use 'someInt'.\n\n"} + }] + +Complete src/Completion.res 450:37 +XXX Not found! +Completable: Cexpression Type[someVariantWithDeprecated] +Raw opens: 2 Shadow.B.place holder ... Shadow.A.place holder +Resolved opens 2 Completion.res Completion.res +[{ + "label": "DoNotUseMe", + "kind": 4, + "tags": [1], + "detail": "DoNotUseMe\n\ntype someVariantWithDeprecated =\n | DoNotUseMe\n | UseMeInstead\n | AndNotMe", + "documentation": {"kind": "markdown", "value": "Deprecated: \n\n"}, + "insertText": "DoNotUseMe", + "insertTextFormat": 2 + }, { + "label": "UseMeInstead", + "kind": 4, + "tags": [], + "detail": "UseMeInstead\n\ntype someVariantWithDeprecated =\n | DoNotUseMe\n | UseMeInstead\n | AndNotMe", + "documentation": null, + "insertText": "UseMeInstead", + "insertTextFormat": 2 + }, { + "label": "AndNotMe", + "kind": 4, + "tags": [1], + "detail": "AndNotMe\n\ntype someVariantWithDeprecated =\n | DoNotUseMe\n | UseMeInstead\n | AndNotMe", + "documentation": {"kind": "markdown", "value": "Deprecated: Use 'UseMeInstead'\n\n"}, + "insertText": "AndNotMe", + "insertTextFormat": 2 + }] +