elbywan / crystalline

A Language Server Protocol implementation for Crystal. 🔮
MIT License
424 stars 21 forks source link

Revert saved code frequently. #84

Open zw963 opened 2 months ago

zw963 commented 2 months ago

This issue happen a lot recent days when i am working a lucky project.

I use emacs, crystalline features work quite well with my emacs lsp-mode, even , i can jump into source code sometimes.

But one issue happen frequently, make me almost want to give up.

this issue happen quite randomally, after i saved code, code revert immedately unexpected.

i even don't mind those revert ( it happen very quick), often i found this issue happen only because the crystal build status never changed after fix bug.

Anyway, i will try to capture some LSP IO debug output next time happen.

please give me some clue about why this happen, only for me??

this probably related to #41 too.

thanks

zw963 commented 2 months ago

It happen again, i saw some logs like following:

Come from crystalline stderr:

[warn] evutil_make_internal_pipe_: pipe: Too many open files
[err] evsig_init_: socketpair: Too many open files

Process crystalline stderr finished

Come from lsp-log:

Command "crystalline" is present on the path.
Command "crystalline" is present on the path.
Found the following clients for /home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/components/shared/field_errors.cr: (server-id crystalline, priority 1)
The following clients were selected based on priority: (server-id crystalline, priority 1)
Cancelling textDocument/hover(2126) in hook after-change-functions
Cancelling textDocument/hover(2127) in hook after-change-functions
Cancelling textDocument/hover(2132) in hook after-change-functions
Cancelling textDocument/hover(2133) in hook after-change-functions

Come from lsp io

[Trace - 05:43:30 PM] Sending notification 'textDocument/didChange'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/operations/create_university.cr",
    "version": 109
  },
  "contentChanges": [
    {
      "range": {
        "start": {
          "line": 31,
          "character": 2
        },
        "end": {
          "line": 37,
          "character": 7
        }
      },
      "rangeLength": 245,
      "text": "before_save code_and_batch_level_must_uniq\n\n  def code_and_batch_level_must_uniq\n    if UniversityQuery.new.code(code.value.not_nil!).batch_level(batch_level.value.not_nil!).first?\n      code.add_error(\"编码和批次的组合, 必须唯一\")\n    end\n  end"
    }
  ]
}

[Trace - 05:43:32 PM] Sending request 'textDocument/formatting - (2155)'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/operations/create_university.cr"
  },
  "options": {
    "tabSize": 2,
    "insertSpaces": true,
    "trimTrailingWhitespace": true,
    "insertFinalNewline": true,
    "trimFinalNewlines": true
  }
}

[Trace - 05:43:32 PM] Received response 'textDocument/formatting - (2155)' in 4ms.
Result: [
  {
    "range": {
      "start": {
        "line": 0,
        "character": 0
      },
      "end": {
        "line": 40,
        "character": 0
      }
    },
    "newText": "class CreateUniversity < University::SaveOperation\n  upsert_lookup_columns name\n  permit_columns name, description, code,\n    is_211, is_985, is_good,\n    score_2023_min, ranking_2023_min,\n    batch_level\n\n  attribute province_code : Int32\n  attribute province_name : String\n  attribute city_code : Int32\n  attribute city_name : String\n\n  before_save do\n    validate_required province_code\n    validate_required province_name\n\n    province = SaveProvince.upsert!(\n      name: province_name.value.to_s,\n      code: province_code.value.as(Int32)\n    )\n\n    city = SaveCity.upsert!(\n      name: city_name.value.to_s,\n      code: city_code.value.as(Int32),\n      province_id: province.id\n    )\n\n    province_id.value = province.id\n    city_id.value = city.id\n  end\n\n  # before_save code_and_batch_level_must_uniq\n\n  # def code_and_batch_level_must_uniq\n  #   if UniversityQuery.new.code(code.value.not_nil!).batch_level(batch_level.value.not_nil!).first?\n  #     code.add_error(\"编码和批次的组合, 必须唯一\")\n  #   end\n  # end\nend\n"
  }
]

[Trace - 05:43:32 PM] Sending notification 'textDocument/didChange'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/operations/create_university.cr",
    "version": 110
  },
  "contentChanges": [
    {
      "range": {
        "start": {
          "line": 0,
          "character": 0
        },
        "end": {
          "line": 39,
          "character": 0
        }
      },
      "rangeLength": 1002,
      "text": "class CreateUniversity < University::SaveOperation\n  upsert_lookup_columns name\n  permit_columns name, description, code,\n    is_211, is_985, is_good,\n    score_2023_min, ranking_2023_min,\n    batch_level\n\n  attribute province_code : Int32\n  attribute province_name : String\n  attribute city_code : Int32\n  attribute city_name : String\n\n  before_save do\n    validate_required province_code\n    validate_required province_name\n\n    province = SaveProvince.upsert!(\n      name: province_name.value.to_s,\n      code: province_code.value.as(Int32)\n    )\n\n    city = SaveCity.upsert!(\n      name: city_name.value.to_s,\n      code: city_code.value.as(Int32),\n      province_id: province.id\n    )\n\n    province_id.value = province.id\n    city_id.value = city.id\n  end\n\n  # before_save code_and_batch_level_must_uniq\n\n  # def code_and_batch_level_must_uniq\n  #   if UniversityQuery.new.code(code.value.not_nil!).batch_level(batch_level.value.not_nil!).first?\n  #     code.add_error(\"编码和批次的组合, 必须唯一\")\n  #   end\n  # end\nend\n"
    }
  ]
}

