Skip to content

OpenQASM VSCode Spec Mode #2582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions source/language_service/src/code_lens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ pub(crate) fn get_code_lenses(
return vec![]; // entrypoint actions don't work in notebooks
}

if matches!(
compilation.kind,
CompilationKind::OpenQASM {
spec_mode: true,
..
}
) {
return vec![]; // entrypoint actions don't work with OpenQASM in spec mode
}

if !compilation.project_errors.is_empty()
|| compilation
.compile_errors
Expand Down
60 changes: 45 additions & 15 deletions source/language_service/src/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use log::trace;
use qsc::{
CompileUnit, LanguageFeatures, PackageStore, PackageType, PassContext, SourceMap, Span, ast,
compile,
compile::{self, package_store_with_stdlib},
display::Lookup,
error::WithSource,
hir::{self, PackageId},
Expand Down Expand Up @@ -63,6 +63,7 @@ pub(crate) enum CompilationKind {
sources: Vec<(Arc<str>, Arc<str>)>,
/// a human-readable name for the package (not a unique URI -- meant to be read by humans)
friendly_name: Arc<str>,
spec_mode: bool,
},
}

Expand Down Expand Up @@ -255,6 +256,7 @@ impl Compilation {
pub(crate) fn new_qasm(
package_type: PackageType,
target_profile: Profile,
openqasm_spec_mode: bool,
sources: Vec<(Arc<str>, Arc<str>)>,
project_errors: Vec<project::Error>,
friendly_name: &Arc<str>,
Expand All @@ -269,28 +271,53 @@ impl Compilation {
None,
);
let res = qsc::qasm::semantic::parse_sources(&sources);
let unit = compile_to_qsharp_ast_with_config(res, config);
let CompileRawQasmResult(store, source_package_id, dependencies, _sig, mut compile_errors) =
qsc::qasm::compile_openqasm(unit, package_type, capabilities);

let compile_unit = store
.get(source_package_id)
.expect("expected to find user package");
let (compile_errors, store, source_package_id, dependencies) = if openqasm_spec_mode {
// these aren't really used, just to satisfy the API for now.
let (stdid, store) = package_store_with_stdlib(capabilities);
let dependencies = vec![(PackageId::CORE, None), (stdid, None)];
// We have OpenQASM errors, convert them to the same type as as the Q#
// compilation errors
let mut compile_errors = Vec::with_capacity(res.errors.len());
for error in res.errors {
let err = WithSource::from_map(
&res.source_map,
qsc::compile::ErrorKind::OpenQasm(error.into_error()),
);
compile_errors.push(err);
}

run_fir_passes(
&mut compile_errors,
target_profile,
&store,
source_package_id,
compile_unit,
);
(compile_errors, store, stdid, dependencies)
} else {
let unit = compile_to_qsharp_ast_with_config(res, config);
let CompileRawQasmResult(
store,
source_package_id,
dependencies,
_sig,
mut compile_errors,
) = qsc::qasm::compile_openqasm(unit, package_type, capabilities);

let compile_unit = store
.get(source_package_id)
.expect("expected to find user package");

run_fir_passes(
&mut compile_errors,
target_profile,
&store,
source_package_id,
compile_unit,
);
(compile_errors, store, source_package_id, dependencies)
};

Self {
package_store: store,
user_package_id: source_package_id,
kind: CompilationKind::OpenQASM {
sources,
friendly_name: friendly_name.clone(),
spec_mode: openqasm_spec_mode,
},
compile_errors,
project_errors,
Expand Down Expand Up @@ -392,6 +419,7 @@ impl Compilation {
target_profile: Profile,
language_features: LanguageFeatures,
lints_config: &[LintOrGroupConfig],
openqasm_spec_mode: bool,
) {
let new = match self.kind {
CompilationKind::OpenProject {
Expand Down Expand Up @@ -424,9 +452,11 @@ impl Compilation {
CompilationKind::OpenQASM {
ref sources,
ref friendly_name,
..
} => Self::new_qasm(
package_type,
target_profile,
openqasm_spec_mode,
sources.clone(),
Vec::new(), // project errors will stay the same
friendly_name,
Expand Down
1 change: 1 addition & 0 deletions source/language_service/src/completion/tests/openqasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ fn compile_project_with_markers_cursor_optional(
Compilation::new_qasm(
PackageType::Lib,
qsc::target::Profile::Unrestricted,
false,
sources,
vec![],
&Arc::from("test project"),
Expand Down
1 change: 1 addition & 0 deletions source/language_service/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub struct WorkspaceConfigurationUpdate {
pub package_type: Option<PackageType>,
pub language_features: Option<LanguageFeatures>,
pub lints_config: Option<Vec<LintOrGroupConfig>>,
pub openqasm_spec_mode: Option<bool>,
pub dev_diagnostics: Option<bool>,
}

Expand Down
12 changes: 12 additions & 0 deletions source/language_service/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct Configuration {
pub package_type: PackageType,
pub language_features: LanguageFeatures,
pub lints_config: Vec<LintOrGroupConfig>,
pub openqasm_spec_mode: bool,
/// Enables non-user-facing developer diagnostics.
pub dev_diagnostics: bool,
}
Expand All @@ -78,6 +79,7 @@ impl Default for Configuration {
package_type: PackageType::Lib,
language_features: LanguageFeatures::default(),
lints_config: Vec::default(),
openqasm_spec_mode: false,
dev_diagnostics: false,
}
}
Expand All @@ -89,6 +91,7 @@ pub struct PartialConfiguration {
pub package_type: Option<PackageType>,
pub language_features: Option<LanguageFeatures>,
pub lints_config: Vec<LintOrGroupConfig>,
pub openqasm_spec_mode: Option<bool>,
}

pub(super) struct CompilationStateUpdater<'a> {
Expand Down Expand Up @@ -310,6 +313,7 @@ impl<'a> CompilationStateUpdater<'a> {
ProjectType::OpenQASM(sources) => Compilation::new_qasm(
configuration.package_type,
configuration.target_profile,
configuration.openqasm_spec_mode,
sources,
loaded_project.errors,
&loaded_project.name,
Expand Down Expand Up @@ -416,6 +420,7 @@ impl<'a> CompilationStateUpdater<'a> {
.manifest
.map(|manifest| manifest.lints)
.unwrap_or_default(),
openqasm_spec_mode: None,
};
let configuration = merge_configurations(&notebook_configuration, &configuration);

Expand Down Expand Up @@ -572,6 +577,11 @@ impl<'a> CompilationStateUpdater<'a> {
self.configuration.lints_config = lints_config;
}

if let Some(openqasm_spec_mode) = configuration.openqasm_spec_mode {
need_recompile |= self.configuration.openqasm_spec_mode != openqasm_spec_mode;
self.configuration.openqasm_spec_mode = openqasm_spec_mode;
}

if let Some(dev_diagnostics) = configuration.dev_diagnostics {
need_recompile |= self.configuration.dev_diagnostics != dev_diagnostics;
self.configuration.dev_diagnostics = dev_diagnostics;
Expand All @@ -598,6 +608,7 @@ impl<'a> CompilationStateUpdater<'a> {
configuration.target_profile,
configuration.language_features,
&lints_config,
configuration.openqasm_spec_mode,
);
}
});
Expand Down Expand Up @@ -767,6 +778,7 @@ fn merge_configurations(
.language_features
.unwrap_or(workspace_scope.language_features),
lints_config: merged_lints,
openqasm_spec_mode: compilation_overrides.openqasm_spec_mode.unwrap_or_default(),
dev_diagnostics: workspace_scope.dev_diagnostics,
}
}
30 changes: 19 additions & 11 deletions source/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
},
"categories": [
"Programming Languages",
"Notebooks"
"Notebooks",
"Debuggers",
"Formatters",
"Linters"
],
"browser": "./out/extension.js",
"virtualWorkspaces": true,
Expand Down Expand Up @@ -161,34 +164,39 @@
"type": "boolean",
"default": false,
"description": "Suppress notifications about new QDK updates. If true, you will not be prompted about new features after updates."
},
"qdk.openqasm.enableSpecMode": {
"type": "boolean",
"default": false,
"description": "Only show OpenQASM syntax and semantic errors. This will disable the Q#-specific integration diagnostics and features."
}
}
},
"menus": {
"editor/title/run": [
{
"command": "qsharp-vscode.runProgram",
"when": "resourceLangId == qsharp || resourceLangId == openqasm || resourceLangId == qsharpcircuit",
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)",
"group": "navigation@1"
},
{
"command": "qsharp-vscode.debugProgram",
"when": "resourceLangId == qsharp || resourceLangId == openqasm || resourceLangId == qsharpcircuit",
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)",
"group": "navigation@2"
}
],
"commandPalette": [
{
"command": "qsharp-vscode.runProgram",
"when": "resourceLangId == qsharp || resourceLangId == openqasm || resourceLangId == qsharpcircuit"
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.debugProgram",
"when": "resourceLangId == qsharp || resourceLangId == openqasm || resourceLangId == qsharpcircuit"
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.runEditorContentsWithCircuit",
"when": "resourceLangId == qsharp || resourceLangId == openqasm"
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.targetSubmit",
Expand All @@ -212,31 +220,31 @@
},
{
"command": "qsharp-vscode.getQir",
"when": "resourceLangId == qsharp || resourceLangId == openqasm"
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.showHistogram",
"when": "resourceLangId == qsharp || resourceLangId == openqasm"
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.showRe",
"when": "resourceLangId == qsharp || resourceLangId == openqasm"
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.showHelp",
"when": "resourceLangId == qsharp"
},
{
"command": "qsharp-vscode.showCircuit",
"when": "resourceLangId == qsharp || resourceLangId == openqasm"
"when": "(resourceLangId == qsharp || resourceLangId == qsharpcircuit) || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.showDocumentation",
"when": "resourceLangId == qsharp"
},
{
"command": "qsharp-vscode.setTargetProfile",
"when": "resourceLangId == qsharp || resourceLangId == openqasm"
"when": "resourceLangId == qsharp || (resourceLangId == openqasm && !config.qdk.openqasm.enableSpecMode)"
},
{
"command": "qsharp-vscode.webOpener",
Expand Down
6 changes: 6 additions & 0 deletions source/vscode/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,9 @@ export function getShowDevDiagnostics(): boolean {
.getConfiguration("Q#")
.get<boolean>("dev.showDevDiagnostics", false);
}

export function getOpenQasmEnableSpecMode(): boolean {
return vscode.workspace
.getConfiguration("qdk")
.get<boolean>("openqasm.enableSpecMode", false);
}
12 changes: 10 additions & 2 deletions source/vscode/src/language-service/activate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import {
openqasmLanguageId,
qsharpLanguageId,
} from "../common.js";
import { getTarget, getShowDevDiagnostics } from "../config.js";
import {
getTarget,
getShowDevDiagnostics,
getOpenQasmEnableSpecMode,
} from "../config.js";
import {
fetchGithubRaw,
findManifestDirectory,
Expand Down Expand Up @@ -317,7 +321,8 @@ function registerConfigurationChangeHandlers(
return vscode.workspace.onDidChangeConfiguration((event) => {
if (
event.affectsConfiguration("Q#.qir.targetProfile") ||
event.affectsConfiguration("Q#.dev.showDevDiagnostics")
event.affectsConfiguration("Q#.dev.showDevDiagnostics") ||
event.affectsConfiguration("qdk.openqasm.enableSpecMode")
) {
updateLanguageServiceConfiguration(languageService);
}
Expand All @@ -329,6 +334,7 @@ async function updateLanguageServiceConfiguration(
) {
const targetProfile = getTarget();
const showDevDiagnostics = getShowDevDiagnostics();
const openqasmSpecMode = getOpenQasmEnableSpecMode();

switch (targetProfile) {
case "base":
Expand All @@ -341,11 +347,13 @@ async function updateLanguageServiceConfiguration(
}
log.debug("Target profile set to: " + targetProfile);
log.debug("Show dev diagnostics set to: " + showDevDiagnostics);
log.debug("OpenQASM spec mode set to: " + openqasmSpecMode);

// Update all configuration settings
languageService.updateConfiguration({
targetProfile: targetProfile,
devDiagnostics: showDevDiagnostics,
openqasmSpecMode: openqasmSpecMode,
lints: [{ lint: "needlessOperation", level: "warn" }],
});
}
3 changes: 3 additions & 0 deletions source/wasm/src/language_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ impl LanguageService {
.languageFeatures
.map(|features| features.iter().collect::<LanguageFeatures>()),
lints_config: config.lints,
openqasm_spec_mode: config.openqasmSpecMode,
dev_diagnostics: config.devDiagnostics,
});
}
Expand Down Expand Up @@ -382,13 +383,15 @@ serializable_type! {
pub languageFeatures: Option<Vec<String>>,
pub lints: Option<Vec<LintOrGroupConfig>>,
pub devDiagnostics: Option<bool>,
pub openqasmSpecMode: Option<bool>,
},
r#"export interface IWorkspaceConfiguration {
targetProfile?: TargetProfile;
packageType?: "exe" | "lib";
languageFeatures?: LanguageFeatures[];
lints?: ({ lint: string; level: string } | { group: string; level: string })[];
devDiagnostics?: boolean;
openqasmSpecMode?: boolean;
}"#,
IWorkspaceConfiguration
}
Expand Down