Comments (11)
I think the issue here is that Parinfer expects that any new text will be correctly indented and adjusts the parentheses to reflect that. Parinfer relies on the author to verify that the indentation is correct, and I don't know if clojure-lsp can make reasonably certain that a given block of code will be correctly indented when moving it from a nested position to a top-level position.
Maybe clojure-lsp can call into cljfmt
? But then that relies on cljfmt knowing how to properly indent the code as well, which might not align with how Parinfer expects the code to be laid out (macros, etc).
from clojure-lsp.
yeah, I don't think manually fixing the space in clojure-lsp will be a good idea, we could call format-range using cljfmt but there are some performance issues with that cljfmt feature
from clojure-lsp.
@vlnn clojure-lsp has nothing related with the paren package you use in the client side, could you elaborate what is "messing with the code"? is that only related to wrong format (spaces)?
from clojure-lsp.
Yes it seems to be related to wrong format (extra spaces) — but it becomes structural problem, you may see how new function on first gif gets (if (> a 3 (+ a 2) a))
instead of (if (> a 3) (+ a 2) a)
. I'm not sure that it's just parinfer's problem, though. I guess some kind of configurable option restricting refactorings from formatting (letting the parinfer or similar things to do its stuff) could become a solution. Or maybe I'm just not aware of one?
from clojure-lsp.
when lsp-mode apply code actions it doesn't call any format IIRC, but you can confirm disabling rangeFormatting feature via lsp-enable-indentation
(this disables range formatting not whole buffer formatting which is ok).
from clojure-lsp.
Also, you can check the Log - client <-> server to know if clojure-lsp is really returning something wrong which I doubt
from clojure-lsp.
I have lsp-enable-indentation
set to nil. I'll reproduce and will add log-client <-> server to the issue.
from clojure-lsp.
log-client <-> server
[Trace - 01:58:40 PM] Sending request 'workspace/executeCommand - (4121)'.
Params: {
"command": "extract-function",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
2,
10,
"new-function"
]
}
[Trace - 01:58:40 PM] Received request 'workspace/applyEdit - (3).
Params: {
"edit": {
"documentChanges": [
{
"textDocument": {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj",
"version": 12
},
"edits": [
{
"range": {
"start": {
"line": 2,
"character": 10
},
"end": {
"line": 4,
"character": 14
}
},
"newText": "(new-function a)"
},
{
"range": {
"start": {
"line": 0,
"character": 0
},
"end": {
"line": 0,
"character": 0
}
},
"newText": "\n(defn- new-function [a]\n (if (> a 3)\n (+ a 2)\n a))\n"
}
]
}
]
}
}
[Trace - 01:58:40 PM] Sending response 'workspace/applyEdit - (3)'. Processing request took 10ms
Params: {
"jsonrpc": "2.0",
"id": 3,
"result": {
"applied": true
}
}
[Trace - 01:58:40 PM] Sending notification 'textDocument/didChange'.
Params: {
"textDocument": {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj",
"version": 14
},
"contentChanges": [
{
"text": "\n(defn- new-function [a]\n (if (> a 3)\n (+ a 2)\n a))\n(defn test-parinfer-lsp []\n (let [a 2\n b (new-function a)]\n b))\n"
}
]
}
[Trace - 01:58:40 PM] Received response 'workspace/executeCommand - (4121)' in 24ms.
Result: {
"documentChanges": [
{
"textDocument": {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj",
"version": 12
},
"edits": [
{
"range": {
"start": {
"line": 0,
"character": 0
},
"end": {
"line": 0,
"character": 0
}
},
"newText": "\n(defn- new-function [a]\n (if (> a 3)\n (+ a 2)\n a))\n"
},
{
"range": {
"start": {
"line": 2,
"character": 10
},
"end": {
"line": 4,
"character": 14
}
},
"newText": "(new-function a)"
}
]
}
]
}
[Trace - 01:58:40 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj",
"diagnostics": [
{
"range": {
"start": {
"line": 5,
"character": 6
},
"end": {
"line": 5,
"character": 23
}
},
"tags": [
1
],
"message": "Unused public var 'user/test-parinfer-lsp'",
"code": "clojure-lsp/unused-public-var",
"langs": [],
"severity": 3,
"source": "clojure-lsp"
}
]
}
[Trace - 01:58:40 PM] Sending request 'textDocument/codeAction - (4122)'.
Params: {
"textDocument": {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj"
},
"range": {
"start": {
"line": 7,
"character": 10
},
"end": {
"line": 7,
"character": 10
}
},
"context": {
"diagnostics": []
}
}
[Trace - 01:58:40 PM] Sending request 'textDocument/documentHighlight - (4123)'.
Params: {
"textDocument": {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj"
},
"position": {
"line": 7,
"character": 10
}
}
[Trace - 01:58:40 PM] Sending request 'textDocument/hover - (4124)'.
Params: {
"textDocument": {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj"
},
"position": {
"line": 7,
"character": 10
}
}
[Trace - 01:58:40 PM] Sending request 'textDocument/codeLens - (4125)'.
Params: {
"textDocument": {
"uri": "file:///Users/va/tmp/test-lsp-parinfer.clj"
}
}
[Trace - 01:58:40 PM] Received response 'textDocument/documentHighlight - (4123)' in 17ms.
Result: []
[Trace - 01:58:40 PM] Received response 'textDocument/codeAction - (4122)' in 19ms.
Result: [
{
"title": "Change coll to vector",
"kind": "refactor",
"command": {
"title": "Change coll",
"command": "change-coll",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10,
"vector"
]
}
},
{
"title": "Change coll to set",
"kind": "refactor",
"command": {
"title": "Change coll",
"command": "change-coll",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10,
"set"
]
}
},
{
"title": "Change coll to map",
"kind": "refactor",
"command": {
"title": "Change coll",
"command": "change-coll",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10,
"map"
]
}
},
{
"title": "Move to let",
"kind": "refactor.extract",
"command": {
"title": "Move to let",
"command": "move-to-let",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10,
"new-binding"
]
}
},
{
"title": "Cycle privacy",
"kind": "refactor.rewrite",
"command": {
"title": "Cycle privacy",
"command": "cycle-privacy",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
},
{
"title": "Extract function",
"kind": "refactor.extract",
"command": {
"title": "Extract function",
"command": "extract-function",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10,
"new-function"
]
}
},
{
"title": "Extract to def",
"kind": "refactor.extract",
"command": {
"title": "Extract to def",
"command": "extract-to-def",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10,
null
]
}
},
{
"title": "Thread first all",
"kind": "refactor.rewrite",
"command": {
"title": "Thread first all",
"command": "thread-first-all",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
},
{
"title": "Thread last all",
"kind": "refactor.rewrite",
"command": {
"title": "Thread last all",
"command": "thread-last-all",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
},
{
"title": "Move another expression to get/get-in",
"kind": "refactor.rewrite",
"command": {
"title": "Move another expression to get/get-in",
"command": "get-in-more",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
},
{
"title": "Move all expressions to get/get-in",
"kind": "refactor.rewrite",
"command": {
"title": "Move all expressions to get/get-in",
"command": "get-in-all",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
},
{
"title": "Sort list",
"kind": "refactor.rewrite",
"command": {
"title": "Sort list",
"command": "sort-clauses",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
},
{
"title": "Drag backward",
"kind": "refactor.rewrite",
"command": {
"title": "Drag backward",
"command": "drag-backward",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
},
{
"title": "Introduce let",
"kind": "refactor.extract",
"command": {
"title": "Introduce let",
"command": "introduce-let",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10,
"new-binding"
]
}
},
{
"title": "Clean namespace",
"kind": "source.organizeImports",
"command": {
"title": "Clean namespace",
"command": "clean-ns",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
7,
10
]
}
}
]
[Trace - 01:58:40 PM] Received response 'textDocument/hover - (4124)' in 20ms.
Result: {
"range": {
"start": {
"line": 7,
"character": 11
},
"end": {
"line": 7,
"character": 23
}
},
"contents": {
"kind": "markdown",
"value": "```clojure\nuser/new-function [a]\n```\n\n----\n\n*[/Users/va/tmp/test-lsp-parinfer.clj](file:///Users/va/tmp/test-lsp-parinfer.clj)*"
}
}
[Trace - 01:58:40 PM] Received response 'textDocument/codeLens - (4125)' in 30ms.
Result: [
{
"range": {
"start": {
"line": 1,
"character": 7
},
"end": {
"line": 1,
"character": 19
}
},
"data": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
2,
8
]
},
{
"range": {
"start": {
"line": 5,
"character": 6
},
"end": {
"line": 5,
"character": 23
}
},
"data": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
6,
7
]
}
]
[Trace - 01:58:40 PM] Sending request 'codeLens/resolve - (4126)'.
Params: {
"range": {
"start": {
"line": 1,
"character": 7
},
"end": {
"line": 1,
"character": 19
}
},
"data": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
2,
8
],
"_workspace": null,
"_pending": true
}
[Trace - 01:58:40 PM] Sending request 'codeLens/resolve - (4127)'.
Params: {
"range": {
"start": {
"line": 5,
"character": 6
},
"end": {
"line": 5,
"character": 23
}
},
"data": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
6,
7
],
"_workspace": null,
"_pending": true
}
[Trace - 01:58:40 PM] Received response 'codeLens/resolve - (4126)' in 3ms.
Result: {
"range": {
"start": {
"line": 1,
"character": 7
},
"end": {
"line": 1,
"character": 19
}
},
"command": {
"title": "1 reference",
"command": "code-lens-references",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
2,
8
]
}
}
[Trace - 01:58:40 PM] Received response 'codeLens/resolve - (4127)' in 3ms.
Result: {
"range": {
"start": {
"line": 5,
"character": 6
},
"end": {
"line": 5,
"character": 23
}
},
"command": {
"title": "0 references",
"command": "code-lens-references",
"arguments": [
"file:///Users/va/tmp/test-lsp-parinfer.clj",
6,
7
]
}
}
In "newText": "\n(defn- new-function [a]\n (if (> a 3)\n (+ a 2)\n a))\n"
I can see lots of extra spaces, which may create that kind of mess.
from clojure-lsp.
Both smart and indent modes of parinfer depend on indentation (in the sense they auto-slurp or auto-barf the current sexp depending on how many extra-spaces prepend it). So my proposal is either to format the code correctly from the beginning (but what is correctly? this will add dependency to something external) or provide the option to skip all the extra spaces leaving bare minimum. This could be an option for dumb terminals as well as for terminals that are too clever.
from clojure-lsp.
Maybe clojure-lsp could look at the column of the initial position, and then cut that amount of whitespace from each line, so that the resulting lines are in the same position relative to each other when moved to the new location.
from clojure-lsp.
Initial position of what? I dont think that extract function should depend on initial position of sexp being extracted, as well as initial position of defn sexp seems to be correct (i.e. without prepending spaces)
from clojure-lsp.
Related Issues (20)
- Support correct namespace for exported clj-kondo hooks
- Add "Create clj-kondo hook" actions HOT 4
- Eglot receives non-sensical urls for external deps HOT 1
- `thread last all` command fails with internal error -32603 HOT 4
- Add ability to safely analyze without executing project.clj HOT 2
- clojure-lsp fails to run on Ahasi Linux HOT 7
- Exception while opening project (workspace/didChangeConfiguration) HOT 1
- lsp-rename incorrectly changing require ns when changed to longer text and changing current namespace HOT 3
- External libraries explorer HOT 3
- Java imports code action breaks namespace form
- Renaming function loses references and requires lsp-restart-workspace
- [Regression] Renaming defrecord results in renaming alias instead of the name HOT 1
- rangeFormatting Internal error on paredit-backward-barf-sexp in Emacs HOT 1
- Deps.edn files are no longer colorized correctly. HOT 24
- False positive: reports definterface methods as unused HOT 3
- Using inline-symbol on a symbol bound via destructuring fails
- False positive: unused-public-var with #(fn) and macroexpand hook HOT 4
- Help to consistently apply namespace aliases. HOT 2
- JetBrains Exception when attemping to refactor/rename a file HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from clojure-lsp.