[Trace - 05:43:32 PM] Sending notification 'textDocument/didSave'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/operations/create_university.cr",
    "version": 110
  }
}

[Trace - 05:43:32 PM] Received request 'window/workDoneProgress/create - (0).
Params: {
  "token": "workspace/compile/343"
}

[Trace - 05:43:32 PM] Sending response 'window/workDoneProgress/create - (0)'. Processing request took 0ms
Params: {
  "jsonrpc": "2.0",
  "id": 0,
  "result": null
}

[Trace - 05:43:32 PM] Received notification '$/progress'.
Params: {
  "token": "workspace/compile/343",
  "value": {
    "title": "Building workspace",
    "message": "/home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/college.cr",
    "kind": "begin"
  }
}

[Trace - 05:43:33 PM] Sending request 'textDocument/hover - (2156)'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/operations/create_university.cr"
  },
  "position": {
    "line": 37,
    "character": 5
  }
}

Forget to mention, every time meet this issue, i run lsp to initalize lsp again will solve this issue.

zw963 commented 2 months ago

This issue probably happen when apply edit or when formatting.

LSP :: Applying 1 edits to `update.cr' ...
Applying 1 edits to `update.cr' ...done
[Trace - 01:12:04 AM] Sending request 'textDocument/formatting - (1570)'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/actions/universities/update.cr"
  },
  "options": {
    "tabSize": 2,
    "insertSpaces": true,
    "trimTrailingWhitespace": true,
    "insertFinalNewline": true,
    "trimFinalNewlines": true
  }
}

[Trace - 01:12:04 AM] Received response 'textDocument/formatting - (1570)' in 5ms.
Result: [
  {
    "range": {
      "start": {
        "line": 0,
        "character": 0
      },
      "end": {
        "line": 15,
        "character": 0
      }
    },
    "newText": "class Universities::Update < BrowserAction\n  put \"/universities/:university_id\" do\n    university = UniversityQuery.find(university_id)\n    SaveUniversity.update(university, params) do |operation, updated_university|\n      if operation.saved?\n        flash.success = \"修改成功\"\n        redirect Show.with(updated_university.id)\n      else\n        flash.failure = \"出错了\"\n        html EditPage, operation: operation, university: updated_university\n      end\n    end\n  end\nend\n"
  }
]

[Trace - 01:12:04 AM] Sending notification 'textDocument/didChange'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/actions/universities/update.cr",
    "version": 55
  },
  "contentChanges": [
    {
      "range": {
        "start": {
          "line": 0,
          "character": 0
        },
        "end": {
          "line": 14,
          "character": 0
        }
      },
      "rangeLength": 469,
      "text": "class Universities::Update < BrowserAction\n  put \"/universities/:university_id\" do\n    university = UniversityQuery.find(university_id)\n    SaveUniversity.update(university, params) do |operation, updated_university|\n      if operation.saved?\n        flash.success = \"修改成功\"\n        redirect Show.with(updated_university.id)\n      else\n        flash.failure = \"出错了\"\n        html EditPage, operation: operation, university: updated_university\n      end\n    end\n  end\nend\n"
    }
  ]
}

[Trace - 01:12:05 AM] Sending notification 'textDocument/didSave'.
Params: {
  "textDocument": {
    "uri": "file:///home/zw963/Crystal/crystal-china/one_in_ten_thousand/college/src/actions/universities/update.cr",
    "version": 55
  }
}

[Trace - 01:12:05 AM] Received request 'window/workDoneProgress/create - (0).
Params: {
  "token": "workspace/compile/484"
}

[Trace - 01:12:05 AM] Sending response 'window/workDoneProgress/create - (0)'. Processing request took 0ms
Params: {
  "jsonrpc": "2.0",
  "id": 0,
  "result": null
}
zw963 commented 1 month ago

This issue is gone after delete following line in my lsp config.

(add-hook 'before-save-hook #'lsp-format-buffer t t)

I need more time to test if this issue caused by lsp-format-buffer conflict with other formatting mode.

zw963 commented 1 month ago

After test a while, quite ensure, this issue related to above lsp-foramt-buffer before save hook, if disable it, no this issue.

zw963 commented 1 month ago

After test a while, quite ensure, this issue related to above lsp-foramt-buffer before save hook, if disable it, no this issue.

But the formatter advice of lsp-format-buffer come from crystalline, right?

I use lsp-mode for a long time, others mode (e.g. dart-mode, rust-mode, go-mode) no this format issue anyway.

zw963 commented 1 month ago

I record a video, for describe how this bug happen when i edit a file called 1.cr.

https://github.com/elbywan/crystalline/assets/549126/c1a38c81-288c-44ad-a948-3618edaa7d16

Explain on the above video:

  1. after some changes, i try to save 1.cr
  2. then, a part of my file get rollbacked.
  3. i try again, use editor undo feature to revert my buffer to the status before save.
  4. i try to save buffer again, part of my file get revert again.