microsoft / qsharp-compiler

Q# compiler, command line tool, and Q# language server
https://docs.microsoft.com/quantum
MIT License
682 stars 171 forks source link

Code completion doesn't recognize attributes #659

Open bamarsha opened 4 years ago

bamarsha commented 4 years ago

Describe the bug

After typing @, typing a letter or pressing Ctrl+Space shows completions for all identifiers and keywords, not just attribute names.

To Reproduce

Steps to reproduce the behavior:

  1. Open a Q# file in Visual Studio Code.
  2. Type @r in a namespace:

    namespace Example {
        @r
    }
  3. Code completion shows identifiers that aren't valid as attributes, like the repeat keyword.

Expected behavior

Code completion should only valid attribute names. It is probably easier to show all user-defined types instead of only user-defined types with the @Attribute() attribute, since I don't think code completion is capable of filtering by attributes right now.

Screenshots

grafik

System information

Additional context

CodeCompletion\FragmentParsing.fs is probably a good place to start. The modifiers parser can parse things that appear before a declaration, like the internal keyword. It should be possible to also parse the @ symbol here followed by a user-defined type name.

https://github.com/microsoft/qsharp-compiler/blob/edc3d1557d62dc3cf1175caf6386e78aee91eb03/src/QsCompiler/TextProcessor/CodeCompletion/FragmentParsing.fs#L25-L27

ashwinpilgaonkar commented 4 years ago

Hi @samarsha, is it okay if I attempt to fix this?

bamarsha commented 4 years ago

Hi @ashwinpilgaonkar, yes, feel free to start working on this! Let me know if you have any questions.

ashwinpilgaonkar commented 4 years ago

@samarsha sure will do, thanks.

ashwinpilgaonkar commented 4 years ago

Hi @samarsha, I seem to be having some trouble with installing the development VSIX extension.

I took the following steps to setup my development environment as per the docs:

  1. Installed vsce globally using npm
  2. Cloned the project and ran bootstrap.ps1
  3. Followed the steps to build a self-contained version of the language server using dotnet publish
  4. Ran vsce package to produce an installable VSIX
  5. Attempted to install the generated VSIX file into VS Code using Local Extension Installer by Edgar Geier

The module activation fails and gives the following error:

