Skip to content

Commit

Permalink
Merge branch 'master' into kh-enable-code-lens-setting
Browse files Browse the repository at this point in the history
* master:
  feat(aztec): search for aztec-nargo on top of nargo bin (#67)
  feat: add `unchecked` keyword highlighting (#72)
  feat: add keyword highlighting for databus visibility keywords (#68)
  chore: Remove format on save override (#65)
  chore: Remove environment reference (#62)
  • Loading branch information
TomAFrench committed Mar 4, 2024
2 parents e222b29 + 0be02a5 commit 83fad2b
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 72 deletions.
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
needs: release-please
if: ${{ needs.release-please.outputs.tag-name }}
runs-on: ubuntu-latest
environment: marketplace
steps:
- name: Setup Node.js
uses: actions/setup-node@v3
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@
},
"configurationDefaults": {
"[noir]": {
"editor.defaultFormatter": "noir-lang.vscode-noir",
"editor.formatOnSave": true
"editor.defaultFormatter": "noir-lang.vscode-noir"
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ export default class Client extends LanguageClient {
});
}

get command(): string {
return this.#command;
}

async refreshProfileInfo() {
const response = await this.sendRequest<NargoProfileRunResult>('nargo/profile/run', { package: '' });

Expand Down
145 changes: 83 additions & 62 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ import {
window,
ProgressLocation,
} from 'vscode';
import os from 'os';

import { languageId } from './constants';
import Client from './client';
import findNargo from './find-nargo';
import findNargo, { findNargoBinaries } from './find-nargo';
import { lspClients, editorLineDecorationManager } from './noir';
import { getNoirStatusBarItem, handleClientStartError } from './noir';

const activeCommands: Map<string, Disposable> = new Map();

Expand Down Expand Up @@ -168,6 +170,15 @@ function registerCommands(uri: Uri) {
});
commands$.push(hideProfileInformationCommand$);

const selectNargoPathCommand$ = commands.registerCommand('nargo.config.path.select', async (..._args) => {
const homeDir = os.homedir();
const foundNargoBinaries = findNargoBinaries(homeDir);
const result = await window.showQuickPick(foundNargoBinaries, { placeHolder: 'Select the Nargo binary to use' });
const config = workspace.getConfiguration('noir', uri);
config.update('nargoPath', result);
});
commands$.push(selectNargoPathCommand$);

activeCommands.set(file, Disposable.from(...commands$));
}

Expand Down Expand Up @@ -246,73 +257,83 @@ async function didOpenTextDocument(document: TextDocument): Promise<Disposable>
const uri = document.uri;
let folder = workspace.getWorkspaceFolder(uri);
let configHandler;
if (folder) {
// If we have nested workspace folders we only start a server on the outer most workspace folder.
folder = getOuterMostWorkspaceFolder(folder);

await addWorkspaceClient(folder);
registerWorkspaceCommands(folder);

configHandler = mutex(folder.uri.toString(), async (e: ConfigurationChangeEvent) => {
if (e.affectsConfiguration('noir.nargoFlags', folder.uri)) {
disposeWorkspaceCommands(folder);
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
registerWorkspaceCommands(folder);
}

if (e.affectsConfiguration('noir.nargoPath', folder.uri)) {
disposeWorkspaceCommands(folder);
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
registerWorkspaceCommands(folder);
}

if (e.affectsConfiguration('noir.enableLSP', folder.uri)) {
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
try {
if (folder) {
// If we have nested workspace folders we only start a server on the outer most workspace folder.
folder = getOuterMostWorkspaceFolder(folder);

await addWorkspaceClient(folder);

const currentLspClient = lspClients.get(folder.uri.toString());
const statusBarItem = getNoirStatusBarItem();
statusBarItem.tooltip = currentLspClient.command;
statusBarItem.show();

registerWorkspaceCommands(folder);

configHandler = mutex(folder.uri.toString(), async (e: ConfigurationChangeEvent) => {
if (e.affectsConfiguration('noir.nargoFlags', folder.uri)) {
disposeWorkspaceCommands(folder);
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
registerWorkspaceCommands(folder);
}

if (e.affectsConfiguration('noir.nargoPath', folder.uri)) {
disposeWorkspaceCommands(folder);
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
registerWorkspaceCommands(folder);
}

if (e.affectsConfiguration('noir.enableLSP', folder.uri)) {
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
}

if (e.affectsConfiguration('noir.enableCodeLens', folder.uri)) {
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
}
});
} else {
// We only want to handle `file:` and `untitled:` schemes because
// vscode sends `output:` schemes for markdown responses from our LSP
if (uri.scheme !== 'file' && uri.scheme !== 'untitled') {
return Disposable.from();
}

if (e.affectsConfiguration('noir.enableCodeLens', folder.uri)) {
await removeWorkspaceClient(folder);
await addWorkspaceClient(folder);
}

});
} else {
// We only want to handle `file:` and `untitled:` schemes because
// vscode sends `output:` schemes for markdown responses from our LSP
if (uri.scheme !== 'file' && uri.scheme !== 'untitled') {
return Disposable.from();
// Each file outside of a workspace gets it's own client
await addFileClient(uri);
registerFileCommands(uri);

configHandler = mutex(uri.toString(), async (e: ConfigurationChangeEvent) => {
if (e.affectsConfiguration('noir.nargoFlags', uri)) {
disposeFileCommands(uri);
await removeFileClient(uri);
await addFileClient(uri);
registerFileCommands(uri);
}

if (e.affectsConfiguration('noir.nargoPath', uri)) {
disposeFileCommands(uri);
await removeFileClient(uri);
await addFileClient(uri);
registerFileCommands(uri);
}

if (e.affectsConfiguration('noir.enableLSP', uri)) {
await removeFileClient(uri);
await addFileClient(uri);
}
});
}

// Each file outside of a workspace gets it's own client
await addFileClient(uri);
registerFileCommands(uri);

configHandler = mutex(uri.toString(), async (e: ConfigurationChangeEvent) => {
if (e.affectsConfiguration('noir.nargoFlags', uri)) {
disposeFileCommands(uri);
await removeFileClient(uri);
await addFileClient(uri);
registerFileCommands(uri);
}

if (e.affectsConfiguration('noir.nargoPath', uri)) {
disposeFileCommands(uri);
await removeFileClient(uri);
await addFileClient(uri);
registerFileCommands(uri);
}

if (e.affectsConfiguration('noir.enableLSP', uri)) {
await removeFileClient(uri);
await addFileClient(uri);
}
});
return workspace.onDidChangeConfiguration(configHandler);
} catch (e) {
handleClientStartError(e);
}

return workspace.onDidChangeConfiguration(configHandler);
}

async function didChangeWorkspaceFolders(event: WorkspaceFoldersChangeEvent) {
Expand Down
62 changes: 56 additions & 6 deletions src/find-nargo.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,66 @@
import os from 'os';
import path from 'path';
import fs from 'fs';
import which from 'which';
import { NargoNotFoundError } from './noir';
import { MarkdownString } from 'vscode';

const nargoBinaries = ['nargo'];
// List of possible nargo binaries to find on Path
// We prioritize 'nargo' as the more standard version.
const NARGO_BINARIES = ['nargo', 'aztec-nargo'];
// List of possible default installations in users folder
const NARGO_INSTALL_LOCATION_POSTFIXES = ['.nargo/bin/nargo', '.aztec/bin/aztec-nargo'];

export default function findNargo() {
for (const bin of nargoBinaries) {
function absoluteInstallLocationPaths(homeDir: string): string[] {
return NARGO_INSTALL_LOCATION_POSTFIXES.map((postfix) => path.join(homeDir, postfix)).filter((filePath) =>
fs.existsSync(filePath),
);
}

export function findNargoBinaries(homeDir: string): string[] {
// Note that JS sets maintain insertion order.
const nargoBinaryPaths: Set<string> = new Set();

for (const bin of NARGO_BINARIES) {
try {
const nargo = which.sync(bin);
const path = which.sync(bin);
// If it didn't throw, we found a nargo binary
return nargo;
nargoBinaryPaths.add(path);
} catch (err) {
// Not found
}
}
throw new Error('Unable to locate any nargo binary. Did you install it?');

// So far we have not found installations on path
// Let's check default installation locations
for (const filePath of absoluteInstallLocationPaths(homeDir)) {
nargoBinaryPaths.add(filePath);
}

return [...nargoBinaryPaths];
}

export default function findNargo() {
const homeDir = os.homedir();
const nargoBinaryPaths = findNargoBinaries(homeDir);

if (nargoBinaryPaths.length > 0) {
return nargoBinaryPaths[0];
} else {
const message = new MarkdownString();
message.appendText(`Could not locate any of\n`);
for (const nargoBinary of NARGO_BINARIES) {
message.appendMarkdown(`\`${nargoBinary}\``);
message.appendText(`\n`);
}

message.appendText(`on \`$PATH\`, or one of default installation locations\n`);
for (const postfix of NARGO_INSTALL_LOCATION_POSTFIXES) {
const filePath = path.join(homeDir, postfix);
message.appendMarkdown(`\`${filePath}\``);
message.appendText(`\n`);
}

throw new NargoNotFoundError(message);
}
}
41 changes: 41 additions & 0 deletions src/noir.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,47 @@
import { MarkdownString, StatusBarAlignment, StatusBarItem, ThemeColor, window } from 'vscode';
import { EditorLineDecorationManager } from './EditorLineDecorationManager';
import Client from './client';

export const lspClients: Map<string, Client> = new Map();

export const editorLineDecorationManager = new EditorLineDecorationManager(lspClients);

let noirStatusBarItem: StatusBarItem;

export function getNoirStatusBarItem() {
if (noirStatusBarItem) {
return noirStatusBarItem;
}
// Create Nargo Status bar item, we only need one for lifetime of plugin
// we will show/update it depending on file user is working with
noirStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Right, 100);
noirStatusBarItem.text = 'Nargo';
noirStatusBarItem.command = 'nargo.config.path.select';

return noirStatusBarItem;
}

export class NargoNotFoundError extends Error {
constructor(markdownMessage?: MarkdownString) {
super(markdownMessage.value);

this.markdownMessage = markdownMessage;
}

markdownMessage: MarkdownString;
}

export function handleClientStartError(err: Error) {
if (err instanceof NargoNotFoundError) {
const backgroundColor = new ThemeColor('statusBarItem.errorBackground');
const foregroundColor = new ThemeColor('statusBarItem.errorForeground');

const statusBarItem = getNoirStatusBarItem();
statusBarItem.backgroundColor = backgroundColor;
statusBarItem.color = foregroundColor;
statusBarItem.tooltip = err.markdownMessage;
statusBarItem.show();
} else {
throw err;
}
}
2 changes: 1 addition & 1 deletion syntaxes/noir.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@
},
{
"name": "keyword.nr",
"match": "\\b(global|comptime|unconstrained|distinct|pub|&mut|mut|self|in|as|let)\\b"
"match": "\\b(global|comptime|unconstrained|unchecked|distinct|pub|call_data|return_data|&mut|mut|self|in|as|let)\\b"
}
]
},
Expand Down

0 comments on commit 83fad2b

Please sign in to comment.