Giter Site home page Giter Site logo

rubberduck3's Introduction

rubberduck-vba

Github-Pages rendering at rubberduck-vba.github.io

rubberduck3's People

Contributors

bzngr avatar mansellan avatar retailcoder avatar tommy9 avatar vogel612 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rubberduck3's Issues

View rubberduck.db online

Hi, Quick issue I will close soon

I'm trying to use this website https://sqliteonline.com/ to view the .db file https://github.com/rubberduck-vba/Rubberduck3/blob/main/Server/Database/Rubberduck.db. I want to know the schema of the db and just view how it is structured. I am able to view the tables but not the Views. The views I guess are higher level structures than the raw tables. If I use

SELECT * From Projects_v1

I get an error that the ID column is ambiguous.

Maybe we are not using the same flavour of SQL it expects? Any tips for viewing that file?

[EPIC] Shell UI

UI work to do around the Rubberduck Editor main window, at a high level.

  • Initializes LSP server (client: addin process)

  • Initializes VBA LSP client

  • Initializes JSON LSP client

  • Accepts workspace root and client process id as command-line arguments

    • Opens workspace provided by command-line args on startup
  • Can load settings from file

    • Can merge with defaults
  • Selectable/dynamic theming (JSON)

    • Light/blue theme (ref.Visual Studio)
      • Looks awesome
    • Dark theme (ref.Visual Studio)
      • Looks awesome
    • Dark/blue theme (ref.VSC/"Abyss")
      • Looks awesome
    • Theme settings
      • ThemeColorSetting record and UI (color picker?)
        • Can render a preview
      • Accents (4)
      • Gradients (4) (auto?)
      • Syntax highlighting palette
        • Client-side regex-based simple rules
        • Semantic highlighting from LSP server
      • Looks awesome
  • Docking panels (side, bottom)

    • Can be hidden/collapsed
    • Can be expanded
    • Can be pinned to remain expanded
    • Option to expand on hover (vs only on click)
    • Looks awesome
  • Tooltabs

    • Can be pinned from frame header
    • Can be closed from frame header
    • Can be dragged from frame header
    • Tooltab header styling respects theme
    • Shows title in frame header
    • Shows settings command in frame header
    • Frame header context menu
      • Can undock tooltab
      • Can pin tooltab
      • Can close tooltab
  • Document/editor tabs

    • Can be pinned (from tab header)
    • Can be closed (from tab header)
    • Tab header styling respects theme
    • Tab header context menu
      • Can undock tab
      • Can pin tab
      • Can close tab
      • Can close all tabs but this one
      • Can close all unpinned tabs
  • Status bar UI

    • Shows server connection status
      • Icon/button shows the server trace toolwindow
    • Shows progress indicator for server-side (LSP) progress reports
      • Can cancel cancellable server operations
    • Document status template
      • Document name
      • Document type
      • IsModified indicator
      • Number of lines
      • Number of characters (bytes?)
      • L1C1 caret location / current selection
    • Source file status template
      • Shows module/component type
      • Shows number of diagnostics in module
        • Button shows diagnostics toolwindow
  • Menu bar UI

    • File menu commands
      • Synchronize workspace
    • Edit menu commands
    • View menu commands
    • Project menu commands
    • Debug menu commands
    • Test menu commands
    • Analyze menu commands
    • Tools menu commands
    • Windows menu commands
    • Help menu commands
    • Looks awesome
  • Floating/undocked document windows

    • Can be re-docked to main window's document tab host
    • Can accept/dock other document tabs
    • Has a status bar
    • Looks awesome
  • Floating/undocked toolwindows

    • Can be re-docked on either side or bottom tooltab areas
      • Toolwindows have a horizontal template when docked at the bottom
    • Can accept/dock other document tabs
    • Looks awesome
  • Base toolwindow UI ("ThunderFrame")

    • Can bind close, pin, and show [that tool's] settings commands
    • Shows title
    • Can bind accept/cancel commands
    • Looks awesome
  • Document tab templates

    • Text document template
    • Markdown document template
      • Shows a preview pane
    • JSON document template
    • Source file document template
    • Looks awesome
  • MessageBox dialog +service

    • ShowMessage/ShowMessageRequest LSP handlers
    • Can render markdown
    • Can be ignored ("do not show again")
    • Can be expanded to show additional markdown content
    • Looks awesome
  • New Project dialog

    • Shows VBA projects from VBE add-in
    • Hides projects drop-down when running without the VBE add-in
    • Can create a project from a template
    • Creates workspace folders
    • Opens the created project
    • Looks awesome
  • Workspace Explorer toolwindow

    • Represents workspaces in a tree view
      • ...without glitchy nodes that shouldn't be there
    • Toolbar shortcuts to create new project/workspace, open existing
    • Open file command (LSP)
      • Bind ENTER and double-click
      • Bind drop into editor document tab host
    • Folder icons change on expand
    • Can be shown (empty) on startup
    • Can rename files/folders
      • Bind to F2 and selected-click
    • Sends LSP notifications
    • Can create files/folders
      • Sends LSP notifications
    • Can delete files/folders
      • Bind to DELETE key
      • Sends LSP notifications
    • Can move (drag/drop) files/folders
      • Sends LSP notifications
    • Can drop files/folders from Windows Explorer (copies them to workspace)
    • Looks awesome
  • Code (Project?) Explorer toolwindow

    • Shows project folders and source files in a tree view
    • Can show all opened projects (like workspaces for workspace explorer)
    • Can show module members
    • Can show/hide signatures
    • Can search/filter nodes
    • Can add/remove modules (LSP)
    • Can add/remove forms (LSP)
    • Can add/remove folders (LSP)
    • Can open documents (LSP)
    • Looks awesome
  • Settings dialog

    • Boolean settings template
    • String setting template
    • Numeric setting template
    • TimeSpan setting template
    • Enum setting template (per enum)
    • List setting template
      • Can remove items from UI
    • Merge and serialize settings, defaults
    • Saves to disk/apply on change
      • Option to save/apply on close
    • Can drag-resize sections
    • Can drag-move/reorder sections
    • Can save/load section layout
    • Can show+focus specific settings
    • Looks awesome
  • Language Server toolwindow

    • Can be paused
    • Can select verbosity
    • Command to open log file
    • Shows LSP LogTrace messages
      • Autoscrolls to bottom
    • Looks awesome
  • Update Server Toolwindow

    • Can be stopped, restarted
    • Can select verbosity
    • Command to open log file
    • Shows update server stdout
      • Autoscrolls to bottom
    • Can check for updates
      • Can schedule to update on close
      • Can skip an update (that would be a "list"-type setting, already exists)
    • Can browse tags, release notes
    • Can rollback an update, install any previous release
    • Looks awesome
  • About dialog

    • Shows version info for RD Editor
    • Shows version info for all servers
    • Lists contributors
    • Lists libraries
    • Credits artworks
    • Links to website, repo, org, shop/ko-fi
    • Looks awesome

Pre-compilation pass to capture alternate definitions

Rubberduck needs a way to access the "dead code" tokens from the pre-compilation parse pass.

That way we could access the different possible declarations of a given definition (RD got 'em backwards I think), and thus support the LSP "definition" (or "declaration"?) requests.

Rubberduck 2.x assumed to be working with compilable code at all times, and would bail otherwise.

Rubberduck 3.0 reports syntax errors instead, so we get to analyze error nodes and still work out the identifier names here:

#If True Then
Sub DoSomething(ByVal Value As Long)
#Else
Sub DoSomething(ByVal Value As Variant)
#End If
   '...
End Sub

There might be a way to recover these nodes as some ConditionalCompilationDeadCodeContext, or to otherwise have a way to suppress the conditional compilation related "syntax errors" - so they don't consistently appear with red squiggles in the Rubberduck Editor. The error handler already filters some specific syntax errors to issue specific error messages, it's wouldn't be impossible to achieve the desired result via syntax errors.

Having this information also allows the LSP server to mark that code as "unreachable" for formatting purposes, so the editor can (should) render it dimmed/fainted. It also gives us multiple navigable definitions for that DoSomething procedure and Value parameter`. Only one of these definitions is ever "live", so identifier resolution and the semantic layer wouldn't necessarily need major tweaks to support this, I think.

Implement a workspace service

Upon initialization, add-in client should set up a virtual workspace that can have virtual folders. Loaded documents should be in this virtual namespace when working in-memory.

Service needs to:

  • expose Load and Unload methods to synchronize the documents loaded in the workspace to and from the VBIDE
  • expose Import and Export methods to synchronize the workspace with a physical folder in the file system (host document must be saved).
  • when bound to a physical root folder, leverage a FileSystemWatcher to synchronize content.
  • expose CreateFolder, RemoveFolder, and RenameFolder methods.
  • expose CreateFile, RemoveFile, and RenameFile methods.

The abstract interface IWorkspaceService should be defined under Rubberduck.Client and implemented under Rubberduck.Server.LSP.

Implement DidChangeTextDocument LSP handler

Specification (LSP)

The document change notification is sent from the client to the server to signal changes to a text document. Before a client can change a text document it must claim ownership of its content using the textDocument/didOpen notification.

The notification sends an array of TextDocumentContentChangeEvent objects, each representing a distinct change of state for a specific Range in a given version of a given document. Client may send the full document every time, or send incremental edits (let's start with full-document only for now).

The editor may send didChange notifications on an idle timer - that is, whenever the user stops typing for a certain (configurable) amount of time.

Alternatively (through editor settings), the user might prefer sending this notification manually; the editor UI should expose a command to do so - the flow is then similar to Rubberduck 2.x, where the parser state is manually refreshed; the command should send a content changed event for each document that was modified since the last synchronization.

LocalDb settings UI

👀 Follows Client console GUI app

Design a XAML control to be loaded into a settings tab in the LocalDb client console application, to be reused in the Rubberduck settings dialog.

LocalDb settings include server and console settings that are shared with other RPC servers; the UI for these settings should be implemented in separate XAML controls that can be reused for the LSP server settings. LocalDb-specific settings are yet to be determined.

[EPIC] Language Server

Phase I

  • Initialize with a client
  • Receive file contents in LSP handlers
  • Load project references
  • Parse all project files
    • Send WorkdoneProgressStart and notify client of ongoing progress
    • Prioritize opened files
    • Send client folding ranges as soon as parse trees are available

Phase II

  • Port the latest RD 2.x parser to the new paradigm
    • Send client semantic highlighting for the active document tab first, open documents second, all others last
    • Send client diagnostics with the same prioritization
  • Implement server-side rename refactoring
    • Send client PreviewRename notification
  • Implement server-side "formatting"
    • Indenter settings

Phase III

  • Handle parameter info requests
  • Handle completion list requests
  • Handle auto-formatting requests

Load a document

The document open notification is sent from the client to the server to signal newly opened text documents. The document’s content is now managed by the client and the server must not try to read the document’s content using the document’s Uri. Open in this sense means it is managed by the client. It doesn’t necessarily mean that its content is presented in an editor. An open notification must not be sent more than once without a corresponding close notification send before. This means open and close notification must be balanced and the max open count for a particular textDocument is one. Note that a server’s ability to fulfill requests is independent of whether a text document is open or closed.

The server receives a TextDocumentItem with the notification:

interface TextDocumentItem {
	/**
	 * The text document's URI.
	 */
	uri: DocumentUri;

	/**
	 * The text document's language identifier.
	 */
	languageId: string;

	/**
	 * The version number of this document (it will increase after each
	 * change, including undo/redo).
	 */
	version: integer;

	/**
	 * The content of the opened text document.
	 */
	text: string;
}

So this is where the server receives the text of the document at a given version. The languageId should be vba, to avoid clashing with "VB.NET" vb. The uri points to a path relative to the workspace root.

The string contains the complete file contents, including headings and attributes that are hidden in the VBIDE, so that's what we want to parse, and we'll want to quickly get a parse tree for it, cache it with the document uri and version as a key... and then sit on it for now - eventually the LSP server is going to send various notifications to the client, and we'll want to launch a semantic pass over all the parse trees and declarations, so having a parse tree associated to a specific version of a document URI is a very good starting point.

This supposes something is holding this state in some (thread-safe) dictionary: we'll need to inject a service that's responsible for just that.

  • Have an abstraction that provides an API to map TextDocumentItem to a parse tree, and to retrieve a parse tree for a given document URI and version
  • Have an abstraction that provides a parse tree given the text content of a TextDocumentItem.
  • Implement a DidOpenHandler class
    • InheritOmniSharp.Extensions.LanguageServer.Protocol.Document.DidOpenTextDocumentHandlerBase; constructor-inject state service
    • Implement the Handle override; access the document from the request parameter (DidOpenTextDocumentParams).
    • Implement the CreateRegistrationOptions override (specify DocumentSelector filters)

Log successful execution of the handler at INFO level; exceptions can be caught, but must be rethrown to return an error result at the JSON-RPC level.

Workspace endpoints (client -> server)

Workspace client-to-server RPC endpoints include the following requests/methods:

Server

  • Configuration (workspace/configuration)
  • ConfigurationDidChange (workspace/didChangeConfiguration)
  • ExecuteCommand (workspace/executeCommand)

File

⚠ Note: in LSP "file" refers and applies to both files and folders.

  • WatcherChanged (workspace/didChangeWatchedFiles)
  • Folders (workspace/workspaceFolders)
  • FoldersDidChange (workspace/didChangeWorkspaceFolders)
  • WillCreate (workspace/willCreateFiles)
  • DidCreate (workspace/didCreateFiles)
  • WillRename (workspace/willRenameFiles)
  • DidRename (workspace/didRenameFiles)
  • WillDelete (workspace/willDeleteFiles)
  • DidDelete (workspace/didDeleteFiles)

Language

  • Diagnostics (workspace/diagnostic)
  • Symbols (workspace/symbol)
  • ResolveSymbol (workspaceSymbol/resolve)

Implement workspace/willRenameFiles notification

Specifications (LSP)

The will rename files request is sent from the client to the server before files are actually renamed as long as the rename is triggered from within the client either by a user action or by applying a workspace edit. The request can return a WorkspaceEdit which will be applied to workspace before the files are renamed. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep renames fast and reliable.

The handler for this request should evaluate whether workspace edits should be applied before the files are created, and promptly return them if that is the case. The cancellation token should be checked regularly to throw if cancellation was requested.

A first iteration is probably perfectly fine with simply returning null.

NOTE: in LSP "files" refers to both files and folders.

Implement client-side file/folder operations

File I/O operations (esp. file watchers) should always run in the client-side process, because a client is allowed to connect to (/own) multiple servers, and multiple processes trying to own the same file/folder is a scenario we'd like to avoid for the same reasons the SQLite database also runs in its own process.

We need to implement a service that the add-in client (commands invoked from the server->client RPC endpoints) will call to create, rename, and delete files and folders as per LSP specifications.

TODO document the relevant specs here

Support for Apple macOS M1/M2

Hello

I have a question regarding the usage of Rubberduck for Apple macOS M1/M2.
It would be great, when this plugin could also be used on these operating systems. The current version supports only x86/x64 and the installation is not possible (also when hosting Windows 11 within a virtual machine).

Are you planning to support this? If yes, do you have already a timeline?

Many thanks for a response!

Implement workspace/workspaceFolders request

Specification (LSP)

The workspace/workspaceFolders request is sent from the server to the client to fetch the current open list of workspace folders. Returns null in the response if only a single file is open in the tool. Returns an empty array if a workspace is open but no folders are configured.

Where WorkspaceFolder is defined as follows:

export interface WorkspaceFolder {
	/**
	 * The associated URI for this workspace folder.
	 */
	uri: DocumentUri;

	/**
	 * The name of the workspace folder. Used to refer to this
	 * workspace folder in the user interface.
	 */
	name: string;
}

Scope:

  • Rubberduck.Core add-in client must define a service that holds client-side workspace state.
  • Rubberduck.Client library must define a client-side handler for this request, that returns the folders in the current workspace.

Fill missing content +RD2 screenshots

Home / layout / nav

/About

  • Markdown page with some history about the project
  • Acknowledgements section

/Features

  • Smart Indenter gif is missing
  • Smart Indenter box summary needs another sentence
  • Refactorings box summary is too long
  • Navigation tools box summary needs another sentence
  • Annotations box summary needs another sentence
  • Make a card full-width when it's alone in its row?
  • Completion gif is too tall (not showing anymore)

UnitTesting

  • Add a table for each type in the fakes API; actually document the feature
  • Test Explorer toolwindow page is empty
  • Settings page is empty

Refactorings

  • Footer pagination should be aligned with header pagination
  • "New" toggle state isn't obvious enough
  • Requesting new items from a url that doesn't should reset to page 1 (there's no page 2 when there are few new item)
  • Items pagination is rendered when the "new" flag is on
  • Should have a message that says "no content" or something when there's nothing and pagination is still shown
  • Screenshots are too large
  • Introduce Field has no content
  • Introduce Parameter has no content
  • Extract Method needs more content, code block examples
  • Move Closer to Usage has no content
  • Move Containing Folder has no content
  • Move to Folder has no content
  • Remove Parameters has no content
  • Reorder Parameters has no content

Navigation Tools

  • Code Explorer toolwindow page has no content
  • Find all Implementations needs screenshots
  • Find all References has no content
  • Find Symbol has no content
  • To-Do Explorer toolwindow page has no content

Annotations

  • Annotate Menu page has no content
  • Parameters table should be aligned with the "Parameters" heading
  • ExcelHotKeyAnnotation should mention something about only working in Excel?

Inspections

  • Code Metrics toolwindow page needs screenshots
  • Inspection Results toolwindow page has no content
  • Align items with the headings on the page / remove the weird margins and padding going on there
  • Fix layout issues for pagination and filtering (add col-md-6)

Completion

  • Self-Closing Pair Completion page needs .gif banners showing it happening
  • Smart-Concat Completion page needs a .gif at the bottom

Implement workspace/willCreateFiles notification

Specifications (LSP)

The will create files request is sent from the client to the server before files are actually created as long as the creation is triggered from within the client either by a user action or by applying a workspace edit. The request can return a WorkspaceEdit which will be applied to workspace before the files are created. Hence the WorkspaceEdit can not manipulate the content of the files to be created. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep creates fast and reliable.

The handler for this request should evaluate whether workspace edits should be applied before the files are created, and promptly return them if that is the case. The cancellation token should be checked regularly to throw if cancellation was requested.

A first iteration is probably perfectly fine with simply returning null.

NOTE: in LSP "files" refers to both files and folders.

Service Layer

The data access layer operates with an internal model that essentially mirrors the database storage. This is great for CRUD operations, but the rest of Rubberduck would rather work with a rich internal API and declaration model: there needs to be a service layer between the data access (CRUD) and the LocalDb clients (i.e. LSP server instances, mostly) that the LocalDb server RSP endpoints can invoke using the deserialized endpoint parameters.

Implement a message box

The custom dialog (a WPF user control that will probably end up hosted in a WPF/XAML popup) should feature a collapsible "details" area, as well as a "don't show this message again" checkbox. This UI will be used by the command that responds to window/showMessage notifications and window/showMessageRequest, notably.

The message text content should scroll vertically when too tall. The dialog can expand a "more information" section, and there should be a checkbox to remember the user's response to a prompt.

Buttons and their caption should be driven by the view model; the right-most button should be the ostensibly default option. Key bindings should attach ENTER to the default command, and ESC should dismiss/cancel the dialog/prompt.

message UI mock-up with lorem ipsum message, ok and cancel buttons

In order to "remember" whether or not to display a prompt, each prompt should have an ID (or unique name?). User settings should then store the prompt result alongside the prompt ID, but this storage logic is beyond the scope of this issue.

implement LSP window/showMessage and window/showMessageRequest endpoints

Implement the client-side handlers for window/showMessage notifications and window/showMessageRequest requests.

ShowMessage

Specification (LSP):

The show message notification is sent from a server to a client to ask the client to display a particular message in the user interface.

In these cases the client receives a model that includes "message action items" that correspond to buttons, and the MessageType instructs us about which icon to use next to the title label.

interface ShowMessageRequestParams {
	/**
	 * The message type. See {@link MessageType}
	 */
	type: MessageType;

	/**
	 * The actual message
	 */
	message: string;

	/**
	 * The message action items to present.
	 */
	actions?: MessageActionItem[];
}

interface MessageActionItem {
	/**
	 * A short title like 'Retry', 'Open Log' etc.
	 */
	title: string;
}

export namespace MessageType {
	/**
	 * An error message.
	 */
	export const Error = 1;
	/**
	 * A warning message.
	 */
	export const Warning = 2;
	/**
	 * An information message.
	 */
	export const Info = 3;
	/**
	 * A log message.
	 */
	export const Log = 4;
}

export type MessageType = 1 | 2 | 3 | 4;

ShowMessageRequest

Specification (LSP):

The show message request is sent from a server to a client to ask the client to display a particular message in the user interface. In addition to the show message notification the request allows to pass actions and to wait for an answer from the client.

The user interface is completed with #19 and should cover every "msgbox" use-case we can anticipate:

various message box configurations

If the UI is already completed, the view model should already make it easy to work with from both handlers. The model should be scoped to this issue otherwise.

Implement workspace/didChangeWatchedFiles notification

Specifications (LSP)

The watched files notification is sent from the client to the server when the client detects changes to files and folders watched by the language client (note although the name suggest that only file events are sent it is about file system events which include folders as well). It is recommended that servers register for these file system events using the registration mechanism. In former implementations clients pushed file events without the server actively asking for it.

An event-driven mechanism to handle create, change, and delete events for files and folders as they are detected (client-side) on the file system.

This feature should be configurable and optional. Limit the number of watched folders to the active workspace.

Implement IntelliSense UI

The Rubberduck Editor needs an IntelliSense UI that appears relative to the caret position to display signature help.

We don't need to worry about the signature index because no members are ever overloaded in VBA, so we only need to ever accommodate a single signature: even in the context of a property call, once we're showing the signature info we've already worked out whether we're looking at the Get, Let, or Set member.

The tooltip should display the member's docstring, and support tracking the active parameter to show it in bold, and eventually show docstrings for individual parameters. The model comes straight from the LSP server.

There should be a key binding to dismiss the tooltip on ESC, and both showing and dismissing the tooltip should fire an EventTelemetry event.

Persist declarations to LocalDb

When the resolver issues a declaration, we need a service to send a save/something request to the LocalDb server... but that's the easy part.

The implication is that when the resolver later looks for declarations in the DeclarationFinder, they're not going to be there: each finder query needs to become a hit on LocalDb through JSON-RPC, so we're probably going to want to be smarter than simply requesting things as we go. Perhaps the request parameters and their corresponding results could be cached locally for the duration of a resolver run, and so we could skip repeated RPC calls that fetch the same declaration; such a cache would presumably be cleared upon completion, if it's needed at all.

Once parse trees are collected for all code files in the workspace, the resolver pass can begin identifying all the declarations.

Instead of storing them in DeclarationFinder state, the LSP server is going to persist the declarations to the Rubberduck.DatabaseServer managed SQLite database via lower-level Json-RPC calls (LSP builds on top of this).

Implement textDocument/foldingRange handler

The client-sided proof-of-concept code produced a ParseTreeListener that should be relatively easy to tweak to output LSP-compliant FoldingRange items (only for the active document) instead of AvalonEdit model items - on the client side the LSP items should be converted into the corresponding AvalonEdit objects, and rendered in the active document.

  • Modify the listener to use the LSP-compliant model types
  • Attach the listener to the parser that processes the active document
  • Return the folding ranges in the response

As with all LSP requests, the server operates with the version of the code that is currently synchronized at the moment of the request.

LSP console client app

This client app should build on top of the similarly-purposed LocalDb client app, from which common client abstractions should already have been extracted to a namespace under Rubberduck.Client.

  • yup, that's done.

We need a relatively complex xaml control that can beautifully layout a bunch of nested configuration settings.

We get a [Console] tab for free by reusing the LocalDb client app UI abstractions, and we'll be able to override the SettingsCommand with one of our own.

  • Have a console tab, but just reuse console settings from LocalDb client.

Only the LSP-specific parts should remain:

  • Settings user control (display it in a tab after the console tab), to be reused in the add-in client) to configure the many LSP client/server knobs and switches.

Assumptions

  • Each application defines its respective MainWindow
  • The XAML user control for server console GUI apps is shared; implementations only need to supply a configuration tab, but they are free to supply as many as needed.

Implementation notes

In order to ensure a consistent user experience across the different applications, the shared XAML user control should be the only child control in the <MainWindow>; styles and icons should be imported from the appropriate shared resources libraries (.resx and .png under Rubberduck.Resourcee, anything .xaml is under Rubberduck.UI.Xaml).

PreviewRename prompt

Before a rename operation is executed, its impacts are assessed, and the user gets an opportunity to [p]review and skip individual diffs if needed:

rename preview confirmation prompt

The number of locations and modules affected could theoretically reflect the checked items - the OK button should be disabled if none are selected (operation would be no-op).

This is purely client-side functionality: the preview diff literally consists of document edits to be performed.

Server -> Client endpoints

Server-to-client RPC endpoints include the following requests/methods:

Window

  • LogMessage (window/logMessage)
  • ShowMessage (window/showMessage)
  • ShowMessageRequest (window/showMessageRequest)
  • ShowDocument (window/showDocument)
  • CreateWorkDoneProgress (window/workDoneProgress/create)
  • CancelWorkDoneProgress (window/workDoneProgress/cancel)-
  • Progress ($/progress)

TextDocument

  • PublishDocumentDiagnostics (textDocument/publishDiagnostics)

Workspace

  • RefreshCodeLens (workspace/codeLens/refresh)
  • RefreshSemanticTokens (workspace/semanticTokens/refresh)
  • RefreshInlayHints (workspace/inlayHints/refresh)
  • RefreshDiagnostics (workspace/diagnostic/refresh)
  • ApplyWorkspaceEdit (workspace/applyEdit)

Implement DidCloseTextDocument LSP handler

Specification (LSP)

The document close notification is sent from the client to the server when the document got closed in the client. The document’s master now exists where the document’s Uri points to (e.g. if the document’s Uri is a file Uri the master now exists on disk). As with the open notification the close notification is about managing the document’s content. Receiving a close notification doesn’t mean that the document was open in an editor before. A close notification requires a previous open notification to be sent. Note that a server’s ability to fulfill requests is independent of whether a text document is open or closed.

The server should update its internal document state upon receiving this notification, and write log entries as appropriate.

DialogShell user control

As I was drawing various mock-ups it occurred to me that we're going to want a coherent user interface, and we're going to be constantly reinventing the wheel if we don't do this.

Let's write a XAML user control that will set the tone for all RD3 dialogs and prompts. Something like this:

Image

ViewModel would include:

  • TitleText
  • IconSource
  • TitleLabelText
  • InstructionsLabelText
  • OptionLabelText
  • CancelButtonText
  • DefaultButtonText
  • HasOption: whether or not to display the OptionLabel and bind OptionLabelText
  • HasCancelButton: whether or not to display the CancelButton and bind CancelButtonText
  • CanResize: whether or not to include minimize/maximize buttons in the control box, and whether the user can drag the border of the control to resize it
  • ClientAreaMinHeight: ensures a minimum breathing space for the client area when [re]sizing.

The bare-bones default configuration might look like this:

Image

  • Refactor MessageBoxControl and any other existing dialogs as a child component of this new control.

Persist COM declarations to LocalDb

The language server cannot access COM libraries directly from the VBIDE process - the client must send a command to the server, passing it the serialized ProjectReference items. The handler for that command can then load the library on the server side and retrieve the declarations: the RD2 code for this should be reusable as-is.

Once the declarations are retrieved, the server should send a Save notification to the database server using IJsonRpcServer.

  • Implement a LSP server command that receives ProjectReference items from the client
    • Import any missing RD2 code to process COM library references; retrieve the declarations
    • Use JsonRpcMethods.Database method names to notify the database server

RD3 Filesystem Criteria

RD3 will operate from a folder hierarchy of exported module files as the 'source of truth' for the VBA code base. There have been numerous discussions in the Discord 'rubberducking' channel regarding how the RD3 Filesystem should work. This Issue is created in an attempt to capture and collate past and future 'Decisions', 'Open Topics', and 'Use Cases' surfaced during the discussions.

Over time, the hope is that this Issue contains sufficient criteria and Use Cases to help facilitate the initial implementation.

Edited 3/13/2023.

  • Adds alternative FileSystem design comment

Terms/Definitions:

  • Filesystem Setup: The interactive process of creating a valid RD3 environment for a new or existing host document
  • Filesystem Initialization: Evaluates the Filesystem of the active host document.
    -- Creates filesystem objects as needed to establish a valid RD3 Filesystem.
  • Filesystem Synchronization: The initialization and design-time processes needed to maintain the host document modules consistent with the "./src" file(s) content.
  • Filesystem Host Folder: The folder containing the host document of interest
  • Filesystem Code Folder: The folder containing the code files of interest to the LSP. The Filesystem Code Folder and the Filesystem Host Folder can be the same folder.

Decisions:

  1. The default Filesystem Code Folder name will be "./src" when the Filesystem Code Folder is a direct child of the Filesystem Host Folder.
  2. Provide Filesystem Setup View(s) assisting the user to establish a valid RD3 Filesystem for a host document

Open Topics:

  1. Filesystem Initialization: Detection and Handling of duplicate file names encountered in the folder hierarchy.
  2. RD3 host document opened on a non-RD3-enabled VBIDE computer
    a. The only issue identified for this topic so far is the potential for losing Folder annotations.
    - Resolution: Users expecting to do this would need to retain annotations per Use Case I @ 2.b.ii.
  3. Filesystem Setup: Introduce project-scope settings (and/or Filesystem Setup settings?):
    a. Retain RD3 Filesystem Setup preferences
    b. Allow user-defined Filesystem Code Folder names other than "./src"

Use Cases:

Use Case I: Filesystem Setup: User's initial use of RD3 starting from an RD2 project

 1. RD3 provides `Filesystem Setup` View(s) to .
 2. @Folder annotations are evaluated to generate a folder structure starting at the `Filesystem Code Folder`
      a. Files without an @Folder annotation are saved in the `Filesystem Code Folder`
      b. Filesystem is synchronized to match host document module content
          1) Unresolved - handling of @Folder annotations after the creation of the folder hierarchy:
               i) Ignore @Folder annotations in the future. (Disable @Folder related inspections?)
               ii) Auto-update @Folder annotations based on actual file locations in the future.
               iii) Make i) and ii) a user choice in `Filesystem Setup` settings
 3. Optional(future): Based on choice of implementing #2 above, Prompt user to  remove @Folder annotations 
 4. If Folder options become a `Filesystem Setting` per 2.b.iii above, re-apply/remove Folder annotations when the user toggles the setting ('Maintain Folder Annotations : boolean' ?).

Use Case II: Filesystem Setup: User's initial use of RD3 starting from multiple RD2 projects stored in the same folder

1. Provide `Filesystem Setup` dialog assisting the user to specify/create a valid RD3 Filesystem
2. Invoke `Filesystem Initialization`

Use Case III: Filesystem Initialization: User opens a host document that has been moved/copied

1. Valid RD3 Filesystem is found: Create folders and files accordingly.
2. Valid RD3 Filesystem is NOT found: Invoke `Filesystem Setup` dialog/process and `Filesystem Initialization`

Use Case IV: Filesystem Synchronization Files and/or file structure manipulated external to RD3

1. This Use Case has a better discussion found in Discord.feature-backlog.Workspace Explorer

Edit History

Edited 3/7/2023.

  • Replaces the use of the term Workspace with Filesystem since Workspace has meaning within the context of a LSP
  • Proposes new terms Filesystem Host Folder and Filesystem Code Folder

Edited 3/5/2023 based on input and comments.

  • Adds 'Terms/Definitions' section
  • Adds 'Decision' item
  • Simplified Use Case content descriptions

TextDocument endpoints (client -> server)

TextDocument client-to-server RPC endpoints include the following requests/methods:

File

⚠ Note: in LSP "file" refers and applies to both files and folders.

  • DidOpen (textDocument/didOpen)
  • DidClose (textDocument/didClose)
  • DidChange (textDocument/didChange)
  • WillSave (textDocument/willSave)
  • WillSaveUntil (textDocument/willSaveUntil)
  • DidSave (textDocument/didSave)

Navigation

  • GoToDeclaration (textDocument/declaration)
  • GoToDefinition (textDocument/definition)
  • GoToTypeDefinition (textDocument/typeDefinition)
  • GoToImplementation (textDocument/implementation)
  • FindReferences (textDocument/references)
  • CodeLens (textDocument/codeLens)
  • ResolveCodeLens (codeLens/resolve)
  • DocumentLinks (textDocument/documentLink)
  • ResolveDocumentLink (documentLink/resolve)

Language

  • PrepareCallHierarchy (textDocument/prepareCallHierarchy)
  • CallHierarchyIncoming (callHierarchy/incomingCalls)
  • CallHierarchyOutgoing (callHierarchy/outgoingCalls)
  • PrepareTypeHierarchy (textDocument/prepareTypeHierarchy)
  • Supertypes (typeHierarchy/supertypes)
  • Subtypes (typeHierarchy/subtypes)
  • Rename (textDocument/rename)
  • PrepareRename (textDocument/prepareRename)
  • Diagnostics (textDocument/diagnostic)
  • CodeAction (textDocument/codeAction)
  • ResolveCodeAction (codeAction/resolve)
  • Monikers (textDocument/moniker)
  • Symbols (textDocument/documentSymbol)
  • SemanticTokens (textDocument/semanticTokens)
  • SemanticTokensFull (textDocument/semanticTokens/full)
  • SemanticTokensDelta (textDocument/semanticTokens/full/delta)

Editor

  • Hover (textDocument/hover)
  • Completion (textDocument/completion)
  • ResolveCompletionItem (completionItem/resolve)
  • SignatureHelp (textDocument/signatureHelp)
  • FoldingRanges (textDocument/foldingRange)
  • Highlights (textDocument/highlights)
  • Formatting (textDocument/formatting)
  • RangeFormatting (textDocument/rangeFormatting)
  • OnTypeFormatting (textDocument/onTypeFormatting)
  • Color (textDocument/documentColor)
  • ColorPresentation (textDocument/colorPresentation)
  • SelectionRange (textDocument/selectionRange)
  • LinkedEditingRanges (textDocument/linkedEditingRange)
  • InlayHints (textDocument/inlayHint)
  • ResolveInlayHint (inlayHint/resolve)

Client console GUI app

🔗 Depends on: Implement base client abstractions in Rubberduck.Client

A small standalone executable that will serve as a proof-of-concept for client/server RPC communications and lay the groundwork and produce abstractions usable for all RPC clients.

As a client, this application should either find or spawn the server process if it isn't already running: all Server.LocalDb clients should be connecting to the same server instance.

The application should present a tabbed UI with a "console" tab showing the server's trace log output, with commands to pause/resume tracing, set the server's trace level and other configuration settings. A status bar should display server info including name, version, uptime, number of connected clients, and the number of RPC messages sent and received.

A "database" tab should present metadata about each table, including the number of records, and the user should be able to double-click on a table or view item (or click a button) to bring up a data grid presenting/previewing the data, and commands to export the data to various formats, including CSV text files and Excel workbooks.

Aside from the LocalDb-specific tabs, the UI components will be mostly shared between the different client applications.

Subtasks

  • Finalize the shared "shell" UI components (xaml) of console client GUI apps
  • Implement a LocalDbClientService class that communicates with the LocalDb RPC server
  • Implement/honor console client configurations/options/capabilities
    • The console UI allows displaying different fonts/sizes/colors (and icons) depending on log level and property. For example the Id property might be configured to be displayed in a bold font, and the actual Message can be dark red for error-level items and the VerboseMessage could be shown in italics at the "info" level, but in monospace bright yellow at the "error" level.
  • Implement the commands:
    • Connect to connect the client app to the LocalDb RPC server process (spawns it if it isn't running)
    • Disconnect to disconnect the client app from the LocalDb RPC server (process will exit if no connected clients remain)
    • Exit to cleanly disconnect the client app before terminating the client process; server remains alive if there are other clients.
    • ClearConsole to remove all messages in the console output; new messages may continue to be displayed.
    • PauseTrace to command the server to temporarily stop writing trace logs altogether, without disabling logging in the server configuration.
    • ResumeTrace to command the server to resume writing all trace logs when trace logging is paused.
    • SaveServerSettings to persist any changes to the server configuration.
    • SaveClientSettings to persist any changes to the client configuration.
    • RefreshServerInfo to request updated server state; this command should be executed with a configurable timer that shouldn't tick more often than once per second. The server uptime can be used to synchronize a local TimeSpan value that represents the estimated server uptime and that can be updated locally between the requests.

Unable to launch RD2 after building RD3

After successfully building the latest main branch of RD3, I've been unable to successfully launch RD2 (2.5.2).

To Reproduce:

  1. Open VS2022 and load RD3 solution
  2. Build RD3 main in VS2022
  3. Load RD2 solution into VS2022
  4. Build RD2
  5. Open Excel followed by opening the Visual Basic Editor
  6. Admire the new Avalon editor

Rebuilding RD2 does not overwrite/correct these changes

(Edited: removed content that is no longer relevant/accurate)

Rename prompt

Implement a prompt based on the MessageBox component, that receives an identifier name from user input in a textbox - mock-up:

mock-up of the prompt with an empty input field, a validation error message saying "field is required", a prompt to rename "class module Class1" with the "object-class" icon next to the "Rename" heading. Cancel buttons is available, Ok button is disabled.

  • New name is required (cannot be null, empty, or whitespace)
  • New name cannot match old name
  • New name defaults to old name, textbox content selected and focused
  • Validation error message is clearly visible (when applicable)
  • Icon (title) represents the DeclarationType of the symbol
  • Confirm (OK) command/button is disabled unless the name is valid

Maximum length - module: 31 characters. Anything else: 255 characters (TODO verify in MSVBAL).

Implement Dragablz container

The editor shell needs to include a Dragablz container so we can have tear-tabs and docking areas.

  • Implement the docking manager ("Dockablz")
  • Implement the tabbed client area ("Dragablz")

I tried doing this early on but the assembly wouldn't load at run-time so I, well, pushed that problem forward 😭

Code pane context menu

We need to implement the code pane context menu completely from scratch, including the bare-bones stuff like Copy and Paste (surely we want these commands in the Rubberduck Editor 🤔😂).

TODO list a subtask for each command to wire up here

Note: some of these commands would remain no-op (and hidden) until a corresponding LSP server method is actually implemented, i.e. we want to wire up "find references" even if the RPC request for it comes back in error.

Parse a module

Wire up and adjust all the necessary RD2 components to produce an ANTLR parse tree for any module loaded in the workspace.

At this stage we only care about getting a parse tree to provide the editor with syntax errors and folding ranges: we need this parse to remain sub-second and as reliably fast as possible for all module under 5K lines of code (half the maximum allowed). Preliminary in-process tests gave excellent sub-second results for all module sizes.

Technically we could also wire up the parse tree inspections/diagnostics, but for performance reasons these will have to run separately from this quick-parse syntactical pass.

RPC Server Platform

Finalize and merge the groundwork PR (see #1).

Requirements:

  • Solution architecture split into client, server, and shared folders
  • All LSP endpoints are documented and templated
  • All shared server and console endpoints are implemented
  • RPC client can successfully send all shared server and console requests and notifications to a RPC server
  • Support progress reporting

Implement workspace file/folder LSP handlers

The handlers themselves should go under Rubberduck.Client, which should have a namespace to keep the workspace handlers together (there will be more workspace handlers to implement in future sprints). Handlers should be injected with interfaces for the services they need, so these services need to have their interfaces in the same assembly, to be implemented under Rubberduck.Server.LSP.

Implement workspace/willDeleteFiles notification

Specifications (LSP)

The will delete files request is sent from the client to the server before files are actually deleted as long as the deletion is triggered from within the client either by a user action or by applying a workspace edit. The request can return a WorkspaceEdit which will be applied to workspace before the files are deleted. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep deletes fast and reliable.

Just return null for now.

NOTE: in LSP "files" refers to both files and folders.

[EPIC] Update Server

  • Runs a JsonRPC server
  • Checks for updates on startup
  • Can update itself
  • Checks for updates before updating RD3
  • Can download RD3 release assets
  • Can update RD3 language server
  • Can update RD3 add-in client
  • Can update RD3 editor
  • Can detect RD3 running processes

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.