[2020-10-05 17:22:09.679] [exthost] [info] ExtensionService#_doActivateExtension quantum.quantum-devkit-vscode {"startup":false,"extensionId":{"value":"quantum.quantum-devkit-vscode","_lower":"quantum.quantum-devkit-vscode"},"activationEvent":"onLanguage:qsharp"}
[2020-10-05 17:22:09.679] [exthost] [info] ExtensionService#loadCommonJSModule file:///c:/Users/ashpi/.vscode/extensions/quantum.quantum-devkit-vscode-0.9999.20102010/out/extension
[2020-10-05 17:22:09.701] [exthost] [error] Activating extension quantum.quantum-devkit-vscode failed due to an error:
[2020-10-05 17:22:09.703] [exthost] [error] Error: Cannot find module 'vscode-extension-telemetry'
Require stack:
- c:\Users\ashpi\.vscode\extensions\quantum.quantum-devkit-vscode-0.9999.20102010\out\telemetry.js
- c:\Users\ashpi\.vscode\extensions\quantum.quantum-devkit-vscode-0.9999.20102010\out\extension.js
- c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\loader.js
- c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\bootstrap-amd.js
- c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\bootstrap-fork.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:844:17)
    at Module._load (internal/modules/cjs/loader.js:737:27)
    at Function.Module._load (electron/js2c/asar.js:769:28)
    at Function.t._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1046:268)
    at Function.i._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1015:981)
    at Function.n._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1012:303)
    at Module.require (internal/modules/cjs/loader.js:899:19)
    at n (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\loader.js:16:135)
    at Object.<anonymous> (c:\Users\ashpi\.vscode\extensions\quantum.quantum-devkit-vscode-0.9999.20102010\out\telemetry.js:7:38)
    at Module.o._compile (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\loader.js:16:360)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1051:10)
    at Module.load (internal/modules/cjs/loader.js:862:32)
    at Module._load (internal/modules/cjs/loader.js:774:14)
    at Function.Module._load (electron/js2c/asar.js:769:28)
    at Function.t._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1046:268)
    at Function.i._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1015:981)
    at Function.n._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1012:303)
    at Module.require (internal/modules/cjs/loader.js:899:19)
    at n (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\loader.js:16:135)
    at Object.<anonymous> (c:\Users\ashpi\.vscode\extensions\quantum.quantum-devkit-vscode-0.9999.20102010\out\extension.js:16:21)
    at Module.o._compile (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\loader.js:16:360)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1051:10)
    at Module.load (internal/modules/cjs/loader.js:862:32)
    at Module._load (internal/modules/cjs/loader.js:774:14)
    at Function.Module._load (electron/js2c/asar.js:769:28)
    at Function.t._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1046:268)
    at Function.i._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1015:981)
    at Function.n._load (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1012:303)
    at Module.require (internal/modules/cjs/loader.js:899:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Function.s [as __$__nodeRequire] (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\loader.js:33:604)
    at p._loadCommonJSModule (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:1017:241)
    at p._doActivateExtension (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:915:625)
    at p._activateExtension (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:914:708)
    at Object.actualActivateExtension (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:912:453)
    at h._activateExtension (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:644:731)
    at c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:644:409
    at Array.map (<anonymous>)
    at h._activateExtensions (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:644:397)
    at h.activateById (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:642:207)
    at p._activateById (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:913:363)
    at p.$activate (c:\Users\ashpi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\services\extensions\node\extensionHostProcess.js:922:391)
    at processTicksAndRejections (internal/process/task_queues.js:94:5)

I even tried to globally install vscode-extension-telemetry using npm but it doesn't seem to solve the problem.

I haven't received any errors at any of the other steps. I'm running the latest version Windows 10 (64-bit), VS Code and .NET Core.

I'm unable to figure out why this is happening. Is there something I'm missing?

bamarsha commented 4 years ago

It looks like the same error is affecting the latest release of the QDK extension for VS Code, actually, so it seems like it is a separate issue that we will hopefully have a fix for soon. However, for some reason it doesn't affect me when I build the VSIX using vsce package - the extension seems to work when I install it.

Can you double-check that there is a node_modules folder in the repository's src/VSCodeExtension folder? If not, running npm install should create it.

Also, instead of using vsce package, you could try running the extension in an experimental VS Code instance. The instructions in the "Debugging" section should help: https://github.com/microsoft/qsharp-compiler/blob/main/src/VSCodeExtension/BUILDING.md#debugging

bamarsha commented 4 years ago

The "Cannot find module 'vscode-extension-telemetry'" problem looks like it was caused by a recent update to vsce, but I think that a new update has fixed it - @ashwinpilgaonkar can you try running npm install -g vsce to update vsce and then building the VSIX again?

ashwinpilgaonkar commented 4 years ago

Hi @samarsha, thanks for all the info! You can find my replies stated below -

The "Cannot find module 'vscode-extension-telemetry'" problem looks like it was caused by a recent update to vsce, but I think that a new update has fixed it - @ashwinpilgaonkar can you try running npm install -g vsce to update vsce and then building the VSIX again?

I just tried it. The same error still shows up.

It looks like the same error is affecting the latest release of the QDK extension for VS Code, actually, so it seems like it is a separate issue that we will hopefully have a fix for soon. However, for some reason it doesn't affect me when I build the VSIX using vsce package - the extension seems to work when I install it.

Oh, I see.

Can you double-check that there is a node_modules folder in the repository's src/VSCodeExtension folder? If not, running npm install should create it.

You're right, the node_modules folder was indeed missing. I ran npm install, but it doesn't seem to change anything. FYI, regardless of whether the node_modules is present or not, VSCode does detect the installation of the extension (I get the option to uninstall/disable it). But the autocomplete doesn't work and VSCode throws the following error Could not download Q# language server.

When I build a self-contained version of the language server and set the quantumDevKit.languageServerPath path in settings.json, it throws up another error - The Q# Language Server has encountered an error. Diagnostics will be reloaded upon saving the file. Details on the encountered error have been logged to the output window.

[Info  - 5:11:24 pm] workspace folder: c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension
[Error - 5:11:27 pm] Error on loading project 'c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\library\Library.csproj': The SDK 'Microsoft.Quantum.Sdk/0.9999.2010.2010-alpha' specified could not be found.  c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\library\Library.csproj.
Ignoring non-Q# project 'c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\library\Library.csproj'.
[Error - 5:11:28 pm] Error on loading project 'c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\unittest\Test.csproj': The SDK 'Microsoft.Quantum.Sdk/0.9999.2010.2010-alpha' specified could not be found.  c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\unittest\Test.csproj.
Ignoring non-Q# project 'c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\unittest\Test.csproj'.
[Error - 5:11:28 pm] Error on loading project 'c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\application\Application.csproj': The SDK 'Microsoft.Quantum.Sdk/0.9999.2010.2010-alpha' specified could not be found.  c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\application\Application.csproj.
Ignoring non-Q# project 'c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\templates\application\Application.csproj'.
[Error - 5:11:28 pm] Error on loading project 'C:\Users\ashpi\AppData\Local\Temp\qsharp\c_x2f__x2f_Users_x2f_ashpi_x2f_OneDrive_x2f_Documents_x2f_Work_x2f_Open Source_x2f_qsharp-compiler_x2f_src_x2f_VSCodeExtension\generated.csproj': The SDK 'Microsoft.Quantum.Sdk/0.9999.2010.2010-alpha' specified could not be found.  C:\Users\ashpi\AppData\Local\Temp\qsharp\c_x2f__x2f_Users_x2f_ashpi_x2f_OneDrive_x2f_Documents_x2f_Work_x2f_Open Source_x2f_qsharp-compiler_x2f_src_x2f_VSCodeExtension\generated.csproj.
Ignoring non-Q# project 'C:\Users\ashpi\AppData\Local\Temp\qsharp\c_x2f__x2f_Users_x2f_ashpi_x2f_OneDrive_x2f_Documents_x2f_Work_x2f_Open Source_x2f_qsharp-compiler_x2f_src_x2f_VSCodeExtension\generated.csproj'.
[Info  - 5:11:28 pm] Failed to load temporary .csproj for c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\Program.qs.
[Info  - 5:11:29 pm] The file c:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\VSCodeExtension\Program.qs is not associated with a compilation unit. Only syntactic diagnostics are generated.
[Error - 5:11:36 pm] 
=============================
System.ArgumentException: no namespace with the given name exists
   at Microsoft.Quantum.QsCompiler.SymbolManagement.NamespaceManager.TryResolveQualifier(NonNullable`1 qualifier, NonNullable`1 nsName, NonNullable`1 source) in C:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\QsCompiler\Core\SymbolTable.fs:line 805
   at Microsoft.Quantum.QsCompiler.SymbolManagement.NamespaceManager.TryGetCallableHeader(QsQualifiedName callableName, FSharpOption`1 declSource, NonNullable`1 nsName, NonNullable`1 source) in C:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\QsCompiler\Core\SymbolTable.fs:line 1586
   at Microsoft.Quantum.QsCompiler.SymbolManagement.NamespaceManager.TryGetCallable(QsQualifiedName callableName, NonNullable`1 nsName, NonNullable`1 source) in C:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\QsCompiler\Core\SymbolTable.fs:line 1600
   at Microsoft.Quantum.QsCompiler.CompilationBuilder.SuggestedEdits.SuggestionsForIndexRange(FileContentManager file, CompilationUnit compilation, Range range) in C:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\QsCompiler\CompilationManager\EditorSupport\CodeActions.cs:line 396
   at Microsoft.Quantum.QsCompiler.CompilationBuilder.EditorCommands.CodeActions(FileContentManager file, CompilationUnit compilation, Range range, CodeActionContext context) in C:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\QsCompiler\CompilationManager\EditorSupport\EditorCommands.cs:line 146
   at Microsoft.Quantum.QsCompiler.CompilationBuilder.ProjectManager.<>c__DisplayClass25_0.<CodeActions>b__0(FileContentManager file, CompilationUnit c) in C:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\QsCompiler\CompilationManager\ProjectManager.cs:line 1032
   at Microsoft.Quantum.QsCompiler.CompilationBuilder.CompilationUnitManager.<FileQuery>g__TryQueryFile|31_0[T](FileContentManager f, <>c__DisplayClass31_0`1& ) in C:\Users\ashpi\OneDrive\Documents\Work\Open Source\qsharp-compiler\src\QsCompiler\CompilationManager\CompilationUnitManager.cs:line 717
=============================

Also, instead of using vsce package, you could try running the extension in an experimental VS Code instance. The instructions in the "Debugging" section should help: https://github.com/microsoft/qsharp-compiler/blob/main/src/VSCodeExtension/BUILDING.md#debugging

Could you help me out with this? I went through the docs but I was unable to locate the Debug tab in VSCode. From the Debug tab in VS Code, ensure that "Extension" is selected in the Debug target menu and press the green ‣.

bamarsha commented 4 years ago

But the autocomplete doesn't work and VSCode throws the following error Could not download Q# language server.

I think this is normal. The extension tries to download a language server with the same version as the extension, but since you built the extension manually, a language server with a matching version number doesn't exist on the download server. So I think setting quantumDevKit.languageServerPath is necessary here.

When I build a self-contained version of the language server and set the quantumDevKit.languageServerPath path in settings.json, it throws up another error - The Q# Language Server has encountered an error. Diagnostics will be reloaded upon saving the file. Details on the encountered error have been logged to the output window.

This is also probably normal, unfortunately - since the language server is asynchronous, sometimes it receives commands that are no longer valid for the current state. These cause exceptions which are ignored in the release build but are shown in debug builds. I think it would be good if the language server handled this more nicely - generally if something is expected to happen often it shouldn't throw an exception, but for now I think it's probably safe to ignore them.

Could you help me out with this? I went through the docs but I was unable to locate the Debug tab in VSCode.

When you have the VSCodeExtension folder open in VS Code, there should be a button on the right that has a triangle and a bug. If you click that, then click the green triangle at the top, it should run the extension:

grafik

ashwinpilgaonkar commented 4 years ago

I think this is normal. The extension tries to download a language server with the same version as the extension, but since you built the extension manually, a language server with a matching version number doesn't exist on the download server. So I think setting quantumDevKit.languageServerPath is necessary here.

Yes.

This is also probably normal, unfortunately - since the language server is asynchronous, sometimes it receives commands that are no longer valid for the current state. These cause exceptions which are ignored in the release build but are shown in debug builds. I think it would be good if the language server handled this more nicely - generally if something is expected to happen often it shouldn't throw an exception, but for now I think it's probably safe to ignore them.

Oh, I see. Okay.

When you have the VSCodeExtension folder open in VS Code, there should be a button on the right that has a triangle and a bug. If you click that, then click the green triangle at the top, it should run the extension:

Thanks, I was able to get the experimental mode running now!

However, there is still a difference in output between the official latest build and the development version, regardless of whether it is installed as a VSIX extension, or being run in debug mode in an experimental instance of VSCode.

image Dev build

image Official latest build

bamarsha commented 4 years ago

Are you editing a Q# file that is not part of a Q# project? Can you try creating a new Q# project and opening a file inside the project folder? One way to do this is press Ctrl+Shift+P and then type "q# create" in the command palette.

The extra completion items RangeEnd, RangeReverse, etc. come from library functions, which means that a project file needs to exist that has a reference to the library package. If you open a Q# file outside of a project folder, the language server tries to automatically create a project file to use, but the project file it creates has a reference to a package with the same version as the language server itself. Since that version number was created locally and doesn't exist on the package server, the autogenerated project file won't work on non-release versions of the language server. #614 is the issue relating to this.

Also, thanks for your patience through all of these confusing issues. :) I think that I will add these to the README/BUILDING.md files so that getting started with developing the language server is more clear in the future.

ashwinpilgaonkar commented 4 years ago

Are you editing a Q# file that is not part of a Q# project? Can you try creating a new Q# project and opening a file inside the project folder? One way to do this is press Ctrl+Shift+P and then type "q# create" in the command palette.

Yes, all along I was using a sample .qs file that wasn't part of a Q# project. Both the screenshots I provided in my previous reply were obtained after testing on that file. I did as you said and created a new Q# project. Now the outputs are matching in both cases. That's one problem solved!

The extra completion items RangeEnd, RangeReverse, etc. come from library functions, which means that a project file needs to exist that has a reference to the library package. If you open a Q# file outside of a project folder, the language server tries to automatically create a project file to use, but the project file it creates has a reference to a package with the same version as the language server itself. Since that version number was created locally and doesn't exist on the package server, the autogenerated project file won't work on non-release versions of the language server. #614 is the issue relating to this.

Okay, it makes a lot of sense now.

Also, thanks for your patience through all of these confusing issues. :) I think that I will add these to the README/BUILDING.md files so that getting started with developing the language server is more clear in the future.

It's no problem at all! In fact its things like these that add to the learning experience. :)

ashwinpilgaonkar commented 4 years ago

Also, just to confirm - this fix should filter out and display only RangeEnd, RangeReverse, RangeStart and RangeStep in the case of "@r,,," correct?

bamarsha commented 4 years ago

I think this screenshot might be a better example:

grafik

I think the only things that should be shown are:

Although ExampleType is technically not an attribute, code completion only supports filtering based on categories like "callable" and "user-defined type" currently. So I think it's OK if we show all user-defined types, even if they aren't necessarily attributes - it would still be a big improvement over the current behavior, and we can possibly add more specific filtering later.

There are also two of each for EntryPoint and ExampleType because one of them is the type itself and the other is the type constructor (which is a callable). If code completion shows only user-defined types, then only the ones with the gray rectangle and two squares should be shown, not the purple cube ones.

ashwinpilgaonkar commented 4 years ago

@samarsha I was going through the FragmentParsing.fs file. Suppose I want to print the output of this statement -

let private modifiers =
    expectedKeyword qsInternal

How can I do that? Where can I view the output?

bamarsha commented 4 years ago

modifiers has type Parser<'a, 'b>, which is basically like a function that takes in a string input and returns a parser result. I think the easiest way to run the parser directly is using F# Interactive:

  1. Temporarily remove private from let private modifers so we can access it from a script.
  2. Open a terminal in the qsharp-compiler\src\QsCompiler\TextProcessor folder.
  3. Run these commands:
dotnet publish
dotnet fsi -I bin\Debug\netstandard2.1\publish -r Microsoft.Quantum.QsTextProcessor.dll

This should open F# Interactive where you can type in F# code now.

open FParsec;;
open Microsoft.Quantum.QsCompiler.TextProcessing.CodeCompletion.FragmentParsing;;
"" + "\u0004" |> runParserOnString modifiers [] "";;

That should output:

val it :
  ParserResult<Quantum.QsCompiler.TextProcessing.CodeCompletion.CompletionKind list,
               Quantum.QsCompiler.DataTypes.QsCompilerDiagnostic list> =
  Success: [Keyword "internal"]

This means that modifiers successfully parsed the empty string "" and said that the internal keyword can appear here. You can try replacing "" with "int", "foo", etc. and it should give the same output. However, if you try to parse "@", it says:

"@" + "\u0004" |> runParserOnString modifiers [] "";;
val it :
  ParserResult<Quantum.QsCompiler.TextProcessing.CodeCompletion.CompletionKind list,
               Quantum.QsCompiler.DataTypes.QsCompilerDiagnostic list> =
  Failure:
Error in Ln: 1 Col: 1
@♦
^
Expecting: identifier, '\u0004' or 'internal'

This part is what we want to change - we want it to recognize @ and say that a user-defined type can follow it.