From fae57f3aa804213b1f69452b951951e9d5b68466 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 13 Dec 2019 17:13:03 +0100 Subject: [PATCH 001/120] Add .fsx completion issue workaround to README.org. Refs #231 --- README.org | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.org b/README.org index 3a5c795..2430b1b 100644 --- a/README.org +++ b/README.org @@ -154,6 +154,17 @@ Because the F# language is sensitive to indentation, you might wan't to highligh =fsharp-mode= is still under development, so you may encounter some issues. Please report them so we can improve things! Open an issue on [[https://github.com/fsharp/emacs-fsharp-mode/][Github]]. +*** No autocompletion in FSX files + +The root cause is documented in this Ionide issue: [[https://github.com/ionide/ionide-vscode-fsharp/issues/1244][4.2.0 - No auto complete or typechecking in FSX files]] + +As a workaround can add a reference to the facade netstandard assembly (path is platform/SDK-dependent). + +On Arch Linux using [[https://aur.archlinux.org/packages/dotnet-sdk-lts-bin][dotnet sdk lts]] add this to your =fsx= file: +#+BEGIN_SRC fsharp +#r "/opt/dotnet/sdk/2.1.801/ref/netstandard.dll" +#+END_SRC + *** Project file issues If your project file does not seem to be being parsed correctly, so From 352762d25a5ff55575e913b533096fa14d66d19c Mon Sep 17 00:00:00 2001 From: Dave Churchill Date: Tue, 14 Jan 2020 14:34:13 +1100 Subject: [PATCH 002/120] Correct the name of the eglot package --- README.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index 2430b1b..e6456e0 100644 --- a/README.org +++ b/README.org @@ -62,14 +62,14 @@ I recommend to use [[https://cask.github.io/why-cask.html][Cask]]. Add this to y ** Eglot integration -=fsharp-eglot= is part of this package and provides integration to [[https://github.com/joaotavora/eglot][Eglot]] Emacs LSP client: +=eglot-fsharp= is part of this package and provides integration to [[https://github.com/joaotavora/eglot][Eglot]] Emacs LSP client: - Automatic =fsautocomplete= download - Workaround for non-LSP standard-compliant Add to your config: #+BEGIN_SRC elisp -(require 'fsharp-eglot) +(require 'eglot-fsharp) #+END_SRC and execute =M-x eglot= From d4d8a9435b1db6c02ff035016c6dbe6f9fee51b2 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 20 May 2020 20:31:50 +0200 Subject: [PATCH 003/120] Ensure a valid (windows) filename ist used for the temporary zip Remove zip after unzip. Fixes #236 --- eglot-fsharp.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index ca6b86c..bc5ff5a 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -71,7 +71,7 @@ ".netcore." "."))) (exe (eglot-fsharp--path-to-server)) - (zip (concat (file-name-directory exe) (file-name-nondirectory url))) + (zip (concat (file-name-directory exe) "fsautocomplete.zip")) (gnutls-algorithm-priority (if (and (not gnutls-algorithm-priority) (boundp 'libgnutls-version) @@ -84,7 +84,8 @@ ;; FIXME: Windows (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) (unless (zerop (call-process "unzip" nil nil nil "-x" zip)) - (error "Failed to unzip %s" zip)))))) + (error "Failed to unzip %s" zip)) + (delete-file zip))))) ;;;###autoload (defun eglot-fsharp (interactive) From 35dccc57f9e47ee9b5f3ac0a48da975709759bbe Mon Sep 17 00:00:00 2001 From: Florian Biermann Date: Fri, 28 Aug 2020 13:45:27 +0200 Subject: [PATCH 004/120] Execute binary directly on Windows --- eglot-fsharp.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index bc5ff5a..411752f 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -95,10 +95,10 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) (cons 'eglot-fsautocomplete - `(,(if (eq eglot-fsharp-server-runtime 'net-core) - "dotnet" - ;; FIXME: Windows - "mono") ,(eglot-fsharp--path-to-server) "--background-service-enabled")))) + `(,(cond ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") + ((eq window-system 'w32) "") + ("mono")) + ,(eglot-fsharp--path-to-server) "--background-service-enabled")))) (defclass eglot-fsautocomplete (eglot-lsp-server) () From 8c60c55ca90769ab0a570db62c1616dce598bc80 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 30 Aug 2020 18:02:56 +0200 Subject: [PATCH 005/120] Conform to Emacs Lisp style guide https://github.com/bbatsov/emacs-lisp-style-guide --- eglot-fsharp.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 411752f..025324d 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -95,9 +95,10 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) (cons 'eglot-fsautocomplete - `(,(cond ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") - ((eq window-system 'w32) "") - ("mono")) + `(,(cond + ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") + ((eq window-system 'w32) "") + (t "mono")) ,(eglot-fsharp--path-to-server) "--background-service-enabled")))) From 1605ac0adfaebabbcc77f965e466e2649075d626 Mon Sep 17 00:00:00 2001 From: wasuken Date: Sun, 27 Sep 2020 10:25:18 +0900 Subject: [PATCH 006/120] Installing of FsAutoComplete from github instead of appveyor. Fixes issue #245. --- eglot-fsharp.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 025324d..1e96995 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -66,10 +66,11 @@ (defun eglot-fsharp--maybe-install () "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) - (let* ((url (format "https://ci.appveyor.com/api/projects/fsautocomplete/fsautocomplete/artifacts/bin/pkgs/fsautocomplete%szip?branch=master" - (if (eq eglot-fsharp-server-runtime 'net-core) - ".netcore." - "."))) + (let* ((url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" + eglot-fsharp-server-version + (if (eq eglot-fsharp-server-runtime 'net-core) + ".netcore." + "."))) (exe (eglot-fsharp--path-to-server)) (zip (concat (file-name-directory exe) "fsautocomplete.zip")) (gnutls-algorithm-priority From 4f8db41446aa960368e791bc747ce822b8b1f126 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 2 Oct 2020 08:24:54 +0200 Subject: [PATCH 007/120] Update to latest fsautocomplete.exe release --- eglot-fsharp.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 1e96995..6066bc8 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -41,7 +41,7 @@ :risky t :type 'directory) -(defcustom eglot-fsharp-server-version "0.38.1" +(defcustom eglot-fsharp-server-version "0.41.1" "FsAutoComplete version." :group 'eglot-fsharp :risky t From 6ca9156e5c71db56893924c5331a6e04b02e27b8 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Thu, 1 Oct 2020 07:54:50 +0200 Subject: [PATCH 008/120] Use Github Actions instead of .travis CI --- .github/workflows/test.yml | 31 ++++++++++++++++++++++++++++ .travis.yml | 42 -------------------------------------- README.org | 2 +- 3 files changed, 32 insertions(+), 43 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..9f50064 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,31 @@ +name: "CI" +on: + pull_request: + push: + # Comment out this section to enable testing of all branches. + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + emacs_version: + - 26.3 + - 27.1 + - snapshot + steps: + - uses: purcell/setup-emacs@master + with: + version: ${{ matrix.emacs_version }} + - uses: actions/setup-dotnet@v1 + - uses: actions/checkout@v2 + - uses: conao3/setup-cask@master + - name: Show dotnet sdks + run: dotnet --list-sdks + - name: Show dotnet version + run: dotnet --info + - name: Test + run: make test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 67c757a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ -language: emacs-lisp -# Emacs fails to build in container-based builds on Travis -# See https://github.com/travis-ci/travis-ci/issues/9061 -# and https://github.com/moby/moby/issues/22801 -sudo: required -dist: bionic -cache: - - directories: - # Cache stable Emacs binaries (saves 1min per job) - - "$HOME/emacs/" -# Allow Emacs snapshot builds to fail and don’t wait for these as they can take -# a looooong time -matrix: - fast_finish: true - allow_failures: - - env: EMACS_VERSION=emacs-snapshot -env: - - EMACS_VERSION=emacs26 - - EMACS_VERSION=emacs-snapshot - -before_install: - # Emacs kelleyk PPA - - sudo add-apt-repository -y ppa:kelleyk/emacs - - sudo apt-get update - - sudo apt install $EMACS_VERSION-nox - - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF - - wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb - - sudo dpkg -i packages-microsoft-prod.deb - - sudo apt-get update - - sudo apt-get install apt-transport-https - - sudo apt-get update - - sudo apt-get install dotnet-sdk-2.1 - - export PATH="$HOME/bin:$PATH" - - export EMACS=$EMACS_VERSION - # Download the makefile to emacs-travis.mk - - wget 'https://raw.githubusercontent.com/flycheck/emacs-travis/master/emacs-travis.mk' - # Install Emacs (according to $EMACS_VERSION) and Cask - - make -f emacs-travis.mk install_cask - - travis_retry sudo apt-get install -y fsharp - -script: - - make test diff --git a/README.org b/README.org index e6456e0..13fa47a 100644 --- a/README.org +++ b/README.org @@ -1,6 +1,6 @@ [[http://melpa.org/#/fsharp-mode][file:http://melpa.org/packages/fsharp-mode-badge.svg]] [[https://stable.melpa.org/#/fsharp-mode][file:https://stable.melpa.org/packages/fsharp-mode-badge.svg]] -[[https://travis-ci.org/fsharp/emacs-fsharp-mode][file:https://travis-ci.org/fsharp/emacs-fsharp-mode.png]] +[[https://github.com/fsharp/emacs-fsharp-mode/actions][file:https://github.com/fsharp/emacs-fsharp-mode/workflows/CI/badge.svg]] * fsharp-mode Provides support for the F# language in Emacs. Includes the following features: From 89ea972c92e2e57c9f3335e037dee863834fef9b Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sat, 3 Oct 2020 14:22:08 +0200 Subject: [PATCH 009/120] Add Github Action for windows-latest This implementation is a hack: - Cask still doesn't work on windows: https://github.com/cask/cask/pull/449. We use a checkout of this pull-request. - Make doesn't work on windows: We use multiple "cask.bat" invocations to do the test. The best long term solution seems to switch to eldev. --- .github/workflows/test.yml | 31 +++++++++++++++++++++++++++++-- Cask | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9f50064..4b9675f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,9 +5,8 @@ on: # Comment out this section to enable testing of all branches. branches: - master - jobs: - build: + gnu-build: runs-on: ubuntu-latest strategy: fail-fast: false @@ -29,3 +28,31 @@ jobs: run: dotnet --info - name: Test run: make test + windows-build: + runs-on: windows-latest + strategy: + fail-fast: false + steps: + - uses: actions/setup-dotnet@v1 + - name: Install Cask/scoop-emacs + run: | + Set-ExecutionPolicy RemoteSigned -scope CurrentUser + Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') + scoop update + scoop bucket add extras + scoop install emacs + scoop install make + echo "$env:PATH" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 + - uses: actions/checkout@v2 + - name: Test # FIXME: cask hack + run: | + git clone https://github.com/tom-bowles/cask cask-windows + Remove-Item -recurse .\cask-windows\test + dotnet restore test/Test1 + Invoke-WebRequest -Uri https://raw.githubusercontent.com/joaotavora/eglot/master/eglot-tests.el -OutFile eglot-tests.el + Start .\Cask-windows\bin\cask.bat -ArgumentList install -NoNewWindow -Wait + Start .\Cask-windows\bin\cask.bat -ArgumentList build -NoNewWindow -Wait + Start .\Cask-windows\bin\cask.bat -ArgumentList "exec buttercup -L . -L test --traceback full" -NoNewWindow -Wait + + + diff --git a/Cask b/Cask index 2a9191a..dc1eaf7 100644 --- a/Cask +++ b/Cask @@ -4,6 +4,6 @@ (package-file "fsharp-mode.el") (files "*.el") ;; FIXME: Use multiple packages: https://github.com/melpa/melpa#example-multiple-packages-in-one-repository ? - (development (depends-on "buttercup")) + From d4ea76ed761c1d15b5fdc32418f0050a59f20702 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 4 Oct 2020 13:34:36 +0200 Subject: [PATCH 010/120] Remove Appveyor CI Job (obsoleted by GH Actions) --- .appveyor/test.bat | 5 ----- appveyor.yml | 20 -------------------- 2 files changed, 25 deletions(-) delete mode 100755 .appveyor/test.bat delete mode 100644 appveyor.yml diff --git a/.appveyor/test.bat b/.appveyor/test.bat deleted file mode 100755 index 80d6048..0000000 --- a/.appveyor/test.bat +++ /dev/null @@ -1,5 +0,0 @@ -set HOME=%~dp0\tmp - -emacs -l test\test-common.el --batch --eval "(progn (set-default-coding-systems 'utf-8) (load-packages))" - -emacs -l test\test-common.el --batch --eval "(progn (set-default-coding-systems 'utf-8) (run-fsharp-unit-tests))" diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 67f25e2..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,20 +0,0 @@ -environment: - FSACVERSION: 0.34.0 - FSharpBinding_BlockingTimeout: 1000 - FSharpBinding_MaxTimeout: 10000 -matrix: - fast_finish: true -install: - - ps: Start-FileDownload "https://github.com/fsharp/FSharp.AutoComplete/releases/download/$env:FSACVERSION/fsautocomplete.zip" - - ps: 7z x fsautocomplete.zip -oemacs-fsharp-mode\bin | select-string -notmatch "ing " - - ps: iex (new-object net.webclient).downloadstring('https://get.scoop.sh') - - ps: scoop install coreutils - - ps: scoop install make - - ps: scoop install grep - - ps: scoop install unzip - - ps: scoop bucket add extras - - ps: scoop install emacs -build_script: - - cmd: .\.appveyor\test.bat -test: off - From 9f2ed8e6ff6855ef109b9ea1308a7c8e2709c624 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Thu, 8 Oct 2020 20:28:42 +0200 Subject: [PATCH 011/120] Add the possibility to always install the latest version Setting `eglot-fsharp-server-version' to 'latest will always install the latest fsautocomplete version. At every start of `eglot-fsharp' it is checked if the installed version is outdated. The github version check is done only once per session, so performance is not affected too much. --- eglot-fsharp.el | 66 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 6066bc8..8904db1 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -1,6 +1,6 @@ ;;; eglot-fsharp.el --- Lua eglot integration -*- lexical-binding: t; -*- -;; Copyright (C) 2019 Jürgen Hötzel +;; Copyright (C) 2019-2020 Jürgen Hötzel ;; Author: Jürgen Hötzel ;; Package-Requires: ((eglot "1.4")) @@ -41,11 +41,13 @@ :risky t :type 'directory) -(defcustom eglot-fsharp-server-version "0.41.1" - "FsAutoComplete version." +(defcustom eglot-fsharp-server-version 'latest + "FsAutoComplete version to install or update." :group 'eglot-fsharp :risky t - :type 'string) + :type '(choice + (const :tag "Latest release" latest) + (string :tag "Version string"))) (defcustom eglot-fsharp-server-runtime (if (executable-find "dotnet") @@ -63,14 +65,48 @@ "netcore/fsautocomplete.dll" "netframework/fsautocomplete.exe")))) +;; cache to prevent repetitive queries +(defvar eglot-fsharp--github-version nil "Latest fsautocomplete.exe GitHub version string.") + +(defun eglot-fsharp--github-version () + "Return latest fsautocomplete.exe GitHub version string." + (or eglot-fsharp--github-version + (with-temp-buffer + (condition-case err + (let ((json-object-type 'hash-table) + (url-mime-accept-string "application/json")) + (url-insert-file-contents "https://github.com/fsharp/fsautocomplete/releases/latest") + (setq eglot-fsharp--github-version (gethash "tag_name" (json-parse-buffer)))) + (file-error + (warn "fsautocomplete.exe update check:: %s" (error-message-string err))))))) + +(defun eglot-fsharp--installed-version () + "Return version string of fsautocomplete." + (when (file-exists-p (eglot-fsharp--path-to-server)) + (let* ((cmd (append (cdr (eglot-fsharp nil)) '("--version"))) + (version-line (concat (car (apply #'process-lines cmd ))))) + (when (string-match "^FsAutoComplete \\([[:digit:].]+\\) " version-line) + (substring version-line (match-beginning 1) (match-end 1)) + (match-string 1 version-line))))) + +(defun eglot-fsharp-current-version-p () + "Return t if the installation is not outdated." + (when (file-exists-p (eglot-fsharp--path-to-server)) + (if (eq eglot-fsharp-server-version 'latest) + (equal (eglot-fsharp--github-version) (eglot-fsharp--installed-version)) + (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) + (defun eglot-fsharp--maybe-install () "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) - (let* ((url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" - eglot-fsharp-server-version - (if (eq eglot-fsharp-server-runtime 'net-core) - ".netcore." - "."))) + (let* ((version (if (eq eglot-fsharp-server-version 'latest) + (eglot-fsharp--github-version) + eglot-fsharp-server-version)) + (url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" + version + (if (eq eglot-fsharp-server-runtime 'net-core) + ".netcore." + "."))) (exe (eglot-fsharp--path-to-server)) (zip (concat (file-name-directory exe) "fsautocomplete.zip")) (gnutls-algorithm-priority @@ -79,20 +115,20 @@ (>= libgnutls-version 30603) (version<= emacs-version "26.2")) "NORMAL:-VERS-TLS1.3" - gnutls-algorithm-priority))) - (unless (file-exists-p exe) + gnutls-algorithm-priority))) + (unless (eglot-fsharp-current-version-p) (url-copy-file url zip t) - ;; FIXME: Windows + ;; FIXME: Windows (unzip preinstalled?) (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) - (unless (zerop (call-process "unzip" nil nil nil "-x" zip)) + (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) (error "Failed to unzip %s" zip)) (delete-file zip))))) ;;;###autoload (defun eglot-fsharp (interactive) -"Return `eglot' contact when FsAutoComplete is installed. + "Return `eglot' contact when FsAutoComplete is installed. Ensure FsAutoComplete is installed (when called INTERACTIVE)." - (unless (or (file-exists-p (eglot-fsharp--path-to-server)) (not interactive)) + (when interactive (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) (cons 'eglot-fsautocomplete From 2883aefce6735dbf52c522faf9e2a9a9a4192671 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Mon, 12 Oct 2020 18:30:00 +0200 Subject: [PATCH 012/120] Use json-read instead of json-parse-buffer This restores compatibility to Emacs 26.3. The native JSON functions are only available since Emacs 27.1. --- eglot-fsharp.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 8904db1..24b7bb4 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -76,7 +76,8 @@ (let ((json-object-type 'hash-table) (url-mime-accept-string "application/json")) (url-insert-file-contents "https://github.com/fsharp/fsautocomplete/releases/latest") - (setq eglot-fsharp--github-version (gethash "tag_name" (json-parse-buffer)))) + (goto-char (point-min)) + (setq eglot-fsharp--github-version (gethash "tag_name" (json-read)))) (file-error (warn "fsautocomplete.exe update check:: %s" (error-message-string err))))))) From 0071a66f0919b8c0da0089073357ad42271d90e5 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 8 Dec 2020 11:30:00 +0100 Subject: [PATCH 013/120] Remove unused local variables Fixes #255 (interference with company-mode) --- fsharp-mode.el | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fsharp-mode.el b/fsharp-mode.el index e2f00b4..6b99fee 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -199,12 +199,7 @@ add-log-current-defun-function underline-minimum-offset compile-command - syntax-propertize-function - company-backends - company-auto-complete - company-auto-complete-chars - company-require-match - company-tooltip-align-annotations)) + syntax-propertize-function)) (setq local-abbrev-table fsharp-mode-abbrev-table paragraph-start (concat "^$\\|" page-delimiter) From c4e9243cb0fe07f7d82884ef24f2a4684a632d05 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sat, 2 Jan 2021 11:30:00 +0100 Subject: [PATCH 014/120] Prepare eglot-fsharp package split Refs #253 --- eglot-fsharp.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 24b7bb4..e8d8b66 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -1,9 +1,9 @@ ;;; eglot-fsharp.el --- Lua eglot integration -*- lexical-binding: t; -*- -;; Copyright (C) 2019-2020 Jürgen Hötzel +;; Copyright (C) 2019-2021 Jürgen Hötzel ;; Author: Jürgen Hötzel -;; Package-Requires: ((eglot "1.4")) +;; Package-Requires: ((eglot "1.4") (fsharp-mode "1.10")) ;; Keywords: languages ;; This program is free software; you can redistribute it and/or modify From 93b3e0036121eec298fe26f1267dd61944612b7a Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 6 Jan 2021 06:51:01 +0100 Subject: [PATCH 015/120] Replace dash.el with seq.el Emacs 25 ships with a sequence library named seq.el. This renders dash.el completely obsolete. --- fsharp-mode-font.el | 3 --- fsharp-mode-util.el | 1 - fsharp-mode.el | 7 +++---- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el index 8f0b3e2..a063919 100644 --- a/fsharp-mode-font.el +++ b/fsharp-mode-font.el @@ -28,9 +28,6 @@ ;;; Code: -;; (require 'fsharp-mode) -;; (require 'dash) - (defgroup fsharp-ui nil "F# UI group for the defcustom interface." :prefix "fsharp-ui-" diff --git a/fsharp-mode-util.el b/fsharp-mode-util.el index 416ddd3..daa65fb 100644 --- a/fsharp-mode-util.el +++ b/fsharp-mode-util.el @@ -24,7 +24,6 @@ ;; Boston, MA 02110-1301, USA. (with-no-warnings (require 'cl)) -(require 'dash) (defvar fsharp-ac-using-mono (case system-type diff --git a/fsharp-mode.el b/fsharp-mode.el index 6b99fee..4b28966 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -7,7 +7,7 @@ ;; 2012-2014 Robin Neatherway ;; 2017-2019 Jürgen Hötzel ;; Maintainer: Jürgen Hötzel -;; Package-Requires: ((emacs "25") (s "1.3.1") (dash "1.1.0") (eglot)) +;; Package-Requires: ((emacs "25") (s "1.3.1") (eglot)) ;; Keywords: languages ;; Version: 1.9.15 @@ -35,7 +35,6 @@ (require 'fsharp-mode-util) (require 'compile) (require 'project) -(require 'dash) (defgroup fsharp nil "Support for the Fsharp programming language, " @@ -45,11 +44,11 @@ ;;; Compilation (defvar fsharp-compile-command - (-any #'fsharp-mode--executable-find '("fsharpc" "fsc")) + (seq-some #'fsharp-mode--executable-find '("fsharpc" "fsc")) "The program used to compile F# source files.") (defvar fsharp-build-command - (-any #'fsharp-mode--msbuild-find '("msbuild" "xbuild")) + (seq-some #'fsharp-mode--msbuild-find '("msbuild" "xbuild")) "The command used to build F# projects and solutions.") ;;; ---------------------------------------------------------------------------- From 08025f3892ea94c77dcbd644a75be23f3d9a3b23 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Mon, 11 Jan 2021 16:04:52 +0100 Subject: [PATCH 016/120] Fix compiler warning: Remove unused expression --- eglot-fsharp.el | 1 - 1 file changed, 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index e8d8b66..d383816 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -87,7 +87,6 @@ (let* ((cmd (append (cdr (eglot-fsharp nil)) '("--version"))) (version-line (concat (car (apply #'process-lines cmd ))))) (when (string-match "^FsAutoComplete \\([[:digit:].]+\\) " version-line) - (substring version-line (match-beginning 1) (match-end 1)) (match-string 1 version-line))))) (defun eglot-fsharp-current-version-p () From ede394b0a755b55c6135578b0434ba05f8ab5022 Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 15 Jan 2021 14:50:46 +0800 Subject: [PATCH 017/120] Fixed mix tabs and spaces --- eglot-fsharp.el | 84 ++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index e8d8b66..7aff207 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -46,8 +46,8 @@ :group 'eglot-fsharp :risky t :type '(choice - (const :tag "Latest release" latest) - (string :tag "Version string"))) + (const :tag "Latest release" latest) + (string :tag "Version string"))) (defcustom eglot-fsharp-server-runtime (if (executable-find "dotnet") @@ -61,9 +61,9 @@ (defun eglot-fsharp--path-to-server () "Return FsAutoComplete path." (file-truename (concat eglot-fsharp-server-install-dir - (if (eq eglot-fsharp-server-runtime 'net-core) - "netcore/fsautocomplete.dll" - "netframework/fsautocomplete.exe")))) + (if (eq eglot-fsharp-server-runtime 'net-core) + "netcore/fsautocomplete.dll" + "netframework/fsautocomplete.exe")))) ;; cache to prevent repetitive queries (defvar eglot-fsharp--github-version nil "Latest fsautocomplete.exe GitHub version string.") @@ -72,58 +72,58 @@ "Return latest fsautocomplete.exe GitHub version string." (or eglot-fsharp--github-version (with-temp-buffer - (condition-case err - (let ((json-object-type 'hash-table) - (url-mime-accept-string "application/json")) - (url-insert-file-contents "https://github.com/fsharp/fsautocomplete/releases/latest") - (goto-char (point-min)) - (setq eglot-fsharp--github-version (gethash "tag_name" (json-read)))) - (file-error - (warn "fsautocomplete.exe update check:: %s" (error-message-string err))))))) + (condition-case err + (let ((json-object-type 'hash-table) + (url-mime-accept-string "application/json")) + (url-insert-file-contents "https://github.com/fsharp/fsautocomplete/releases/latest") + (goto-char (point-min)) + (setq eglot-fsharp--github-version (gethash "tag_name" (json-read)))) + (file-error + (warn "fsautocomplete.exe update check:: %s" (error-message-string err))))))) (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." (when (file-exists-p (eglot-fsharp--path-to-server)) (let* ((cmd (append (cdr (eglot-fsharp nil)) '("--version"))) - (version-line (concat (car (apply #'process-lines cmd ))))) + (version-line (concat (car (apply #'process-lines cmd ))))) (when (string-match "^FsAutoComplete \\([[:digit:].]+\\) " version-line) - (substring version-line (match-beginning 1) (match-end 1)) - (match-string 1 version-line))))) + (substring version-line (match-beginning 1) (match-end 1)) + (match-string 1 version-line))))) (defun eglot-fsharp-current-version-p () "Return t if the installation is not outdated." (when (file-exists-p (eglot-fsharp--path-to-server)) (if (eq eglot-fsharp-server-version 'latest) - (equal (eglot-fsharp--github-version) (eglot-fsharp--installed-version)) + (equal (eglot-fsharp--github-version) (eglot-fsharp--installed-version)) (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) (defun eglot-fsharp--maybe-install () "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) (let* ((version (if (eq eglot-fsharp-server-version 'latest) - (eglot-fsharp--github-version) - eglot-fsharp-server-version)) - (url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" - version - (if (eq eglot-fsharp-server-runtime 'net-core) - ".netcore." - "."))) - (exe (eglot-fsharp--path-to-server)) - (zip (concat (file-name-directory exe) "fsautocomplete.zip")) - (gnutls-algorithm-priority - (if (and (not gnutls-algorithm-priority) - (boundp 'libgnutls-version) - (>= libgnutls-version 30603) - (version<= emacs-version "26.2")) - "NORMAL:-VERS-TLS1.3" - gnutls-algorithm-priority))) + (eglot-fsharp--github-version) + eglot-fsharp-server-version)) + (url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" + version + (if (eq eglot-fsharp-server-runtime 'net-core) + ".netcore." + "."))) + (exe (eglot-fsharp--path-to-server)) + (zip (concat (file-name-directory exe) "fsautocomplete.zip")) + (gnutls-algorithm-priority + (if (and (not gnutls-algorithm-priority) + (boundp 'libgnutls-version) + (>= libgnutls-version 30603) + (version<= emacs-version "26.2")) + "NORMAL:-VERS-TLS1.3" + gnutls-algorithm-priority))) (unless (eglot-fsharp-current-version-p) (url-copy-file url zip t) ;; FIXME: Windows (unzip preinstalled?) (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) - (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) - (error "Failed to unzip %s" zip)) - (delete-file zip))))) + (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) + (error "Failed to unzip %s" zip)) + (delete-file zip))))) ;;;###autoload (defun eglot-fsharp (interactive) @@ -133,8 +133,8 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) (cons 'eglot-fsautocomplete - `(,(cond - ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") + `(,(cond + ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") ((eq window-system 'w32) "") (t "mono")) ,(eglot-fsharp--path-to-server) "--background-service-enabled")))) @@ -152,10 +152,10 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." "FsAutoComplete breaks spec and and returns error instead of empty list." (if (eq major-mode 'fsharp-mode) (condition-case err - (cl-call-next-method) - (jsonrpc-error - (when (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration")) - nil))) + (cl-call-next-method) + (jsonrpc-error + (when (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration")) + nil))) (when (cl-next-method-p) (cl-call-next-method)))) From 45ea30cc4f2806504cf1e79a4a5d2cd04be50ff4 Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 15 Jan 2021 14:51:21 +0800 Subject: [PATCH 018/120] Fixed indentation --- eglot-fsharp.el | 86 ++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 7aff207..f0ef542 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -46,8 +46,8 @@ :group 'eglot-fsharp :risky t :type '(choice - (const :tag "Latest release" latest) - (string :tag "Version string"))) + (const :tag "Latest release" latest) + (string :tag "Version string"))) (defcustom eglot-fsharp-server-runtime (if (executable-find "dotnet") @@ -61,9 +61,9 @@ (defun eglot-fsharp--path-to-server () "Return FsAutoComplete path." (file-truename (concat eglot-fsharp-server-install-dir - (if (eq eglot-fsharp-server-runtime 'net-core) - "netcore/fsautocomplete.dll" - "netframework/fsautocomplete.exe")))) + (if (eq eglot-fsharp-server-runtime 'net-core) + "netcore/fsautocomplete.dll" + "netframework/fsautocomplete.exe")))) ;; cache to prevent repetitive queries (defvar eglot-fsharp--github-version nil "Latest fsautocomplete.exe GitHub version string.") @@ -72,58 +72,58 @@ "Return latest fsautocomplete.exe GitHub version string." (or eglot-fsharp--github-version (with-temp-buffer - (condition-case err - (let ((json-object-type 'hash-table) - (url-mime-accept-string "application/json")) - (url-insert-file-contents "https://github.com/fsharp/fsautocomplete/releases/latest") - (goto-char (point-min)) - (setq eglot-fsharp--github-version (gethash "tag_name" (json-read)))) - (file-error - (warn "fsautocomplete.exe update check:: %s" (error-message-string err))))))) + (condition-case err + (let ((json-object-type 'hash-table) + (url-mime-accept-string "application/json")) + (url-insert-file-contents "https://github.com/fsharp/fsautocomplete/releases/latest") + (goto-char (point-min)) + (setq eglot-fsharp--github-version (gethash "tag_name" (json-read)))) + (file-error + (warn "fsautocomplete.exe update check:: %s" (error-message-string err))))))) (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." (when (file-exists-p (eglot-fsharp--path-to-server)) (let* ((cmd (append (cdr (eglot-fsharp nil)) '("--version"))) - (version-line (concat (car (apply #'process-lines cmd ))))) + (version-line (concat (car (apply #'process-lines cmd ))))) (when (string-match "^FsAutoComplete \\([[:digit:].]+\\) " version-line) - (substring version-line (match-beginning 1) (match-end 1)) - (match-string 1 version-line))))) + (substring version-line (match-beginning 1) (match-end 1)) + (match-string 1 version-line))))) (defun eglot-fsharp-current-version-p () "Return t if the installation is not outdated." (when (file-exists-p (eglot-fsharp--path-to-server)) (if (eq eglot-fsharp-server-version 'latest) - (equal (eglot-fsharp--github-version) (eglot-fsharp--installed-version)) + (equal (eglot-fsharp--github-version) (eglot-fsharp--installed-version)) (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) (defun eglot-fsharp--maybe-install () "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) (let* ((version (if (eq eglot-fsharp-server-version 'latest) - (eglot-fsharp--github-version) - eglot-fsharp-server-version)) - (url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" - version - (if (eq eglot-fsharp-server-runtime 'net-core) - ".netcore." - "."))) - (exe (eglot-fsharp--path-to-server)) - (zip (concat (file-name-directory exe) "fsautocomplete.zip")) - (gnutls-algorithm-priority - (if (and (not gnutls-algorithm-priority) - (boundp 'libgnutls-version) - (>= libgnutls-version 30603) - (version<= emacs-version "26.2")) - "NORMAL:-VERS-TLS1.3" - gnutls-algorithm-priority))) + (eglot-fsharp--github-version) + eglot-fsharp-server-version)) + (url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" + version + (if (eq eglot-fsharp-server-runtime 'net-core) + ".netcore." + "."))) + (exe (eglot-fsharp--path-to-server)) + (zip (concat (file-name-directory exe) "fsautocomplete.zip")) + (gnutls-algorithm-priority + (if (and (not gnutls-algorithm-priority) + (boundp 'libgnutls-version) + (>= libgnutls-version 30603) + (version<= emacs-version "26.2")) + "NORMAL:-VERS-TLS1.3" + gnutls-algorithm-priority))) (unless (eglot-fsharp-current-version-p) (url-copy-file url zip t) ;; FIXME: Windows (unzip preinstalled?) (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) - (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) - (error "Failed to unzip %s" zip)) - (delete-file zip))))) + (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) + (error "Failed to unzip %s" zip)) + (delete-file zip))))) ;;;###autoload (defun eglot-fsharp (interactive) @@ -133,11 +133,11 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) (cons 'eglot-fsautocomplete - `(,(cond - ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") + `(,(cond + ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") ((eq window-system 'w32) "") (t "mono")) - ,(eglot-fsharp--path-to-server) "--background-service-enabled")))) + ,(eglot-fsharp--path-to-server) "--background-service-enabled")))) (defclass eglot-fsautocomplete (eglot-lsp-server) () @@ -152,10 +152,10 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." "FsAutoComplete breaks spec and and returns error instead of empty list." (if (eq major-mode 'fsharp-mode) (condition-case err - (cl-call-next-method) - (jsonrpc-error - (when (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration")) - nil))) + (cl-call-next-method) + (jsonrpc-error + (when (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration")) + nil))) (when (cl-next-method-p) (cl-call-next-method)))) From 310320e998c433d65ef6a303c36474c69293d6fa Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 15 Jan 2021 14:52:33 +0800 Subject: [PATCH 019/120] Correct footer --- eglot-fsharp.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index f0ef542..34c12f4 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -162,4 +162,4 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (add-to-list 'eglot-server-programs `(fsharp-mode . eglot-fsharp)) (provide 'eglot-fsharp) -;;; eglot-fsharp.el ends herep +;;; eglot-fsharp.el ends here From 4cb097cf72d8a127a66baa3baa0b3f91662debde Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 15 Jan 2021 15:00:49 +0800 Subject: [PATCH 020/120] Fixed byte compile warnings --- eglot-fsharp.el | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 34c12f4..11b4d87 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -85,9 +85,8 @@ "Return version string of fsautocomplete." (when (file-exists-p (eglot-fsharp--path-to-server)) (let* ((cmd (append (cdr (eglot-fsharp nil)) '("--version"))) - (version-line (concat (car (apply #'process-lines cmd ))))) + (version-line (concat (car (apply #'process-lines cmd))))) (when (string-match "^FsAutoComplete \\([[:digit:].]+\\) " version-line) - (substring version-line (match-beginning 1) (match-end 1)) (match-string 1 version-line))))) (defun eglot-fsharp-current-version-p () @@ -143,19 +142,18 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (defclass eglot-fsautocomplete (eglot-lsp-server) () :documentation "F# FsAutoComplete langserver.") -(cl-defmethod eglot-initialization-options ((server eglot-fsautocomplete)) +(cl-defmethod eglot-initialization-options ((_server eglot-fsautocomplete)) "Passes through required FsAutoComplete initialization options." '(:automaticWorkspaceInit t)) ;; FIXME: this should be fixed in FsAutocomplete -(cl-defmethod xref-backend-definitions :around ((type symbol) _identifier) +(cl-defmethod xref-backend-definitions :around ((_type symbol) _identifier) "FsAutoComplete breaks spec and and returns error instead of empty list." (if (eq major-mode 'fsharp-mode) (condition-case err (cl-call-next-method) (jsonrpc-error - (when (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration")) - nil))) + (not (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration"))))) (when (cl-next-method-p) (cl-call-next-method)))) From bd0c43b340541d5d1faffefdaeaa93c3f6e5e45a Mon Sep 17 00:00:00 2001 From: JenChieh Date: Fri, 15 Jan 2021 15:02:33 +0800 Subject: [PATCH 021/120] Fixed package lint --- eglot-fsharp.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 11b4d87..2abc695 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -3,8 +3,10 @@ ;; Copyright (C) 2019-2021 Jürgen Hötzel ;; Author: Jürgen Hötzel -;; Package-Requires: ((eglot "1.4") (fsharp-mode "1.10")) +;; Package-Requires: ((emacs "27.1") (eglot "1.4") (fsharp-mode "1.10")) +;; Version: 1.10 ;; Keywords: languages +;; URL: https://github.com/fsharp/emacs-fsharp-mode ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by From 1c71dfa0b182f1b466db71dcf73c984b65340ac4 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 15 Jan 2021 18:13:13 +0100 Subject: [PATCH 022/120] Relax version restriction to 26.3 (minimum version tested) --- eglot-fsharp.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 2abc695..956b649 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2019-2021 Jürgen Hötzel ;; Author: Jürgen Hötzel -;; Package-Requires: ((emacs "27.1") (eglot "1.4") (fsharp-mode "1.10")) +;; Package-Requires: ((emacs "26.3") (eglot "1.4") (fsharp-mode "1.10")) ;; Version: 1.10 ;; Keywords: languages ;; URL: https://github.com/fsharp/emacs-fsharp-mode From 8987dbcd7b1114d2da9bba6fa2b1b7ca8ba98999 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 15 Jan 2021 19:10:05 +0100 Subject: [PATCH 023/120] Bump version Fixes package-lint error: eglot-fsharp.el:6:52 (package-lint-warning) Version dependency for fsharp-mode appears too high: try 1.9.15 --- fsharp-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsharp-mode.el b/fsharp-mode.el index 4b28966..61d7960 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -9,7 +9,7 @@ ;; Maintainer: Jürgen Hötzel ;; Package-Requires: ((emacs "25") (s "1.3.1") (eglot)) ;; Keywords: languages -;; Version: 1.9.15 +;; Version: 1.11-snapshot ;; This file is not part of GNU Emacs. From 8a915c64197caa63f4a4e31d11bd25129838a627 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 24 Jan 2021 12:51:13 +0100 Subject: [PATCH 024/120] Fix typo --- eglot-fsharp.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 956b649..20829b4 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -1,4 +1,4 @@ -;;; eglot-fsharp.el --- Lua eglot integration -*- lexical-binding: t; -*- +;;; eglot-fsharp.el --- fsharp-mode eglot integration -*- lexical-binding: t; -*- ;; Copyright (C) 2019-2021 Jürgen Hötzel From ae9aacf48ff0523a643270f6b4131799fb17c055 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 24 Jan 2021 13:00:08 +0100 Subject: [PATCH 025/120] Fix typo in License file --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index 064244c..0e749dc 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -2,7 +2,7 @@ Copyright 2011-2015 Robin Neatherway - Jurgen Hurtzel + Jürgen Hötzel Jason Imison Chris Barrett From 906cf4bd85951130a686e6cfc8b9eef40627b2f5 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 24 Jan 2021 13:18:09 +0100 Subject: [PATCH 026/120] Use correct (github compatible) license file format --- LICENSE | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE.md | 208 ----------------------------------------------------- 2 files changed, 202 insertions(+), 208 deletions(-) create mode 100644 LICENSE delete mode 100644 LICENSE.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 0e749dc..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,208 +0,0 @@ -Copyright 2011-2015 - - - Robin Neatherway - Jürgen Hötzel - Jason Imison - Chris Barrett - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - ------------------------------------------------------------- - -Apache License, Version 2.0 -=========================== - -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -### TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - -**1. Definitions.** - - - "License" shall mean the terms and conditions for use, reproduction, -and distribution as defined by Sections 1 through 9 of this document. - - - "Licensor" shall mean the copyright owner or entity authorized by -the copyright owner that is granting the License. - - - "Legal Entity" shall mean the union of the acting entity and all -other entities that control, are controlled by, or are under common -control with that entity. For the purposes of this definition, -"control" means (i) the power, direct or indirect, to cause the -direction or management of such entity, whether by contract or -otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - - - "You" (or "Your") shall mean an individual or Legal Entity -exercising permissions granted by this License. - - - "Source" form shall mean the preferred form for making modifications, -including but not limited to software source code, documentation -source, and configuration files. - - - "Object" form shall mean any form resulting from mechanical -transformation or translation of a Source form, including but -not limited to compiled object code, generated documentation, -and conversions to other media types. - - - "Work" shall mean the work of authorship, whether in Source or -Object form, made available under the License, as indicated by a -copyright notice that is included in or attached to the work -(an example is provided in the Appendix below). - - - "Derivative Works" shall mean any work, whether in Source or Object -form, that is based on (or derived from) the Work and for which the -editorial revisions, annotations, elaborations, or other modifications -represent, as a whole, an original work of authorship. For the purposes -of this License, Derivative Works shall not include works that remain -separable from, or merely link (or bind by name) to the interfaces of, -the Work and Derivative Works thereof. - - - "Contribution" shall mean any work of authorship, including -the original version of the Work and any modifications or additions -to that Work or Derivative Works thereof, that is intentionally -submitted to Licensor for inclusion in the Work by the copyright owner -or by an individual or Legal Entity authorized to submit on behalf of -the copyright owner. For the purposes of this definition, "submitted" -means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, -and issue tracking systems that are managed by, or on behalf of, the -Licensor for the purpose of discussing and improving the Work, but -excluding communication that is conspicuously marked or otherwise -designated in writing by the copyright owner as "Not a Contribution." - - - "Contributor" shall mean Licensor and any individual or Legal Entity -on behalf of whom a Contribution has been received by Licensor and -subsequently incorporated within the Work. - -**2. Grant of Copyright License.** -Subject to the terms and conditions of -this License, each Contributor hereby grants to You a perpetual, -worldwide, non-exclusive, no-charge, royalty-free, irrevocable -copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the -Work and such Derivative Works in Source or Object form. - -**3. Grant of Patent License.** -Subject to the terms and conditions of -this License, each Contributor hereby grants to You a perpetual, -worldwide, non-exclusive, no-charge, royalty-free, irrevocable -(except as stated in this section) patent license to make, have made, -use, offer to sell, sell, import, and otherwise transfer the Work, -where such license applies only to those patent claims licensable -by such Contributor that are necessarily infringed by their -Contribution(s) alone or by combination of their Contribution(s) -with the Work to which such Contribution(s) was submitted. If You -institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work -or a Contribution incorporated within the Work constitutes direct -or contributory patent infringement, then any patent licenses -granted to You under this License for that Work shall terminate -as of the date such litigation is filed. - -**4. Redistribution.** -You may reproduce and distribute copies of the -Work or Derivative Works thereof in any medium, with or without -modifications, and in Source or Object form, provided that You -meet the following conditions: - - - You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - - You must cause any modified files to carry prominent notices - stating that You changed the files; and - - - You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - - If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - -You may add Your own copyright statement to Your modifications and -may provide additional or different license terms and conditions -for use, reproduction, or distribution of Your modifications, or -for any such Derivative Works as a whole, provided Your use, -reproduction, and distribution of the Work otherwise complies with -the conditions stated in this License. - -**5. Submission of Contributions.** -Unless You explicitly state otherwise, -any Contribution intentionally submitted for inclusion in the Work -by You to the Licensor shall be under the terms and conditions of -this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify -the terms of any separate license agreement you may have executed -with Licensor regarding such Contributions. - -**6. Trademarks.** -This License does not grant permission to use the trade -names, trademarks, service marks, or product names of the Licensor, -except as required for reasonable and customary use in describing the -origin of the Work and reproducing the content of the NOTICE file. - -**7. Disclaimer of Warranty.** -Unless required by applicable law or -agreed to in writing, Licensor provides the Work (and each -Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied, including, without limitation, any warranties or conditions -of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A -PARTICULAR PURPOSE. You are solely responsible for determining the -appropriateness of using or redistributing the Work and assume any -risks associated with Your exercise of permissions under this License. - -**8. Limitation of Liability.** -In no event and under no legal theory, -whether in tort (including negligence), contract, or otherwise, -unless required by applicable law (such as deliberate and grossly -negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, -incidental, or consequential damages of any character arising as a -result of this License or out of the use or inability to use the -Work (including but not limited to damages for loss of goodwill, -work stoppage, computer failure or malfunction, or any and all -other commercial damages or losses), even if such Contributor -has been advised of the possibility of such damages. - -**9. Accepting Warranty or Additional Liability.** -While redistributing -the Work or Derivative Works thereof, You may choose to offer, -and charge a fee for, acceptance of support, warranty, indemnity, -or other liability obligations and/or rights consistent with this -License. However, in accepting such obligations, You may act only -on Your own behalf and on Your sole responsibility, not on behalf -of any other Contributor, and only if You agree to indemnify, -defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason -of your accepting any such warranty or additional liability. From 303caa4023f56f647421d809eb240126225dd182 Mon Sep 17 00:00:00 2001 From: Kien Nguyen Date: Wed, 28 Oct 2020 09:19:18 +0900 Subject: [PATCH 027/120] fsharp-mode: do not explicitly depend on eglot --- Cask | 3 ++- fsharp-mode.el | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cask b/Cask index dc1eaf7..35803d5 100644 --- a/Cask +++ b/Cask @@ -5,5 +5,6 @@ (files "*.el") ;; FIXME: Use multiple packages: https://github.com/melpa/melpa#example-multiple-packages-in-one-repository ? (development - (depends-on "buttercup")) + (depends-on "buttercup") + (depends-on "eglot")) diff --git a/fsharp-mode.el b/fsharp-mode.el index 61d7960..0263a36 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -5,9 +5,9 @@ ;; Author: 1993-1997 Xavier Leroy, Jacques Garrigue and Ian T Zimmerman ;; 2010-2011 Laurent Le Brun ;; 2012-2014 Robin Neatherway -;; 2017-2019 Jürgen Hötzel +;; 2017-2021 Jürgen Hötzel ;; Maintainer: Jürgen Hötzel -;; Package-Requires: ((emacs "25") (s "1.3.1") (eglot)) +;; Package-Requires: ((emacs "25") (s "1.3.1")) ;; Keywords: languages ;; Version: 1.11-snapshot From b6095e08ff228388cc7a07885ddc92d742047610 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 24 Jan 2021 14:52:24 +0100 Subject: [PATCH 028/120] Document the eglot packet-split Refs #253. --- README.org | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.org b/README.org index 13fa47a..a36d69d 100644 --- a/README.org +++ b/README.org @@ -14,10 +14,10 @@ Provides support for the F# language in Emacs. Includes the following features: - Jump to definition [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html][Find Identifier References]] (Xref) ** LSP mode -Previous versions of =fsharp-mode= (mis)used a second repository [[https://github.com/rneatherway/emacs-fsharp-mode-bin][emacs-fsharp-mode-bin]] to distribute =fsautocomplete.exe= and =fsharp-mode= together. -The current version of =fsharp-mode= installs =fsautocomplete.exe= automatically via [[https://github.com/joaotavora/eglot][eglot-fsharp]] (part of this repo) or -[[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] (untested). +The current version of =fsharp-mode= installs =fsautocomplete.exe= +automatically via =eglot-fsharp.el= (part of this mono repo, [[https://melpa.org/#/eglot-fsharp][eglot-fsharp +on melpa]]) or [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] (untested). =fsharp-mode= is tested with Emacs 26.1+ and NET Core 2.1 (LTS) @@ -62,10 +62,9 @@ I recommend to use [[https://cask.github.io/why-cask.html][Cask]]. Add this to y ** Eglot integration -=eglot-fsharp= is part of this package and provides integration to [[https://github.com/joaotavora/eglot][Eglot]] Emacs LSP client: +The =eglot-fsharp= integration is not part of [[https://melpa.org/#/fsharp-mode][fsharp-mode on melpa]]. - - Automatic =fsautocomplete= download - - Workaround for non-LSP standard-compliant +It is available via the seperate package [[https://melpa.org/#/eglot-fsharp][eglot-fsharp on melpa]]. Add to your config: #+BEGIN_SRC elisp From 95572ededaedc03997c7c59cdf0d6a4b33ff28c5 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 26 Jan 2021 05:46:53 +0100 Subject: [PATCH 029/120] Fix remaining package-lint errors: add jsonrpc explicitly --- eglot-fsharp.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 20829b4..39e6758 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2019-2021 Jürgen Hötzel ;; Author: Jürgen Hötzel -;; Package-Requires: ((emacs "26.3") (eglot "1.4") (fsharp-mode "1.10")) +;; Package-Requires: ((emacs "26.3") (eglot "1.4") (fsharp-mode "1.10") (jsonrpc "1.0.14")) ;; Version: 1.10 ;; Keywords: languages ;; URL: https://github.com/fsharp/emacs-fsharp-mode From 05a2c6a441d09501b81db382b18060fdd8540774 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Tue, 26 Jan 2021 22:58:12 +0900 Subject: [PATCH 030/120] Replace dash functions and fix byte-compile warnings --- fsharp-mode-util.el | 43 +++++++++++++++++++++++-------------------- fsharp-mode.el | 4 +++- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/fsharp-mode-util.el b/fsharp-mode-util.el index daa65fb..d20106a 100644 --- a/fsharp-mode-util.el +++ b/fsharp-mode-util.el @@ -1,4 +1,4 @@ -;;; fsharp-mode-util.el --- utility functions +;;; fsharp-mode-util.el --- utility functions -*- lexical-binding: t -*- ;; Copyright (C) 2015 Robin Neatherway @@ -23,10 +23,10 @@ ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. -(with-no-warnings (require 'cl)) +(require 'cl-lib) (defvar fsharp-ac-using-mono - (case system-type + (cl-case system-type ((windows-nt cygwin msdos) nil) (otherwise t)) "Whether the .NET runtime in use is mono. @@ -35,36 +35,39 @@ for all *nix.") (defun fsharp-mode--program-files-x86 () (file-name-as-directory - (car (-drop-while 'not - (list (getenv "ProgramFiles(x86)") - (getenv "ProgramFiles") - "C:\\Program Files (x86)"))))) + (or (getenv "ProgramFiles(x86)") + (getenv "ProgramFiles") + "C:\\Program Files (x86)"))) (defun fsharp-mode--vs2017-msbuild-find (exe) "Return EXE absolute path for Visual Studio 2017, if existent, else nil." - (->> (--map (concat (fsharp-mode--program-files-x86) - "Microsoft Visual Studio/2017/" - it - "msbuild/15.0/bin/" - exe) - '("Enterprise/" "Professional/" "Community/" "BuildTools/")) - (--first (file-executable-p it)))) + (let ((candidates (mapcar (lambda (edition) + (concat (fsharp-mode--program-files-x86) + edition + "msbuild/15.0/bin/" + exe)) + '("Enterprise/" "Professional/" + "Community/" "BuildTools/")))) + (cl-find-if (lambda (exe) (file-executable-p exe)) candidates))) (defun fsharp-mode--msbuild-find (exe) (if fsharp-ac-using-mono (executable-find exe) - (let* ((searchdirs (--map (concat (fsharp-mode--program-files-x86) - "MSBuild/" it "/Bin") - '("14.0" "13.0" "12.0"))) + (let* ((searchdirs (mapcar (lambda (ver) + (concat (fsharp-mode--program-files-x86) + "MSBuild/" ver "/Bin")) + '("14.0" "13.0" "12.0"))) (exec-path (append searchdirs exec-path))) (or (fsharp-mode--vs2017-msbuild-find exe) (executable-find exe))))) (defun fsharp-mode--executable-find (exe) (if fsharp-ac-using-mono (executable-find exe) - (let* ((searchdirs (--map (concat (fsharp-mode--program-files-x86) - "Microsoft SDKs/F#/" it "/Framework/v4.0") - '("10.1" "4.0" "3.1" "3.0"))) + (let* ((searchdirs (mapcar (lambda (ver) + (concat (fsharp-mode--program-files-x86) + "Microsoft SDKs/F#/" + ver "/Framework/v4.0")) + '("10.1" "4.0" "3.1" "3.0"))) (exec-path (append searchdirs exec-path))) (executable-find exe)))) diff --git a/fsharp-mode.el b/fsharp-mode.el index 0263a36..a060e4a 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -35,6 +35,8 @@ (require 'fsharp-mode-util) (require 'compile) (require 'project) +(require 'subr-x) +(require 'seq) (defgroup fsharp nil "Support for the Fsharp programming language, " @@ -358,7 +360,7 @@ folders relative to DIR-OR-FILE." ;; Make project.el aware of fsharp projects (defun fsharp-mode-project-root (dir) - (-when-let (project-file (fsharp-mode/find-sln-or-fsproj dir)) + (when-let (project-file (fsharp-mode/find-sln-or-fsproj dir)) (cons 'fsharp (file-name-directory project-file)))) (cl-defmethod project-roots ((project (head fsharp))) From caacbe523eeaf4588e0123cb191224c27f31cbb6 Mon Sep 17 00:00:00 2001 From: Rafal Gwozdzinski Date: Sun, 31 Jan 2021 09:42:00 +0100 Subject: [PATCH 031/120] New defcustom: `fsharp-autosave-on-file-load': Optional autosave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jürgen Hötzel --- fsharp-mode.el | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fsharp-mode.el b/fsharp-mode.el index a060e4a..183b65d 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -171,6 +171,13 @@ (defvar fsharp-mode-hook nil "Hook for fsharp-mode") +(defcustom fsharp-autosave-on-file-load nil + "Determine if buffer should be automatically saved on +`fsharp-load-buffer-file'. +If set to t, the buffer will always be saved, silently." + :type 'boolean + :group 'fsharp-mode) + ;;;###autoload (define-derived-mode fsharp-mode prog-mode "fsharp" :syntax-table fsharp-mode-syntax-table @@ -290,10 +297,11 @@ (require 'inf-fsharp-mode) (let* ((name buffer-file-name) (command (concat "#load \"" name "\""))) - (when (buffer-modified-p) - (when (y-or-n-p (concat "Do you want to save \"" name "\" before -loading it? ")) - (save-buffer))) + (when (and (buffer-modified-p) + (or fsharp-autosave-on-file-load + (y-or-n-p (concat "Do you want to save \"" name + "\" before loading it? ")))) + (save-buffer)) (fsharp-run-process-if-needed) (fsharp-simple-send inferior-fsharp-buffer-name command))) From 955cb168781a4b7c36a3fa16fd6b98b74f64c772 Mon Sep 17 00:00:00 2001 From: Rafal Gwozdzinski Date: Sun, 31 Jan 2021 16:27:31 +0100 Subject: [PATCH 032/120] Generic face for custom operators that contain pipe char sequence. --- fsharp-mode-font.el | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el index a063919..d77e463 100644 --- a/fsharp-mode-font.el +++ b/fsharp-mode-font.el @@ -171,6 +171,17 @@ with initial value INITVALUE and optional DOCSTRING." "<|\\{1,3\\}\\||\\{1,3\\}>" "Match the full range of pipe operators -- |>, ||>, |||>, etc.") +(def-fsharp-compiled-var fsharp-custom-operator-with-pipe-regexp + (let ((op-chars "!%&\\*\\+\\-\\./<=>@\\^~") ;; all F# custom operator chars except for `|` + (backward-pipe "<|\\{1,3\\}") + (forward-pipe "|\\{1,3\\}>") + (alt "\\|")) + (concat "[" op-chars "|]*" backward-pipe "[" op-chars "]+" + alt "[" op-chars "|]+" backward-pipe "[" op-chars "]*" + alt "[" op-chars "]*" forward-pipe "[" op-chars "|]+" + alt "[" op-chars "]+" forward-pipe "[" op-chars "|]*")) + "Match operators that contains pipe sequence -- <|>, |>>, <<|, etc.") + (def-fsharp-compiled-var fsharp-operator-case-regexp "\\s-+\\(|\\)[A-Za-z0-9_' ]" "Match literal | in contexts like match and type declarations.") @@ -297,6 +308,7 @@ with initial value INITVALUE and optional DOCSTRING." nil nil (1 font-lock-function-name-face) (2 'fsharp-ui-operator-face))) + (,fsharp-custom-operator-with-pipe-regexp . 'fsharp-ui-generic-face) (,fsharp-operator-pipe-regexp . 'fsharp-ui-operator-face) (,fsharp-member-function-regexp 1 font-lock-function-name-face) (,fsharp-overload-operator-regexp 1 font-lock-function-name-face) From 58f49aebc2d34fdcda1d04ee31418029885b23f8 Mon Sep 17 00:00:00 2001 From: Rafal Gwozdzinski Date: Wed, 3 Feb 2021 06:32:57 +0100 Subject: [PATCH 033/120] Add font tests --- test/fsharp-mode-font-tests.el | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 test/fsharp-mode-font-tests.el diff --git a/test/fsharp-mode-font-tests.el b/test/fsharp-mode-font-tests.el new file mode 100644 index 0000000..14a2174 --- /dev/null +++ b/test/fsharp-mode-font-tests.el @@ -0,0 +1,44 @@ +;;; fsharp-mode-font-tests.el --- -*- lexical-binding: t; -*- + +(require 'buttercup) + +(require 'fsharp-mode) +(require 'fsharp-mode-font) + +(defmacro with-highlighted (src &rest body) + "Insert SRC in a temporary fsharp-mode buffer, apply syntax highlighting, +then run BODY." + `(with-temp-buffer + (fsharp-mode) + (insert ,src) + (goto-char (point-min)) + ;; Ensure we've syntax-highlighted the whole buffer. + (if (fboundp 'font-lock-ensure) + (font-lock-ensure) + (with-no-warnings + (font-lock-fontify-buffer))) + ,@body)) + +(defun str-face (op) + (goto-char (point-min)) + (search-forward op) + (left-char) + (face-at-point)) + +(describe "When locking operators" + (it "uses ui operator face for pipes" + (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" + (should (eq (str-face "|>") 'fsharp-ui-operator-face)) + (should (eq (str-face "||>") 'fsharp-ui-operator-face)) + (should (eq (str-face "|||>") 'fsharp-ui-operator-face)) + (should (eq (str-face "<|") 'fsharp-ui-operator-face)) + (should (eq (str-face "<||") 'fsharp-ui-operator-face)) + (should (eq (str-face "<|||") 'fsharp-ui-operator-face))))) + +(describe "When locking operators" + (it "uses ui generic face for custom operators containing pipes" + (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" + (should (eq (str-face "<<|") 'fsharp-ui-generic-face)) + (should (eq (str-face "|>>") 'fsharp-ui-generic-face)) + (should (eq (str-face "<|>") 'fsharp-ui-generic-face)) + (should (eq (str-face "<<|!") 'fsharp-ui-generic-face))))) From 20db4460656f1e859b1dd084158205ed6121aeef Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 28 Mar 2021 17:26:33 +0200 Subject: [PATCH 034/120] Add Emacs 27.2 to build matrix --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4b9675f..9395e97 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,7 @@ jobs: emacs_version: - 26.3 - 27.1 + - 27.2 - snapshot steps: - uses: purcell/setup-emacs@master From 0461fc401229fecf61b4820237ddcbeb8b05e9e9 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Mon, 29 Mar 2021 22:46:51 +0200 Subject: [PATCH 035/120] Fix invalid unix permissions of fsautocomplete Workaround for FAKE issue: https://github.com/fsharp/FsAutoComplete/issues/715 --- eglot-fsharp.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 39e6758..752a391 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -124,7 +124,12 @@ (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) (error "Failed to unzip %s" zip)) - (delete-file zip))))) + (unless (eq system-type 'windows-nt) + (dolist (file (directory-files-recursively (file-name-directory (eglot-fsharp--path-to-server)) "." t)) + (if (file-directory-p file) + (chmod file #o755) + (chmod file #o644))))) + (delete-file zip)))) ;;;###autoload (defun eglot-fsharp (interactive) From 41eb84a3c70600195966b17b725de6a95d864a9a Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 30 Mar 2021 16:30:09 +0200 Subject: [PATCH 036/120] Adapt the tests to the latest fsautocomplete version The jump to definition in pervasives is now available. --- test/integration-tests.el | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/test/integration-tests.el b/test/integration-tests.el index d3bec19..05a6391 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -63,17 +63,13 @@ (eglot-fsharp--sniff-diagnostics) (completion-at-point) (expect (looking-back "X\\.func") :to-be t))) - (it "doesn't throw error when definition does not exist" + (it "finds definition in pervasives" (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") (eglot-fsharp--sniff-diagnostics) (goto-char 253) (expect (current-word) :to-equal "printfn") ;sanity check - (expect - (condition-case err - (call-interactively #'xref-find-definitions) - (user-error - (cadr err))) - :to-equal "No definitions found for: LSP identifier at point."))) + (call-interactively #'xref-find-definitions) + (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs"))) (it "finds definitions in other files of Project" (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") (goto-char 150) From 0be5080eff1a839b6d4add8f3245dbf73f4d3f5c Mon Sep 17 00:00:00 2001 From: Keith Pinson Date: Wed, 31 Mar 2021 12:19:13 -0400 Subject: [PATCH 037/120] fix: `//`-comments filled incorrectly (`//` not acting as prefix) The problem is described [here](https://github.com/syl20bnr/spacemacs/issues/11326). I haven't been writing much F# lately but I found that `emacs-scala-mode` has the same problem and this fix works well for it, so I thought I would submit it here too. --- fsharp-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/fsharp-mode.el b/fsharp-mode.el index 183b65d..fd5fe13 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -218,6 +218,7 @@ If set to t, the buffer will always be saved, silently." comment-end "" comment-column 40 comment-start-skip "///* *" + adaptive-fill-regexp "[ \t]*\\(//+[ \t]*\\)*" comment-indent-function 'fsharp-comment-indent-function indent-region-function 'fsharp-indent-region indent-line-function 'fsharp-indent-line From 93b1fbc31d73286a18640a36fc2be87d1736e0f2 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 31 Mar 2021 21:31:37 +0200 Subject: [PATCH 038/120] Make `adaptive-fill-regexp` buffer-local This prevents effects on other major modes depending on the Emacs default. --- fsharp-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/fsharp-mode.el b/fsharp-mode.el index fd5fe13..c8e0153 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -201,6 +201,7 @@ If set to t, the buffer will always be saved, silently." comment-column comment-start-skip comment-indent-function + adaptive-fill-regexp parse-sexp-ignore-comments indent-region-function indent-line-function From 38eccc8d082964d58573fb4c9f9475ff488ed9e5 Mon Sep 17 00:00:00 2001 From: Rafal Gwozdzinski Date: Fri, 6 Aug 2021 10:13:54 +0200 Subject: [PATCH 039/120] Fix operator font tests --- test/fsharp-mode-font-tests.el | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/test/fsharp-mode-font-tests.el b/test/fsharp-mode-font-tests.el index 14a2174..55397f4 100644 --- a/test/fsharp-mode-font-tests.el +++ b/test/fsharp-mode-font-tests.el @@ -1,9 +1,7 @@ ;;; fsharp-mode-font-tests.el --- -*- lexical-binding: t; -*- (require 'buttercup) - (require 'fsharp-mode) -(require 'fsharp-mode-font) (defmacro with-highlighted (src &rest body) "Insert SRC in a temporary fsharp-mode buffer, apply syntax highlighting, @@ -22,23 +20,23 @@ then run BODY." (defun str-face (op) (goto-char (point-min)) (search-forward op) - (left-char) + (left-char 2) (face-at-point)) (describe "When locking operators" (it "uses ui operator face for pipes" (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" - (should (eq (str-face "|>") 'fsharp-ui-operator-face)) - (should (eq (str-face "||>") 'fsharp-ui-operator-face)) - (should (eq (str-face "|||>") 'fsharp-ui-operator-face)) - (should (eq (str-face "<|") 'fsharp-ui-operator-face)) - (should (eq (str-face "<||") 'fsharp-ui-operator-face)) - (should (eq (str-face "<|||") 'fsharp-ui-operator-face))))) + (should (equal (str-face " |> ") 'fsharp-ui-operator-face)) + (should (equal (str-face " ||> ") 'fsharp-ui-operator-face)) + (should (equal (str-face " |||> ") 'fsharp-ui-operator-face)) + (should (equal (str-face " <| ") 'fsharp-ui-operator-face)) + (should (equal (str-face " <|| ") 'fsharp-ui-operator-face)) + (should (equal (str-face " <||| ") 'fsharp-ui-operator-face))))) (describe "When locking operators" (it "uses ui generic face for custom operators containing pipes" (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" - (should (eq (str-face "<<|") 'fsharp-ui-generic-face)) - (should (eq (str-face "|>>") 'fsharp-ui-generic-face)) - (should (eq (str-face "<|>") 'fsharp-ui-generic-face)) - (should (eq (str-face "<<|!") 'fsharp-ui-generic-face))))) + (should (equal (str-face "<<| ") 'fsharp-ui-generic-face)) + (should (equal (str-face " |>> ") 'fsharp-ui-generic-face)) + (should (equal (str-face " <|> ") 'fsharp-ui-generic-face)) + (should (equal (str-face " <<|!") 'fsharp-ui-generic-face))))) From d5800d8a796d8e3c716b383d34e52818e0242ea6 Mon Sep 17 00:00:00 2001 From: Johan von Tangen Sivertsen Date: Mon, 4 Oct 2021 09:24:19 +0200 Subject: [PATCH 040/120] Update README.org Add some hints on how to use completions and go-to-reference. --- README.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.org b/README.org index a36d69d..93a1b09 100644 --- a/README.org +++ b/README.org @@ -73,6 +73,8 @@ Add to your config: and execute =M-x eglot= +With eglot running use `xref-find-definitions` (bound to =M-.= pr. default) to go to definition. Completions are accessable via. `completion-at-point` (or a completion backend ex. company-mode [[https://melpa.org/#/company]]) + ** Projects From 074ba9917e2ae33086835ea08c79e36990a44ece Mon Sep 17 00:00:00 2001 From: Naoya Yamashita Date: Wed, 20 Oct 2021 02:01:16 +0900 Subject: [PATCH 041/120] remove unneeded `files` directive (files "*.el") is not needed. Before this commit: $ cask files eglot-fsharp.el fsharp-mode-font.el fsharp-mode-structure.el fsharp-mode-util.el fsharp-mode.el inf-fsharp-mode.el After this commit: $ cask files eglot-fsharp.el fsharp-mode-font.el fsharp-mode-structure.el fsharp-mode-util.el fsharp-mode.el inf-fsharp-mode.el --- Cask | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cask b/Cask index 35803d5..cc6c144 100644 --- a/Cask +++ b/Cask @@ -2,9 +2,8 @@ (source melpa) (package-file "fsharp-mode.el") -(files "*.el") + ;; FIXME: Use multiple packages: https://github.com/melpa/melpa#example-multiple-packages-in-one-repository ? (development (depends-on "buttercup") (depends-on "eglot")) - From cbd48f448b4e5b42c2c04d4608c3b50a60ed2256 Mon Sep 17 00:00:00 2001 From: Naoya Yamashita Date: Wed, 20 Oct 2021 02:10:33 +0900 Subject: [PATCH 042/120] fix indentation --- eglot-fsharp.el | 2 +- fsharp-mode-font.el | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 752a391..3d8069f 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -129,7 +129,7 @@ (if (file-directory-p file) (chmod file #o755) (chmod file #o644))))) - (delete-file zip)))) + (delete-file zip)))) ;;;###autoload (defun eglot-fsharp (interactive) diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el index d77e463..648e90d 100644 --- a/fsharp-mode-font.el +++ b/fsharp-mode-font.el @@ -177,9 +177,9 @@ with initial value INITVALUE and optional DOCSTRING." (forward-pipe "|\\{1,3\\}>") (alt "\\|")) (concat "[" op-chars "|]*" backward-pipe "[" op-chars "]+" - alt "[" op-chars "|]+" backward-pipe "[" op-chars "]*" - alt "[" op-chars "]*" forward-pipe "[" op-chars "|]+" - alt "[" op-chars "]+" forward-pipe "[" op-chars "|]*")) + alt "[" op-chars "|]+" backward-pipe "[" op-chars "]*" + alt "[" op-chars "]*" forward-pipe "[" op-chars "|]+" + alt "[" op-chars "]+" forward-pipe "[" op-chars "|]*")) "Match operators that contains pipe sequence -- <|>, |>>, <<|, etc.") (def-fsharp-compiled-var fsharp-operator-case-regexp @@ -382,16 +382,14 @@ with initial value INITVALUE and optional DOCSTRING." 'syntax-table (string-to-syntax ".")) (put-text-property (match-beginning 0) (match-end 0) 'syntax-table (string-to-syntax "|")) - nil))) - ) + nil)))) (t ; Then we are in a triple-quoted string (when (re-search-forward "\"\"\"" end 'move) (put-text-property (- (match-beginning 0) 1) (match-beginning 0) 'syntax-table (string-to-syntax ".")) (put-text-property (match-beginning 0) (match-end 0) - 'syntax-table (string-to-syntax "|"))) - ))))) + 'syntax-table (string-to-syntax "|")))))))) (provide 'fsharp-mode-font) From 0e713614c3020813a3df6b81a9ded2ea5a40e5ec Mon Sep 17 00:00:00 2001 From: Naoya Yamashita Date: Wed, 20 Oct 2021 02:10:47 +0900 Subject: [PATCH 043/120] fix closing paren --- fsharp-mode-structure.el | 33 ++++++++++----------------------- inf-fsharp-mode.el | 4 +--- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index 4d913e0..2fb1a04 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -285,8 +285,7 @@ to scan." "Returns non-nil if the current line should dedent one level." (save-excursion (progn (back-to-indentation) - (looking-at fsharp-outdent-re)) - )) + (looking-at fsharp-outdent-re)))) (defun fsharp--indenting-comment-p () @@ -459,8 +458,7 @@ comment." (goto-char here) (beginning-of-line) (delete-horizontal-space) - (indent-to (- indent outdent)) - ))))) + (indent-to (- indent outdent))))))) ;; Electric deletion @@ -582,8 +580,7 @@ This function is normally bound to `indent-line-function' so (delete-horizontal-space) (indent-to need))) (if move-to-indentation-p (back-to-indentation))) - (insert-tab))) - ))) + (insert-tab)))))) ;; NOTE[gastove|2019-10-25] An interesting point: this function is *only* ever @@ -686,8 +683,7 @@ above, but only when the previous line is not itself a continuation line." ;; statement, add some extra offset. (+ (current-column) (if (fsharp-statement-opens-block-p) fsharp-continuation-offset 0) - 1) - ))) + 1)))) (defun fsharp--compute-indentation-relative-to-previous (honor-block-close-p) @@ -720,11 +716,7 @@ lines (if any)" (back-to-indentation) (and (not (looking-at prefix-re)) (or (looking-at "[^/]") - (not (zerop (current-column))) - )) - )) - )) - ))) + (not (zerop (current-column)))))))))))) ;; if we landed inside a string, go to the beginning of that ;; string. this handles triple quoted, multi-line spanning ;; strings. @@ -742,8 +734,7 @@ lines (if any)" fsharp-indent-offset (if (and honor-block-close-p (fsharp-statement-closes-block-p)) (- fsharp-indent-offset) - 0))))) - ) + 0)))))) (defun fsharp-newline-and-indent () @@ -857,8 +848,7 @@ it's tried again going backward." (or noninteractive (message "%s value of fsharp-indent-offset set to %d" (if global "Global" "Local") - fsharp-indent-offset))) - )) + fsharp-indent-offset))))) (defun fsharp-comment-indent-function () "Fsharp version of `comment-indent-function'." @@ -873,8 +863,7 @@ it's tried again going backward." (setq eol (match-beginning 0))) (goto-char eol) (skip-chars-backward " \t") - (max comment-column (+ (current-column) (if (bolp) 0 1))) - ))) + (max comment-column (+ (current-column) (if (bolp) 0 1)))))) (defun fsharp-narrow-to-defun (&optional class) "Make text outside current defun invisible. @@ -1142,8 +1131,7 @@ To mark the current `def', see `\\[fsharp-mark-def-or-class]'." (start-of-stmt (goto-char (fsharp-point 'bos))) (start-re (cond ((eq class 'either) "^[ \t]*\\(type\\|let\\)\\>") (class "^[ \t]*type\\>") - (t "^[ \t]*let\\>"))) - ) + (t "^[ \t]*let\\>")))) ;; searching backward (if (and (< 0 count) (or (/= start-of-stmt start-of-line) @@ -1621,8 +1609,7 @@ moves to the end of the block (& does not set mark or display a msg)." (while (and (setq last-pos (point)) ; always true -- side effect (fsharp-goto-statement-below) - (> (current-indentation) initial-indent) - ))) + (> (current-indentation) initial-indent)))) ;; else plain code line; stop at next blank line, or stmt or ;; indenting comment line indented < diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el index 15e821d..4a17abe 100644 --- a/inf-fsharp-mode.el +++ b/inf-fsharp-mode.el @@ -146,9 +146,7 @@ Input and output via buffer `*inferior-fsharp*'." (while (> count 0) (previous-multiframe-window) - (setq count (- count 1))) - ) - ) + (setq count (- count 1))))) (defun inferior-fsharp-eval-region (start end) "Send the current region to the inferior fsharp process." From e3cbb2c34183739d8223c68d9beeb646b0cb2555 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 27 Oct 2021 17:31:00 +0200 Subject: [PATCH 044/120] Add workarounds for integration test - Restart eglot server - Sniff for current file-name whether parsing is complete. --- test/integration-tests.el | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/integration-tests.el b/test/integration-tests.el index 05a6391..9da6bd3 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -28,11 +28,13 @@ (require 'eglot-fsharp) (require 'eglot-tests) -(defun eglot-fsharp--sniff-diagnostics () +(defun eglot-fsharp--sniff-diagnostics (file-name-suffix) (eglot--sniffing (:server-notifications s-notifs) (eglot--wait-for (s-notifs 20) - (&key _id method &allow-other-keys) - (string= method "textDocument/publishDiagnostics")))) + (&key _id method params &allow-other-keys) + (and + (string= method "textDocument/publishDiagnostics") + (string-suffix-p file-name-suffix (plist-get params :uri)))))) (describe "F# LSP server" (it "Can be installed" @@ -45,7 +47,7 @@ (flymake-mode t) (flymake-start) (goto-char (point-min)) - (eglot-fsharp--sniff-diagnostics) + (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") (flymake-goto-next-error 1 '() t) (expect (face-at-point) :to-be 'flymake-error ))) (it "is enabled on F# Files" @@ -53,23 +55,24 @@ (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete))) (it "provides completion" (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs") - (eglot-fsharp--sniff-diagnostics) + (eglot-fsharp--sniff-diagnostics "test/Test1/FileTwo.fs") (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil))) (it "completes function in other modules" (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") (search-forward "X.func") (delete-char -3) - ;; ERROR in fsautocomplet.exe? Should block instead of "no type check results" - (eglot-fsharp--sniff-diagnostics) + (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") (completion-at-point) (expect (looking-back "X\\.func") :to-be t))) (it "finds definition in pervasives" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (eglot-fsharp--sniff-diagnostics) - (goto-char 253) - (expect (current-word) :to-equal "printfn") ;sanity check - (call-interactively #'xref-find-definitions) - (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs"))) + (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") + (eglot-shutdown-all) ;FIXME: Why is a restart required + (eglot--tests-connect 10) + (search-forward "printfn") + (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") + (expect (current-word) :to-equal "printfn") ;sanity check + (call-interactively #'xref-find-definitions) + (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs"))) (it "finds definitions in other files of Project" (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") (goto-char 150) From b9e358adc8ef3c9b980419417ab819c831abe439 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 27 Oct 2021 17:31:00 +0200 Subject: [PATCH 045/120] Update TargetFramework for integration tests to net5.0 --- test/Test1/Test1.fsproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Test1/Test1.fsproj b/test/Test1/Test1.fsproj index 348b5cb..3d3561e 100644 --- a/test/Test1/Test1.fsproj +++ b/test/Test1/Test1.fsproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.1 + net5.0 From 18cb50b3425d54ae6ec984fc6a67721758dfa075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 31 Oct 2021 17:06:26 +0100 Subject: [PATCH 046/120] Fix byte-compile warnings --- inf-fsharp-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el index 4a17abe..e14871c 100644 --- a/inf-fsharp-mode.el +++ b/inf-fsharp-mode.el @@ -28,7 +28,7 @@ (require 'comint) (require 'fsharp-mode-util) -(with-no-warnings (require 'cl)) +(require 'cl-lib) ;; User modifiable variables From 12df37a4cab99a7719e4af9620a4223f4a517154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 14 Nov 2021 13:56:07 +0100 Subject: [PATCH 047/120] Prefer dotnet core FSI Fixes #280 --- inf-fsharp-mode.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el index e14871c..b3dc36e 100644 --- a/inf-fsharp-mode.el +++ b/inf-fsharp-mode.el @@ -38,10 +38,11 @@ "*If true, display the inferior fsharp buffer when evaluating expressions.") (defvar inferior-fsharp-program - (if fsharp-ac-using-mono - "fsharpi --readline-" - (concat "\"" (fsharp-mode--executable-find "fsi.exe") "\" --fsi-server-input-codepage:65001")) - "*Program name for invoking an inferior fsharp from Emacs.") + (cond + ((executable-find "dotnet") "dotnet fsi --readline-") + (fsharp-ac-using-mono "fsharpi --readline-") + (t (concat "\"" (fsharp-mode--executable-find "fsi.exe") "\" --fsi-server-input-codepage:65001"))) + "Inferior F# command.") ;; End of User modifiable variables From 07208091d33f8cd0d311b6b98c8a50dde9f150f8 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Mon, 15 Nov 2021 15:15:26 +0100 Subject: [PATCH 048/120] Use fsautocomplete 0.48.2 for integration Tests Testing fails when using fsautocomplete >= 0.49. --- test/integration-tests.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/integration-tests.el b/test/integration-tests.el index 9da6bd3..5e20f62 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -28,6 +28,8 @@ (require 'eglot-fsharp) (require 'eglot-tests) +(setq eglot-fsharp-server-version "0.48.2") + (defun eglot-fsharp--sniff-diagnostics (file-name-suffix) (eglot--sniffing (:server-notifications s-notifs) (eglot--wait-for (s-notifs 20) From 24d5b4c3adf53b801615340e225fc33632ed8822 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Wed, 29 Dec 2021 00:11:14 +0900 Subject: [PATCH 049/120] Use cl-lib function instead of cl.el's one --- inf-fsharp-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el index b3dc36e..7db9a09 100644 --- a/inf-fsharp-mode.el +++ b/inf-fsharp-mode.el @@ -79,7 +79,7 @@ be sent from another buffer in fsharp mode. ;; use compilation mode to parse errors, but RET and C-cC-c should still be from comint-mode (compilation-minor-mode) (make-local-variable 'minor-mode-map-alist) - (setq minor-mode-map-alist (assq-delete-all 'compilation-minor-mode (copy-seq minor-mode-map-alist)))) + (setq minor-mode-map-alist (assq-delete-all 'compilation-minor-mode (cl-copy-seq minor-mode-map-alist)))) (defconst inferior-fsharp-buffer-subname "inferior-fsharp") (defconst inferior-fsharp-buffer-name From 5013666bddcade94531d5c5f788772d014e1035c Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Wed, 26 Jan 2022 02:44:48 -0500 Subject: [PATCH 050/120] switching dotnet core over to using a tool install --- eglot-fsharp.el | 99 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 28 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 3d8069f..542ff53 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -51,6 +51,9 @@ (const :tag "Latest release" latest) (string :tag "Version string"))) +(defcustom eglot-fsharp-server-verbose nil + "If non-nil include debug output in the server logs.") + (defcustom eglot-fsharp-server-runtime (if (executable-find "dotnet") 'net-core @@ -64,12 +67,16 @@ "Return FsAutoComplete path." (file-truename (concat eglot-fsharp-server-install-dir (if (eq eglot-fsharp-server-runtime 'net-core) - "netcore/fsautocomplete.dll" + "netcore/fsautocomplete" "netframework/fsautocomplete.exe")))) ;; cache to prevent repetitive queries (defvar eglot-fsharp--github-version nil "Latest fsautocomplete.exe GitHub version string.") +(defun eglot-fsharp--clean-version (version) + "Remove any spurious prefix from the version string VERSION." + (string-trim-left version "[Vv]")) + (defun eglot-fsharp--github-version () "Return latest fsautocomplete.exe GitHub version string." (or eglot-fsharp--github-version @@ -95,21 +102,16 @@ "Return t if the installation is not outdated." (when (file-exists-p (eglot-fsharp--path-to-server)) (if (eq eglot-fsharp-server-version 'latest) - (equal (eglot-fsharp--github-version) (eglot-fsharp--installed-version)) - (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) - -(defun eglot-fsharp--maybe-install () - "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." - (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) - (let* ((version (if (eq eglot-fsharp-server-version 'latest) - (eglot-fsharp--github-version) - eglot-fsharp-server-version)) - (url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete%szip" - version - (if (eq eglot-fsharp-server-runtime 'net-core) - ".netcore." - "."))) - (exe (eglot-fsharp--path-to-server)) + (equal (eglot-fsharp--clean-version (eglot-fsharp--github-version)) + (eglot-fsharp--clean-version (eglot-fsharp--installed-version))) + (equal (eglot-fsharp--clean-version eglot-fsharp-server-version) + (eglot-fsharp--clean-version (eglot-fsharp--installed-version)))))) + +(defun eglot-fsharp--install-w32 (version) + "Download and install the full framework version of F# compiler service at version VERSION in `eglot-fsharp-server-install-dir'." + (let* ((url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete.zip" + version)) + (exe (eglot-fsharp--path-to-server)) (zip (concat (file-name-directory exe) "fsautocomplete.zip")) (gnutls-algorithm-priority (if (and (not gnutls-algorithm-priority) @@ -117,8 +119,8 @@ (>= libgnutls-version 30603) (version<= emacs-version "26.2")) "NORMAL:-VERS-TLS1.3" - gnutls-algorithm-priority))) - (unless (eglot-fsharp-current-version-p) + gnutls-algorithm-priority)))) + (unless (eglot-fsharp-current-version-p) (url-copy-file url zip t) ;; FIXME: Windows (unzip preinstalled?) (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) @@ -129,21 +131,62 @@ (if (file-directory-p file) (chmod file #o755) (chmod file #o644))))) - (delete-file zip)))) + (delete-file zip))) + + +(defun eglot-fsharp--process-tool-action (response) + "Process the result of calling the dotnet tool installation returning RESPONSE code." + (if (eq response 1) + (let ((minibuffer-message-timeout 5) + (msg (format "Error installing fsautocomplete see %s" (concat default-directory "error_output.txt")) )) + (minibuffer-message msg) + (error "Failed to install dotnet tool fsautocomplete")))) + +(defun eglot-fsharp--install-core (version) + "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." + (let ((vers (eglot-fsharp--clean-version version)) + (default-directory (file-name-directory (eglot-fsharp--path-to-server)))) + (unless (eglot-fsharp-current-version-p) + (if (file-exists-p (eglot-fsharp--path-to-server)) + (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil + "error_output.txt") + nil "tool" "uninstall" + "fsautocomplete" "--tool-path" + default-directory))) + (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil "error_output.txt") nil + "tool" "install" "fsautocomplete" + "--tool-path" default-directory "--version" + vers))))) + +(defun eglot-fsharp--maybe-install () + "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." + (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) + (let* ((version (if (eq eglot-fsharp-server-version 'latest) + (eglot-fsharp--github-version) + eglot-fsharp-server-version))) + (if (eq eglot-fsharp-server-runtime 'net-core) + (eglot-fsharp--install-core version) + (eglot-fsharp--install-w32 version)))) ;;;###autoload -(defun eglot-fsharp (interactive) +(defun eglot-fsharp + (interactive) "Return `eglot' contact when FsAutoComplete is installed. Ensure FsAutoComplete is installed (when called INTERACTIVE)." - (when interactive - (eglot-fsharp--maybe-install)) + (when interactive (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) - (cons 'eglot-fsautocomplete - `(,(cond - ((eq eglot-fsharp-server-runtime 'net-core) "dotnet") - ((eq window-system 'w32) "") - (t "mono")) - ,(eglot-fsharp--path-to-server) "--background-service-enabled")))) + (let ((cmd-list (cond ((eq eglot-fsharp-server-runtime 'net-core) + `(,(eglot-fsharp--path-to-server))) + ((eq window-system 'w32) + `("" , (eglot-fsharp--path-to-server))) + (t `("mono" ,(eglot-fsharp--path-to-server))))) + (arg-list (if eglot-fsharp-server-verbose + `("--background-service-enabled" "-v") + `("--background-service-enabled") + ))) + (cons 'eglot-fsautocomplete (append cmd-list arg-list))))) + + (defclass eglot-fsautocomplete (eglot-lsp-server) () From 1b47760ceda47e7221870c5e5fbafe0ec8ca8baa Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Mon, 4 Apr 2022 20:26:57 +0200 Subject: [PATCH 051/120] Add 28.1 to build matrix --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9395e97..fc4ed61 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,6 +15,7 @@ jobs: - 26.3 - 27.1 - 27.2 + - 28.1 - snapshot steps: - uses: purcell/setup-emacs@master From 85c14dd20733cecc91cded58f3b1c1afad8a8bbe Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Mon, 4 Apr 2022 21:00:23 +0200 Subject: [PATCH 052/120] Use "dotnet tool search" to determine latest fsautocomplete version --- eglot-fsharp.el | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 542ff53..b8ab947 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -77,18 +77,10 @@ "Remove any spurious prefix from the version string VERSION." (string-trim-left version "[Vv]")) -(defun eglot-fsharp--github-version () - "Return latest fsautocomplete.exe GitHub version string." - (or eglot-fsharp--github-version - (with-temp-buffer - (condition-case err - (let ((json-object-type 'hash-table) - (url-mime-accept-string "application/json")) - (url-insert-file-contents "https://github.com/fsharp/fsautocomplete/releases/latest") - (goto-char (point-min)) - (setq eglot-fsharp--github-version (gethash "tag_name" (json-read)))) - (file-error - (warn "fsautocomplete.exe update check:: %s" (error-message-string err))))))) +(defun eglot-fsharp--latest-version () + "Return latest fsautocomplete.exe version." + (seq-some (lambda (s) (and (string-match "^Latest Version: \\(.*\\)$" s) (match-string 1 s))) + (process-lines "dotnet" "tool" "search" "fsautocomplete" "--detail"))) (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." From 04cc1be0c3fb077688032d8a596e6ec8b2769dfc Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 5 Apr 2022 17:12:45 +0200 Subject: [PATCH 053/120] Use "dotnet tool list" to determine installed version --- eglot-fsharp.el | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index b8ab947..83cd3fa 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -84,11 +84,8 @@ (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." - (when (file-exists-p (eglot-fsharp--path-to-server)) - (let* ((cmd (append (cdr (eglot-fsharp nil)) '("--version"))) - (version-line (concat (car (apply #'process-lines cmd))))) - (when (string-match "^FsAutoComplete \\([[:digit:].]+\\) " version-line) - (match-string 1 version-line))))) + (seq-some (lambda (s) (and (string-match "^fsautocomplete[[:space:]]+\\([0-9\.]*\\)[[:space:]]+" s) (match-string 1 s))) + (process-lines "dotnet" "tool" "list" "--tool-path" (file-name-directory (eglot-fsharp--path-to-server))))) (defun eglot-fsharp-current-version-p () "Return t if the installation is not outdated." From 2a8ec2b4ee69b96389adbe28902298ca4c8a8476 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 5 Apr 2022 09:57:13 +0200 Subject: [PATCH 054/120] Add macos to build matrix --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc4ed61..8b56c5b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,6 +11,7 @@ jobs: strategy: fail-fast: false matrix: + os: [ubuntu-latest, macos-latest] emacs_version: - 26.3 - 27.1 From 6a2034532f083ffd6ec3a07880c81b06c21b5280 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 5 Apr 2022 10:24:45 +0200 Subject: [PATCH 055/120] Cache eglot-fsharp--latest-version --- eglot-fsharp.el | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 83cd3fa..df5d1f6 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -71,7 +71,7 @@ "netframework/fsautocomplete.exe")))) ;; cache to prevent repetitive queries -(defvar eglot-fsharp--github-version nil "Latest fsautocomplete.exe GitHub version string.") +(defvar eglot-fsharp--latest-version nil "Latest fsautocomplete.exe version string.") (defun eglot-fsharp--clean-version (version) "Remove any spurious prefix from the version string VERSION." @@ -79,8 +79,11 @@ (defun eglot-fsharp--latest-version () "Return latest fsautocomplete.exe version." - (seq-some (lambda (s) (and (string-match "^Latest Version: \\(.*\\)$" s) (match-string 1 s))) - (process-lines "dotnet" "tool" "search" "fsautocomplete" "--detail"))) + (if eglot-fsharp--latest-version + eglot-fsharp--latest-version + (setq eglot-fsharp--latest-version + (seq-some (lambda (s) (and (string-match "^Latest Version: \\(.*\\)$" s) (match-string 1 s))) + (process-lines "dotnet" "tool" "search" "fsautocomplete" "--detail"))))) (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." @@ -91,7 +94,7 @@ "Return t if the installation is not outdated." (when (file-exists-p (eglot-fsharp--path-to-server)) (if (eq eglot-fsharp-server-version 'latest) - (equal (eglot-fsharp--clean-version (eglot-fsharp--github-version)) + (equal (eglot-fsharp--clean-version (eglot-fsharp--latest-version)) (eglot-fsharp--clean-version (eglot-fsharp--installed-version))) (equal (eglot-fsharp--clean-version eglot-fsharp-server-version) (eglot-fsharp--clean-version (eglot-fsharp--installed-version)))))) @@ -151,7 +154,7 @@ "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) (let* ((version (if (eq eglot-fsharp-server-version 'latest) - (eglot-fsharp--github-version) + (eglot-fsharp--latest-version) eglot-fsharp-server-version))) (if (eq eglot-fsharp-server-runtime 'net-core) (eglot-fsharp--install-core version) From ccf007b43c2cbe4d49a6c09c3b4de4177cceeaf7 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 5 Apr 2022 10:39:00 +0200 Subject: [PATCH 056/120] Remove obsolete function --- eglot-fsharp.el | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index df5d1f6..4de557e 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -73,10 +73,6 @@ ;; cache to prevent repetitive queries (defvar eglot-fsharp--latest-version nil "Latest fsautocomplete.exe version string.") -(defun eglot-fsharp--clean-version (version) - "Remove any spurious prefix from the version string VERSION." - (string-trim-left version "[Vv]")) - (defun eglot-fsharp--latest-version () "Return latest fsautocomplete.exe version." (if eglot-fsharp--latest-version @@ -94,10 +90,9 @@ "Return t if the installation is not outdated." (when (file-exists-p (eglot-fsharp--path-to-server)) (if (eq eglot-fsharp-server-version 'latest) - (equal (eglot-fsharp--clean-version (eglot-fsharp--latest-version)) - (eglot-fsharp--clean-version (eglot-fsharp--installed-version))) - (equal (eglot-fsharp--clean-version eglot-fsharp-server-version) - (eglot-fsharp--clean-version (eglot-fsharp--installed-version)))))) + (equal (eglot-fsharp--latest-version) + (eglot-fsharp--installed-version)) + (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) (defun eglot-fsharp--install-w32 (version) "Download and install the full framework version of F# compiler service at version VERSION in `eglot-fsharp-server-install-dir'." @@ -136,8 +131,7 @@ (defun eglot-fsharp--install-core (version) "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." - (let ((vers (eglot-fsharp--clean-version version)) - (default-directory (file-name-directory (eglot-fsharp--path-to-server)))) + (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) (unless (eglot-fsharp-current-version-p) (if (file-exists-p (eglot-fsharp--path-to-server)) (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil @@ -148,7 +142,7 @@ (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil "error_output.txt") nil "tool" "install" "fsautocomplete" "--tool-path" default-directory "--version" - vers))))) + version))))) (defun eglot-fsharp--maybe-install () "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." @@ -156,9 +150,9 @@ (let* ((version (if (eq eglot-fsharp-server-version 'latest) (eglot-fsharp--latest-version) eglot-fsharp-server-version))) - (if (eq eglot-fsharp-server-runtime 'net-core) - (eglot-fsharp--install-core version) - (eglot-fsharp--install-w32 version)))) + (if (eq eglot-fsharp-server-runtime 'net-core) + (eglot-fsharp--install-core version) + (eglot-fsharp--install-w32 version)))) ;;;###autoload (defun eglot-fsharp From 5d584b18b320258cf061be4433c4ec7be5415ebe Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 5 Apr 2022 10:51:32 +0200 Subject: [PATCH 057/120] Use latest fsautocomplete version in tests --- test/integration-tests.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/integration-tests.el b/test/integration-tests.el index 5e20f62..ec3ed53 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -28,8 +28,6 @@ (require 'eglot-fsharp) (require 'eglot-tests) -(setq eglot-fsharp-server-version "0.48.2") - (defun eglot-fsharp--sniff-diagnostics (file-name-suffix) (eglot--sniffing (:server-notifications s-notifs) (eglot--wait-for (s-notifs 20) @@ -41,7 +39,7 @@ (describe "F# LSP server" (it "Can be installed" (eglot-fsharp--maybe-install) - (expect (file-exists-p (eglot-fsharp--path-to-server)) :to-be t)) + (expect (eglot-fsharp--installed-version) :to-equal (eglot-fsharp--latest-version))) (it "shows flymake errors" (with-current-buffer (eglot--find-file-noselect "test/Test1/Error.fs") (eglot--tests-connect 10) From e2de4b0c38fefcd1150956a3053bba132db4209a Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 5 Apr 2022 12:00:01 +0200 Subject: [PATCH 058/120] Add Pervasive testfile Prevents side-effects with other integration tests --- test/Test1/Pervasive.fs | 3 +++ test/Test1/Test1.fsproj | 1 + test/integration-tests.el | 1 - 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 test/Test1/Pervasive.fs diff --git a/test/Test1/Pervasive.fs b/test/Test1/Pervasive.fs new file mode 100644 index 0000000..4fb011c --- /dev/null +++ b/test/Test1/Pervasive.fs @@ -0,0 +1,3 @@ +let printtest args = + printfn "Hello %d" 10 + 0 diff --git a/test/Test1/Test1.fsproj b/test/Test1/Test1.fsproj index 3d3561e..15ef69f 100644 --- a/test/Test1/Test1.fsproj +++ b/test/Test1/Test1.fsproj @@ -9,6 +9,7 @@ + diff --git a/test/integration-tests.el b/test/integration-tests.el index ec3ed53..84c1b84 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -66,7 +66,6 @@ (expect (looking-back "X\\.func") :to-be t))) (it "finds definition in pervasives" (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (eglot-shutdown-all) ;FIXME: Why is a restart required (eglot--tests-connect 10) (search-forward "printfn") (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") From 17866a01a24edf6728847a792a29e64e453fa3b8 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Thu, 7 Apr 2022 13:52:26 +0200 Subject: [PATCH 059/120] New test: "Can be invoked" --- test/integration-tests.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/integration-tests.el b/test/integration-tests.el index 84c1b84..2ce5884 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -40,6 +40,10 @@ (it "Can be installed" (eglot-fsharp--maybe-install) (expect (eglot-fsharp--installed-version) :to-equal (eglot-fsharp--latest-version))) + (it "Can be invoked" + ;; FIXME: Should use dotnet tool run + (expect (car (process-lines (eglot-fsharp--path-to-server) "--version")) + :to-match (rx line-start "FsAutoComplete" (1+ space) (eval (eglot-fsharp--installed-version))))) (it "shows flymake errors" (with-current-buffer (eglot--find-file-noselect "test/Test1/Error.fs") (eglot--tests-connect 10) From 737c9347f3c7ccf2d56c345b2841c6c26e33a244 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Thu, 7 Apr 2022 14:31:51 +0200 Subject: [PATCH 060/120] setup-dotnet: Use explicit dotnet version --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8b56c5b..006ca3d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] + dotnet: [6.0.200] emacs_version: - 26.3 - 27.1 @@ -23,6 +24,8 @@ jobs: with: version: ${{ matrix.emacs_version }} - uses: actions/setup-dotnet@v1 + with: + dotnet-version: ${{ matrix.dotnet }} - uses: actions/checkout@v2 - uses: conao3/setup-cask@master - name: Show dotnet sdks From 2ef572ff52d5b245ca26505c3e12b7d356b23ffc Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Thu, 7 Apr 2022 14:56:49 +0200 Subject: [PATCH 061/120] Remove support for Emacs 26.3 --- .github/workflows/test.yml | 1 - eglot-fsharp.el | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 006ca3d..c04d1e6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,6 @@ jobs: os: [ubuntu-latest, macos-latest] dotnet: [6.0.200] emacs_version: - - 26.3 - 27.1 - 27.2 - 28.1 diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 4de557e..e6ff8c9 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2019-2021 Jürgen Hötzel ;; Author: Jürgen Hötzel -;; Package-Requires: ((emacs "26.3") (eglot "1.4") (fsharp-mode "1.10") (jsonrpc "1.0.14")) +;; Package-Requires: ((emacs "27.1") (eglot "1.4") (fsharp-mode "1.10") (jsonrpc "1.0.14")) ;; Version: 1.10 ;; Keywords: languages ;; URL: https://github.com/fsharp/emacs-fsharp-mode From e52e71a7144f973d8d48cc5afc57f5a2f1cfcc99 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Thu, 7 Apr 2022 15:43:25 +0200 Subject: [PATCH 062/120] Update Docs --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index 93a1b09..4983d8b 100644 --- a/README.org +++ b/README.org @@ -19,7 +19,7 @@ The current version of =fsharp-mode= installs =fsautocomplete.exe= automatically via =eglot-fsharp.el= (part of this mono repo, [[https://melpa.org/#/eglot-fsharp][eglot-fsharp on melpa]]) or [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] (untested). -=fsharp-mode= is tested with Emacs 26.1+ and NET Core 2.1 (LTS) +=fsharp-mode= is tested with Emacs 27.1+ and NET Core 6 (LTS) ** Installation From ee2440c93b718481ba2b8e025b70654900487fd8 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 8 Apr 2022 15:15:17 +0200 Subject: [PATCH 063/120] Remove unused dependency --- fsharp-mode.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fsharp-mode.el b/fsharp-mode.el index c8e0153..54e6697 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -5,9 +5,9 @@ ;; Author: 1993-1997 Xavier Leroy, Jacques Garrigue and Ian T Zimmerman ;; 2010-2011 Laurent Le Brun ;; 2012-2014 Robin Neatherway -;; 2017-2021 Jürgen Hötzel +;; 2017-2022 Jürgen Hötzel ;; Maintainer: Jürgen Hötzel -;; Package-Requires: ((emacs "25") (s "1.3.1")) +;; Package-Requires: ((emacs "25")) ;; Keywords: languages ;; Version: 1.11-snapshot From 73fc04979707b7ea42c1b756579c94b735790eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 9 Apr 2022 20:06:46 +0200 Subject: [PATCH 064/120] Use C-locale when interacting with "dotnet search" Prevent parsing failures when using non-C-locales --- eglot-fsharp.el | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index e6ff8c9..9890528 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -75,11 +75,12 @@ (defun eglot-fsharp--latest-version () "Return latest fsautocomplete.exe version." - (if eglot-fsharp--latest-version - eglot-fsharp--latest-version - (setq eglot-fsharp--latest-version - (seq-some (lambda (s) (and (string-match "^Latest Version: \\(.*\\)$" s) (match-string 1 s))) - (process-lines "dotnet" "tool" "search" "fsautocomplete" "--detail"))))) + (let ((process-environment (cons "LANG=C" process-environment))) ;FIXME: Does this work in Windows + (if eglot-fsharp--latest-version + eglot-fsharp--latest-version + (setq eglot-fsharp--latest-version + (seq-some (lambda (s) (and (string-match "^Latest Version: \\(.*\\)$" s) (match-string 1 s))) + (process-lines "dotnet" "tool" "search" "fsautocomplete" "--detail")))))) (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." From e440709635b939f47e4e4bb9e8ba3460e6d09f89 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sat, 23 Apr 2022 14:49:23 +0200 Subject: [PATCH 065/120] `fsharp-mode-project-root`: Don't traverse filesystem twice Use improved regex. --- fsharp-mode.el | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/fsharp-mode.el b/fsharp-mode.el index 54e6697..8d25a25 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -347,15 +347,7 @@ whole string." (defun fsharp-mode/find-sln-or-fsproj (dir-or-file) "Search for a solution or F# project file in any enclosing folders relative to DIR-OR-FILE." - (or (fsharp-mode/find-sln dir-or-file) - (fsharp-mode/find-fsproj dir-or-file))) - -(defun fsharp-mode/find-sln (dir-or-file) - (fsharp-mode-search-upwards (rx (0+ nonl) ".sln" eol) - (file-name-directory dir-or-file))) - -(defun fsharp-mode/find-fsproj (dir-or-file) - (fsharp-mode-search-upwards (rx (0+ nonl) ".fsproj" eol) + (fsharp-mode-search-upwards (rx (0+ nonl) (or ".fsproj" ".sln") eol) (file-name-directory dir-or-file))) (defun fsharp-mode-search-upwards (regex dir) From e079429ac3cd94fa01b943b970f72ecb4d5bf955 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sat, 23 Apr 2022 15:10:58 +0200 Subject: [PATCH 066/120] Fix CI: New versions of fsautocomplete.exe changed version output --- test/integration-tests.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration-tests.el b/test/integration-tests.el index 2ce5884..666707b 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -43,7 +43,7 @@ (it "Can be invoked" ;; FIXME: Should use dotnet tool run (expect (car (process-lines (eglot-fsharp--path-to-server) "--version")) - :to-match (rx line-start "FsAutoComplete" (1+ space) (eval (eglot-fsharp--installed-version))))) + :to-match (rx line-start (? "FsAutoComplete" (1+ space)) (eval (eglot-fsharp--installed-version))))) (it "shows flymake errors" (with-current-buffer (eglot--find-file-noselect "test/Test1/Error.fs") (eglot--tests-connect 10) From 82ab2164bb407511ed366aac54bf37a310fc052a Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Thu, 28 Apr 2022 19:53:52 -0300 Subject: [PATCH 067/120] fix: adds match! as a valid keyword --- fsharp-mode-font.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el index 648e90d..c9c4770 100644 --- a/fsharp-mode-font.el +++ b/fsharp-mode-font.el @@ -242,7 +242,7 @@ with initial value INITVALUE and optional DOCSTRING." "exception" "extern" "false" "finally" "for" "fun" "function" "global" "if" "in" "inherit" "inline" "interface" "internal" "lazy" "let" "let!" - "match" "member" "module" "mutable" "namespace" + "match" "match!" "member" "module" "mutable" "namespace" "new" "not" "null" "of" "open" "or" "override" "private" "public" "rec" "return" "return!" "select" "static" "struct" "then" "to" "true" From bf6b76981c7c2e362c75a818512ef78fee41bb96 Mon Sep 17 00:00:00 2001 From: Florian Biermann Date: Mon, 30 May 2022 11:12:18 +0100 Subject: [PATCH 068/120] Use fsautocomplete.exe on Windows --- eglot-fsharp.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 9890528..dd72af2 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -67,7 +67,7 @@ "Return FsAutoComplete path." (file-truename (concat eglot-fsharp-server-install-dir (if (eq eglot-fsharp-server-runtime 'net-core) - "netcore/fsautocomplete" + (concat "netcore/fsautocomplete" (if (eq system-type 'windows-nt) ".exe" "")) "netframework/fsautocomplete.exe")))) ;; cache to prevent repetitive queries From e1fd9f222b6b0d78237417a996053dd30d2e1406 Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Tue, 31 May 2022 22:57:25 -0300 Subject: [PATCH 069/120] add: applicative keyword on highlight --- fsharp-mode-font.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el index c9c4770..698f65e 100644 --- a/fsharp-mode-font.el +++ b/fsharp-mode-font.el @@ -236,7 +236,7 @@ with initial value INITVALUE and optional DOCSTRING." ;; F# keywords (3.4) (def-fsharp-compiled-var fsharp-ui-fsharp-threefour-keywords - '("abstract" "and" "as" "assert" "base" "begin" + '("abstract" "and" "and!" "as" "assert" "base" "begin" "class" "default" "delegate" "do" "do!" "done" "downcast" "downto" "elif" "else" "end" "exception" "extern" "false" "finally" "for" "fun" From 8881451d9675a17d530f6516f892dae803d84b9f Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 1 Jun 2022 19:38:41 +0200 Subject: [PATCH 070/120] Update Keywords to F# 5.0 --- fsharp-mode-font.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el index 698f65e..945d148 100644 --- a/fsharp-mode-font.el +++ b/fsharp-mode-font.el @@ -234,7 +234,7 @@ with initial value INITVALUE and optional DOCSTRING." (def-fsharp-compiled-var fsharp-ui-identifier-replacements '("__SOURCE_DIRECTORY__" "__SOURCE_FILE__" "__LINE__")) -;; F# keywords (3.4) +;; F# keywords (5.0) (def-fsharp-compiled-var fsharp-ui-fsharp-threefour-keywords '("abstract" "and" "and!" "as" "assert" "base" "begin" "class" "default" "delegate" "do" "do!" "done" From a2903e6bc28602f3af1b836b61f41bec64bd85b0 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 1 Jun 2022 21:03:51 +0200 Subject: [PATCH 071/120] Generalize version string match LANG=C workaround doesn't work on Windows --- eglot-fsharp.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index dd72af2..3c4ace8 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -75,11 +75,11 @@ (defun eglot-fsharp--latest-version () "Return latest fsautocomplete.exe version." - (let ((process-environment (cons "LANG=C" process-environment))) ;FIXME: Does this work in Windows + (let ((process-environment (cons "LANG=C" process-environment))) ;FIXME: Doesn't work in Windows (if eglot-fsharp--latest-version eglot-fsharp--latest-version (setq eglot-fsharp--latest-version - (seq-some (lambda (s) (and (string-match "^Latest Version: \\(.*\\)$" s) (match-string 1 s))) + (seq-some (lambda (s) (and (string-match "^[[:alnum:]]* Version: \\(.*\\)$" s) (match-string 1 s))) (process-lines "dotnet" "tool" "search" "fsautocomplete" "--detail")))))) (defun eglot-fsharp--installed-version () From 7be32c00e8d8aee3ed40a756f974800b4e20ab62 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sat, 4 Jun 2022 14:26:12 +0200 Subject: [PATCH 072/120] Also install specific version in integration tests Refs #297 --- eglot-fsharp.el | 16 ++++++++-------- test/integration-tests.el | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 3c4ace8..eb6a0d9 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -87,10 +87,10 @@ (seq-some (lambda (s) (and (string-match "^fsautocomplete[[:space:]]+\\([0-9\.]*\\)[[:space:]]+" s) (match-string 1 s))) (process-lines "dotnet" "tool" "list" "--tool-path" (file-name-directory (eglot-fsharp--path-to-server))))) -(defun eglot-fsharp-current-version-p () +(defun eglot-fsharp-current-version-p (version) "Return t if the installation is not outdated." (when (file-exists-p (eglot-fsharp--path-to-server)) - (if (eq eglot-fsharp-server-version 'latest) + (if (eq version 'latest) (equal (eglot-fsharp--latest-version) (eglot-fsharp--installed-version)) (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) @@ -108,7 +108,7 @@ (version<= emacs-version "26.2")) "NORMAL:-VERS-TLS1.3" gnutls-algorithm-priority)))) - (unless (eglot-fsharp-current-version-p) + (unless (eglot-fsharp-current-version-p version) (url-copy-file url zip t) ;; FIXME: Windows (unzip preinstalled?) (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) @@ -133,7 +133,7 @@ (defun eglot-fsharp--install-core (version) "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) - (unless (eglot-fsharp-current-version-p) + (unless (eglot-fsharp-current-version-p version) (if (file-exists-p (eglot-fsharp--path-to-server)) (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil "error_output.txt") @@ -145,12 +145,12 @@ "--tool-path" default-directory "--version" version))))) -(defun eglot-fsharp--maybe-install () +(defun eglot-fsharp--maybe-install (&optional version) "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) - (let* ((version (if (eq eglot-fsharp-server-version 'latest) - (eglot-fsharp--latest-version) - eglot-fsharp-server-version))) + (let* ((version (or version (if (eq eglot-fsharp-server-version 'latest) + (eglot-fsharp--latest-version) + eglot-fsharp-server-version)))) (if (eq eglot-fsharp-server-runtime 'net-core) (eglot-fsharp--install-core version) (eglot-fsharp--install-w32 version)))) diff --git a/test/integration-tests.el b/test/integration-tests.el index 666707b..1646876 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -37,6 +37,9 @@ (string-suffix-p file-name-suffix (plist-get params :uri)))))) (describe "F# LSP server" + (it "can be installed @version 0.52.0" + (eglot-fsharp--maybe-install "0.52.0") + (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) (it "Can be installed" (eglot-fsharp--maybe-install) (expect (eglot-fsharp--installed-version) :to-equal (eglot-fsharp--latest-version))) From c4bdaca0a45e6678737b050ea740d7e0df179888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 5 Jun 2022 15:18:06 +0200 Subject: [PATCH 073/120] Enforce code style via .dir-locals.el --- .dir-locals.el | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .dir-locals.el diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..f4b5d5e --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,5 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((emacs-lisp-mode . ((indent-tabs-mode . nil) + (fill-column . 120)))) From e1a9aa2916410f9d7050b12728419f38fb928774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 5 Jun 2022 15:22:48 +0200 Subject: [PATCH 074/120] .gitignore: Ignore Emacs backup files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f6d7269..954af47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.elc bin tmp +*~ # Useful for doing releases emacs-fsharp-mode-bin/ From 5ff264a25c75fb9fd1c42295fda93dddc76b4624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 5 Jun 2022 15:23:23 +0200 Subject: [PATCH 075/120] Reindent all files using .dir-locals.el setup --- eglot-fsharp.el | 26 +- fsharp-mode-font.el | 214 ++++++++-------- test/fsharp-mode-font-tests.el | 28 +-- test/fsharp-mode-structure-tests.el | 370 ++++++++++++++-------------- test/integration-tests.el | 110 +++++---- 5 files changed, 375 insertions(+), 373 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index eb6a0d9..30ab7e1 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -108,18 +108,18 @@ (version<= emacs-version "26.2")) "NORMAL:-VERS-TLS1.3" gnutls-algorithm-priority)))) - (unless (eglot-fsharp-current-version-p version) - (url-copy-file url zip t) - ;; FIXME: Windows (unzip preinstalled?) - (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) - (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) - (error "Failed to unzip %s" zip)) - (unless (eq system-type 'windows-nt) - (dolist (file (directory-files-recursively (file-name-directory (eglot-fsharp--path-to-server)) "." t)) - (if (file-directory-p file) - (chmod file #o755) - (chmod file #o644))))) - (delete-file zip))) + (unless (eglot-fsharp-current-version-p version) + (url-copy-file url zip t) + ;; FIXME: Windows (unzip preinstalled?) + (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) + (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) + (error "Failed to unzip %s" zip)) + (unless (eq system-type 'windows-nt) + (dolist (file (directory-files-recursively (file-name-directory (eglot-fsharp--path-to-server)) "." t)) + (if (file-directory-p file) + (chmod file #o755) + (chmod file #o644))))) + (delete-file zip))) (defun eglot-fsharp--process-tool-action (response) @@ -169,7 +169,7 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (t `("mono" ,(eglot-fsharp--path-to-server))))) (arg-list (if eglot-fsharp-server-verbose `("--background-service-enabled" "-v") - `("--background-service-enabled") + `("--background-service-enabled") ))) (cons 'eglot-fsautocomplete (append cmd-list arg-list))))) diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el index 945d148..0af65b2 100644 --- a/fsharp-mode-font.el +++ b/fsharp-mode-font.el @@ -61,97 +61,97 @@ with initial value INITVALUE and optional DOCSTRING." (defvar ,sym ,init ,docstring))) (def-fsharp-compiled-var fsharp-shebang-regexp - "\\(^#!.*?\\)\\([A-Za-z0-9_-]+\\)$" - "Capture the #! and path of a shebag in one group and the + "\\(^#!.*?\\)\\([A-Za-z0-9_-]+\\)$" + "Capture the #! and path of a shebag in one group and the executable in another.") (def-fsharp-compiled-var fsharp-access-control-regexp - "private\\s-+\\|internal\\s-+\\|public\\s-+" - "Match `private', `internal', or `public', followed by a space, + "private\\s-+\\|internal\\s-+\\|public\\s-+" + "Match `private', `internal', or `public', followed by a space, with no capture.") (def-fsharp-compiled-var fsharp-access-control-regexp-noncapturing - (format "\\(?:%s\\)" fsharp-access-control-regexp) - "Same as `fsharp-access-control-regexp', but captures") + (format "\\(?:%s\\)" fsharp-access-control-regexp) + "Same as `fsharp-access-control-regexp', but captures") (def-fsharp-compiled-var fsharp-inline-rec-regexp - "inline\\s-+\\|rec\\s-+" - "Match `inline' or `rec', followed by a space.") + "inline\\s-+\\|rec\\s-+" + "Match `inline' or `rec', followed by a space.") (def-fsharp-compiled-var fsharp-inline-rec-regexp-noncapturing - (format "\\(?:%s\\)" fsharp-inline-rec-regexp) - "Match `inline' or `rec', followed by a space, with no capture.") + (format "\\(?:%s\\)" fsharp-inline-rec-regexp) + "Match `inline' or `rec', followed by a space, with no capture.") (def-fsharp-compiled-var fsharp-valid-identifier-regexp - "[A-Za-z0-9_']+" - "Match a normal, valid F# identifier -- alphanumeric characters + "[A-Za-z0-9_']+" + "Match a normal, valid F# identifier -- alphanumeric characters plus ' and underbar. Does not capture") (def-fsharp-compiled-var fsharp-function-def-regexp - (concat "\\<\\(?:let\\|and\\|with\\)\\s-+" - fsharp-inline-rec-regexp-noncapturing "?" - fsharp-access-control-regexp-noncapturing "*" - (format "\\(%s\\)" fsharp-valid-identifier-regexp) - "\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)" ;; matches function arguments or open-paren; unclear why 0-9 not in class - )) + (concat "\\<\\(?:let\\|and\\|with\\)\\s-+" + fsharp-inline-rec-regexp-noncapturing "?" + fsharp-access-control-regexp-noncapturing "*" + (format "\\(%s\\)" fsharp-valid-identifier-regexp) + "\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)" ;; matches function arguments or open-paren; unclear why 0-9 not in class + )) (def-fsharp-compiled-var fsharp-pattern-function-regexp - (concat "\\<\\(?:let\\|and\\)\\s-+" - fsharp-inline-rec-regexp-noncapturing "?" - fsharp-access-control-regexp-noncapturing "*" - (format "\\(%s\\)" fsharp-valid-identifier-regexp) - "\\s-*=\\s-*function") - "Matches an implicit matcher, eg let foo m = function | \"cat\" -> etc.") + (concat "\\<\\(?:let\\|and\\)\\s-+" + fsharp-inline-rec-regexp-noncapturing "?" + fsharp-access-control-regexp-noncapturing "*" + (format "\\(%s\\)" fsharp-valid-identifier-regexp) + "\\s-*=\\s-*function") + "Matches an implicit matcher, eg let foo m = function | \"cat\" -> etc.") ;; Note that this regexp is used for iMenu. To font-lock active patterns, we ;; need to use an anchored match in fsharp-font-lock-keywords. (def-fsharp-compiled-var fsharp-active-pattern-regexp - (concat "\\<\\(?:let\\|and\\)\\s-+" - fsharp-inline-rec-regexp-noncapturing "?" - fsharp-access-control-regexp-noncapturing "*" - "(\\(|[A-Za-z0-9_'|]+|\\))\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)")) + (concat "\\<\\(?:let\\|and\\)\\s-+" + fsharp-inline-rec-regexp-noncapturing "?" + fsharp-access-control-regexp-noncapturing "*" + "(\\(|[A-Za-z0-9_'|]+|\\))\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)")) (def-fsharp-compiled-var fsharp-member-access-regexp - "\\<\\(?:override\\|member\\|abstract\\)\\s-+" - "Matches members declarations and modifiers on classes.") + "\\<\\(?:override\\|member\\|abstract\\)\\s-+" + "Matches members declarations and modifiers on classes.") (def-fsharp-compiled-var fsharp-member-function-regexp - (concat fsharp-member-access-regexp - fsharp-inline-rec-regexp-noncapturing "?" - fsharp-access-control-regexp-noncapturing "*" - "\\(?:" fsharp-valid-identifier-regexp "\\.\\)?" - "\\(" fsharp-valid-identifier-regexp "\\)") - "Captures the final identifier in a member function declaration.") + (concat fsharp-member-access-regexp + fsharp-inline-rec-regexp-noncapturing "?" + fsharp-access-control-regexp-noncapturing "*" + "\\(?:" fsharp-valid-identifier-regexp "\\.\\)?" + "\\(" fsharp-valid-identifier-regexp "\\)") + "Captures the final identifier in a member function declaration.") (def-fsharp-compiled-var fsharp-overload-operator-regexp - (concat fsharp-member-access-regexp - fsharp-inline-rec-regexp-noncapturing "?" - fsharp-access-control-regexp-noncapturing "*" - "\\(([!%&*+-./<=>?@^|~]+)\\)") - "Match operators when overloaded by a type/class.") + (concat fsharp-member-access-regexp + fsharp-inline-rec-regexp-noncapturing "?" + fsharp-access-control-regexp-noncapturing "*" + "\\(([!%&*+-./<=>?@^|~]+)\\)") + "Match operators when overloaded by a type/class.") (def-fsharp-compiled-var fsharp-constructor-regexp - (concat "^\\s-*" - fsharp-access-control-regexp-noncapturing "*" - "\\<\\(new\\) *(.*)[^=]*=") - "Matches the `new' keyword in a constructor") + (concat "^\\s-*" + fsharp-access-control-regexp-noncapturing "*" + "\\<\\(new\\) *(.*)[^=]*=") + "Matches the `new' keyword in a constructor") (def-fsharp-compiled-var fsharp-type-def-regexp - (concat "^\\s-*\\<\\(?:type\\|inherit\\)\\s-+" - fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times - "\\([A-Za-z0-9_'.]+\\)")) + (concat "^\\s-*\\<\\(?:type\\|inherit\\)\\s-+" + fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times + "\\([A-Za-z0-9_'.]+\\)")) (def-fsharp-compiled-var fsharp-var-or-arg-regexp - "\\_<\\([A-Za-z_][A-Za-z0-9_']*\\)\\_>") + "\\_<\\([A-Za-z_][A-Za-z0-9_']*\\)\\_>") (def-fsharp-compiled-var fsharp-explicit-field-regexp - (concat "^\\s-*\\(?:val\\|abstract\\)\\s-*\\(?:mutable\\s-+\\)?" - fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times - "\\([A-Za-z_][A-Za-z0-9_']*\\)\\s-*:\\s-*\\([A-Za-z_][A-Za-z0-9_'<> \t]*\\)")) + (concat "^\\s-*\\(?:val\\|abstract\\)\\s-*\\(?:mutable\\s-+\\)?" + fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times + "\\([A-Za-z_][A-Za-z0-9_']*\\)\\s-*:\\s-*\\([A-Za-z_][A-Za-z0-9_'<> \t]*\\)")) (def-fsharp-compiled-var fsharp-attributes-regexp - "\\(\\[<[A-Za-z0-9_]+[( ]?\\)\\(\".*\"\\)?\\()?>\\]\\)" - "Match attributes like []; separately groups contained strings in attributes like []") + "\\(\\[<[A-Za-z0-9_]+[( ]?\\)\\(\".*\"\\)?\\()?>\\]\\)" + "Match attributes like []; separately groups contained strings in attributes like []") ;; F# makes extensive use of operators, many of which have some kind of ;; structural significance. @@ -164,27 +164,27 @@ with initial value INITVALUE and optional DOCSTRING." ;; | -- match / type expressions (def-fsharp-compiled-var fsharp-operator-quote-regexp - "\\(<@\\{1,2\\}\\)\\(?:.*\\)\\(@\\{1,2\\}>\\)" - "Font lock <@/<@@ and @>/@@> operators.") + "\\(<@\\{1,2\\}\\)\\(?:.*\\)\\(@\\{1,2\\}>\\)" + "Font lock <@/<@@ and @>/@@> operators.") (def-fsharp-compiled-var fsharp-operator-pipe-regexp - "<|\\{1,3\\}\\||\\{1,3\\}>" - "Match the full range of pipe operators -- |>, ||>, |||>, etc.") + "<|\\{1,3\\}\\||\\{1,3\\}>" + "Match the full range of pipe operators -- |>, ||>, |||>, etc.") (def-fsharp-compiled-var fsharp-custom-operator-with-pipe-regexp - (let ((op-chars "!%&\\*\\+\\-\\./<=>@\\^~") ;; all F# custom operator chars except for `|` - (backward-pipe "<|\\{1,3\\}") - (forward-pipe "|\\{1,3\\}>") - (alt "\\|")) - (concat "[" op-chars "|]*" backward-pipe "[" op-chars "]+" - alt "[" op-chars "|]+" backward-pipe "[" op-chars "]*" - alt "[" op-chars "]*" forward-pipe "[" op-chars "|]+" - alt "[" op-chars "]+" forward-pipe "[" op-chars "|]*")) - "Match operators that contains pipe sequence -- <|>, |>>, <<|, etc.") + (let ((op-chars "!%&\\*\\+\\-\\./<=>@\\^~") ;; all F# custom operator chars except for `|` + (backward-pipe "<|\\{1,3\\}") + (forward-pipe "|\\{1,3\\}>") + (alt "\\|")) + (concat "[" op-chars "|]*" backward-pipe "[" op-chars "]+" + alt "[" op-chars "|]+" backward-pipe "[" op-chars "]*" + alt "[" op-chars "]*" forward-pipe "[" op-chars "|]+" + alt "[" op-chars "]+" forward-pipe "[" op-chars "|]*")) + "Match operators that contains pipe sequence -- <|>, |>>, <<|, etc.") (def-fsharp-compiled-var fsharp-operator-case-regexp - "\\s-+\\(|\\)[A-Za-z0-9_' ]" - "Match literal | in contexts like match and type declarations.") + "\\s-+\\(|\\)[A-Za-z0-9_' ]" + "Match literal | in contexts like match and type declarations.") (defvar fsharp-imenu-generic-expression `((nil ,(concat "^\\s-*" fsharp-function-def-regexp) 1) @@ -215,52 +215,52 @@ with initial value INITVALUE and optional DOCSTRING." ;; Preprocessor directives (3.3) (def-fsharp-compiled-var fsharp-ui-preproessor-directives - '("#if" "#else" "#endif" "#light")) + '("#if" "#else" "#endif" "#light")) ;; Compiler directives (12.4) (def-fsharp-compiled-var fsharp-ui-compiler-directives - '("#nowarn" "#load" "#r" "#reference" "#I" - "#Include" "#q" "#quit" "#time" "#help")) + '("#nowarn" "#load" "#r" "#reference" "#I" + "#Include" "#q" "#quit" "#time" "#help")) ;; Lexical matters (18.4) (def-fsharp-compiled-var fsharp-ui-lexical-matters - '("#indent")) + '("#indent")) ;; Line Directives (3.9) (def-fsharp-compiled-var fsharp-ui-line-directives - '("#line")) + '("#line")) ;; Identifier replacements (3.11) (def-fsharp-compiled-var fsharp-ui-identifier-replacements - '("__SOURCE_DIRECTORY__" "__SOURCE_FILE__" "__LINE__")) + '("__SOURCE_DIRECTORY__" "__SOURCE_FILE__" "__LINE__")) ;; F# keywords (5.0) (def-fsharp-compiled-var fsharp-ui-fsharp-threefour-keywords - '("abstract" "and" "and!" "as" "assert" "base" "begin" - "class" "default" "delegate" "do" "do!" "done" - "downcast" "downto" "elif" "else" "end" - "exception" "extern" "false" "finally" "for" "fun" - "function" "global" "if" "in" "inherit" "inline" - "interface" "internal" "lazy" "let" "let!" - "match" "match!" "member" "module" "mutable" "namespace" - "new" "not" "null" "of" "open" "or" "override" - "private" "public" "rec" "return" "return!" - "select" "static" "struct" "then" "to" "true" - "try" "type" "upcast" "use" "use!" "val" "void" - "when" "while" "with" "yield" "yield!")) + '("abstract" "and" "and!" "as" "assert" "base" "begin" + "class" "default" "delegate" "do" "do!" "done" + "downcast" "downto" "elif" "else" "end" + "exception" "extern" "false" "finally" "for" "fun" + "function" "global" "if" "in" "inherit" "inline" + "interface" "internal" "lazy" "let" "let!" + "match" "match!" "member" "module" "mutable" "namespace" + "new" "not" "null" "of" "open" "or" "override" + "private" "public" "rec" "return" "return!" + "select" "static" "struct" "then" "to" "true" + "try" "type" "upcast" "use" "use!" "val" "void" + "when" "while" "with" "yield" "yield!")) ;; "Reserved because they are reserved in OCaml" (def-fsharp-compiled-var fsharp-ui-ocaml-reserved-words - '("asr" "land" "lor" "lsl" "lsr" "lxor" "mod" "sig")) + '("asr" "land" "lor" "lsl" "lsr" "lxor" "mod" "sig")) ;; F# reserved words for future use (def-fsharp-compiled-var fsharp-ui-reserved-words - '("atomic" "break" "checked" "component" "const" - "constraint" "constructor" "continue" "eager" - "event" "external" "fixed" "functor" "include" - "method" "mixin" "object" "parallel" "process" - "protected" "pure" "sealed" "tailcall" "trait" - "virtual" "volatile")) + '("atomic" "break" "checked" "component" "const" + "constraint" "constructor" "continue" "eager" + "event" "external" "fixed" "functor" "include" + "method" "mixin" "object" "parallel" "process" + "protected" "pure" "sealed" "tailcall" "trait" + "virtual" "volatile")) ;; RMD 2016-09-30 -- This was pulled out separately with the following comment ;; when I got here. Not clear to me why it's on it's own, or even precisely what @@ -270,21 +270,21 @@ with initial value INITVALUE and optional DOCSTRING." ;; Workflows not yet handled by fsautocomplete but async ;; always present (def-fsharp-compiled-var fsharp-ui-async-words - '("async") - "Just the word async, in a list.") + '("async") + "Just the word async, in a list.") (def-fsharp-compiled-var fsharp-ui-word-list-regexp - (regexp-opt - `(,@fsharp-ui-async-words - ,@fsharp-ui-compiler-directives - ,@fsharp-ui-fsharp-threefour-keywords - ,@fsharp-ui-identifier-replacements - ,@fsharp-ui-lexical-matters - ,@fsharp-ui-ocaml-reserved-words - ,@fsharp-ui-preproessor-directives - ,@fsharp-ui-reserved-words - ,@fsharp-ui-line-directives) - 'symbols)) + (regexp-opt + `(,@fsharp-ui-async-words + ,@fsharp-ui-compiler-directives + ,@fsharp-ui-fsharp-threefour-keywords + ,@fsharp-ui-identifier-replacements + ,@fsharp-ui-lexical-matters + ,@fsharp-ui-ocaml-reserved-words + ,@fsharp-ui-preproessor-directives + ,@fsharp-ui-reserved-words + ,@fsharp-ui-line-directives) + 'symbols)) (defconst fsharp-font-lock-keywords (eval-when-compile diff --git a/test/fsharp-mode-font-tests.el b/test/fsharp-mode-font-tests.el index 55397f4..55eb423 100644 --- a/test/fsharp-mode-font-tests.el +++ b/test/fsharp-mode-font-tests.el @@ -24,19 +24,19 @@ then run BODY." (face-at-point)) (describe "When locking operators" - (it "uses ui operator face for pipes" - (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" - (should (equal (str-face " |> ") 'fsharp-ui-operator-face)) - (should (equal (str-face " ||> ") 'fsharp-ui-operator-face)) - (should (equal (str-face " |||> ") 'fsharp-ui-operator-face)) - (should (equal (str-face " <| ") 'fsharp-ui-operator-face)) - (should (equal (str-face " <|| ") 'fsharp-ui-operator-face)) - (should (equal (str-face " <||| ") 'fsharp-ui-operator-face))))) + (it "uses ui operator face for pipes" + (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" + (should (equal (str-face " |> ") 'fsharp-ui-operator-face)) + (should (equal (str-face " ||> ") 'fsharp-ui-operator-face)) + (should (equal (str-face " |||> ") 'fsharp-ui-operator-face)) + (should (equal (str-face " <| ") 'fsharp-ui-operator-face)) + (should (equal (str-face " <|| ") 'fsharp-ui-operator-face)) + (should (equal (str-face " <||| ") 'fsharp-ui-operator-face))))) (describe "When locking operators" - (it "uses ui generic face for custom operators containing pipes" - (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" - (should (equal (str-face "<<| ") 'fsharp-ui-generic-face)) - (should (equal (str-face " |>> ") 'fsharp-ui-generic-face)) - (should (equal (str-face " <|> ") 'fsharp-ui-generic-face)) - (should (equal (str-face " <<|!") 'fsharp-ui-generic-face))))) + (it "uses ui generic face for custom operators containing pipes" + (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!" + (should (equal (str-face "<<| ") 'fsharp-ui-generic-face)) + (should (equal (str-face " |>> ") 'fsharp-ui-generic-face)) + (should (equal (str-face " <|> ") 'fsharp-ui-generic-face)) + (should (equal (str-face " <<|!") 'fsharp-ui-generic-face))))) diff --git a/test/fsharp-mode-structure-tests.el b/test/fsharp-mode-structure-tests.el index a5b9da1..dd6653b 100644 --- a/test/fsharp-mode-structure-tests.el +++ b/test/fsharp-mode-structure-tests.el @@ -53,46 +53,46 @@ ;;-------------------------------- Predicates --------------------------------;; (describe "The `fsharp-backslash-continuation-line-p' predicate" - (it "returns true when we expect it to" - (let ((file (file-truename (concat fsharp-struct-test-files-dir "ContinuationLines.fs")))) - (with-current-buffer (find-file-noselect file) - (beginning-of-buffer) - (should (eq (fsharp--hanging-operator-continuation-line-p) nil)) - (forward-line 1) - (should (eq (fsharp--hanging-operator-continuation-line-p) nil)) - (forward-line 5) - (should (eq (fsharp--hanging-operator-continuation-line-p) t)))))) + (it "returns true when we expect it to" + (let ((file (file-truename (concat fsharp-struct-test-files-dir "ContinuationLines.fs")))) + (with-current-buffer (find-file-noselect file) + (beginning-of-buffer) + (should (eq (fsharp--hanging-operator-continuation-line-p) nil)) + (forward-line 1) + (should (eq (fsharp--hanging-operator-continuation-line-p) nil)) + (forward-line 5) + (should (eq (fsharp--hanging-operator-continuation-line-p) t)))))) (describe "The `fsharp-in-literal-p'" - (it "return non-nil in both strings and comments?" - (let ((literals-file (file-truename (concat fsharp-struct-test-files-dir "Literals.fs")))) - (with-current-buffer (find-file-noselect literals-file) - ;; Comments - (goto-char 3) - (should (eq (fsharp-in-literal-p) 'comment)) - (goto-char 642) - (should (eq (fsharp-in-literal-p) 'comment)) - (goto-char 968) - (should (eq (fsharp-in-literal-p) 'comment)) - (goto-char 1481) - (should (eq (fsharp-in-literal-p) 'comment)) - (goto-char 2124) - (should (eq (fsharp-in-literal-p) 'comment)) - ;; String literals - (goto-char 2717) - (should (eq (fsharp-in-literal-p) 'string)) - ;; This string contains an inner, backslash-escaped string. - ;; First, with point outside the backslash-escaped string: - (goto-char 2759) - (should (eq (fsharp-in-literal-p) 'string)) - ;; ...and now with point inside it - (goto-char 2774) - (should (eq (fsharp-in-literal-p) 'string)) - ;; Inside triple-quoted strings - (goto-char 2835) - (should (eq (fsharp-in-literal-p) 'string)) - (goto-char 2900) - (should (eq (fsharp-in-literal-p) 'string)))))) + (it "return non-nil in both strings and comments?" + (let ((literals-file (file-truename (concat fsharp-struct-test-files-dir "Literals.fs")))) + (with-current-buffer (find-file-noselect literals-file) + ;; Comments + (goto-char 3) + (should (eq (fsharp-in-literal-p) 'comment)) + (goto-char 642) + (should (eq (fsharp-in-literal-p) 'comment)) + (goto-char 968) + (should (eq (fsharp-in-literal-p) 'comment)) + (goto-char 1481) + (should (eq (fsharp-in-literal-p) 'comment)) + (goto-char 2124) + (should (eq (fsharp-in-literal-p) 'comment)) + ;; String literals + (goto-char 2717) + (should (eq (fsharp-in-literal-p) 'string)) + ;; This string contains an inner, backslash-escaped string. + ;; First, with point outside the backslash-escaped string: + (goto-char 2759) + (should (eq (fsharp-in-literal-p) 'string)) + ;; ...and now with point inside it + (goto-char 2774) + (should (eq (fsharp-in-literal-p) 'string)) + ;; Inside triple-quoted strings + (goto-char 2835) + (should (eq (fsharp-in-literal-p) 'string)) + (goto-char 2900) + (should (eq (fsharp-in-literal-p) 'string)))))) ;; NOTE[gastove|2019-10-31] I am entirely convinced this doesn't work precisely ;; as it should, because it depends on `fsharp-goto-beyond-final-line', which I @@ -113,161 +113,161 @@ ;;--------------------- Nesting and Indentation Functions ---------------------;; (describe "The `fsharp-nesting-level' function" - (it "returns nil when we expect it to" - (with-temp-buffer - (insert "let x = 5") - (end-of-buffer) - (should (eq (fsharp-nesting-level) nil))))) + (it "returns nil when we expect it to" + (with-temp-buffer + (insert "let x = 5") + (end-of-buffer) + (should (eq (fsharp-nesting-level) nil))))) (describe "The `fsharp-nesting-level' function" - :var ((file (file-truename (concat fsharp-struct-test-files-dir "Nesting.fs")))) - (it "correctly return the point position of the opening pair closest to point" - ;; The character positions use here reference characters noted in comments in Nesting.fs - ;; Test a normal list - (with-current-buffer (find-file-noselect file) - (goto-char 645) - (should (eq (fsharp-nesting-level) 640))) - - ;; Get the opening bracket of an inner list from a single-line nested list - (with-current-buffer (find-file-noselect file) - (goto-char 717) - (should (eq (fsharp-nesting-level) 706))) - - ;; Opening bracket for a multi-line non-nested list - (with-current-buffer (find-file-noselect file) - (goto-char 795) - (should (eq (fsharp-nesting-level) 777))) - - ;; Inner most opening bracket for a multi-line multi-nested list - (with-current-buffer (find-file-noselect file) - (goto-char 960) - (should (eq (fsharp-nesting-level) 955))) - ;; Middle opening bracket for same list as previous - (with-current-buffer (find-file-noselect file) - (goto-char 954) - (should (eq (fsharp-nesting-level) 953))) - (with-current-buffer (find-file-noselect file) - (goto-char 974) - (should (eq (fsharp-nesting-level) 953))) - ;; Outermost opening bracket for same list - (with-current-buffer (find-file-noselect file) - (goto-char 977) - (should (eq (fsharp-nesting-level) 947))) - - ;; Basic Async form, should return the opening { - (with-current-buffer (find-file-noselect file) - (goto-char 1088) - (should (eq (fsharp-nesting-level) 1060))) - ;; Same async form, inner async call - (with-current-buffer (find-file-noselect file) - (goto-char 1129) - (should (eq (fsharp-nesting-level) 1121))) - - ;; Lambda, wrapped in parens, should return the opening ( - (with-current-buffer (find-file-noselect file) - (goto-char 1238) - (should (eq (fsharp-nesting-level) 1208))))) + :var ((file (file-truename (concat fsharp-struct-test-files-dir "Nesting.fs")))) + (it "correctly return the point position of the opening pair closest to point" + ;; The character positions use here reference characters noted in comments in Nesting.fs + ;; Test a normal list + (with-current-buffer (find-file-noselect file) + (goto-char 645) + (should (eq (fsharp-nesting-level) 640))) + + ;; Get the opening bracket of an inner list from a single-line nested list + (with-current-buffer (find-file-noselect file) + (goto-char 717) + (should (eq (fsharp-nesting-level) 706))) + + ;; Opening bracket for a multi-line non-nested list + (with-current-buffer (find-file-noselect file) + (goto-char 795) + (should (eq (fsharp-nesting-level) 777))) + + ;; Inner most opening bracket for a multi-line multi-nested list + (with-current-buffer (find-file-noselect file) + (goto-char 960) + (should (eq (fsharp-nesting-level) 955))) + ;; Middle opening bracket for same list as previous + (with-current-buffer (find-file-noselect file) + (goto-char 954) + (should (eq (fsharp-nesting-level) 953))) + (with-current-buffer (find-file-noselect file) + (goto-char 974) + (should (eq (fsharp-nesting-level) 953))) + ;; Outermost opening bracket for same list + (with-current-buffer (find-file-noselect file) + (goto-char 977) + (should (eq (fsharp-nesting-level) 947))) + + ;; Basic Async form, should return the opening { + (with-current-buffer (find-file-noselect file) + (goto-char 1088) + (should (eq (fsharp-nesting-level) 1060))) + ;; Same async form, inner async call + (with-current-buffer (find-file-noselect file) + (goto-char 1129) + (should (eq (fsharp-nesting-level) 1121))) + + ;; Lambda, wrapped in parens, should return the opening ( + (with-current-buffer (find-file-noselect file) + (goto-char 1238) + (should (eq (fsharp-nesting-level) 1208))))) (describe "The `fsharp--compute-indentaiton-open-bracket'" - :var ((file (file-truename (concat fsharp-struct-test-files-dir "BracketIndent.fs")))) - (it "returns the correct indentation in a variety of cases" - (with-current-buffer (find-file-noselect file) - ;; Opening bracket on same line as let, elements on same line; test element - (goto-char 44) - (let* ((nesting-level (fsharp-nesting-level)) - (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) - ;; The value we expect - (should (eq indent-at-point 18)) - ;; Both entrypoints should have the same answer - (should (eq indent-at-point (fsharp-compute-indentation t)))) - - ;; Opening bracket on same line as let, elements on same line; test newline - (goto-char 81) - (let* ((nesting-level (fsharp-nesting-level)) - (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) - ;; The value we expect - (should (eq indent-at-point 18)) - ;; Both entrypoints should have the same answer - (should (eq indent-at-point (fsharp-compute-indentation t)))) - - ;; Opening bracket on same line as let, elements on new line; test element - (goto-char 148) - (let* ((nesting-level (fsharp-nesting-level)) - (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) - (should (eq indent-at-point 4)) - (should (eq indent-at-point (fsharp-compute-indentation t)))) - - ;; Opening bracket on same line as let, elements on new line; test newline - (goto-char 155) - (let* ((nesting-level (fsharp-nesting-level)) - (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) - (should (eq indent-at-point 4)) - (should (eq indent-at-point (fsharp-compute-indentation t)))) - - ;; Opening bracket on own line; test element - (goto-char 231) - (let* ((nesting-level (fsharp-nesting-level)) - (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) - (should (eq indent-at-point 6)) - (should (eq indent-at-point (fsharp-compute-indentation t)))) - - ;; Opening bracket on own line; test newline - (goto-char 236) - (let* ((nesting-level (fsharp-nesting-level)) - (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) - (should (eq indent-at-point 6)) - (should (eq indent-at-point (fsharp-compute-indentation t))))))) + :var ((file (file-truename (concat fsharp-struct-test-files-dir "BracketIndent.fs")))) + (it "returns the correct indentation in a variety of cases" + (with-current-buffer (find-file-noselect file) + ;; Opening bracket on same line as let, elements on same line; test element + (goto-char 44) + (let* ((nesting-level (fsharp-nesting-level)) + (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) + ;; The value we expect + (should (eq indent-at-point 18)) + ;; Both entrypoints should have the same answer + (should (eq indent-at-point (fsharp-compute-indentation t)))) + + ;; Opening bracket on same line as let, elements on same line; test newline + (goto-char 81) + (let* ((nesting-level (fsharp-nesting-level)) + (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) + ;; The value we expect + (should (eq indent-at-point 18)) + ;; Both entrypoints should have the same answer + (should (eq indent-at-point (fsharp-compute-indentation t)))) + + ;; Opening bracket on same line as let, elements on new line; test element + (goto-char 148) + (let* ((nesting-level (fsharp-nesting-level)) + (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) + (should (eq indent-at-point 4)) + (should (eq indent-at-point (fsharp-compute-indentation t)))) + + ;; Opening bracket on same line as let, elements on new line; test newline + (goto-char 155) + (let* ((nesting-level (fsharp-nesting-level)) + (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) + (should (eq indent-at-point 4)) + (should (eq indent-at-point (fsharp-compute-indentation t)))) + + ;; Opening bracket on own line; test element + (goto-char 231) + (let* ((nesting-level (fsharp-nesting-level)) + (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) + (should (eq indent-at-point 6)) + (should (eq indent-at-point (fsharp-compute-indentation t)))) + + ;; Opening bracket on own line; test newline + (goto-char 236) + (let* ((nesting-level (fsharp-nesting-level)) + (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level))) + (should (eq indent-at-point 6)) + (should (eq indent-at-point (fsharp-compute-indentation t))))))) (describe "The `fsharp--compute-indentation-continuation-line' function" - :var ((continuation-line "let x = 5 +")) - (it "indents correctly" - (with-temp-buffer - (fsharp-mode) - (insert continuation-line) - (fsharp-newline-and-indent) - (should (eq (fsharp--compute-indentation-continuation-line) 8)) - (should (eq (fsharp--compute-indentation-continuation-line) (fsharp-compute-indentation t)))))) + :var ((continuation-line "let x = 5 +")) + (it "indents correctly" + (with-temp-buffer + (fsharp-mode) + (insert continuation-line) + (fsharp-newline-and-indent) + (should (eq (fsharp--compute-indentation-continuation-line) 8)) + (should (eq (fsharp--compute-indentation-continuation-line) (fsharp-compute-indentation t)))))) (describe "The `fsharp-compute-indentation-relative-to-previous' function'" - :var ((file (concat fsharp-struct-test-files-dir "Relative.fs"))) - (it "indents correctly releative to previous line" - ;; Discriminated unions - (with-current-buffer (find-file-noselect file) - (goto-char 57) - (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) - (should (eq (fsharp--compute-indentation-relative-to-previous t) - (fsharp-compute-indentation t))) - - ;; If/Else blocks - ;; if an if then are on the same line, the next line is indented - (goto-char 96) - (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) - (should (eq (fsharp--compute-indentation-relative-to-previous t) - (fsharp-compute-indentation t))) - - ;; An else is not indented further; *however*, the indentation relative to - ;; previous will be 4, but `fsharp-compute-indentation' will return 0 - ;; because the previous line is not a continuation line. - ;; - ;; However! This test case doesn't currently work. Indentation code - ;; produces indent of 0, but the compute indentation functions proudce an - ;; indent of 4, which is wrong. - ;; - ;; (goto-char 124) - ;; (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) - ;; (should-not (eq (fsharp--compute-indentation-relative-to-previous t) - ;; (fsharp-compute-indentation t))) - - ;; when a then is on its own line, the next line is indented - (goto-char 154) - (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) - (should (eq (fsharp--compute-indentation-relative-to-previous t) - (fsharp-compute-indentation t))) - ;; likewise an else - (goto-char 180) - (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) - (should (eq (fsharp--compute-indentation-relative-to-previous t) - (fsharp-compute-indentation t)))))) + :var ((file (concat fsharp-struct-test-files-dir "Relative.fs"))) + (it "indents correctly releative to previous line" + ;; Discriminated unions + (with-current-buffer (find-file-noselect file) + (goto-char 57) + (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) + (should (eq (fsharp--compute-indentation-relative-to-previous t) + (fsharp-compute-indentation t))) + + ;; If/Else blocks + ;; if an if then are on the same line, the next line is indented + (goto-char 96) + (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) + (should (eq (fsharp--compute-indentation-relative-to-previous t) + (fsharp-compute-indentation t))) + + ;; An else is not indented further; *however*, the indentation relative to + ;; previous will be 4, but `fsharp-compute-indentation' will return 0 + ;; because the previous line is not a continuation line. + ;; + ;; However! This test case doesn't currently work. Indentation code + ;; produces indent of 0, but the compute indentation functions proudce an + ;; indent of 4, which is wrong. + ;; + ;; (goto-char 124) + ;; (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) + ;; (should-not (eq (fsharp--compute-indentation-relative-to-previous t) + ;; (fsharp-compute-indentation t))) + + ;; when a then is on its own line, the next line is indented + (goto-char 154) + (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) + (should (eq (fsharp--compute-indentation-relative-to-previous t) + (fsharp-compute-indentation t))) + ;; likewise an else + (goto-char 180) + (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) + (should (eq (fsharp--compute-indentation-relative-to-previous t) + (fsharp-compute-indentation t)))))) diff --git a/test/integration-tests.el b/test/integration-tests.el index 1646876..74c1ccd 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -1,6 +1,6 @@ ;;; integration-tests.el --- -*- lexical-binding: t; -*- -;; Copyright (C) 2019 Jürgen Hötzel +;; Copyright (C) 2019-2022 Jürgen Hötzel ;; Author: Jürgen Hötzel ;; Keywords: abbrev, abbrev @@ -30,61 +30,63 @@ (defun eglot-fsharp--sniff-diagnostics (file-name-suffix) (eglot--sniffing (:server-notifications s-notifs) - (eglot--wait-for (s-notifs 20) - (&key _id method params &allow-other-keys) - (and - (string= method "textDocument/publishDiagnostics") - (string-suffix-p file-name-suffix (plist-get params :uri)))))) + (eglot--wait-for (s-notifs 20) + (&key _id method params &allow-other-keys) + (and + (string= method "textDocument/publishDiagnostics") + (string-suffix-p file-name-suffix (plist-get params :uri)))))) (describe "F# LSP server" - (it "can be installed @version 0.52.0" - (eglot-fsharp--maybe-install "0.52.0") - (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) - (it "Can be installed" - (eglot-fsharp--maybe-install) - (expect (eglot-fsharp--installed-version) :to-equal (eglot-fsharp--latest-version))) - (it "Can be invoked" - ;; FIXME: Should use dotnet tool run - (expect (car (process-lines (eglot-fsharp--path-to-server) "--version")) - :to-match (rx line-start (? "FsAutoComplete" (1+ space)) (eval (eglot-fsharp--installed-version))))) - (it "shows flymake errors" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Error.fs") - (eglot--tests-connect 10) - (search-forward "nonexisting") - (flymake-mode t) - (flymake-start) - (goto-char (point-min)) - (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") - (flymake-goto-next-error 1 '() t) - (expect (face-at-point) :to-be 'flymake-error ))) - (it "is enabled on F# Files" - (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs") - (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete))) - (it "provides completion" - (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs") - (eglot-fsharp--sniff-diagnostics "test/Test1/FileTwo.fs") - (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil))) - (it "completes function in other modules" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (search-forward "X.func") - (delete-char -3) - (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") - (completion-at-point) - (expect (looking-back "X\\.func") :to-be t))) - (it "finds definition in pervasives" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (eglot--tests-connect 10) - (search-forward "printfn") - (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") - (expect (current-word) :to-equal "printfn") ;sanity check - (call-interactively #'xref-find-definitions) - (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs"))) - (it "finds definitions in other files of Project" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (goto-char 150) - (expect (current-word) :to-equal "NewObjectType") ;sanity check - (call-interactively #'xref-find-definitions) - (expect (file-name-nondirectory (buffer-file-name)) :to-equal "FileTwo.fs")))) + :var (latest-version) + :before-all (setq latest-version (eglot-fsharp--latest-version)) + (it "can be installed @version 0.52.0" + (eglot-fsharp--maybe-install "0.52.0") + (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) + (it (format "Can be installed (using latest version: %s)" latest-version) + (eglot-fsharp--maybe-install) + (expect (eglot-fsharp--installed-version) :to-equal latest-version)) + (it "Can be invoked" + ;; FIXME: Should use dotnet tool run + (expect (car (process-lines (eglot-fsharp--path-to-server) "--version")) + :to-match (rx line-start (? "FsAutoComplete" (1+ space)) (eval (eglot-fsharp--installed-version))))) + (it "shows flymake errors" + (with-current-buffer (eglot--find-file-noselect "test/Test1/Error.fs") + (eglot--tests-connect 10) + (search-forward "nonexisting") + (flymake-mode t) + (flymake-start) + (goto-char (point-min)) + (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") + (flymake-goto-next-error 1 '() t) + (expect (face-at-point) :to-be 'flymake-error ))) + (it "is enabled on F# Files" + (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs") + (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete))) + (it "provides completion" + (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs") + (eglot-fsharp--sniff-diagnostics "test/Test1/FileTwo.fs") + (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil))) + (it "completes function in other modules" + (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") + (search-forward "X.func") + (delete-char -3) + (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") + (completion-at-point) + (expect (looking-back "X\\.func") :to-be t))) + (it "finds definition in pervasives" + (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") + (eglot--tests-connect 10) + (search-forward "printfn") + (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") + (expect (current-word) :to-equal "printfn") ;sanity check + (call-interactively #'xref-find-definitions) + (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs"))) + (it "finds definitions in other files of Project" + (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") + (goto-char 150) + (expect (current-word) :to-equal "NewObjectType") ;sanity check + (call-interactively #'xref-find-definitions) + (expect (file-name-nondirectory (buffer-file-name)) :to-equal "FileTwo.fs")))) (provide 'integration-tests) ;;; integration-tests.el ends here From a2f8d581dc7e158d22f4df4de54c7994ed31b53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 5 Jun 2022 15:28:31 +0200 Subject: [PATCH 076/120] Update copyright/maintainer --- eglot-fsharp.el | 4 ++-- fsharp-mode-structure.el | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 30ab7e1..7656ec2 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -1,8 +1,8 @@ ;;; eglot-fsharp.el --- fsharp-mode eglot integration -*- lexical-binding: t; -*- -;; Copyright (C) 2019-2021 Jürgen Hötzel +;; Copyright (C) 2019-2022 Jürgen Hötzel -;; Author: Jürgen Hötzel +;; Author: Jürgen Hötzel ;; Package-Requires: ((emacs "27.1") (eglot "1.4") (fsharp-mode "1.10") (jsonrpc "1.0.14")) ;; Version: 1.10 ;; Keywords: languages diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index 2fb1a04..674f612 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2010 Laurent Le Brun ;; Author: 2010-2011 Laurent Le Brun -;; Maintainer: Robin Neatherway +;; Maintainer: Jürgen Hötzel ;; Keywords: languages ;; This file is not part of GNU Emacs. From fc92b95c45a692283b8a0d643443f7decd302fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 5 Jun 2022 15:39:13 +0200 Subject: [PATCH 077/120] Replace Cask with Eldev - Remove Makefile use Eldev to download Eglot test helpers. - Use Eldev in GH Actions --- .github/workflows/test.yml | 33 ++++++++++++++++++------------- Cask | 9 --------- Eldev | 20 +++++++++++++++++++ Makefile | 40 -------------------------------------- 4 files changed, 39 insertions(+), 63 deletions(-) delete mode 100644 Cask create mode 100644 Eldev delete mode 100644 Makefile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c04d1e6..36042c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,20 +26,27 @@ jobs: with: dotnet-version: ${{ matrix.dotnet }} - uses: actions/checkout@v2 - - uses: conao3/setup-cask@master + - name: Install Eldev + run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh - name: Show dotnet sdks run: dotnet --list-sdks - name: Show dotnet version run: dotnet --info - name: Test - run: make test + run: | + echo "Archives:" + eldev archives + echo "Dependencies:" + eldev -v dependencies + echo "Testing:" + eldev -dtT test windows-build: runs-on: windows-latest strategy: fail-fast: false steps: - uses: actions/setup-dotnet@v1 - - name: Install Cask/scoop-emacs + - name: Install scoop-emacs run: | Set-ExecutionPolicy RemoteSigned -scope CurrentUser Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') @@ -49,15 +56,13 @@ jobs: scoop install make echo "$env:PATH" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 - uses: actions/checkout@v2 - - name: Test # FIXME: cask hack + - name: Install Eldev + run: curl.exe -fsSL https://raw.github.com/doublep/eldev/master/webinstall/eldev.bat | cmd /Q + - name: Test run: | - git clone https://github.com/tom-bowles/cask cask-windows - Remove-Item -recurse .\cask-windows\test - dotnet restore test/Test1 - Invoke-WebRequest -Uri https://raw.githubusercontent.com/joaotavora/eglot/master/eglot-tests.el -OutFile eglot-tests.el - Start .\Cask-windows\bin\cask.bat -ArgumentList install -NoNewWindow -Wait - Start .\Cask-windows\bin\cask.bat -ArgumentList build -NoNewWindow -Wait - Start .\Cask-windows\bin\cask.bat -ArgumentList "exec buttercup -L . -L test --traceback full" -NoNewWindow -Wait - - - + echo "Archives:" + ~/.local/bin/eldev.bat archives + echo "Dependencies:" + ~/.local/bin/eldev.bat dependencies + echo "Testing:" + ~/.local/bin/eldev.bat -p -dtT test diff --git a/Cask b/Cask deleted file mode 100644 index cc6c144..0000000 --- a/Cask +++ /dev/null @@ -1,9 +0,0 @@ -(source gnu) -(source melpa) - -(package-file "fsharp-mode.el") - -;; FIXME: Use multiple packages: https://github.com/melpa/melpa#example-multiple-packages-in-one-repository ? -(development - (depends-on "buttercup") - (depends-on "eglot")) diff --git a/Eldev b/Eldev new file mode 100644 index 0000000..e134b54 --- /dev/null +++ b/Eldev @@ -0,0 +1,20 @@ +; -*- mode: emacs-lisp; lexical-binding: t -*- +;; FIXME: Use if-modified-since header? +(unless (and (file-exists-p "eglot-tests.el") (< (time-to-seconds (time-subtract (current-time) + (file-attribute-modification-time (file-attributes "eglot-tests.el")))) + 86400)) + (url-copy-file "https://raw.githubusercontent.com/joaotavora/eglot/master/eglot-tests.el" "eglot-tests.el" t)) + + +(setq package-lint-main-file "eglot-fsharp.el") +(setq eldev-project-main-file "eglot-fsharp.el") + +(eldev-use-package-archive 'melpa-unstable) +(eldev-use-package-archive 'gnu) +(eldev-use-plugin 'autoloads) +(setq package-archive-priorities + '(("melpa-unstable" . 400) + ("gnu" . 300))) + + + diff --git a/Makefile b/Makefile deleted file mode 100644 index 75a67d8..0000000 --- a/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -all: build -export EMACS ?= emacs -EMACSFLAGS = -L . -CASK = cask -VERSION = $(shell git describe --tags --abbrev=0 | sed 's/^v//') -PKG = fsharp-mode - -elpa-$(EMACS): - $(CASK) install - $(CASK) update - touch $@ - -test/eglot-tests.el: - curl -o eglot-tests.el https://raw.githubusercontent.com/joaotavora/eglot/master/eglot-tests.el - -elpa: elpa-$(EMACS) - -build: elpa version - $(CASK) build - -version: - $(EMACS) --version - -test/Test1/restored: - dotnet restore test/Test1 - touch test/Test1/restored - -test: version build test/eglot-tests.el test/Test1/restored - $(CASK) exec buttercup -L . -L ./test --traceback full - -clean: - rm -f .depend elpa-$(EMACS) $(OBJECTS) $(PKG)-autoloads.el - -elpaclean: clean - rm -f elpa* - rm -rf .cask # Clean packages installed for development - -run-$(PKG): elpa - cask exec $(EMACS) -Q -L . --eval "(require '$(PKG))" - From 77bea0547fdddec31d37c5d93f68da135b089099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 5 Jun 2022 20:17:17 +0200 Subject: [PATCH 078/120] Refactor Integration tests - Use single F# LSP session for all tests: The seems to be a race condition when restarting the F# LSP session for each test. - "dotnet restore" before running integration tests - Use own util functions for eglot instead of downloading eglot-tests - Fix flymake integration test: Need to notify `textDocument/didChange` to trigger diagnostics. - Improve Debugging of integration tests: Output jsonrpc events buffer on timeout. --- Eldev | 6 - test/eglot-fsharp-integration-util.el | 164 ++++++++++++++++++++++++++ test/integration-tests.el | 117 +++++++++--------- 3 files changed, 222 insertions(+), 65 deletions(-) create mode 100644 test/eglot-fsharp-integration-util.el diff --git a/Eldev b/Eldev index e134b54..6b01e5e 100644 --- a/Eldev +++ b/Eldev @@ -1,10 +1,4 @@ ; -*- mode: emacs-lisp; lexical-binding: t -*- -;; FIXME: Use if-modified-since header? -(unless (and (file-exists-p "eglot-tests.el") (< (time-to-seconds (time-subtract (current-time) - (file-attribute-modification-time (file-attributes "eglot-tests.el")))) - 86400)) - (url-copy-file "https://raw.githubusercontent.com/joaotavora/eglot/master/eglot-tests.el" "eglot-tests.el" t)) - (setq package-lint-main-file "eglot-fsharp.el") (setq eldev-project-main-file "eglot-fsharp.el") diff --git a/test/eglot-fsharp-integration-util.el b/test/eglot-fsharp-integration-util.el new file mode 100644 index 0000000..2dca357 --- /dev/null +++ b/test/eglot-fsharp-integration-util.el @@ -0,0 +1,164 @@ +;;; eglot-fsharp-integration-util.el --- Helper for eglot integration tests -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Jürgen Hötzel + +;; Author: Jürgen Hötzel +;; Keywords: processes + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +;;; Code: +(require 'edebug) + +(cl-defmacro eglot-fsharp--with-timeout (timeout &body body) + (declare (indent 1) (debug t)) + `(eglot-fsharp--call-with-timeout ,timeout (lambda () ,@body))) + +(defun eglot-fsharp--call-with-timeout (timeout fn) + (let* ((tag (gensym "eglot-test-timeout")) + (timed-out (make-symbol "timeout")) + (timeout-and-message + (if (listp timeout) timeout + (list timeout "waiting for test to finish"))) + (timeout (car timeout-and-message)) + (message (cadr timeout-and-message)) + (timer) + (retval)) + (unwind-protect + (setq retval + (catch tag + (setq timer + (run-with-timer timeout nil + (lambda () + (unless edebug-active + (throw tag timed-out))))) + (funcall fn))) + (cancel-timer timer) + (when (eq retval timed-out) + (warn "Received Events for %s : %s" + (file-name-nondirectory (buffer-file-name)) + (with-current-buffer (jsonrpc-events-buffer (eglot-current-server)) (buffer-string))) + (error "%s" (concat "Timed out " message)))))) + + +(defun eglot-fsharp--find-file-noselect (file &optional noerror) + (unless (or noerror + (file-readable-p file)) (error "%s does not exist" file)) + (find-file-noselect file)) + +(defun eglot-fsharp--tests-connect (&optional timeout) + (let* ((timeout (or timeout 10)) + (eglot-sync-connect t) + (eglot-connect-timeout timeout)) + (apply #'eglot--connect (eglot--guess-contact)))) + +(cl-defmacro eglot-fsharp--wait-for ((events-sym &optional (timeout 1) message) args &body body) + "Spin until FN match in EVENTS-SYM, flush events after it. +Pass TIMEOUT to `eglot--with-timeout'." + (declare (indent 2) (debug (sexp sexp sexp &rest form))) + `(eglot-fsharp--with-timeout '(,timeout ,(or message + (format "waiting for:\n%s" (pp-to-string body)))) + (let ((event + (cl-loop thereis (cl-loop for json in ,events-sym + for method = (plist-get json :method) + when (keywordp method) + do (plist-put json :method + (substring + (symbol-name method) + 1)) + when (funcall + (jsonrpc-lambda ,args ,@body) json) + return (cons json before) + collect json into before) + for i from 0 + when (zerop (mod i 5)) + ;; do (eglot--message "still struggling to find in %s" + ;; ,events-sym) + do + ;; `read-event' is essential to have the file + ;; watchers come through. + (read-event "[eglot] Waiting a bit..." nil 0.1) + (accept-process-output nil 0.1)))) + (setq ,events-sym (cdr event)) + (eglot--message "Event detected:\n%s" + (pp-to-string (car event)))))) + + +(cl-defmacro eglot-fsharp--sniffing ((&key server-requests + server-notifications + server-replies + client-requests + client-notifications + client-replies) + &rest body) + "Run BODY saving LSP JSON messages in variables, most recent first." + (declare (indent 1) (debug (sexp &rest form))) + (let ((log-event-ad-sym (make-symbol "eglot-fsharp--event-sniff"))) + `(unwind-protect + (let ,(delq nil (list server-requests + server-notifications + server-replies + client-requests + client-notifications + client-replies)) + (advice-add + #'jsonrpc--log-event :before + (lambda (_proc message &optional type) + (cl-destructuring-bind (&key method id _error &allow-other-keys) + message + (let ((req-p (and method id)) + (notif-p method) + (reply-p id)) + (cond + ((eq type 'server) + (cond (req-p ,(when server-requests + `(push message ,server-requests))) + (notif-p ,(when server-notifications + `(push message ,server-notifications))) + (reply-p ,(when server-replies + `(push message ,server-replies))))) + ((eq type 'client) + (cond (req-p ,(when client-requests + `(push message ,client-requests))) + (notif-p ,(when client-notifications + `(push message ,client-notifications))) + (reply-p ,(when client-replies + `(push message ,client-replies))))))))) + '((name . ,log-event-ad-sym))) + ,@body) + (advice-remove #'jsonrpc--log-event ',log-event-ad-sym)))) + + + +(defun eglot-fsharp--sniff-diagnostics (file-name-suffix) + (eglot-fsharp--sniffing (:server-notifications s-notifs) + (eglot-fsharp--wait-for (s-notifs 20) + (&key _id method params &allow-other-keys) + (and + (string= method "textDocument/publishDiagnostics") + (string-suffix-p file-name-suffix (plist-get params :uri)))))) + +(defun eglot-fsharp--sniff-method (method-name) + (eglot-fsharp--sniffing (:server-notifications s-notifs) + (eglot-fsharp--wait-for (s-notifs 20) + (&key _id method params &allow-other-keys) + (and + (string= method method-name))))) + +(provide 'eglot-fsharp-integration-util) +;;; integration-util.el ends here diff --git a/test/integration-tests.el b/test/integration-tests.el index 74c1ccd..6c56867 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -26,67 +26,66 @@ (require 'buttercup) (require 'eglot-fsharp) -(require 'eglot-tests) +(load "test/eglot-fsharp-integration-util.el") -(defun eglot-fsharp--sniff-diagnostics (file-name-suffix) - (eglot--sniffing (:server-notifications s-notifs) - (eglot--wait-for (s-notifs 20) - (&key _id method params &allow-other-keys) - (and - (string= method "textDocument/publishDiagnostics") - (string-suffix-p file-name-suffix (plist-get params :uri)))))) +(describe "F# LSP Installation" + :before-all (setq latest-version (eglot-fsharp--latest-version)) + (it "succeeds using version 0.52.0" + (eglot-fsharp--maybe-install "0.52.0") + (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) + (it (format "succeeds using latest version: %s)" latest-version) + (eglot-fsharp--maybe-install) + (expect (eglot-fsharp--installed-version) :to-equal latest-version))) + +(describe "F# LSP Client" + :before-all (progn (setq latest-version (eglot-fsharp--latest-version)) + (with-temp-buffer (unless (zerop (process-file "dotnet" nil (current-buffer) nil "restore" "test/Test1")) + (signal 'file-error (buffer-string)))) + (eglot-fsharp--maybe-install) + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") + (eglot-fsharp--tests-connect 10) + (eglot-fsharp--sniff-method "fsharp/notifyWorkspace"))) + + (it "Can be invoked" + ;; FIXME: Should use dotnet tool run + (expect (process-file (eglot-fsharp--path-to-server) nil nil nil "--version") + :to-equal 0)) + (it "is enabled on F# Files" + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") + (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete))) + (it "shows flymake errors" + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Error.fs") + (flymake-mode t) + (flymake-start) + (goto-char (point-min)) + (search-forward "nonexisting") + (insert "x") + (eglot--signal-textDocument/didChange) + (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") + (flymake-goto-next-error 1 '() t) + (expect (face-at-point) :to-be 'flymake-error ))) + (it "provides completion" + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") + (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil))) + (it "completes function in other modules" + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Program.fs") + (search-forward "X.func") + (delete-char -3) + (completion-at-point) + (expect (looking-back "X\\.func") :to-be t))) + (it "finds definition in pervasives" + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Program.fs") + (search-forward "printfn") + (expect (current-word) :to-equal "printfn") ;sanity check + (call-interactively #'xref-find-definitions) + (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs"))) + (it "finds definitions in other files of Project" + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Program.fs") + (goto-char 150) + (expect (current-word) :to-equal "NewObjectType") ;sanity check + (call-interactively #'xref-find-definitions) + (expect (file-name-nondirectory (buffer-file-name)) :to-equal "FileTwo.fs")))) -(describe "F# LSP server" - :var (latest-version) - :before-all (setq latest-version (eglot-fsharp--latest-version)) - (it "can be installed @version 0.52.0" - (eglot-fsharp--maybe-install "0.52.0") - (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) - (it (format "Can be installed (using latest version: %s)" latest-version) - (eglot-fsharp--maybe-install) - (expect (eglot-fsharp--installed-version) :to-equal latest-version)) - (it "Can be invoked" - ;; FIXME: Should use dotnet tool run - (expect (car (process-lines (eglot-fsharp--path-to-server) "--version")) - :to-match (rx line-start (? "FsAutoComplete" (1+ space)) (eval (eglot-fsharp--installed-version))))) - (it "shows flymake errors" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Error.fs") - (eglot--tests-connect 10) - (search-forward "nonexisting") - (flymake-mode t) - (flymake-start) - (goto-char (point-min)) - (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") - (flymake-goto-next-error 1 '() t) - (expect (face-at-point) :to-be 'flymake-error ))) - (it "is enabled on F# Files" - (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs") - (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete))) - (it "provides completion" - (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs") - (eglot-fsharp--sniff-diagnostics "test/Test1/FileTwo.fs") - (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil))) - (it "completes function in other modules" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (search-forward "X.func") - (delete-char -3) - (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") - (completion-at-point) - (expect (looking-back "X\\.func") :to-be t))) - (it "finds definition in pervasives" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (eglot--tests-connect 10) - (search-forward "printfn") - (eglot-fsharp--sniff-diagnostics "test/Test1/Program.fs") - (expect (current-word) :to-equal "printfn") ;sanity check - (call-interactively #'xref-find-definitions) - (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs"))) - (it "finds definitions in other files of Project" - (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs") - (goto-char 150) - (expect (current-word) :to-equal "NewObjectType") ;sanity check - (call-interactively #'xref-find-definitions) - (expect (file-name-nondirectory (buffer-file-name)) :to-equal "FileTwo.fs")))) (provide 'integration-tests) ;;; integration-tests.el ends here From 07496d4c7b7b1f98de6a637628c9e1434ca44866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 14:26:03 +0200 Subject: [PATCH 079/120] Integration test: reload "project.el" Emacs 27.x Workaround: https://github.com/joaotavora/eglot/issues/549 --- test/integration-tests.el | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration-tests.el b/test/integration-tests.el index 6c56867..2e4e790 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -24,6 +24,7 @@ ;;; Code: +(load "project") ;Emacs 27 workaround: https://github.com/joaotavora/eglot/issues/549 (require 'buttercup) (require 'eglot-fsharp) (load "test/eglot-fsharp-integration-util.el") From 0a05c5d38ab881da3c1678c58e2d583905a3ee99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 15:08:57 +0200 Subject: [PATCH 080/120] Use jcs090218/setup-emacs-windows for Windows CI --- .github/workflows/test.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 36042c7..dbfd577 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,15 +46,10 @@ jobs: fail-fast: false steps: - uses: actions/setup-dotnet@v1 - - name: Install scoop-emacs - run: | - Set-ExecutionPolicy RemoteSigned -scope CurrentUser - Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') - scoop update - scoop bucket add extras - scoop install emacs - scoop install make - echo "$env:PATH" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 + - name: Set up Emacs on Windows + uses: jcs090218/setup-emacs-windows@master + with: + version: 28.1 - uses: actions/checkout@v2 - name: Install Eldev run: curl.exe -fsSL https://raw.github.com/doublep/eldev/master/webinstall/eldev.bat | cmd /Q From 91010b716f7898038e1b90cc15a77628122dfd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 16:14:06 +0200 Subject: [PATCH 081/120] Integration tests: Don't install multiple versions on Windows: fsautocomplete process don't seem to terminate: "Access denied" when trying to install a different version. --- test/integration-tests.el | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/test/integration-tests.el b/test/integration-tests.el index 2e4e790..02a95a4 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -29,14 +29,17 @@ (require 'eglot-fsharp) (load "test/eglot-fsharp-integration-util.el") -(describe "F# LSP Installation" - :before-all (setq latest-version (eglot-fsharp--latest-version)) - (it "succeeds using version 0.52.0" - (eglot-fsharp--maybe-install "0.52.0") - (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) - (it (format "succeeds using latest version: %s)" latest-version) - (eglot-fsharp--maybe-install) - (expect (eglot-fsharp--installed-version) :to-equal latest-version))) +;; FIXME/HELP WANTED: fsautocomplete process don't seem to terminate on windows (Access denied when trying to install +;; different version) +(unless (eq system-type 'windows-nt) + (describe "F# LSP Installation" + :before-all (setq latest-version (eglot-fsharp--latest-version)) + (it "succeeds using version 0.52.0" + (eglot-fsharp--maybe-install "0.52.0") + (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) + (it (format "succeeds using latest version: %s)" latest-version) + (eglot-fsharp--maybe-install) + (expect (eglot-fsharp--installed-version) :to-equal latest-version)))) (describe "F# LSP Client" :before-all (progn (setq latest-version (eglot-fsharp--latest-version)) From 8d2ab2841701ef7c86d20430452cde66c46dad6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 16:32:27 +0200 Subject: [PATCH 082/120] signal stderr of "dotnet install" failure Improves CI debugging --- eglot-fsharp.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 7656ec2..a53cba4 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -124,11 +124,11 @@ (defun eglot-fsharp--process-tool-action (response) "Process the result of calling the dotnet tool installation returning RESPONSE code." - (if (eq response 1) - (let ((minibuffer-message-timeout 5) - (msg (format "Error installing fsautocomplete see %s" (concat default-directory "error_output.txt")) )) - (minibuffer-message msg) - (error "Failed to install dotnet tool fsautocomplete")))) + (when (>= response 1) + (error "Failed to install dotnet tool fsautocomplete: %s" + (with-temp-buffer + (insert-file-contents "error_output.txt") + (buffer-string))))) (defun eglot-fsharp--install-core (version) "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." From add296fcc5516cab79210c89ca9b049c971f7e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 16:39:18 +0200 Subject: [PATCH 083/120] CI: Show dotnet version on Windows --- .github/workflows/test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dbfd577..ee6c908 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,6 +46,12 @@ jobs: fail-fast: false steps: - uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.200 + - name: Show dotnet sdks + run: dotnet --list-sdks + - name: Show dotnet version + run: dotnet --info - name: Set up Emacs on Windows uses: jcs090218/setup-emacs-windows@master with: From 52c3c12b3590a0944dc837c126d4c602e9a07dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 16:48:21 +0200 Subject: [PATCH 084/120] Debug output: Show fsautocomplete version that will be installed --- eglot-fsharp.el | 1 + 1 file changed, 1 insertion(+) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index a53cba4..6dfaa86 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -134,6 +134,7 @@ "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) (unless (eglot-fsharp-current-version-p version) + (message "Installing fsautocomplete version %s" version) (if (file-exists-p (eglot-fsharp--path-to-server)) (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil "error_output.txt") From 2381a07f97d8179850c2eca2c0ed69c3e89a3109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 17:22:00 +0200 Subject: [PATCH 085/120] Use Nuget API instead of parsing output of "dotnet tool search" Prevents parsing issues because of localisation (No LANG=C on Windows). --- eglot-fsharp.el | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 6dfaa86..c97a5cb 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -75,12 +75,10 @@ (defun eglot-fsharp--latest-version () "Return latest fsautocomplete.exe version." - (let ((process-environment (cons "LANG=C" process-environment))) ;FIXME: Doesn't work in Windows - (if eglot-fsharp--latest-version - eglot-fsharp--latest-version - (setq eglot-fsharp--latest-version - (seq-some (lambda (s) (and (string-match "^[[:alnum:]]* Version: \\(.*\\)$" s) (match-string 1 s))) - (process-lines "dotnet" "tool" "search" "fsautocomplete" "--detail")))))) + (let* ((json (with-temp-buffer (url-insert-file-contents "https://azuresearch-usnc.nuget.org/query?q=fsautocomplete&prerelease=false&packageType=DotnetTool") + (json-parse-buffer))) + (versions (gethash "versions" (aref (gethash "data" json) 0)))) + (gethash "version" (aref versions (1- (length versions)))))) (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." From ab625668310bdf88390faa53c29eb5f2e90608f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 17:30:54 +0200 Subject: [PATCH 086/120] Run CI on PR only --- .github/workflows/test.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ee6c908..e61c787 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,10 +1,6 @@ name: "CI" on: pull_request: - push: - # Comment out this section to enable testing of all branches. - branches: - - master jobs: gnu-build: runs-on: ubuntu-latest From 15964df7c65a3b46d704c85873619fec073eabc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sat, 18 Jun 2022 17:40:02 +0200 Subject: [PATCH 087/120] Revert "Run CI on PR only" Required for CI badge: This reverts commit ab625668310bdf88390faa53c29eb5f2e90608f9. --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e61c787..ee6c908 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,10 @@ name: "CI" on: pull_request: + push: + # Comment out this section to enable testing of all branches. + branches: + - master jobs: gnu-build: runs-on: ubuntu-latest From 40db2e5fd5080989c7166cf7499ab286dc4b6c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 19 Jun 2022 14:07:59 +0200 Subject: [PATCH 088/120] Refactor "dotnet tool (un)install fsautocomplete" error reporting - Use temp-file instead of hardcoded stderr-file. - Report the exact command that failed. --- eglot-fsharp.el | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index c97a5cb..5a92954 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -119,30 +119,32 @@ (chmod file #o644))))) (delete-file zip))) - -(defun eglot-fsharp--process-tool-action (response) - "Process the result of calling the dotnet tool installation returning RESPONSE code." - (when (>= response 1) - (error "Failed to install dotnet tool fsautocomplete: %s" - (with-temp-buffer - (insert-file-contents "error_output.txt") - (buffer-string))))) - (defun eglot-fsharp--install-core (version) "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." - (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) - (unless (eglot-fsharp-current-version-p version) - (message "Installing fsautocomplete version %s" version) - (if (file-exists-p (eglot-fsharp--path-to-server)) - (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil - "error_output.txt") - nil "tool" "uninstall" - "fsautocomplete" "--tool-path" - default-directory))) - (eglot-fsharp--process-tool-action (call-process "dotnet" nil '(nil "error_output.txt") nil - "tool" "install" "fsautocomplete" - "--tool-path" default-directory "--version" - version))))) + (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server))) + (stderr-file (make-temp-file "dotnet_stderr"))) + (condition-case err + (progn + (unless (eglot-fsharp-current-version-p version) + (message "Installing fsautocomplete version %s" version) + (when (file-exists-p (eglot-fsharp--path-to-server)) + (unless (zerop (call-process "dotnet" nil `(nil + ,stderr-file) + nil "tool" "uninstall" + "fsautocomplete" "--tool-path" + default-directory)) + (error "'dotnet tool uninstall fsautocomplete --tool-path %s' failed" default-directory)))) + (unless (zerop (call-process "dotnet" nil `(nil ,stderr-file) nil + "tool" "install" "fsautocomplete" + "--tool-path" default-directory "--version" + version)) + (error "'dotnet tool install fsautocomplete --tool-path %s --version ' failed" default-directory version))) + (error + (let ((stderr (with-temp-buffer + (insert-file-contents stderr-file) + (buffer-string)))) + (delete-file stderr-file) + (signal (car err) (format "%s: %s" (cdr err) stderr))))))) (defun eglot-fsharp--maybe-install (&optional version) "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." From 7d828553fae1bf679e0d49409a6031f424922c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 19 Jun 2022 19:23:48 +0200 Subject: [PATCH 089/120] Add FSI tests Refs #293 --- test/fsi-tests.el | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test/fsi-tests.el diff --git a/test/fsi-tests.el b/test/fsi-tests.el new file mode 100644 index 0000000..c0b56ec --- /dev/null +++ b/test/fsi-tests.el @@ -0,0 +1,73 @@ +;;; fsi-tests.el --- Tests for F# interactive -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Jürgen Hötzel + +;; Author: Jürgen Hötzel +;; Keywords: processes + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +;;; Code: + +(load "project") ;Emacs 27 workaround: https://github.com/joaotavora/eglot/issues/549 +(require 'buttercup) +(require 'fsharp-mode) + +(defun fsi-tests-wait-for-regex (timeout regexp) + (while (and (> timeout 0) (not (progn (goto-char (point-min)) (search-forward-regexp regexp nil t)))) + (message "[FSI Interactive] Waiting a bit...") + (accept-process-output (get-buffer-process (current-buffer)) 0.2) + (setq timeout (1- timeout)))) + + +(describe "F# interactive" + :before-all (run-fsharp inferior-fsharp-program) + :before-each (with-current-buffer (get-buffer inferior-fsharp-buffer-name) + (comint-clear-buffer)) + (it "can eval expressions" + (let ((fsharp-autosave-on-file-load t) + (fsx-file (make-temp-file "fsi" nil ".fsx" " +1 + 1;; +"))) + (with-current-buffer (find-file-noselect fsx-file) + (fsharp-eval-region (point-min) (point-max)) + (with-current-buffer (get-buffer inferior-fsharp-buffer-name) + (fsi-tests-wait-for-regex 25 "it: int = 2$") + (let ((result (match-string-no-properties 0))) + (expect result :to-equal "it: int = 2")))))) + (it "can load nuget references" + (let ((fsharp-autosave-on-file-load t) + (timeout 50) + (fsx-file (make-temp-file "fsi" nil ".fsx" " +#r \"nuget: Newtonsoft.Json\";; +open Newtonsoft.Json;; + +let o = {| X = 2; Y = \"Hello\" |};; + +printfn \"xxx:%s:xxx\" (JsonConvert.SerializeObject o);;"))) + (with-current-buffer (find-file-noselect fsx-file) + (fsharp-load-buffer-file) + (with-current-buffer (get-buffer inferior-fsharp-buffer-name) + (fsi-tests-wait-for-regex 25 "xxx:\\(.*\\):xxx") + (let ((json-str (match-string-no-properties 1))) + (unless json-str + (warn "FSI output doesn't contain marker: %s" (buffer-substring-no-properties (point-min) (point-max)))) + (expect json-str :to-equal "{\"X\":2,\"Y\":\"Hello\"}"))))))) + +(provide 'fsi-tests) +;;; fsi-tests.el ends here From b13e983ac437f1664c9ee438c601da8660c8c27c Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 24 Jun 2022 22:39:29 +0200 Subject: [PATCH 090/120] Use pty for inferior F# process Ensures line-buffering of inferior F# output. Refs #293 --- inf-fsharp-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el index 7db9a09..8843bfe 100644 --- a/inf-fsharp-mode.el +++ b/inf-fsharp-mode.el @@ -100,7 +100,7 @@ If FILE is not a Tramp filename return FILENAME" (or cmd (read-from-minibuffer "fsharp toplevel to run: " inferior-fsharp-program))) (let ((cmdlist (inferior-fsharp-args-to-list inferior-fsharp-program)) - (process-connection-type nil)) + (process-connection-type 'pty)) (with-current-buffer (apply (function make-comint) inferior-fsharp-buffer-subname (car cmdlist) nil From a8703bf50333e1c295f212b7ea6959f1a87d3548 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Wed, 29 Jun 2022 16:55:26 +0900 Subject: [PATCH 091/120] Add missing format specifier --- eglot-fsharp.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 5a92954..ff872bc 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -138,7 +138,7 @@ "tool" "install" "fsautocomplete" "--tool-path" default-directory "--version" version)) - (error "'dotnet tool install fsautocomplete --tool-path %s --version ' failed" default-directory version))) + (error "'dotnet tool install fsautocomplete --tool-path %s --version %s' failed" default-directory version))) (error (let ((stderr (with-temp-buffer (insert-file-contents stderr-file) From 9b1b807c4d142431406a984d1c207281ccaf447d Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Thu, 30 Jun 2022 11:03:09 +0900 Subject: [PATCH 092/120] Fix byte-compile warnings - specify ':type' attribute for defcustom variables - escape quotes in docstring --- eglot-fsharp.el | 3 ++- fsharp-mode-structure.el | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index ff872bc..6d99285 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -52,7 +52,8 @@ (string :tag "Version string"))) (defcustom eglot-fsharp-server-verbose nil - "If non-nil include debug output in the server logs.") + "If non-nil include debug output in the server logs." + :type 'boolean) (defcustom eglot-fsharp-server-runtime (if (executable-find "dotnet") diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index 674f612..b7664fb 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -268,7 +268,7 @@ This function preserves point and mark." (defun fsharp-in-literal-p (&optional lim) "Return non-nil if point is in a Fsharp literal (a comment or string). The return value is specifically one of the symbols -'comment or 'string. Optional argument LIM indicates the +\\='comment or \\='string. Optional argument LIM indicates the beginning of the containing form, i.e. the limit on how far back to scan." ;; NOTE: Watch out for infinite recursion between this function and From c8482eaa5c2c2d85652a701f5935576d9402f6d5 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Thu, 30 Jun 2022 21:38:38 +0200 Subject: [PATCH 093/120] Remove support for .NET full framework fsautocomplete dropped support for the full framework: fsharp/FsAutoComplete#652 --- eglot-fsharp.el | 58 +++++-------------------------------------------- 1 file changed, 6 insertions(+), 52 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 6d99285..67b4a43 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -55,21 +55,9 @@ "If non-nil include debug output in the server logs." :type 'boolean) -(defcustom eglot-fsharp-server-runtime - (if (executable-find "dotnet") - 'net-core - 'net-framework) - "The .NET runtime to use." - :group 'eglot-fsharp - :type '(choice (const :tag "Use .Net Core" net-core) - (const :tag "Use .Net Framework" net-framework))) - (defun eglot-fsharp--path-to-server () "Return FsAutoComplete path." - (file-truename (concat eglot-fsharp-server-install-dir - (if (eq eglot-fsharp-server-runtime 'net-core) - (concat "netcore/fsautocomplete" (if (eq system-type 'windows-nt) ".exe" "")) - "netframework/fsautocomplete.exe")))) + (file-truename (concat eglot-fsharp-server-install-dir "netcore/fsautocomplete" (if (eq system-type 'windows-nt) ".exe" "")))) ;; cache to prevent repetitive queries (defvar eglot-fsharp--latest-version nil "Latest fsautocomplete.exe version string.") @@ -94,32 +82,6 @@ (eglot-fsharp--installed-version)) (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) -(defun eglot-fsharp--install-w32 (version) - "Download and install the full framework version of F# compiler service at version VERSION in `eglot-fsharp-server-install-dir'." - (let* ((url (format "https://github.com/fsharp/FsAutoComplete/releases/download/%s/fsautocomplete.zip" - version)) - (exe (eglot-fsharp--path-to-server)) - (zip (concat (file-name-directory exe) "fsautocomplete.zip")) - (gnutls-algorithm-priority - (if (and (not gnutls-algorithm-priority) - (boundp 'libgnutls-version) - (>= libgnutls-version 30603) - (version<= emacs-version "26.2")) - "NORMAL:-VERS-TLS1.3" - gnutls-algorithm-priority)))) - (unless (eglot-fsharp-current-version-p version) - (url-copy-file url zip t) - ;; FIXME: Windows (unzip preinstalled?) - (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server)))) - (unless (zerop (call-process "unzip" nil nil nil "-o" zip)) - (error "Failed to unzip %s" zip)) - (unless (eq system-type 'windows-nt) - (dolist (file (directory-files-recursively (file-name-directory (eglot-fsharp--path-to-server)) "." t)) - (if (file-directory-p file) - (chmod file #o755) - (chmod file #o644))))) - (delete-file zip))) - (defun eglot-fsharp--install-core (version) "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server))) @@ -153,9 +115,7 @@ (let* ((version (or version (if (eq eglot-fsharp-server-version 'latest) (eglot-fsharp--latest-version) eglot-fsharp-server-version)))) - (if (eq eglot-fsharp-server-runtime 'net-core) - (eglot-fsharp--install-core version) - (eglot-fsharp--install-w32 version)))) + (eglot-fsharp--install-core version))) ;;;###autoload (defun eglot-fsharp @@ -164,16 +124,10 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (when interactive (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) - (let ((cmd-list (cond ((eq eglot-fsharp-server-runtime 'net-core) - `(,(eglot-fsharp--path-to-server))) - ((eq window-system 'w32) - `("" , (eglot-fsharp--path-to-server))) - (t `("mono" ,(eglot-fsharp--path-to-server))))) - (arg-list (if eglot-fsharp-server-verbose - `("--background-service-enabled" "-v") - `("--background-service-enabled") - ))) - (cons 'eglot-fsautocomplete (append cmd-list arg-list))))) + (cons 'eglot-fsautocomplete (cons (eglot-fsharp--path-to-server) + (if eglot-fsharp-server-verbose + `("--background-service-enabled" "-v") + `("--background-service-enabled")))))) From a8fe13b20382135d4ab204466e2f5e02df935ff3 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 1 Jul 2022 21:52:02 +0200 Subject: [PATCH 094/120] FSI tests: Code cleanup Move inline fsx code from .el to separate .fsx files. --- test/expression.fsx | 1 + test/fsi-tests.el | 53 ++++++++++++++++++--------------------------- test/nuget.fsx | 6 +++++ 3 files changed, 28 insertions(+), 32 deletions(-) create mode 100644 test/expression.fsx create mode 100644 test/nuget.fsx diff --git a/test/expression.fsx b/test/expression.fsx new file mode 100644 index 0000000..0bcc167 --- /dev/null +++ b/test/expression.fsx @@ -0,0 +1 @@ +1 + 1;; diff --git a/test/fsi-tests.el b/test/fsi-tests.el index c0b56ec..ae38069 100644 --- a/test/fsi-tests.el +++ b/test/fsi-tests.el @@ -36,38 +36,27 @@ (describe "F# interactive" - :before-all (run-fsharp inferior-fsharp-program) - :before-each (with-current-buffer (get-buffer inferior-fsharp-buffer-name) - (comint-clear-buffer)) - (it "can eval expressions" - (let ((fsharp-autosave-on-file-load t) - (fsx-file (make-temp-file "fsi" nil ".fsx" " -1 + 1;; -"))) - (with-current-buffer (find-file-noselect fsx-file) - (fsharp-eval-region (point-min) (point-max)) - (with-current-buffer (get-buffer inferior-fsharp-buffer-name) - (fsi-tests-wait-for-regex 25 "it: int = 2$") - (let ((result (match-string-no-properties 0))) - (expect result :to-equal "it: int = 2")))))) - (it "can load nuget references" - (let ((fsharp-autosave-on-file-load t) - (timeout 50) - (fsx-file (make-temp-file "fsi" nil ".fsx" " -#r \"nuget: Newtonsoft.Json\";; -open Newtonsoft.Json;; - -let o = {| X = 2; Y = \"Hello\" |};; - -printfn \"xxx:%s:xxx\" (JsonConvert.SerializeObject o);;"))) - (with-current-buffer (find-file-noselect fsx-file) - (fsharp-load-buffer-file) - (with-current-buffer (get-buffer inferior-fsharp-buffer-name) - (fsi-tests-wait-for-regex 25 "xxx:\\(.*\\):xxx") - (let ((json-str (match-string-no-properties 1))) - (unless json-str - (warn "FSI output doesn't contain marker: %s" (buffer-substring-no-properties (point-min) (point-max)))) - (expect json-str :to-equal "{\"X\":2,\"Y\":\"Hello\"}"))))))) + :before-all (run-fsharp inferior-fsharp-program) + :before-each (with-current-buffer (get-buffer inferior-fsharp-buffer-name) + (comint-clear-buffer)) + (it "can eval expressions" + (with-current-buffer (find-file-noselect "test/expression.fsx") + (fsharp-eval-region (point-min) (point-max)) + (with-current-buffer (get-buffer inferior-fsharp-buffer-name) + (fsi-tests-wait-for-regex 25 "it: int = 2$") + (let ((result (match-string-no-properties 0))) + (expect result :to-equal "it: int = 2"))))) + (it "can load nuget references" + (let ((timeout 50) + (fsx-file "test/nuget.fsx")) + (with-current-buffer (find-file-noselect fsx-file) + (fsharp-load-buffer-file) + (with-current-buffer (get-buffer inferior-fsharp-buffer-name) + (fsi-tests-wait-for-regex 25 "xxx:\\(.*\\):xxx") + (let ((json-str (match-string-no-properties 1))) + (unless json-str + (warn "FSI output doesn't contain marker: %s" (buffer-substring-no-properties (point-min) (point-max)))) + (expect json-str :to-equal "{\"X\":2,\"Y\":\"Hello\"}"))))))) (provide 'fsi-tests) ;;; fsi-tests.el ends here diff --git a/test/nuget.fsx b/test/nuget.fsx new file mode 100644 index 0000000..4c32d7f --- /dev/null +++ b/test/nuget.fsx @@ -0,0 +1,6 @@ +#r "nuget: Newtonsoft.Json";; +open Newtonsoft.Json;; + +let o = {| X = 2; Y = "Hello" |};; + +printfn "xxx:%s:xxx" (JsonConvert.SerializeObject o);; From c8bb586621a230a83e292c419624d3a6b1faee91 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 1 Jul 2022 22:15:31 +0200 Subject: [PATCH 095/120] fsi-tests: Fix invalid timeout implemtation --- test/fsi-tests.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fsi-tests.el b/test/fsi-tests.el index ae38069..3da1a65 100644 --- a/test/fsi-tests.el +++ b/test/fsi-tests.el @@ -31,7 +31,7 @@ (defun fsi-tests-wait-for-regex (timeout regexp) (while (and (> timeout 0) (not (progn (goto-char (point-min)) (search-forward-regexp regexp nil t)))) (message "[FSI Interactive] Waiting a bit...") - (accept-process-output (get-buffer-process (current-buffer)) 0.2) + (accept-process-output (get-buffer-process (current-buffer)) 0.2 nil t) (setq timeout (1- timeout)))) From 84f736990d11b76c4636b7e1edc4c1e53db26d45 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Fri, 1 Jul 2022 22:23:25 +0200 Subject: [PATCH 096/120] Tests: Fix invalid fsi-tests-wait-for-regex timeout implementation --- test/fsi-tests.el | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/fsi-tests.el b/test/fsi-tests.el index 3da1a65..450e07f 100644 --- a/test/fsi-tests.el +++ b/test/fsi-tests.el @@ -29,10 +29,12 @@ (require 'fsharp-mode) (defun fsi-tests-wait-for-regex (timeout regexp) - (while (and (> timeout 0) (not (progn (goto-char (point-min)) (search-forward-regexp regexp nil t)))) - (message "[FSI Interactive] Waiting a bit...") - (accept-process-output (get-buffer-process (current-buffer)) 0.2 nil t) - (setq timeout (1- timeout)))) + (let ((start-time (float-time))) + (while (and (< (- (float-time) start-time) timeout) + (not (progn (goto-char (point-min)) (search-forward-regexp regexp nil t)))) + (if (accept-process-output (get-buffer-process (current-buffer)) 0.2) + (message "[FSI Interactive] received output...") + (message "[FSI Interactive] waiting for output..."))))) (describe "F# interactive" From cb5a3420117f581b141176654526ad2df603ec4b Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Tue, 25 Oct 2022 14:53:07 -0400 Subject: [PATCH 097/120] Update console app parameters `--background-service` has been deprecated, switch to experimental adaptive lsp service change the `-v` parameter to `--verbose` to align with the documentation --- eglot-fsharp.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 67b4a43..384fa25 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -126,8 +126,8 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (when (file-exists-p (eglot-fsharp--path-to-server)) (cons 'eglot-fsautocomplete (cons (eglot-fsharp--path-to-server) (if eglot-fsharp-server-verbose - `("--background-service-enabled" "-v") - `("--background-service-enabled")))))) + `("--verbose" "--adaptive-lsp-server-enabled") + `("--adaptive-lsp-server-enabled")))))) From f8873096d24cac7b30419854347220f37345e780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Thu, 27 Oct 2022 21:23:38 +0200 Subject: [PATCH 098/120] Add `eglot-fsharp-server-args' for additional arguments Make ("--adaptive-lsp-server-enabled") the default args because the server crashes on boot without the adaptive flag. Remove `eglot-fsharp-server-verbose'. --- eglot-fsharp.el | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 384fa25..d4ea66a 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -51,9 +51,9 @@ (const :tag "Latest release" latest) (string :tag "Version string"))) -(defcustom eglot-fsharp-server-verbose nil - "If non-nil include debug output in the server logs." - :type 'boolean) +(defcustom eglot-fsharp-server-args '("--adaptive-lsp-server-enabled") + "Arguments for the fsautocomplete command when using `eglot-fsharp'." + :type '(repeat string)) (defun eglot-fsharp--path-to-server () "Return FsAutoComplete path." @@ -125,11 +125,7 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (when interactive (eglot-fsharp--maybe-install)) (when (file-exists-p (eglot-fsharp--path-to-server)) (cons 'eglot-fsautocomplete (cons (eglot-fsharp--path-to-server) - (if eglot-fsharp-server-verbose - `("--verbose" "--adaptive-lsp-server-enabled") - `("--adaptive-lsp-server-enabled")))))) - - + eglot-fsharp-server-args)))) (defclass eglot-fsautocomplete (eglot-lsp-server) () From 80f4d3a0341c35cb52ea7cc8eb531514240dedf8 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 6 Nov 2022 21:43:27 +0100 Subject: [PATCH 099/120] Remove "echo" caused by pty-mode inferior fsharp process Refs #311 --- inf-fsharp-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el index 8843bfe..fbfb05d 100644 --- a/inf-fsharp-mode.el +++ b/inf-fsharp-mode.el @@ -73,7 +73,7 @@ be sent from another buffer in fsharp mode. (set (make-local-variable 'comment-column) 40) (set (make-local-variable 'comment-start-skip) "(\\*+ *") (set (make-local-variable 'parse-sexp-ignore-comments) nil) - (set (make-local-variable 'comint-process-echoes) nil) + (set (make-local-variable 'comint-process-echoes) t) (run-hooks 'inferior-fsharp-mode-hooks) ;; use compilation mode to parse errors, but RET and C-cC-c should still be from comint-mode From 842174faf791e1a12fbd13863c94e37744feab44 Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Thu, 25 Aug 2022 01:15:23 -0400 Subject: [PATCH 100/120] Additional FSautocomplete init parameters --- eglot-fsharp.el | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index d4ea66a..3b7de45 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -133,7 +133,21 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (cl-defmethod eglot-initialization-options ((_server eglot-fsautocomplete)) "Passes through required FsAutoComplete initialization options." - '(:automaticWorkspaceInit t)) + '( + :automaticWorkspaceInit t + :keywordsAutocomplete t + :externalAutocomplete nil + :linter t + :unionCaseStubGeneration t + :recordStubGeneration t + :interfaceStubGeneration t + :interfaceStubGenerationObjectIdentifier "this" + :unusedOpensAnalyzer t + :unusedDeclarationsAnalyzer t + :useSdkScripts t + :simplifyNameAnalyzer nil + :resolveNamespaces t + :enableReferenceCodeLens t)) ;; FIXME: this should be fixed in FsAutocomplete (cl-defmethod xref-backend-definitions :around ((_type symbol) _identifier) From f631cae3943a31eb0d76acfa160366823234c8d3 Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Fri, 3 Feb 2023 15:15:37 -0500 Subject: [PATCH 101/120] Add customizable variable for fsautocomplete parameters --- README.org | 4 ++-- eglot-fsharp.el | 36 +++++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/README.org b/README.org index 4983d8b..9d6c0bb 100644 --- a/README.org +++ b/README.org @@ -183,8 +183,8 @@ This project is maintained by the [[http://fsharp.org/][F# Software Foundation]], with the repository hosted on [[https://github.com/fsharp/emacs-fsharp-mode][GitHub]]. -Pull requests are welcome. Please run the test-suite with =make -test= before submitting a pull request. +Pull requests are welcome. Please run the test-suite with [Eldev](https://doublep.github.io/eldev/) =eldev -dtT test= +before submitting a pull request. *** Maintainers diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 3b7de45..f15ac9f 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -55,6 +55,26 @@ "Arguments for the fsautocomplete command when using `eglot-fsharp'." :type '(repeat string)) +(defcustom eglot-fsharp-fsautocomplete-args '( + :automaticWorkspaceInit t + :keywordsAutocomplete t + :externalAutocomplete nil + :linter t + :unionCaseStubGeneration t + :recordStubGeneration t + :interfaceStubGeneration t + :interfaceStubGenerationObjectIdentifier "this" + :unusedOpensAnalyzer t + :unusedDeclarationsAnalyzer t + :useSdkScripts t + :simplifyNameAnalyzer nil + :resolveNamespaces t + :enableReferenceCodeLens t) + "Arguments for the fsautocomplete initialization." + :group 'eglot-fsharp + :risky t + ) + (defun eglot-fsharp--path-to-server () "Return FsAutoComplete path." (file-truename (concat eglot-fsharp-server-install-dir "netcore/fsautocomplete" (if (eq system-type 'windows-nt) ".exe" "")))) @@ -133,21 +153,7 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (cl-defmethod eglot-initialization-options ((_server eglot-fsautocomplete)) "Passes through required FsAutoComplete initialization options." - '( - :automaticWorkspaceInit t - :keywordsAutocomplete t - :externalAutocomplete nil - :linter t - :unionCaseStubGeneration t - :recordStubGeneration t - :interfaceStubGeneration t - :interfaceStubGenerationObjectIdentifier "this" - :unusedOpensAnalyzer t - :unusedDeclarationsAnalyzer t - :useSdkScripts t - :simplifyNameAnalyzer nil - :resolveNamespaces t - :enableReferenceCodeLens t)) + `(:fSharp ,eglot-fsharp-fsautocomplete-args)) ;; FIXME: this should be fixed in FsAutocomplete (cl-defmethod xref-backend-definitions :around ((_type symbol) _identifier) From 186052e07a6d0e3d20f4fd53c59b081d330c60c4 Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Fri, 3 Feb 2023 17:24:59 -0500 Subject: [PATCH 102/120] Updating test matrix --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ee6c908..f10cef1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,9 +14,9 @@ jobs: os: [ubuntu-latest, macos-latest] dotnet: [6.0.200] emacs_version: - - 27.1 - 27.2 - 28.1 + - 28.2 - snapshot steps: - uses: purcell/setup-emacs@master From d087e4efa48a10c7635edcfef0a215c0fb5357e1 Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Fri, 3 Feb 2023 17:41:23 -0500 Subject: [PATCH 103/120] increase notification timeout --- test/eglot-fsharp-integration-util.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/eglot-fsharp-integration-util.el b/test/eglot-fsharp-integration-util.el index 2dca357..ed27f81 100644 --- a/test/eglot-fsharp-integration-util.el +++ b/test/eglot-fsharp-integration-util.el @@ -147,7 +147,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (defun eglot-fsharp--sniff-diagnostics (file-name-suffix) (eglot-fsharp--sniffing (:server-notifications s-notifs) - (eglot-fsharp--wait-for (s-notifs 20) + (eglot-fsharp--wait-for (s-notifs 30) (&key _id method params &allow-other-keys) (and (string= method "textDocument/publishDiagnostics") @@ -155,7 +155,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (defun eglot-fsharp--sniff-method (method-name) (eglot-fsharp--sniffing (:server-notifications s-notifs) - (eglot-fsharp--wait-for (s-notifs 20) + (eglot-fsharp--wait-for (s-notifs 30) (&key _id method params &allow-other-keys) (and (string= method method-name))))) From ff035ca17b603da895242cd77853b7c22befbc8c Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Fri, 3 Feb 2023 18:10:03 -0500 Subject: [PATCH 104/120] sniff signal before trigger the text change. There's a potential race condition where the diagnostic message arrives before the signal sniffing is attached. --- test/eglot-fsharp-integration-util.el | 4 ++-- test/integration-tests.el | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/eglot-fsharp-integration-util.el b/test/eglot-fsharp-integration-util.el index ed27f81..2dca357 100644 --- a/test/eglot-fsharp-integration-util.el +++ b/test/eglot-fsharp-integration-util.el @@ -147,7 +147,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (defun eglot-fsharp--sniff-diagnostics (file-name-suffix) (eglot-fsharp--sniffing (:server-notifications s-notifs) - (eglot-fsharp--wait-for (s-notifs 30) + (eglot-fsharp--wait-for (s-notifs 20) (&key _id method params &allow-other-keys) (and (string= method "textDocument/publishDiagnostics") @@ -155,7 +155,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (defun eglot-fsharp--sniff-method (method-name) (eglot-fsharp--sniffing (:server-notifications s-notifs) - (eglot-fsharp--wait-for (s-notifs 30) + (eglot-fsharp--wait-for (s-notifs 20) (&key _id method params &allow-other-keys) (and (string= method method-name))))) diff --git a/test/integration-tests.el b/test/integration-tests.el index 02a95a4..9e66957 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -61,11 +61,11 @@ (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Error.fs") (flymake-mode t) (flymake-start) + (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") (goto-char (point-min)) (search-forward "nonexisting") (insert "x") (eglot--signal-textDocument/didChange) - (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") (flymake-goto-next-error 1 '() t) (expect (face-at-point) :to-be 'flymake-error ))) (it "provides completion" From ceafc404df945d86c41099a057232cd5a248c5a9 Mon Sep 17 00:00:00 2001 From: August Feng Date: Sun, 11 Dec 2022 22:46:22 -0500 Subject: [PATCH 105/120] disable self run mode hooks and let emacs run it If we run the hook ourselves, we could cause unexpected behaviours in case an external entity also adds hooks to the major mode. --- fsharp-mode.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fsharp-mode.el b/fsharp-mode.el index 8d25a25..eab2f66 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -241,9 +241,7 @@ If set to t, the buffer will always be saved, silently." (let ((file (buffer-file-name))) (when file - (setq compile-command (fsharp-mode-choose-compile-command file)))) - - (run-hooks 'fsharp-mode-hook)) + (setq compile-command (fsharp-mode-choose-compile-command file))))) (defun fsharp-mode-choose-compile-command (file) "Format an appropriate compilation command, depending on several factors: From 8a1501764317d3414f2d97d7679504910600e934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 19 Feb 2023 15:58:22 +0100 Subject: [PATCH 106/120] Code cleanup --- fsharp-mode.el | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fsharp-mode.el b/fsharp-mode.el index eab2f66..4305bd7 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -239,9 +239,8 @@ If set to t, the buffer will always be saved, silently." ;; has no deterministic indentation. (when (boundp 'electric-indent-inhibit) (setq electric-indent-inhibit t)) - (let ((file (buffer-file-name))) - (when file - (setq compile-command (fsharp-mode-choose-compile-command file))))) + (when-let ((file (buffer-file-name))) + (setq compile-command (fsharp-mode-choose-compile-command file)))) (defun fsharp-mode-choose-compile-command (file) "Format an appropriate compilation command, depending on several factors: From 7623e1d6e93b5d3b647ab3a58969d68cf2a2a3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 19 Feb 2023 16:04:10 +0100 Subject: [PATCH 107/120] Update copyright year --- eglot-fsharp.el | 2 +- fsharp-mode.el | 2 +- test/eglot-fsharp-integration-util.el | 2 +- test/fsi-tests.el | 2 +- test/integration-tests.el | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index f15ac9f..1e89103 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -1,6 +1,6 @@ ;;; eglot-fsharp.el --- fsharp-mode eglot integration -*- lexical-binding: t; -*- -;; Copyright (C) 2019-2022 Jürgen Hötzel +;; Copyright (C) 2019-2023 Jürgen Hötzel ;; Author: Jürgen Hötzel ;; Package-Requires: ((emacs "27.1") (eglot "1.4") (fsharp-mode "1.10") (jsonrpc "1.0.14")) diff --git a/fsharp-mode.el b/fsharp-mode.el index 4305bd7..c8720ab 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -5,7 +5,7 @@ ;; Author: 1993-1997 Xavier Leroy, Jacques Garrigue and Ian T Zimmerman ;; 2010-2011 Laurent Le Brun ;; 2012-2014 Robin Neatherway -;; 2017-2022 Jürgen Hötzel +;; 2017-2023 Jürgen Hötzel ;; Maintainer: Jürgen Hötzel ;; Package-Requires: ((emacs "25")) ;; Keywords: languages diff --git a/test/eglot-fsharp-integration-util.el b/test/eglot-fsharp-integration-util.el index 2dca357..c1fbf83 100644 --- a/test/eglot-fsharp-integration-util.el +++ b/test/eglot-fsharp-integration-util.el @@ -1,6 +1,6 @@ ;;; eglot-fsharp-integration-util.el --- Helper for eglot integration tests -*- lexical-binding: t; -*- -;; Copyright (C) 2022 Jürgen Hötzel +;; Copyright (C) 2022-2023 Jürgen Hötzel ;; Author: Jürgen Hötzel ;; Keywords: processes diff --git a/test/fsi-tests.el b/test/fsi-tests.el index 450e07f..4b22d18 100644 --- a/test/fsi-tests.el +++ b/test/fsi-tests.el @@ -1,6 +1,6 @@ ;;; fsi-tests.el --- Tests for F# interactive -*- lexical-binding: t; -*- -;; Copyright (C) 2022 Jürgen Hötzel +;; Copyright (C) 2022-2023 Jürgen Hötzel ;; Author: Jürgen Hötzel ;; Keywords: processes diff --git a/test/integration-tests.el b/test/integration-tests.el index 9e66957..52fb570 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -1,6 +1,6 @@ ;;; integration-tests.el --- -*- lexical-binding: t; -*- -;; Copyright (C) 2019-2022 Jürgen Hötzel +;; Copyright (C) 2019-2023 Jürgen Hötzel ;; Author: Jürgen Hötzel ;; Keywords: abbrev, abbrev From 6e3c9186ac2f136c3a1cfce898e9deb2482b286e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20H=C3=B6tzel?= Date: Sun, 19 Mar 2023 19:52:01 +0100 Subject: [PATCH 108/120] Make `eglot-fsharp' tramp aware Install "fsautocomplete" on the remote host if `default-directory' is a tramp filename. Add pipe-workaround for remote fsautocomplete processes: There seems to be a problem related to CRLF coded input in remote fsautocomplete processes. Wrapping the process using a cat pipe fixes the issue. Even when setting `process-connection-type' to nil or 'pipe there is still a pseudo tty for the started remote process: https://www.gnu.org/software/emacs/manual/html_node/tramp/Remote-processes.html#Remote-process-connection-type Fixes #324 --- eglot-fsharp.el | 52 +++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 1e89103..5438f5b 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -91,35 +91,38 @@ (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." - (seq-some (lambda (s) (and (string-match "^fsautocomplete[[:space:]]+\\([0-9\.]*\\)[[:space:]]+" s) (match-string 1 s))) - (process-lines "dotnet" "tool" "list" "--tool-path" (file-name-directory (eglot-fsharp--path-to-server))))) + (with-temp-buffer + (process-file "dotnet" nil t nil "tool" "list" "--tool-path" (file-name-directory (eglot-fsharp--path-to-server))) + (goto-char (point-min)) + (when (search-forward-regexp "^fsautocomplete[[:space:]]+\\([0-9\.]*\\)[[:space:]]+" nil t) + (match-string 1)))) (defun eglot-fsharp-current-version-p (version) - "Return t if the installation is not outdated." - (when (file-exists-p (eglot-fsharp--path-to-server)) - (if (eq version 'latest) - (equal (eglot-fsharp--latest-version) - (eglot-fsharp--installed-version)) - (equal eglot-fsharp-server-version (eglot-fsharp--installed-version))))) + "Return t if the installation is up-to-date compared to VERSION string." + (and (file-exists-p (concat (file-remote-p default-directory) (eglot-fsharp--path-to-server))) + (equal version (eglot-fsharp--installed-version)))) (defun eglot-fsharp--install-core (version) "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'." - (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server))) - (stderr-file (make-temp-file "dotnet_stderr"))) + (let* ((default-directory (concat (file-remote-p default-directory) + (file-name-directory (eglot-fsharp--path-to-server)))) + (stderr-file (make-temp-file "dotnet_stderr")) + (local-tool-path (or (file-remote-p default-directory 'localname) default-directory))) (condition-case err (progn (unless (eglot-fsharp-current-version-p version) (message "Installing fsautocomplete version %s" version) - (when (file-exists-p (eglot-fsharp--path-to-server)) - (unless (zerop (call-process "dotnet" nil `(nil + (when (file-exists-p (concat (file-remote-p default-directory) + (eglot-fsharp--path-to-server))) + (unless (zerop (process-file "dotnet" nil `(nil ,stderr-file) nil "tool" "uninstall" "fsautocomplete" "--tool-path" - default-directory)) + local-tool-path)) (error "'dotnet tool uninstall fsautocomplete --tool-path %s' failed" default-directory)))) - (unless (zerop (call-process "dotnet" nil `(nil ,stderr-file) nil + (unless (zerop (process-file "dotnet" nil `(nil ,stderr-file) nil "tool" "install" "fsautocomplete" - "--tool-path" default-directory "--version" + "--tool-path" local-tool-path "--version" version)) (error "'dotnet tool install fsautocomplete --tool-path %s --version %s' failed" default-directory version))) (error @@ -131,21 +134,24 @@ (defun eglot-fsharp--maybe-install (&optional version) "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." - (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t) + (make-directory (concat (file-remote-p default-directory) + (file-name-directory (eglot-fsharp--path-to-server))) t) (let* ((version (or version (if (eq eglot-fsharp-server-version 'latest) (eglot-fsharp--latest-version) eglot-fsharp-server-version)))) - (eglot-fsharp--install-core version))) + (unless (eglot-fsharp-current-version-p version) + (eglot-fsharp--install-core version)))) ;;;###autoload -(defun eglot-fsharp - (interactive) - "Return `eglot' contact when FsAutoComplete is installed. +(defun eglot-fsharp (interactive) + "Return `eglot' contact when FsAutoComplete is installed. Ensure FsAutoComplete is installed (when called INTERACTIVE)." (when interactive (eglot-fsharp--maybe-install)) - (when (file-exists-p (eglot-fsharp--path-to-server)) - (cons 'eglot-fsautocomplete (cons (eglot-fsharp--path-to-server) - eglot-fsharp-server-args)))) + (cons 'eglot-fsautocomplete + (if (file-remote-p default-directory) + `("sh" ,shell-command-switch ,(concat "cat|" (mapconcat #'shell-quote-argument + (cons (eglot-fsharp--path-to-server) eglot-fsharp-server-args) " "))) + (cons (eglot-fsharp--path-to-server) eglot-fsharp-server-args)))) (defclass eglot-fsautocomplete (eglot-lsp-server) () From e221789249f3716a3381f1ce626c705d500545be Mon Sep 17 00:00:00 2001 From: Andrew McGuier Date: Fri, 24 Mar 2023 04:22:49 -0400 Subject: [PATCH 109/120] Updating the configuration object to match Ionide configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Andrew McGuier Co-authored-by: Jürgen Hötzel --- eglot-fsharp.el | 83 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index 5438f5b..bce6c81 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -56,23 +56,66 @@ :type '(repeat string)) (defcustom eglot-fsharp-fsautocomplete-args '( - :automaticWorkspaceInit t - :keywordsAutocomplete t - :externalAutocomplete nil - :linter t - :unionCaseStubGeneration t - :recordStubGeneration t - :interfaceStubGeneration t - :interfaceStubGenerationObjectIdentifier "this" - :unusedOpensAnalyzer t - :unusedDeclarationsAnalyzer t - :useSdkScripts t - :simplifyNameAnalyzer nil - :resolveNamespaces t - :enableReferenceCodeLens t) - "Arguments for the fsautocomplete initialization." - :group 'eglot-fsharp - :risky t + :automaticWorkspaceInit t + :abstractClassStubGeneration t + :abstractClassStubGenerationMethodBody + "failwith \"Not Implemented\"" + :abstractClassStubGenerationObjectIdentifier "this" + :addFsiWatcher nil + :codeLenses (:references (:enabled t) + :signature (:enabled t)) + :disableFailedProjectNotifications nil + :dotnetRoot "" + :enableAdaptiveLspServer t + :enableAnalyzers nil + :enableMSBuildProjectGraph nil + :enableReferenceCodeLens t + :excludeProjectDirectories [".git" "paket-files" ".fable" "packages" "node_modules"] + :externalAutocomplete nil + :fsac (:attachDebugger nil + :cachedTypeCheckCount 200 + :conserveMemory nil + :dotnetArgs nil + :netCoreDllPath "" + :parallelReferenceResolution nil + :silencedLogs nil) + :fsiExtraParameters nil + :fsiSdkFilePath "" + :generateBinlog nil + :indentationSize 4 + :inlayHints (:disableLongTooltip nil + :enabled t + :parameterNames t + :typeAnnotations t) + :inlineValues (:enabled nil + :prefix "//") + :interfaceStubGeneration t + :interfaceStubGenerationMethodBody "failwith \"Not Implemented\"" + :interfaceStubGenerationObjectIdentifier "this" + :keywordsAutocomplete t + :lineLens (:enabled "replaceCodeLens" + :prefix " // ") + :linter t + :pipelineHints (:enabled t + :prefix " // ") + :recordStubGeneration t + :recordStubGenerationBody "failwith \"Not Implemented\"" + :resolveNamespaces t + :saveOnSendLastSelection nil + :simplifyNameAnalyzer t + :smartIndent nil + :suggestGitignore t + :suggestSdkScripts t + :unionCaseStubGeneration t + :unionCaseStubGenerationBody "failwith \"Not Implemented\"" + :unusedDeclarationsAnalyzer t + :unusedOpensAnalyzer t + :verboseLogging nil + :workspaceModePeekDeepLevel 4 + :workspacePath "") + "Arguments for the fsautocomplete workspace configuration." + :group 'eglot-fsharp + :risky t ) (defun eglot-fsharp--path-to-server () @@ -142,9 +185,9 @@ (unless (eglot-fsharp-current-version-p version) (eglot-fsharp--install-core version)))) - ;;;###autoload +;;;###autoload (defun eglot-fsharp (interactive) - "Return `eglot' contact when FsAutoComplete is installed. + "Return `eglot' contact when FsAutoComplete is installed. Ensure FsAutoComplete is installed (when called INTERACTIVE)." (when interactive (eglot-fsharp--maybe-install)) (cons 'eglot-fsautocomplete @@ -159,7 +202,7 @@ Ensure FsAutoComplete is installed (when called INTERACTIVE)." (cl-defmethod eglot-initialization-options ((_server eglot-fsautocomplete)) "Passes through required FsAutoComplete initialization options." - `(:fSharp ,eglot-fsharp-fsautocomplete-args)) + eglot-fsharp-fsautocomplete-args) ;; FIXME: this should be fixed in FsAutocomplete (cl-defmethod xref-backend-definitions :around ((_type symbol) _identifier) From 202277528cc9343ddc882a396978d11d716f9ec0 Mon Sep 17 00:00:00 2001 From: August Feng Date: Tue, 20 Jun 2023 15:41:28 -0400 Subject: [PATCH 110/120] Enable nxml-mode for fsproj files --- fsharp-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/fsharp-mode.el b/fsharp-mode.el index c8720ab..41199e6 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -114,6 +114,7 @@ ;;;###autoload (add-to-list 'auto-mode-alist '("\\.fs[iylx]?\\'" . fsharp-mode)) +(add-to-list 'auto-mode-alist '("\\.fsproj\\'" . nxml-mode)) (defvar fsharp-mode-syntax-table nil "Syntax table in use in fsharp mode buffers.") From 993ffee2e714eba4d39529b7b7d5ee9c2541f02d Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 14 May 2024 17:38:25 +0200 Subject: [PATCH 111/120] Allow to use "fsautocomplete" from the global tool-path. Setting `eglot-fsharp-server-install-dir' to nil disables the custom "~/.emacs.d/FsAutoComplete/netcore/" tool path. Fixes #341 --- eglot-fsharp.el | 51 +++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index bce6c81..bcb820e 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -1,6 +1,6 @@ ;;; eglot-fsharp.el --- fsharp-mode eglot integration -*- lexical-binding: t; -*- -;; Copyright (C) 2019-2023 Jürgen Hötzel +;; Copyright (C) 2019-2024 Jürgen Hötzel ;; Author: Jürgen Hötzel ;; Package-Requires: ((emacs "27.1") (eglot "1.4") (fsharp-mode "1.10") (jsonrpc "1.0.14")) @@ -41,7 +41,7 @@ "Install directory for FsAutoComplete." :group 'eglot-fsharp :risky t - :type 'directory) + :type '(choice directory (const :tag "Use dotnet default for tool-path" nil))) (defcustom eglot-fsharp-server-version 'latest "FsAutoComplete version to install or update." @@ -63,7 +63,7 @@ :abstractClassStubGenerationObjectIdentifier "this" :addFsiWatcher nil :codeLenses (:references (:enabled t) - :signature (:enabled t)) + :signature (:enabled t)) :disableFailedProjectNotifications nil :dotnetRoot "" :enableAdaptiveLspServer t @@ -120,7 +120,10 @@ (defun eglot-fsharp--path-to-server () "Return FsAutoComplete path." - (file-truename (concat eglot-fsharp-server-install-dir "netcore/fsautocomplete" (if (eq system-type 'windows-nt) ".exe" "")))) + (let ((base (if eglot-fsharp-server-install-dir + (concat eglot-fsharp-server-install-dir "netcore/") + "~/.dotnet/tools/"))) + (expand-file-name (concat base "fsautocomplete" (if (eq system-type 'windows-nt) ".exe" ""))))) ;; cache to prevent repetitive queries (defvar eglot-fsharp--latest-version nil "Latest fsautocomplete.exe version string.") @@ -135,7 +138,9 @@ (defun eglot-fsharp--installed-version () "Return version string of fsautocomplete." (with-temp-buffer - (process-file "dotnet" nil t nil "tool" "list" "--tool-path" (file-name-directory (eglot-fsharp--path-to-server))) + (if eglot-fsharp-server-install-dir + (process-file "dotnet" nil t nil "tool" "list" "--tool-path" (file-name-directory (eglot-fsharp--path-to-server))) + (process-file "dotnet" nil t nil "tool" "list" "-g")) (goto-char (point-min)) (when (search-forward-regexp "^fsautocomplete[[:space:]]+\\([0-9\.]*\\)[[:space:]]+" nil t) (match-string 1)))) @@ -150,35 +155,35 @@ (let* ((default-directory (concat (file-remote-p default-directory) (file-name-directory (eglot-fsharp--path-to-server)))) (stderr-file (make-temp-file "dotnet_stderr")) - (local-tool-path (or (file-remote-p default-directory 'localname) default-directory))) + (local-tool-path (or (file-remote-p default-directory 'localname) default-directory)) + (process-file-uninstall-args (if eglot-fsharp-server-install-dir + (list "dotnet" nil `(nil ,stderr-file) nil "tool" "uninstall" "fsautocomplete" "--tool-path" local-tool-path) + (list "dotnet" nil `(nil ,stderr-file) nil "tool" "uninstall" "-g" "fsautocomplete"))) + (process-file-install-args (if eglot-fsharp-server-install-dir + (list "dotnet" nil `(nil ,stderr-file) nil "tool" "install" "fsautocomplete" "--tool-path" local-tool-path "--version" version) + (list "dotnet" nil `(nil ,stderr-file) nil "tool" "install" "fsautocomplete" "-g" "--version" version)))) + (make-directory default-directory t) (condition-case err (progn - (unless (eglot-fsharp-current-version-p version) - (message "Installing fsautocomplete version %s" version) - (when (file-exists-p (concat (file-remote-p default-directory) - (eglot-fsharp--path-to-server))) - (unless (zerop (process-file "dotnet" nil `(nil - ,stderr-file) - nil "tool" "uninstall" - "fsautocomplete" "--tool-path" - local-tool-path)) - (error "'dotnet tool uninstall fsautocomplete --tool-path %s' failed" default-directory)))) - (unless (zerop (process-file "dotnet" nil `(nil ,stderr-file) nil - "tool" "install" "fsautocomplete" - "--tool-path" local-tool-path "--version" - version)) + (unless (or (eglot-fsharp-current-version-p version) (not (eglot-fsharp--installed-version))) + (message "Uninstalling fsautocomplete version %s" (eglot-fsharp--installed-version)) + (unless (zerop (apply #'process-file process-file-uninstall-args)) + (error "'dotnet tool uninstall fsautocomplete ... failed"))) + (unless (zerop (apply #'process-file process-file-install-args)) (error "'dotnet tool install fsautocomplete --tool-path %s --version %s' failed" default-directory version))) (error (let ((stderr (with-temp-buffer (insert-file-contents stderr-file) (buffer-string)))) (delete-file stderr-file) - (signal (car err) (format "%s: %s" (cdr err) stderr))))))) + (signal (car err) (format "%s: %s" (cdr err) stderr))))) + (message "Installed fsautocomplete to %s" (eglot-fsharp--path-to-server)))) (defun eglot-fsharp--maybe-install (&optional version) "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'." - (make-directory (concat (file-remote-p default-directory) - (file-name-directory (eglot-fsharp--path-to-server))) t) + (unless eglot-fsharp-server-install-dir + (make-directory (concat (file-remote-p default-directory) + (file-name-directory (eglot-fsharp--path-to-server))) t)) (let* ((version (or version (if (eq eglot-fsharp-server-version 'latest) (eglot-fsharp--latest-version) eglot-fsharp-server-version)))) From 65feb1ef5d662af57f268484dbb9f35179190a5a Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 14 May 2024 21:11:19 +0200 Subject: [PATCH 112/120] Increase default test timeout --- test/eglot-fsharp-integration-util.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/eglot-fsharp-integration-util.el b/test/eglot-fsharp-integration-util.el index c1fbf83..7d16f52 100644 --- a/test/eglot-fsharp-integration-util.el +++ b/test/eglot-fsharp-integration-util.el @@ -62,7 +62,7 @@ (find-file-noselect file)) (defun eglot-fsharp--tests-connect (&optional timeout) - (let* ((timeout (or timeout 10)) + (let* ((timeout (or timeout 30)) (eglot-sync-connect t) (eglot-connect-timeout timeout)) (apply #'eglot--connect (eglot--guess-contact)))) From cfc7047fc1acec702de0c10cad12ab89a972230a Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 14 May 2024 21:16:41 +0200 Subject: [PATCH 113/120] Tests: Update dotnet version / Add new Emacs release --- .github/workflows/test.yml | 90 +++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f10cef1..20fc682 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,58 +12,58 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - dotnet: [6.0.200] + dotnet: [8.0.x] emacs_version: - 27.2 - - 28.1 - 28.2 + - 29.3 - snapshot steps: - - uses: purcell/setup-emacs@master - with: - version: ${{ matrix.emacs_version }} - - uses: actions/setup-dotnet@v1 - with: - dotnet-version: ${{ matrix.dotnet }} - - uses: actions/checkout@v2 - - name: Install Eldev - run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh - - name: Show dotnet sdks - run: dotnet --list-sdks - - name: Show dotnet version - run: dotnet --info - - name: Test - run: | - echo "Archives:" - eldev archives - echo "Dependencies:" - eldev -v dependencies - echo "Testing:" - eldev -dtT test + - uses: purcell/setup-emacs@master + with: + version: ${{ matrix.emacs_version }} + - uses: actions/setup-dotnet@v1 + with: + dotnet-version: ${{ matrix.dotnet }} + - uses: actions/checkout@v2 + - name: Install Eldev + run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh + - name: Show dotnet sdks + run: dotnet --list-sdks + - name: Show dotnet version + run: dotnet --info + - name: Test + run: | + echo "Archives:" + eldev archives + echo "Dependencies:" + eldev -v dependencies + echo "Testing:" + eldev -dtT test windows-build: runs-on: windows-latest strategy: fail-fast: false steps: - - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 6.0.200 - - name: Show dotnet sdks - run: dotnet --list-sdks - - name: Show dotnet version - run: dotnet --info - - name: Set up Emacs on Windows - uses: jcs090218/setup-emacs-windows@master - with: - version: 28.1 - - uses: actions/checkout@v2 - - name: Install Eldev - run: curl.exe -fsSL https://raw.github.com/doublep/eldev/master/webinstall/eldev.bat | cmd /Q - - name: Test - run: | - echo "Archives:" - ~/.local/bin/eldev.bat archives - echo "Dependencies:" - ~/.local/bin/eldev.bat dependencies - echo "Testing:" - ~/.local/bin/eldev.bat -p -dtT test + - uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.200 + - name: Show dotnet sdks + run: dotnet --list-sdks + - name: Show dotnet version + run: dotnet --info + - name: Set up Emacs on Windows + uses: jcs090218/setup-emacs-windows@master + with: + version: 28.1 + - uses: actions/checkout@v2 + - name: Install Eldev + run: curl.exe -fsSL https://raw.github.com/doublep/eldev/master/webinstall/eldev.bat | cmd /Q + - name: Test + run: | + echo "Archives:" + ~/.local/bin/eldev.bat archives + echo "Dependencies:" + ~/.local/bin/eldev.bat dependencies + echo "Testing:" + ~/.local/bin/eldev.bat -p -dtT test From fe8037f354eaa4ab29923be6d434d178edf71fc2 Mon Sep 17 00:00:00 2001 From: DEADBLACKCLOVER Date: Sun, 22 Dec 2024 12:30:19 +0700 Subject: [PATCH 114/120] Added eglot-fsharp-server-path --- eglot-fsharp.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/eglot-fsharp.el b/eglot-fsharp.el index bcb820e..1ca7940 100644 --- a/eglot-fsharp.el +++ b/eglot-fsharp.el @@ -36,6 +36,11 @@ :link '(url-link "https://github.com/fsharp/FsAutoComplete") :group 'eglot) +(defcustom eglot-fsharp-server-path "~/.dotnet/tools/" + "Path to the location of FsAutoComplete." + :group 'eglot-fsharp + :risky t) + (defcustom eglot-fsharp-server-install-dir (locate-user-emacs-file "FsAutoComplete/") "Install directory for FsAutoComplete." @@ -122,7 +127,7 @@ "Return FsAutoComplete path." (let ((base (if eglot-fsharp-server-install-dir (concat eglot-fsharp-server-install-dir "netcore/") - "~/.dotnet/tools/"))) + eglot-fsharp-server-path))) (expand-file-name (concat base "fsautocomplete" (if (eq system-type 'windows-nt) ".exe" ""))))) ;; cache to prevent repetitive queries From dac487f6be752a94910b64e2d0d94445a0cac00d Mon Sep 17 00:00:00 2001 From: 64J0 Date: Fri, 7 Feb 2025 17:15:13 -0300 Subject: [PATCH 115/120] update tests on ci by: - using new action versions - using .NET 9 - improving test structure to make it easier to understand which step is failing and comment automated tests code that are currently failing (must be fixed in another PR) --- .github/workflows/test.yml | 37 ++++++++++++++++----------- test/Test1/Test1.fsproj | 2 +- test/eglot-fsharp-integration-util.el | 2 +- test/integration-tests.el | 28 ++++++++++---------- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 20fc682..9e97395 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,52 +2,56 @@ name: "CI" on: pull_request: push: - # Comment out this section to enable testing of all branches. branches: - master jobs: gnu-build: - runs-on: ubuntu-latest strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - dotnet: [8.0.x] + dotnet: [9.0.x] emacs_version: - - 27.2 - 28.2 - - 29.3 + - 29.4 - snapshot + runs-on: ${{ matrix.os }} steps: + - uses: actions/checkout@v4 + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ matrix.dotnet }} - uses: purcell/setup-emacs@master with: version: ${{ matrix.emacs_version }} - - uses: actions/setup-dotnet@v1 - with: - dotnet-version: ${{ matrix.dotnet }} - - uses: actions/checkout@v2 - name: Install Eldev run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh - name: Show dotnet sdks run: dotnet --list-sdks - name: Show dotnet version run: dotnet --info - - name: Test + - name: Eldev archives run: | echo "Archives:" eldev archives + - name: Eldev dependencies + run: | echo "Dependencies:" eldev -v dependencies + - name: Test + run: | echo "Testing:" eldev -dtT test + windows-build: runs-on: windows-latest strategy: fail-fast: false steps: - - uses: actions/setup-dotnet@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.200 + dotnet-version: 9.0.x - name: Show dotnet sdks run: dotnet --list-sdks - name: Show dotnet version @@ -55,15 +59,18 @@ jobs: - name: Set up Emacs on Windows uses: jcs090218/setup-emacs-windows@master with: - version: 28.1 - - uses: actions/checkout@v2 + version: 29.4 - name: Install Eldev run: curl.exe -fsSL https://raw.github.com/doublep/eldev/master/webinstall/eldev.bat | cmd /Q - - name: Test + - name: Eldev archives run: | echo "Archives:" ~/.local/bin/eldev.bat archives + - name: Eldev dependencies + run: | echo "Dependencies:" ~/.local/bin/eldev.bat dependencies + - name: Test + run: | echo "Testing:" ~/.local/bin/eldev.bat -p -dtT test diff --git a/test/Test1/Test1.fsproj b/test/Test1/Test1.fsproj index 15ef69f..5cccab9 100644 --- a/test/Test1/Test1.fsproj +++ b/test/Test1/Test1.fsproj @@ -2,7 +2,7 @@ Exe - net5.0 + net9.0 diff --git a/test/eglot-fsharp-integration-util.el b/test/eglot-fsharp-integration-util.el index 7d16f52..c1fbf83 100644 --- a/test/eglot-fsharp-integration-util.el +++ b/test/eglot-fsharp-integration-util.el @@ -62,7 +62,7 @@ (find-file-noselect file)) (defun eglot-fsharp--tests-connect (&optional timeout) - (let* ((timeout (or timeout 30)) + (let* ((timeout (or timeout 10)) (eglot-sync-connect t) (eglot-connect-timeout timeout)) (apply #'eglot--connect (eglot--guess-contact)))) diff --git a/test/integration-tests.el b/test/integration-tests.el index 52fb570..65e7e07 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -48,26 +48,28 @@ (eglot-fsharp--maybe-install) (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") (eglot-fsharp--tests-connect 10) - (eglot-fsharp--sniff-method "fsharp/notifyWorkspace"))) + ;; (eglot-fsharp--sniff-method "fsharp/notifyWorkspace") + ) + ) (it "Can be invoked" ;; FIXME: Should use dotnet tool run (expect (process-file (eglot-fsharp--path-to-server) nil nil nil "--version") - :to-equal 0)) + :to-equal 0)) (it "is enabled on F# Files" (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete))) - (it "shows flymake errors" - (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Error.fs") - (flymake-mode t) - (flymake-start) - (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") - (goto-char (point-min)) - (search-forward "nonexisting") - (insert "x") - (eglot--signal-textDocument/didChange) - (flymake-goto-next-error 1 '() t) - (expect (face-at-point) :to-be 'flymake-error ))) + ;; (it "shows flymake errors" + ;; (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Error.fs") + ;; (flymake-mode t) + ;; (flymake-start) + ;; (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") + ;; (goto-char (point-min)) + ;; (search-forward "nonexisting") + ;; (insert "x") + ;; (eglot--signal-textDocument/didChange) + ;; (flymake-goto-next-error 1 '() t) + ;; (expect (face-at-point) :to-be 'flymake-error ))) (it "provides completion" (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil))) From 41f31e91e2632d1f51ce58a174531fdfc6098f13 Mon Sep 17 00:00:00 2001 From: 64J0 Date: Fri, 7 Feb 2025 19:23:04 -0300 Subject: [PATCH 116/120] add pr template --- .github/pull_request_template.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..e27a787 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +## Description + + + +## How to test + + + +## Related issues + + From 08e6efa7c8d86f2684cbfba9afde9c2e86968414 Mon Sep 17 00:00:00 2001 From: 64J0 Date: Tue, 25 Feb 2025 17:53:50 -0300 Subject: [PATCH 117/120] bump tests fsautocomplete version to 0.77.2 --- test/integration-tests.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration-tests.el b/test/integration-tests.el index 65e7e07..6534f6c 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -34,9 +34,9 @@ (unless (eq system-type 'windows-nt) (describe "F# LSP Installation" :before-all (setq latest-version (eglot-fsharp--latest-version)) - (it "succeeds using version 0.52.0" - (eglot-fsharp--maybe-install "0.52.0") - (expect (eglot-fsharp--installed-version) :to-equal "0.52.0")) + (it "succeeds using version 0.77.2" + (eglot-fsharp--maybe-install "0.77.2") + (expect (eglot-fsharp--installed-version) :to-equal "0.77.2")) (it (format "succeeds using latest version: %s)" latest-version) (eglot-fsharp--maybe-install) (expect (eglot-fsharp--installed-version) :to-equal latest-version)))) From 466c04d800b46f3577744a166e696bfec998fe98 Mon Sep 17 00:00:00 2001 From: 64J0 Date: Wed, 26 Feb 2025 19:08:17 -0300 Subject: [PATCH 118/120] uncomment broken tests --- test/integration-tests.el | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/test/integration-tests.el b/test/integration-tests.el index 6534f6c..6fbe599 100644 --- a/test/integration-tests.el +++ b/test/integration-tests.el @@ -48,9 +48,7 @@ (eglot-fsharp--maybe-install) (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") (eglot-fsharp--tests-connect 10) - ;; (eglot-fsharp--sniff-method "fsharp/notifyWorkspace") - ) - ) + (eglot-fsharp--sniff-method "fsharp/notifyWorkspace"))) (it "Can be invoked" ;; FIXME: Should use dotnet tool run @@ -59,17 +57,17 @@ (it "is enabled on F# Files" (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete))) - ;; (it "shows flymake errors" - ;; (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Error.fs") - ;; (flymake-mode t) - ;; (flymake-start) - ;; (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") - ;; (goto-char (point-min)) - ;; (search-forward "nonexisting") - ;; (insert "x") - ;; (eglot--signal-textDocument/didChange) - ;; (flymake-goto-next-error 1 '() t) - ;; (expect (face-at-point) :to-be 'flymake-error ))) + (it "shows flymake errors" + (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Error.fs") + (flymake-mode t) + (flymake-start) + (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs") + (goto-char (point-min)) + (search-forward "nonexisting") + (insert "x") + (eglot--signal-textDocument/didChange) + (flymake-goto-next-error 1 '() t) + (expect (face-at-point) :to-be 'flymake-error ))) (it "provides completion" (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs") (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil))) From 4fe16b07518cad6caa5a2072a5b92309c0650885 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 21 Mar 2023 17:21:31 +0100 Subject: [PATCH 119/120] Add (failing) indentation test for first line after opening bracket --- test/fsharp-mode-structure-tests.el | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/fsharp-mode-structure-tests.el b/test/fsharp-mode-structure-tests.el index dd6653b..7792b38 100644 --- a/test/fsharp-mode-structure-tests.el +++ b/test/fsharp-mode-structure-tests.el @@ -271,3 +271,11 @@ (should (eq (fsharp--compute-indentation-relative-to-previous t) 4)) (should (eq (fsharp--compute-indentation-relative-to-previous t) (fsharp-compute-indentation t)))))) + +(describe "The `fsharp-compute-indentation'" + :var ((file (concat fsharp-struct-test-files-dir "BracketIndent.fs"))) + (it "indents on the first line after opening bracket" + (with-current-buffer (find-file-noselect file) + (goto-char (point-min)) + (search-forward-regexp "let formatTwo = \\[\n") + (should (eq (fsharp-compute-indentation t) fsharp-indent-offset))))) From bb32718845beae427aba713203571daccdd5fea9 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Tue, 21 Mar 2023 17:22:26 +0100 Subject: [PATCH 120/120] Indentation: Handle first line after opening bracket Fixes: "End position is smaller than start position" error. --- fsharp-mode-structure.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index b7664fb..30376a3 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -766,6 +766,10 @@ dedenting." (open-bracket-pos (fsharp-nesting-level))) (cond + ((and open-bracket-pos (eq (and (looking-back "[[:space:]\n\r]+" nil t) + (match-beginning 0)) + (1+ open-bracket-pos))) + fsharp-indent-offset) ;; Continuation Lines ((fsharp-continuation-line-p) (if open-bracket-pos