Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I get "Extract into variable" assist but not "Extract into function" #11577

Closed
krobelus opened this issue Feb 27, 2022 · 5 comments
Closed

I get "Extract into variable" assist but not "Extract into function" #11577

krobelus opened this issue Feb 27, 2022 · 5 comments

Comments

@krobelus
Copy link
Contributor

The VSCode extension provides "Extract into function" as expected, but when using another client (kak-lsp) I merely get "Extract into variable".

The VSCode extension and kak-lsp have a number of differences in capabilities, but I didn't see anything relevant.

I made both clients use this binary:

$ rust-analyzer --version
rust-analyzer 2022-02-21

Reproducible with this Rust file:

fn main() {
    let n = 100;
    for i in 0..n {
        println!("{}", i);
    }
}

Initialization looks like this

Feb 27 20:50:48.144 DEBG To server: {
  "jsonrpc": "2.0",
  "method": "initialize",
  "params": {
    "capabilities": {
      "general": {
        "markdown": {
          "parser": "kak-lsp",
          "version": "12.0.1-snapshot"
        }
      },
      "offsetEncoding": [
        "utf-8",
        "utf-16"
      ],
      "textDocument": {
        "callHierarchy": {
          "dynamicRegistration": false
        },
        "codeAction": {
          "codeActionLiteralSupport": {
            "codeActionKind": {
              "valueSet": [
                "quickfix",
                "refactor",
                "refactor.extract",
                "refactor.inline",
                "refactor.rewrite",
                "source",
                "source.organizeImports"
              ]
            }
          },
          "dynamicRegistration": false,
          "isPreferredSupport": false,
          "resolveSupport": {
            "properties": []
          }
        },
        "codeLens": {
          "dynamicRegistration": false
        },
        "colorProvider": {
          "dynamicRegistration": false
        },
        "completion": {
          "completionItem": {
            "commitCharactersSupport": false,
            "deprecatedSupport": false,
            "documentationFormat": [
              "markdown",
              "plaintext"
            ],
            "preselectSupport": false,
            "resolveSupport": {
              "properties": [
                "additionalTextEdits"
              ]
            },
            "snippetSupport": false
          },
          "completionItemKind": {
            "valueSet": [
              1,
              2,
              3,
              4,
              5,
              6,
              7,
              8,
              9,
              10,
              11,
              12,
              13,
              14,
              15,
              16,
              17,
              18,
              19,
              20,
              21,
              22,
              23,
              24,
              25
            ]
          },
          "contextSupport": false,
          "dynamicRegistration": false
        },
        "declaration": {
          "dynamicRegistration": false,
          "linkSupport": false
        },
        "definition": {
          "dynamicRegistration": false,
          "linkSupport": false
        },
        "documentHighlight": {
          "dynamicRegistration": false
        },
        "documentLink": {
          "dynamicRegistration": false,
          "tooltipSupport": false
        },
        "documentSymbol": {
          "dynamicRegistration": false,
          "hierarchicalDocumentSymbolSupport": true
        },
        "formatting": {
          "dynamicRegistration": false
        },
        "hover": {
          "contentFormat": [
            "markdown",
            "plaintext"
          ],
          "dynamicRegistration": false
        },
        "implementation": {
          "dynamicRegistration": false,
          "linkSupport": false
        },
        "onTypeFormatting": {
          "dynamicRegistration": false
        },
        "publishDiagnostics": {
          "relatedInformation": false
        },
        "rangeFormatting": {
          "dynamicRegistration": false
        },
        "references": {
          "dynamicRegistration": false
        },
        "rename": {
          "dynamicRegistration": false,
          "prepareSupport": false
        },
        "selectionRange": {},
        "semanticTokens": {
          "dynamicRegistration": false,
          "formats": [
            "relative"
          ],
          "requests": {
            "full": true,
            "range": false
          },
          "tokenModifiers": [
            "documentation",
            "readonly",
            "constant"
          ],
          "tokenTypes": [
            "string",
            "operator",
            "function",
            "keyword",
            "comment",
            "type",
            "namespace",
            "variable"
          ]
        },
        "signatureHelp": {
          "contextSupport": false,
          "dynamicRegistration": false,
          "signatureInformation": {
            "documentationFormat": [
              "plaintext"
            ],
            "parameterInformation": {
              "labelOffsetSupport": false
            }
          }
        },
        "synchronization": {
          "didSave": true,
          "dynamicRegistration": false,
          "willSave": false,
          "willSaveWaitUntil": false
        },
        "typeDefinition": {
          "dynamicRegistration": false,
          "linkSupport": false
        }
      },
      "window": {
        "workDoneProgress": true
      },
      "workspace": {
        "applyEdit": false,
        "configuration": true,
        "didChangeConfiguration": {
          "dynamicRegistration": false
        },
        "executeCommand": {
          "dynamicRegistration": false
        },
        "symbol": {
          "dynamicRegistration": false,
          "symbolKind": {
            "valueSet": [
              1,
              2,
              3,
              4,
              5,
              6,
              7,
              8,
              9,
              10,
              11,
              12,
              13,
              14,
              15,
              16,
              17,
              18,
              19,
              20,
              21,
              22,
              23,
              24,
              25,
              26
            ]
          }
        },
        "workspaceEdit": {
          "changeAnnotationSupport": {},
          "documentChanges": true,
          "failureHandling": "abort",
          "normalizesLineEndings": false,
          "resourceOperations": [
            "create",
            "delete",
            "rename"
          ]
        },
        "workspaceFolders": false
      }
    },
    "clientInfo": {
      "name": "kak-lsp",
      "version": "12.0.1-snapshot"
    },
    "initializationOptions": {
      "hoverActions": {
        "enable": false
      }
    },
    "processId": 243062,
    "rootPath": "/home/johannes/git/kak-lsp/t",
    "rootUri": "file:///home/johannes/git/kak-lsp/t",
    "trace": "off"
  },
  "id": 0
}
Feb 27 20:50:48.220 DEBG From server: {
  "jsonrpc": "2.0",
  "id": 0,
  "result": {
    "capabilities": {
      "textDocumentSync": {
        "openClose": true,
        "change": 2,
        "save": {}
      },
      "selectionRangeProvider": true,
      "hoverProvider": true,
      "completionProvider": {
        "resolveProvider": true,
        "triggerCharacters": [
          ":",
          ".",
          "'"
        ]
      },
      "signatureHelpProvider": {
        "triggerCharacters": [
          "(",
          ","
        ]
      },
      "definitionProvider": true,
      "typeDefinitionProvider": true,
      "implementationProvider": true,
      "referencesProvider": true,
      "documentHighlightProvider": true,
      "documentSymbolProvider": true,
      "workspaceSymbolProvider": true,
      "codeActionProvider": {
        "codeActionKinds": [
          "",
          "quickfix",
          "refactor",
          "refactor.extract",
          "refactor.inline",
          "refactor.rewrite"
        ],
        "resolveProvider": true
      },
      "codeLensProvider": {
        "resolveProvider": true
      },
      "documentFormattingProvider": true,
      "documentRangeFormattingProvider": false,
      "documentOnTypeFormattingProvider": {
        "firstTriggerCharacter": "=",
        "moreTriggerCharacter": [
          ".",
          ">",
          "{"
        ]
      },
      "renameProvider": {
        "prepareProvider": true
      },
      "foldingRangeProvider": true,
      "declarationProvider": true,
      "workspace": {
        "fileOperations": {
          "willRename": {
            "filters": [
              {
                "scheme": "file",
                "pattern": {
                  "glob": "**/*.rs",
                  "matches": "file"
                }
              },
              {
                "scheme": "file",
                "pattern": {
                  "glob": "**",
                  "matches": "folder"
                }
              }
            ]
          }
        }
      },
      "callHierarchyProvider": true,
      "semanticTokensProvider": {
        "legend": {
          "tokenTypes": [
            "comment",
            "keyword",
            "string",
            "number",
            "regexp",
            "operator",
            "namespace",
            "type",
            "struct",
            "class",
            "interface",
            "enum",
            "enumMember",
            "typeParameter",
            "function",
            "method",
            "property",
            "macro",
            "variable",
            "parameter",
            "angle",
            "arithmetic",
            "attribute",
            "attributeBracket",
            "bitwise",
            "boolean",
            "brace",
            "bracket",
            "builtinAttribute",
            "builtinType",
            "character",
            "colon",
            "comma",
            "comparison",
            "constParameter",
            "derive",
            "dot",
            "escapeSequence",
            "formatSpecifier",
            "generic",
            "label",
            "lifetime",
            "logical",
            "macroBang",
            "operator",
            "parenthesis",
            "punctuation",
            "selfKeyword",
            "semicolon",
            "typeAlias",
            "toolModule",
            "union",
            "unresolvedReference"
          ],
          "tokenModifiers": [
            "documentation",
            "declaration",
            "definition",
            "static",
            "abstract",
            "deprecated",
            "readonly",
            "defaultLibrary",
            "async",
            "attribute",
            "callable",
            "constant",
            "consuming",
            "controlFlow",
            "crateRoot",
            "injected",
            "intraDocLink",
            "library",
            "mutable",
            "public",
            "reference",
            "trait",
            "unsafe"
          ]
        },
        "range": true,
        "full": {
          "delta": true
        }
      },
      "experimental": {
        "externalDocs": true,
        "hoverRange": true,
        "joinLines": true,
        "matchingBrace": true,
        "moveItem": true,
        "onEnter": true,
        "openCargoToml": true,
        "parentModule": true,
        "runnables": {
          "kinds": [
            "cargo"
          ]
        },
        "ssr": true,
        "workspaceSymbolScopeKindFiltering": true
      }
    },
    "serverInfo": {
      "name": "rust-analyzer",
      "version": "2022-02-21"
    },
    "offsetEncoding": "utf-8"
  }
}

