Skip to content

Commit

Permalink
Warn users when using V2 API features with micro:bit V1
Browse files Browse the repository at this point in the history
  • Loading branch information
microbit-robert committed May 3, 2024
1 parent 2126e74 commit efcb956
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 13 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions public/workers/pyright-main-4d883fb033fc7fbb9f75.worker.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions public/workers/pyright-main-fbd1b969112a733566b7.worker.js

This file was deleted.

This file was deleted.

9 changes: 9 additions & 0 deletions src/device/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ export interface ConnectOptions {
serial?: boolean;
}

export type BoardVersion = "V1" | "V2";

export interface DeviceConnection extends EventEmitter {
status: ConnectionStatus;

Expand All @@ -153,6 +155,13 @@ export interface DeviceConnection extends EventEmitter {
*/
connect(options?: ConnectOptions): Promise<ConnectionStatus>;

/**
* Get the board version.
*
* @returns the board version or null if there is no connection.
*/
getBoardVersion(): BoardVersion | null;

/**
* Flash the micro:bit.
*
Expand Down
5 changes: 5 additions & 0 deletions src/device/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: MIT
*/
import {
BoardVersion,
ConnectionStatus,
DeviceConnection,
EVENT_FLASH,
Expand Down Expand Up @@ -62,6 +63,10 @@ export class MockDeviceConnection
return this.status;
}

getBoardVersion(): BoardVersion | null {
return "V2";
}

/**
* Flash the micro:bit.
*
Expand Down
5 changes: 5 additions & 0 deletions src/device/simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import EventEmitter from "events";
import { Logging } from "../logging/logging";
import {
BoardVersion,
ConnectionStatus,
DeviceConnection,
EVENT_FLASH,
Expand Down Expand Up @@ -262,6 +263,10 @@ export class SimulatorDeviceConnection
return this.status;
}

getBoardVersion(): BoardVersion | null {
return "V2";
}

async flash(
dataSource: FlashDataSource,
options: {
Expand Down
10 changes: 9 additions & 1 deletion src/device/webusb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { withTimeout, TimeoutError } from "./async-util";
import { DAPWrapper } from "./dap-wrapper";
import { PartialFlashing } from "./partial-flashing";
import {
BoardVersion,
ConnectionStatus,
ConnectOptions,
DeviceConnection,
Expand Down Expand Up @@ -172,6 +173,14 @@ export class MicrobitWebUSBConnection
});
}

getBoardVersion(): BoardVersion | null {
if (!this.connection) {
return null;
}
const boardId = this.connection.boardSerialInfo.id;
return boardId.isV1() ? "V1" : boardId.isV2() ? "V2" : null;
}

async flash(
dataSource: FlashDataSource,
options: {
Expand Down Expand Up @@ -297,7 +306,6 @@ export class MicrobitWebUSBConnection
} finally {
this.connection = undefined;
this.setStatus(ConnectionStatus.NOT_CONNECTED);

this.logging.log("Disconnection complete");
this.logging.event({
type: "WebUSB-info",
Expand Down
6 changes: 6 additions & 0 deletions src/editor/codemirror/CodeMirror.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { languageServer } from "./language-server/view";
import { lintGutter } from "./lint/lint";
import { codeStructure } from "./structure-highlighting";
import themeExtensions from "./themeExtensions";
import { useDevice } from "../../device/device-hooks";

interface CodeMirrorProps {
className?: string;
Expand Down Expand Up @@ -81,6 +82,7 @@ const CodeMirror = ({
const actionFeedback = useActionFeedback();
const [sessionSettings, setSessionSettings] = useSessionSettings();
const { apiReferenceMap } = useDocumentation();
const device = useDevice();

// Reset undo/redo events on file change.
useEffect(() => {
Expand Down Expand Up @@ -131,6 +133,7 @@ const CodeMirror = ({
client
? languageServer(
client,
device,
uri,
intl,
logging,
Expand Down Expand Up @@ -172,6 +175,7 @@ const CodeMirror = ({
parameterHelpOption,
uri,
apiReferenceMap,
device,
]);
useEffect(() => {
// Do this separately as we don't want to destroy the view whenever options needed for initialization change.
Expand All @@ -191,6 +195,7 @@ const CodeMirror = ({
client
? languageServer(
client,
device,
uri,
intl,
logging,
Expand All @@ -215,6 +220,7 @@ const CodeMirror = ({
logging,
uri,
apiReferenceMap,
device,
]);

const { location } = selection;
Expand Down
15 changes: 13 additions & 2 deletions src/editor/codemirror/language-server/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Text } from "@codemirror/state";
import * as LSP from "vscode-languageserver-protocol";
import { Diagnostic } from "../lint/lint";
import { positionToOffset } from "./positions";
import { DeviceConnection } from "../../../device/device";

const severityMapping = {
[LSP.DiagnosticSeverity.Error]: "error",
Expand All @@ -17,10 +18,20 @@ const severityMapping = {

export const diagnosticsMapping = (
document: Text,
lspDiagnostics: LSP.Diagnostic[]
lspDiagnostics: LSP.Diagnostic[],
device: DeviceConnection
): Diagnostic[] =>
lspDiagnostics
.map(({ range, message, severity, tags }): Diagnostic | undefined => {
.map(({ range, message, severity, tags, code }): Diagnostic | undefined => {
console.log(code);
console.log(device);
// Only show warnings for using V2 API features if a V1 board is connected.
if (
code === "reportMicrobitV2ApiUse" &&
device.getBoardVersion() !== "V1"
) {
return undefined;
}
let from = positionToOffset(document, range.start);
let to = positionToOffset(document, range.end);
// Skip if we can't map to the current document.
Expand Down
22 changes: 18 additions & 4 deletions src/editor/codemirror/language-server/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { autocompletion } from "./autocompletion";
import { BaseLanguageServerView, clientFacet, uriFacet } from "./common";
import { diagnosticsMapping } from "./diagnostics";
import { signatureHelp } from "./signatureHelp";
import { DeviceConnection, EVENT_STATUS } from "../../../device/device";

/**
* The main extension. This synchronises the diagnostics between the client
Expand All @@ -26,24 +27,35 @@ class LanguageServerView extends BaseLanguageServerView implements PluginValue {
if (params.uri === this.uri) {
const diagnostics = diagnosticsMapping(
this.view.state.doc,
params.diagnostics
params.diagnostics,
this.device
);
this.view.dispatch(setDiagnostics(this.view.state, diagnostics));
}
};
private destroyed = false;
constructor(view: EditorView) {
private onDeviceStatusChanged = () => {
const diagnostics = diagnosticsMapping(
this.view.state.doc,
this.client.allDiagnostics(),
this.device
);
this.view.dispatch(setDiagnostics(this.view.state, diagnostics));
};
constructor(view: EditorView, private device: DeviceConnection) {
super(view);

this.client.on("diagnostics", this.diagnosticsListener);
this.device.on(EVENT_STATUS, this.onDeviceStatusChanged);

// Is there a better way to do this? We can 't dispatch at this point.
// It would be best to do this with initial state and avoid the dispatch.
setTimeout(() => {
if (!this.destroyed) {
const diagnostics = diagnosticsMapping(
view.state.doc,
this.client.currentDiagnostics(this.uri)
this.client.currentDiagnostics(this.uri),
device
);
view.dispatch(setDiagnostics(view.state, diagnostics));
}
Expand All @@ -63,6 +75,7 @@ class LanguageServerView extends BaseLanguageServerView implements PluginValue {
destroy() {
this.destroyed = true;
this.client.removeListener("diagnostics", this.diagnosticsListener);
this.device.on(EVENT_STATUS, this.onDeviceStatusChanged);
// We don't own the client/connection which might outlive us, just our notifications.
}
}
Expand All @@ -84,6 +97,7 @@ interface Options {
*/
export function languageServer(
client: LanguageServerClient,
device: DeviceConnection,
uri: string,
intl: IntlShape,
logging: Logging,
Expand All @@ -93,7 +107,7 @@ export function languageServer(
return [
uriFacet.of(uri),
clientFacet.of(client),
ViewPlugin.define((view) => new LanguageServerView(view)),
ViewPlugin.define((view) => new LanguageServerView(view, device)),
signatureHelp(intl, options.signatureHelp.automatic, apiReferenceMap),
autocompletion(intl, logging, apiReferenceMap),
];
Expand Down
2 changes: 1 addition & 1 deletion src/language-server/pyright.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { baseUrl } from "../base";
import { createUri, LanguageServerClient } from "./client";

// This is modified by bin/update-pyright.sh
const workerScriptName = "pyright-main-fbd1b969112a733566b7.worker.js";
const workerScriptName = "pyright-main-4d883fb033fc7fbb9f75.worker.js";

// Very simple cache to avoid React re-creating pointlessly in development.
let counter = 0;
Expand Down

0 comments on commit efcb956

Please sign in to comment.