Skip to content

Commit b1a5c2e

Browse files
committed
Refactoring
1 parent 88f8290 commit b1a5c2e

File tree

14 files changed

+142
-172
lines changed

14 files changed

+142
-172
lines changed

language_service/src/qasm.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ use qsc::{qasm::parser::ast::StmtKind, LanguageFeatures};
77
use qsc_project::{FileSystemAsync, PackageGraphSources, PackageInfo, Project};
88
use rustc_hash::FxHashMap;
99

10-
pub async fn load_openqasm_project<T>(
11-
project_host: &T,
12-
doc_uri: &Arc<str>,
13-
) -> Result<Project, Vec<qsc::project::Error>>
10+
pub async fn load_openqasm_project<T>(project_host: &T, doc_uri: &Arc<str>) -> Project
1411
where
1512
T: FileSystemAsync + ?Sized,
1613
{
@@ -75,7 +72,7 @@ where
7572

7673
let sources = loaded_files.into_iter().collect::<Vec<_>>();
7774

78-
Ok(Project {
75+
Project {
7976
package_graph_sources: PackageGraphSources {
8077
root: PackageInfo {
8178
sources,
@@ -90,7 +87,7 @@ where
9087
lints: Vec::default(),
9188
errors,
9289
project_type: qsc_project::ProjectType::OpenQASM,
93-
})
90+
}
9491
}
9592

9693
fn get_file_name_from_uri(uri: &Arc<str>) -> Arc<str> {

language_service/src/state.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ impl<'a> CompilationStateUpdater<'a> {
183183

184184
async fn load_project_from_doc_uri(&mut self, doc_uri: &Arc<str>, text: &Arc<str>) -> Project {
185185
if is_openqasm_file(doc_uri) {
186-
if let Ok(project) = crate::load_openqasm_project(&*self.project_host, doc_uri).await {
187-
return project;
188-
}
186+
return crate::load_openqasm_project(&*self.project_host, doc_uri).await;
189187
}
190188
match self.load_manifest(doc_uri).await {
191189
Ok(Some(p)) => p,

vscode/src/common.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,19 @@ export function isQsharpNotebookCell(document: TextDocument): boolean {
5252
);
5353
}
5454

55+
// Returns true for only Q# notebook cell documents.
56+
export function isOpenQasmNotebookCell(document: TextDocument): boolean {
57+
return (
58+
document.languageId === openqasmLanguageId &&
59+
document.uri.scheme === "vscode-notebook-cell"
60+
);
61+
}
62+
5563
// Returns true for all OpenQASM documents, including unsaved files, notebook cells, etc.
5664
export function isOpenQasmDocument(document: TextDocument): boolean {
5765
return (
5866
document.languageId === openqasmLanguageId &&
59-
(Utils.extname(document.uri) === ".qasm" ||
60-
Utils.extname(document.uri) === ".inc" ||
61-
document.isUntitled) &&
67+
(hasOpenQasmExt(document.uri) || document.isUntitled) &&
6268
document.uri.scheme !== "git" &&
6369
document.uri.scheme !== "pr" &&
6470
// The Copilot Chat window also creates documents with various schemes that start
@@ -67,6 +73,11 @@ export function isOpenQasmDocument(document: TextDocument): boolean {
6773
);
6874
}
6975

76+
export function hasOpenQasmExt(uri: vscode.Uri): boolean {
77+
const ext = Utils.extname(uri);
78+
return ext === ".qasm" || ext === ".inc";
79+
}
80+
7081
export const qsharpExtensionId = "qsharp-vscode";
7182

7283
export function basename(path: string): string | undefined {

vscode/src/debugger/activate.ts

+14-29
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import * as vscode from "vscode";
88
import { qsharpExtensionId } from "../common";
99
import { clearCommandDiagnostics } from "../diagnostics";
1010
import {
11+
FullProgramConfigOrError,
1112
getActiveOpenQasmDocumentUri,
1213
getActiveQSharpDocumentUri,
1314
getOpenQasmProgramForDocument,
14-
getProgramForDocument,
15+
getQSharpProgramForDocument,
1516
} from "../programConfig";
1617
import { getRandomGuid } from "../utils";
1718
import { QscDebugSession } from "./session";
@@ -37,7 +38,9 @@ export async function activateDebugger(
3738
vscode.debug.registerDebugConfigurationProvider("qsharp", provider),
3839
);
3940

40-
const factory = new InlineDebugAdapterFactory();
41+
const factory = new InlineDebugAdapterFactory((uri) =>
42+
getQSharpProgramForDocument(uri),
43+
);
4144
context.subscriptions.push(
4245
vscode.debug.registerDebugAdapterDescriptorFactory("qsharp", factory),
4346
);
@@ -47,7 +50,9 @@ export async function activateDebugger(
4750
vscode.debug.registerDebugConfigurationProvider("openqasm", qasm_provider),
4851
);
4952

50-
const qasm_factory = new InlineOpenQasmDebugAdapterFactory();
53+
const qasm_factory = new InlineDebugAdapterFactory((uri) =>
54+
getOpenQasmProgramForDocument(uri),
55+
);
5156
context.subscriptions.push(
5257
vscode.debug.registerDebugAdapterDescriptorFactory(
5358
"openqasm",
@@ -382,39 +387,19 @@ class OpenQasmDebugConfigProvider implements vscode.DebugConfigurationProvider {
382387
class InlineDebugAdapterFactory
383388
implements vscode.DebugAdapterDescriptorFactory
384389
{
385-
async createDebugAdapterDescriptor(
386-
session: vscode.DebugSession,
387-
_executable: vscode.DebugAdapterExecutable | undefined,
388-
): Promise<vscode.DebugAdapterDescriptor> {
389-
const worker = debugServiceWorkerFactory();
390-
const uri = vscode.Uri.parse(session.configuration.programUri);
391-
const program = await getProgramForDocument(uri);
392-
if (!program.success) {
393-
throw new Error(program.errorMsg);
394-
}
390+
constructor(
391+
private programLoader: (
392+
uri: vscode.Uri,
393+
) => Promise<FullProgramConfigOrError>,
394+
) {}
395395

396-
const qscSession = new QscDebugSession(
397-
worker,
398-
session.configuration,
399-
program.programConfig,
400-
);
401-
402-
await qscSession.init(getRandomGuid());
403-
404-
return new vscode.DebugAdapterInlineImplementation(qscSession);
405-
}
406-
}
407-
408-
class InlineOpenQasmDebugAdapterFactory
409-
implements vscode.DebugAdapterDescriptorFactory
410-
{
411396
async createDebugAdapterDescriptor(
412397
session: vscode.DebugSession,
413398
_executable: vscode.DebugAdapterExecutable | undefined,
414399
): Promise<vscode.DebugAdapterDescriptor> {
415400
const worker = debugServiceWorkerFactory();
416401
const uri = vscode.Uri.parse(session.configuration.programUri);
417-
const program = await getOpenQasmProgramForDocument(uri);
402+
const program = await this.programLoader(uri);
418403
if (!program.success) {
419404
throw new Error(program.errorMsg);
420405
}

vscode/src/diagnostics.ts

+9-29
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
import { IQSharpError, log, qsharpLibraryUriScheme } from "qsharp-lang";
4+
import { IQSharpError, log } from "qsharp-lang";
55
import * as vscode from "vscode";
66
import {
7+
hasOpenQasmExt,
78
qsharpExtensionId,
89
qsharpLanguageId,
910
toVsCodeDiagnostic,
1011
} from "./common.js";
12+
import { getSourceUri } from "./utils.js";
1113

1214
/**
1315
* Initialize diagnostics for `qsharp.json` files and failures
@@ -176,9 +178,13 @@ function reportIfQSharpErrors(e: unknown) {
176178

177179
for (const error of qsharpErrors) {
178180
const uri = getSourceUri(error.document);
181+
let languageId = "Q#";
182+
if (hasOpenQasmExt(uri)) {
183+
languageId = "OpenQASM";
184+
}
179185

180186
const diagnostics = byUri.get(uri) || [];
181-
error.diagnostic.message = `Q# command error: ${error.diagnostic.message}`;
187+
error.diagnostic.message = `${languageId} command error: ${error.diagnostic.message}`;
182188
diagnostics.push(toVsCodeDiagnostic(error.diagnostic));
183189
byUri.set(uri, diagnostics);
184190
}
@@ -191,34 +197,8 @@ function reportIfQSharpErrors(e: unknown) {
191197
vscode.commands.executeCommand("workbench.action.problems.focus");
192198

193199
vscode.window.showErrorMessage(
194-
"The Q# command returned errors. Please see the Problems view.",
200+
"The command returned errors. Please see the Problems view.",
195201
{ modal: true },
196202
);
197203
}
198204
}
199-
200-
/**
201-
* This is temporary until we're able to report proper stdlib and project URIs from
202-
* the wasm layer. See https://github.com/microsoft/qsharp/blob/f8d344b32a1f1f918f3c91edf58c975db10f4370/wasm/src/diagnostic.rs
203-
*
204-
* @param maybeUri A source name returned from a Q# diagnostic
205-
* @returns A VS code URI that's okay to use in a Diagnostic object
206-
*/
207-
function getSourceUri(maybeUri: string): vscode.Uri {
208-
// An error without a span (e.g. "no entrypoint found") gets reported as a "project-level" error.
209-
// See: https://github.com/microsoft/qsharp/blob/f8d344b32a1f1f918f3c91edf58c975db10f4370/wasm/src/diagnostic.rs#L191
210-
// Ideally this would be a proper URI pointing to the project root or root document.
211-
// For now, make up a fake file path for display purposes.
212-
if (maybeUri === "<project>") {
213-
return vscode.Uri.file("Q# project");
214-
}
215-
216-
try {
217-
return vscode.Uri.parse(maybeUri, true);
218-
} catch {
219-
// Not a URI, assume it's a filename from the stdlib
220-
// This URI should ideally be properly propagated from
221-
// https://github.com/microsoft/qsharp/blob/f8d344b32a1f1f918f3c91edf58c975db10f4370/wasm/src/diagnostic.rs#L105
222-
return vscode.Uri.from({ scheme: qsharpLibraryUriScheme, path: maybeUri });
223-
}
224-
}

vscode/src/language-service/activate.ts

+44-37
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as vscode from "vscode";
1111
import {
1212
isCircuitDocument,
1313
isOpenQasmDocument,
14+
isOpenQasmNotebookCell,
1415
isQsharpDocument,
1516
isQsharpNotebookCell,
1617
openqasmLanguageId,
@@ -212,71 +213,41 @@ function registerDocumentUpdateHandlers(
212213
languageService: ILanguageService,
213214
): vscode.Disposable[] {
214215
vscode.workspace.textDocuments.forEach((document) => {
215-
updateIfQsharpDocument(document);
216-
updateIfOpenQasmDocument(document);
216+
updateIfSupportedDocument(document);
217217
});
218218

219219
// we manually send an OpenDocument telemetry event if this is a Q# document, because the
220220
// below subscriptions won't fire for documents that are already open when the extension is activated
221221
vscode.workspace.textDocuments.forEach((document) => {
222-
if (isQsharpDocument(document)) {
223-
const documentType = isQsharpNotebookCell(document)
224-
? QsharpDocumentType.JupyterCell
225-
: isCircuitDocument(document)
226-
? QsharpDocumentType.Circuit
227-
: QsharpDocumentType.Qsharp;
228-
sendTelemetryEvent(
229-
EventType.OpenedDocument,
230-
{ documentType },
231-
{ linesOfCode: document.lineCount },
232-
);
233-
}
234-
if (isOpenQasmDocument(document)) {
235-
const documentType = QsharpDocumentType.OpenQasm;
236-
sendTelemetryEvent(
237-
EventType.OpenedDocument,
238-
{ documentType },
239-
{ linesOfCode: document.lineCount },
240-
);
241-
}
222+
sendDocumentOpenedEvent(document);
242223
});
243224

244225
const subscriptions = [];
245226
subscriptions.push(
246227
vscode.workspace.onDidOpenTextDocument((document) => {
247-
const documentType = isQsharpNotebookCell(document)
248-
? QsharpDocumentType.JupyterCell
249-
: isCircuitDocument(document)
250-
? QsharpDocumentType.Circuit
251-
: isQsharpDocument(document)
252-
? QsharpDocumentType.Qsharp
253-
: isOpenQasmDocument(document)
254-
? QsharpDocumentType.OpenQasm
255-
: QsharpDocumentType.Other;
228+
const documentType = determineDocumentType(document);
256229
if (documentType !== QsharpDocumentType.Other) {
257230
sendTelemetryEvent(
258231
EventType.OpenedDocument,
259232
{ documentType },
260233
{ linesOfCode: document.lineCount },
261234
);
262235
}
263-
updateIfQsharpDocument(document);
264-
updateIfOpenQasmDocument(document);
236+
updateIfSupportedDocument(document);
265237
}),
266238
);
267239

268240
subscriptions.push(
269241
vscode.workspace.onDidChangeTextDocument((evt) => {
270-
updateIfQsharpDocument(evt.document);
271-
updateIfOpenQasmDocument(evt.document);
242+
updateIfSupportedDocument(evt.document);
272243
}),
273244
);
274245

275246
subscriptions.push(
276247
vscode.workspace.onDidCloseTextDocument((document) => {
277248
if (
278249
(isQsharpDocument(document) && !isQsharpNotebookCell(document)) ||
279-
(isOpenQasmDocument(document) && !isQsharpNotebookCell(document))
250+
(isOpenQasmDocument(document) && !isOpenQasmNotebookCell(document))
280251
) {
281252
languageService.closeDocument(document.uri.toString());
282253
}
@@ -333,7 +304,7 @@ function registerDocumentUpdateHandlers(
333304
}
334305

335306
async function updateIfOpenQasmDocument(document: vscode.TextDocument) {
336-
if (isOpenQasmDocument(document) && !isQsharpNotebookCell(document)) {
307+
if (isOpenQasmDocument(document) && !isOpenQasmNotebookCell(document)) {
337308
const content = document.getText();
338309

339310
languageService.updateDocument(
@@ -344,9 +315,45 @@ function registerDocumentUpdateHandlers(
344315
}
345316
}
346317

318+
async function updateIfSupportedDocument(document: vscode.TextDocument) {
319+
updateIfQsharpDocument(document);
320+
updateIfOpenQasmDocument(document);
321+
}
322+
347323
return subscriptions;
348324
}
349325

326+
function determineDocumentType(document: vscode.TextDocument) {
327+
return isQsharpNotebookCell(document) || isOpenQasmNotebookCell(document)
328+
? QsharpDocumentType.JupyterCell
329+
: isCircuitDocument(document)
330+
? QsharpDocumentType.Circuit
331+
: isQsharpDocument(document)
332+
? QsharpDocumentType.Qsharp
333+
: isOpenQasmDocument(document)
334+
? QsharpDocumentType.OpenQasm
335+
: QsharpDocumentType.Other;
336+
}
337+
338+
function sendDocumentOpenedEvent(document: vscode.TextDocument) {
339+
if (isQsharpDocument(document)) {
340+
const documentType = determineDocumentType(document);
341+
sendTelemetryEvent(
342+
EventType.OpenedDocument,
343+
{ documentType },
344+
{ linesOfCode: document.lineCount },
345+
);
346+
}
347+
if (isOpenQasmDocument(document)) {
348+
const documentType = QsharpDocumentType.OpenQasm;
349+
sendTelemetryEvent(
350+
EventType.OpenedDocument,
351+
{ documentType },
352+
{ linesOfCode: document.lineCount },
353+
);
354+
}
355+
}
356+
350357
function registerConfigurationChangeHandlers(
351358
languageService: ILanguageService,
352359
) {

0 commit comments

Comments
 (0)