when I select lines 3-5 (the for loop) and ask for code actions I get "Extract into variable" instead of "Extract into function"

Feb 27 20:50:56.384 DEBG To server: {
  "jsonrpc": "2.0",
  "method": "textDocument/codeAction",
  "params": {
    "context": {
      "diagnostics": []
    },
    "range": {
      "end": {
        "character": 5,
        "line": 4
      },
      "start": {
        "character": 0,
        "line": 2
      }
    },
    "textDocument": {
      "uri": "file:///home/johannes/git/kak-lsp/t/main.rs"
    }
  },
  "id": 1
}
Feb 27 20:50:56.386 DEBG From server: {
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "title": "Extract into variable",
      "kind": "refactor.extract",
      "edit": {
        "documentChanges": [
          {
            "textDocument": {
              "uri": "file:///home/johannes/git/kak-lsp/t/main.rs",
              "version": 1
            },
            "edits": [
              {
                "range": {
                  "start": {
                    "line": 2,
                    "character": 4
                  },
                  "end": {
                    "line": 2,
                    "character": 4
                  }
                },
                "newText": "let var_name = for i in 0..n {\n        println!(\"{}\", i);\n    };\n    "
              },
              {
                "range": {
                  "start": {
                    "line": 2,
                    "character": 4
                  },
                  "end": {
                    "line": 4,
                    "character": 5
                  }
                },
                "newText": "var_name"
              }
            ]
          }
        ],
        "changeAnnotations": {
          "OutsideWorkspace": {
            "label": "Edit outside of the workspace",
            "needsConfirmation": true,
            "description": "This edit lies outside of the workspace and may affect dependencies"
          }
        }
      }
    }
  ]
}

