From df339be778282f4ec18e15db1bc6d8698e052808 Mon Sep 17 00:00:00 2001 From: Gregory Gridin <51379812+ggridin@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:39:06 -0700 Subject: [PATCH] Add edit/run for kata examples - issue 591 (#1829) Add the edit/run for kata examples. This PR closes https://github.com/microsoft/qsharp/issues/591 Monaco editor model should have a unique URI (with few exceptions). So, either kata lesson ID or kata exercise ID is provided to the model. The Editor.tsx implementation is replacing "kataExercise" parameter with "kataSection" that contains both lesson.id and exercise.id. The function parameter "key" is not in use and was removed. --- playground/src/editor.tsx | 18 +++++++++-------- playground/src/kata.tsx | 42 +++++++++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/playground/src/editor.tsx b/playground/src/editor.tsx index 8f530a653f..00e35d56a4 100644 --- a/playground/src/editor.tsx +++ b/playground/src/editor.tsx @@ -19,6 +19,8 @@ import { Exercise, getExerciseSources } from "qsharp-lang/katas-md"; import { codeToCompressedBase64, lsRangeToMonacoRange } from "./utils.js"; import { ActiveTab } from "./main.js"; +import type { KataSection } from "qsharp-lang/katas"; + type ErrCollection = { checkDiags: VSDiagnostic[]; shotDiags: VSDiagnostic[]; @@ -80,7 +82,7 @@ export function Editor(props: { compilerState: CompilerState; defaultShots: number; evtTarget: QscEventTarget; - kataExercise?: Exercise; + kataSection?: KataSection; onRestartCompiler: () => void; shotError?: VSDiagnostic; showExpr: boolean; @@ -197,9 +199,9 @@ export function Editor(props: { } as ProgramConfig; try { - if (props.kataExercise) { + if (props.kataSection?.type === "exercise") { // This is for a kata exercise. Provide the sources that implement the solution verification. - const sources = await getExerciseSources(props.kataExercise); + const sources = await getExerciseSources(props.kataSection as Exercise); // check uses the unrestricted profile and doesn't do code gen, // so we just pass the sources await props.compiler.checkExerciseSolution( @@ -243,12 +245,12 @@ export function Editor(props: { editor.current = newEditor; const srcModel = monaco.editor.getModel( - monaco.Uri.parse(props.kataExercise?.id ?? "main.qs"), + monaco.Uri.parse(props.kataSection?.id ?? "main.qs"), ) ?? monaco.editor.createModel( "", "qsharp", - monaco.Uri.parse(props.kataExercise?.id ?? "main.qs"), + monaco.Uri.parse(props.kataSection?.id ?? "main.qs"), ); srcModel.setValue(props.code); newEditor.setModel(srcModel); @@ -293,8 +295,8 @@ export function Editor(props: { useEffect(() => { props.languageService.updateConfiguration({ targetProfile: profile, - packageType: props.kataExercise ? "lib" : "exe", - lints: props.kataExercise + packageType: props.kataSection ? "lib" : "exe", + lints: props.kataSection ? [] : [{ lint: "needlessOperation", level: "warn" }], }); @@ -314,7 +316,7 @@ export function Editor(props: { log.info("Removing diagnostics listener"); props.languageService.removeEventListener("diagnostics", onDiagnostics); }; - }, [props.languageService, props.kataExercise]); + }, [props.languageService, props.kataSection]); useEffect(() => { const theEditor = editor.current; diff --git a/playground/src/kata.tsx b/playground/src/kata.tsx index 2452e0970f..3aa5650ea5 100644 --- a/playground/src/kata.tsx +++ b/playground/src/kata.tsx @@ -81,6 +81,9 @@ function LessonElem(props: Props & { section: KataSection }) { if (props.section.type !== "lesson") throw "Invalid section type"; const lesson = props.section; + const [shotError, setShotError] = useState(); + const [evtHandler] = useState(() => new QscEventTarget(true)); + return (
@@ -94,9 +97,38 @@ function LessonElem(props: Props & { section: KataSection }) { switch (item.type) { case "example": return ( -
-                  {item.code}
-                
+ <> + ({})} + setHir={() => ({})} + setQir={() => ({})} + activeTab="results-tab" + languageService={props.languageService} + > + setShotError(diag)} + ast="" + hir="" + qir="" + activeTab="results-tab" + setActiveTab={() => undefined} + > + ); case "text-content": return ; @@ -140,8 +172,7 @@ function ExerciseElem(props: Props & { section: KataSection }) { compiler_worker_factory={props.compiler_worker_factory} onRestartCompiler={props.onRestartCompiler} code={exercise.placeholderCode} - kataExercise={exercise} - key={exercise.id} + kataSection={exercise} profile={getProfile()} setAst={() => ({})} setHir={() => ({})} @@ -150,7 +181,6 @@ function ExerciseElem(props: Props & { section: KataSection }) { languageService={props.languageService} >