#1089: IDE2 falls back to new sketch if opening failed. (#1152)

IDE2 falls back to a new sketch if the opening fails.

Closes #1089

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta
2022-07-18 11:10:33 +02:00
committed by GitHub
parent fe31d15b9f
commit 8ad10b5adf
35 changed files with 881 additions and 659 deletions

View File

@@ -10,12 +10,13 @@ import { promisify } from 'util';
import URI from '@theia/core/lib/common/uri';
import { FileUri } from '@theia/core/lib/node';
import { isWindows, isOSX } from '@theia/core/lib/common/os';
import { ConfigService } from '../common/protocol/config-service';
import { ConfigServiceImpl } from './config-service-impl';
import {
SketchesService,
Sketch,
SketchRef,
SketchContainer,
SketchesError,
} from '../common/protocol/sketches-service';
import { firstToLowerCase } from '../common/utils';
import { NotificationServiceServerImpl } from './notification-service-server';
@@ -28,6 +29,7 @@ import {
import { duration } from '../common/decorators';
import * as glob from 'glob';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { ServiceError } from './service-error';
const WIN32_DRIVE_REGEXP = /^[a-zA-Z]:\\/;
@@ -48,8 +50,8 @@ export class SketchesServiceImpl
? tempDir
: maybeNormalizeDrive(fs.realpathSync.native(tempDir));
@inject(ConfigService)
protected readonly configService: ConfigService;
@inject(ConfigServiceImpl)
protected readonly configService: ConfigServiceImpl;
@inject(NotificationServiceServerImpl)
protected readonly notificationService: NotificationServiceServerImpl;
@@ -201,7 +203,18 @@ export class SketchesServiceImpl
const sketch = await new Promise<SketchWithDetails>((resolve, reject) => {
client.loadSketch(req, async (err, resp) => {
if (err) {
reject(err);
reject(
isNotFoundError(err)
? SketchesError.NotFound(
fixErrorMessage(
err,
requestSketchPath,
this.configService.cliConfiguration?.directories.user
),
uri
)
: err
);
return;
}
const responseSketchPath = maybeNormalizeDrive(resp.getLocationPath());
@@ -448,26 +461,15 @@ void loop() {
private async _isSketchFolder(
uri: string
): Promise<SketchWithDetails | undefined> {
const fsPath = FileUri.fsPath(uri);
let stat: fs.Stats | undefined;
try {
stat = await promisify(fs.lstat)(fsPath);
} catch {}
if (stat && stat.isDirectory()) {
const basename = path.basename(fsPath);
const files = await promisify(fs.readdir)(fsPath);
for (let i = 0; i < files.length; i++) {
if (files[i] === basename + '.ino' || files[i] === basename + '.pde') {
try {
const sketch = await this.loadSketch(
FileUri.create(fsPath).toString()
);
return sketch;
} catch {}
}
const sketch = await this.loadSketch(uri);
return sketch;
} catch (err) {
if (SketchesError.NotFound.is(err)) {
return undefined;
}
throw err;
}
return undefined;
}
async isTemp(sketch: SketchRef): Promise<boolean> {
@@ -588,6 +590,40 @@ interface SketchWithDetails extends Sketch {
readonly mtimeMs: number;
}
// https://github.com/arduino/arduino-cli/issues/1797
function fixErrorMessage(
err: ServiceError,
sketchPath: string,
sketchbookPath: string | undefined
): string {
if (!sketchbookPath) {
return err.details; // No way to repair the error message. The current sketchbook path is not available.
}
// Original: `Can't open sketch: no valid sketch found in /Users/a.kitta/Documents/Arduino: missing /Users/a.kitta/Documents/Arduino/Arduino.ino`
// Fixed: `Can't open sketch: no valid sketch found in /Users/a.kitta/Documents/Arduino: missing $sketchPath`
const message = err.details;
const incorrectMessageSuffix = path.join(sketchbookPath, 'Arduino.ino');
if (
message.startsWith("Can't open sketch: no valid sketch found in") &&
message.endsWith(`${incorrectMessageSuffix}`)
) {
const sketchName = path.basename(sketchPath);
const correctMessagePrefix = message.substring(
0,
message.length - incorrectMessageSuffix.length
);
return `${correctMessagePrefix}${path.join(
sketchPath,
`${sketchName}.ino`
)}`;
}
return err.details;
}
function isNotFoundError(err: unknown): err is ServiceError {
return ServiceError.is(err) && err.code === 5; // `NOT_FOUND` https://grpc.github.io/grpc/core/md_doc_statuscodes.html
}
/**
* If on Windows, will change the input `C:\\path\\to\\somewhere` to `c:\\path\\to\\somewhere`.
*/