Originally reported in kakoune-lsp/kakoune-lsp#594

@flodiebold
Copy link
Member

flodiebold commented Feb 28, 2022

That's really weird. I get the same results as in VSCode with Emacs. At first I thought it might be related to the experimental snippet capability, but the extract function assist should still work without it. Also, that would not explain why you get the extract variable assist.

Can you try getting code actions in a few more places? For example selecting the 100, the 0..n and the println!("{}", n);.

Also, can you try actually applying the extract variable assist and then check what hovering over var_name says? The reason that you shouldn't get the assist there is that it shouldn't appear for expressions of type (), so I'm curious what type you get there.

@flodiebold
Copy link
Member

flodiebold commented Feb 28, 2022

Ah, I can reproduce this for files that are not part of the module tree. Are you testing in a new cargo project? It seems like kak-lsp/t might just be a folder with test files, not a proper project?

This probably works in VSCode because of the detached files support, which currently requires custom initialization options that only the VSCode plugin provides.

@krobelus
Copy link
Contributor Author

Ah, I can reproduce this for files that are not part of the module tree. Are you testing in a new cargo project? It seems like kak-lsp/t might just be a folder with test files, not a proper project?

This probably works in VSCode because of the detached files support, which currently requires custom initialization options that only the VSCode plugin provides.

yup that's it, it works inside a project.
Closing as this is probably not something that can realistically be supported.
My rookie mistake, thanks a ton for debugging this!

This probably works in VSCode because of the detached files support, which currently requires custom initialization options that only the VSCode plugin provides.

that sounds cool and scary at the same time

then check what hovering over var_name says?

I didn't get anything on hover, likely because of the missing project setup.

@Lordworms
Copy link

I got the same problem right now
image

@mawkler
Copy link

mawkler commented Aug 23, 2024

Your code snippet works for me in Neovim (using rustaceanvim) with rust-analyzer v2024-08-19:

fn main() {
    let n = 100;
    for i in 0..n {
        println!("{}", i);
    }
}

However, if I add #[tokio::main] to it I only get the code action "Extract into variable" after selecting the three for-loop lines:

#[tokio::main]
async fn main() {
    let n = 100;
    for i in 0..n {
        println!("{}", i);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants