diff --git a/package-lock.json b/package-lock.json index 53bd9a3..8505621 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1735,9 +1735,9 @@ } }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", diff --git a/src/common/utility.ts b/src/common/utility.ts index 3057750..f179f22 100644 --- a/src/common/utility.ts +++ b/src/common/utility.ts @@ -143,13 +143,5 @@ export class Utility { return fs.readJson(filePath, { encoding: Constants.UTF8 }); } - /** - * get json content from file in synchronous way - * @param filePath file path - */ - public static getJsonContentSync(filePath: string): any { - return fs.readJsonSync(filePath, { encoding: Constants.UTF8 }); - } - private constructor() {} } diff --git a/src/extension.ts b/src/extension.ts index 8357dfb..78367ba 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -198,10 +198,8 @@ function initCommand( } function initIntelliSense(context: vscode.ExtensionContext): void { - if (!IntelliSenseUtility.initGraph(context)) { - UI.showNotification(MessageType.Warn, UIConstants.INTELLISENSE_NOT_ENABLED_MSG); - return; - } + // init DigitalTwin graph + IntelliSenseUtility.initGraph(context); // register providers of completionItem and hover const selector: vscode.DocumentSelector = { language: "json", @@ -221,9 +219,9 @@ function initIntelliSense(context: vscode.ExtensionContext): void { Constants.CHANNEL_NAME, ); const diagnosticProvider = new DigitalTwinDiagnosticProvider(); - const activateTextEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - if (activateTextEditor) { - diagnosticProvider.updateDiagnostics(activateTextEditor.document, diagnosticCollection); + const activeTextEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + if (activeTextEditor) { + diagnosticProvider.updateDiagnostics(activeTextEditor.document, diagnosticCollection); } context.subscriptions.push(diagnosticCollection); context.subscriptions.push( diff --git a/src/intelliSense/digitalTwinCompletionItemProvider.ts b/src/intelliSense/digitalTwinCompletionItemProvider.ts index e8b0a3d..f6f09b2 100644 --- a/src/intelliSense/digitalTwinCompletionItemProvider.ts +++ b/src/intelliSense/digitalTwinCompletionItemProvider.ts @@ -281,10 +281,7 @@ export class DigitalTwinCompletionItemProvider implements vscode.CompletionItemP if (propertyNode) { properties.push(propertyNode); } - if (required.has(DigitalTwinConstants.CONTEXT)) { - properties.push({ id: DigitalTwinConstants.CONTEXT }); - } - // suggest @type property for the case that object type is inferred and @type is requried (e.g. inlined Interface) + // suggest @type property for inline Interface if (required.has(DigitalTwinConstants.TYPE)) { properties.push({ id: DigitalTwinConstants.TYPE }); } diff --git a/src/intelliSense/digitalTwinDiagnosticProvider.ts b/src/intelliSense/digitalTwinDiagnosticProvider.ts index 1035438..231c6d6 100644 --- a/src/intelliSense/digitalTwinDiagnosticProvider.ts +++ b/src/intelliSense/digitalTwinDiagnosticProvider.ts @@ -153,7 +153,12 @@ export class DigitalTwinDiagnosticProvider { DigitalTwinDiagnosticProvider.validateProperties(jsonNode, classNode, problems, exist); // validate required property if (classNode.constraint && classNode.constraint.required) { - const requiredProperty: string[] = classNode.constraint.required.filter((p) => !exist.has(p)); + const requiredProperty: string[] = classNode.constraint.required.filter((p) => { + // @context is not required for inline Interface + const isInterfaceSchem: boolean = + p === DigitalTwinConstants.CONTEXT && digitalTwinNode.label === DigitalTwinConstants.SCHEMA; + return !exist.has(p) && !isInterfaceSchem; + }); if (requiredProperty.length > 0) { const message: string = [DiagnosticMessage.MissingRequiredProperties, ...requiredProperty].join( Constants.LINE_FEED, @@ -425,11 +430,12 @@ export class DigitalTwinDiagnosticProvider { * @param collection diagnostic collection */ public updateDiagnostics(document: vscode.TextDocument, collection: vscode.DiagnosticCollection): void { + // clean diagnostic cache + collection.delete(document.uri); const jsonNode: parser.Node | undefined = IntelliSenseUtility.parseDigitalTwinModel(document.getText()); if (!jsonNode) { return; } - collection.delete(document.uri); const diagnostics: vscode.Diagnostic[] = this.provideDiagnostics(document, jsonNode); collection.set(document.uri, diagnostics); } diff --git a/src/intelliSense/digitalTwinGraph.ts b/src/intelliSense/digitalTwinGraph.ts index 0983577..5795b16 100644 --- a/src/intelliSense/digitalTwinGraph.ts +++ b/src/intelliSense/digitalTwinGraph.ts @@ -89,10 +89,10 @@ export class DigitalTwinGraph { * get singleton instance of DigitalTwin graph * @param context extension context */ - public static getInstance(context: vscode.ExtensionContext): DigitalTwinGraph { + public static async getInstance(context: vscode.ExtensionContext): Promise { if (!DigitalTwinGraph.instance) { DigitalTwinGraph.instance = new DigitalTwinGraph(); - DigitalTwinGraph.instance.init(context); + await DigitalTwinGraph.instance.init(context); } return DigitalTwinGraph.instance; } @@ -179,15 +179,15 @@ export class DigitalTwinGraph { } /** - * read configuration file, return json object + * resolve definition * @param context extension context * @param fileName file name */ - private static readConfiguration(context: vscode.ExtensionContext, fileName: string): any { + private static async resolveDefinition(context: vscode.ExtensionContext, fileName: string): Promise { const filePath: string = context.asAbsolutePath( path.join(Constants.RESOURCE_FOLDER, Constants.DEFINITION_FOLDER, fileName), ); - return Utility.getJsonContentSync(filePath); + return await Utility.getJsonContent(filePath); } private classNodes: Map; @@ -234,15 +234,15 @@ export class DigitalTwinGraph { * inititalize DigitalTwin graph * @param context extension context */ - private init(context: vscode.ExtensionContext): void { + private async init(context: vscode.ExtensionContext): Promise { let contextJson; let constraintJson; let graphJson; - // load DigitalTwin definitions by configuration file + // load definition file try { - contextJson = DigitalTwinGraph.readConfiguration(context, Constants.CONTEXT_FILE_NAME); - constraintJson = DigitalTwinGraph.readConfiguration(context, Constants.CONSTRAINT_FILE_NAME); - graphJson = DigitalTwinGraph.readConfiguration(context, Constants.GRAPH_FILE_NAME); + contextJson = await DigitalTwinGraph.resolveDefinition(context, Constants.CONTEXT_FILE_NAME); + constraintJson = await DigitalTwinGraph.resolveDefinition(context, Constants.CONSTRAINT_FILE_NAME); + graphJson = await DigitalTwinGraph.resolveDefinition(context, Constants.GRAPH_FILE_NAME); } catch (error) { return; } diff --git a/src/intelliSense/intelliSenseUtility.ts b/src/intelliSense/intelliSenseUtility.ts index b5c7770..2a33aa8 100644 --- a/src/intelliSense/intelliSenseUtility.ts +++ b/src/intelliSense/intelliSenseUtility.ts @@ -30,9 +30,8 @@ export interface PropertyPair { * Utility for IntelliSense */ export class IntelliSenseUtility { - public static initGraph(context: vscode.ExtensionContext): boolean { - IntelliSenseUtility.graph = DigitalTwinGraph.getInstance(context); - return IntelliSenseUtility.graph.initialized(); + public static async initGraph(context: vscode.ExtensionContext): Promise { + IntelliSenseUtility.graph = await DigitalTwinGraph.getInstance(context); } /** @@ -66,6 +65,9 @@ export class IntelliSenseUtility { * get entry node of DigitalTwin model */ public static getEntryNode(): PropertyNode | undefined { + if (!IntelliSenseUtility.graph) { + return undefined; + } return IntelliSenseUtility.graph.getPropertyNode(DigitalTwinConstants.ENTRY_NODE); } @@ -74,6 +76,9 @@ export class IntelliSenseUtility { * @param name property name */ public static getPropertyNode(name: string): PropertyNode | undefined { + if (!IntelliSenseUtility.graph) { + return undefined; + } return IntelliSenseUtility.graph.getPropertyNode(name); } @@ -82,6 +87,9 @@ export class IntelliSenseUtility { * @param name class name */ public static getClasNode(name: string): ClassNode | undefined { + if (!IntelliSenseUtility.graph) { + return undefined; + } return IntelliSenseUtility.graph.getClassNode(name); } diff --git a/src/modelRepository/modelRepositoryManager.ts b/src/modelRepository/modelRepositoryManager.ts index 2dcb763..30cf10d 100644 --- a/src/modelRepository/modelRepositoryManager.ts +++ b/src/modelRepository/modelRepositoryManager.ts @@ -226,10 +226,14 @@ export class ModelRepositoryManager { throw new BadRequestError("pageSize should be greater than 0"); } + // only show output when keyword is defined + const showOutput: boolean = keyword ? true : false; const operation = `Search ${type} by keyword "${keyword}" from ${ publicRepository ? RepositoryType.Public : RepositoryType.Company }`; - this.outputChannel.start(operation, this.component); + if (showOutput) { + this.outputChannel.start(operation, this.component); + } let result: SearchResult; try { @@ -239,7 +243,9 @@ export class ModelRepositoryManager { throw new ProcessError(operation, error, this.component); } - this.outputChannel.end(operation, this.component); + if (showOutput) { + this.outputChannel.end(operation, this.component); + } return result; } diff --git a/src/views/ui.ts b/src/views/ui.ts index f03cc2d..0f9529e 100644 --- a/src/views/ui.ts +++ b/src/views/ui.ts @@ -201,7 +201,13 @@ export class UI { const items: Array> = []; await Promise.all( files.map(async (f) => { - const fileInfo: ModelFileInfo | undefined = await Utility.getModelFileInfo(f.path); + let fileInfo: ModelFileInfo | undefined; + try { + fileInfo = await Utility.getModelFileInfo(f.fsPath); + } catch { + // skip if file is not a valid json + return; + } if (fileInfo) { if (!type || type === fileInfo.type) { items.push({ diff --git a/src/views/uiConstants.ts b/src/views/uiConstants.ts index bfea4cf..5f7893c 100644 --- a/src/views/uiConstants.ts +++ b/src/views/uiConstants.ts @@ -21,5 +21,4 @@ export class UIConstants { "No device model is found in current workspace. Please open the folder that contains models and try again"; public static readonly ASK_TO_SAVE_MSG = "The following files contain unsaved changes, do you want to save them?"; public static readonly ASK_TO_OVERWRITE_MSG = "do you want to overwrite it?"; - public static readonly INTELLISENSE_NOT_ENABLED_MSG = "Fail to enable intelliSense"; }