feat(intellisense): add hover feature for intelliSense
This commit is contained in:
Родитель
8b15446cb1
Коммит
fc73d089c8
|
@ -26,12 +26,12 @@ export class Utility {
|
||||||
const pattern = new RegExp(keys.join("|"), flag);
|
const pattern = new RegExp(keys.join("|"), flag);
|
||||||
return str.replace(pattern, (matched) => {
|
return str.replace(pattern, (matched) => {
|
||||||
const value: string | undefined = replacement.get(matched);
|
const value: string | undefined = replacement.get(matched);
|
||||||
return value ? value : matched;
|
return value || matched;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async validateModelName(name: string, type: ModelType, folder?: string): Promise<string | undefined> {
|
public static async validateModelName(name: string, type: ModelType, folder?: string): Promise<string | undefined> {
|
||||||
if (!name || name.trim() === "") {
|
if (!name || name.trim() === Constants.EMPTY_STRING) {
|
||||||
return `Name ${Constants.NOT_EMPTY_MSG}`;
|
return `Name ${Constants.NOT_EMPTY_MSG}`;
|
||||||
}
|
}
|
||||||
if (!Constants.MODEL_NAME_REGEX.test(name)) {
|
if (!Constants.MODEL_NAME_REGEX.test(name)) {
|
||||||
|
@ -48,7 +48,7 @@ export class Utility {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static validateNotEmpty(name: string, placeholder: string): string | undefined {
|
public static validateNotEmpty(name: string, placeholder: string): string | undefined {
|
||||||
if (!name || name.trim() === "") {
|
if (!name || name.trim() === Constants.EMPTY_STRING) {
|
||||||
return `${placeholder} ${Constants.NOT_EMPTY_MSG}`;
|
return `${placeholder} ${Constants.NOT_EMPTY_MSG}`;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -25,7 +25,7 @@ export class DeviceModelManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static generateModelFileName(name: string, type: ModelType): string {
|
public static generateModelFileName(name: string, type: ModelType): string {
|
||||||
const fileType: string = type.replace(/\s+/g, "").toLowerCase();
|
const fileType: string = type.replace(/\s+/g, Constants.EMPTY_STRING).toLowerCase();
|
||||||
return `${name}.${fileType}.json`;
|
return `${name}.${fileType}.json`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
import * as parser from "jsonc-parser";
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
|
import { IntelliSenseUtility } from "./intelliSenseUtility";
|
||||||
|
|
||||||
export class DigitalTwinCompletionItemProvider implements vscode.CompletionItemProvider {
|
export class DigitalTwinCompletionItemProvider implements vscode.CompletionItemProvider {
|
||||||
public provideCompletionItems(
|
public provideCompletionItems(
|
||||||
|
@ -10,6 +12,9 @@ export class DigitalTwinCompletionItemProvider implements vscode.CompletionItemP
|
||||||
token: vscode.CancellationToken,
|
token: vscode.CancellationToken,
|
||||||
context: vscode.CompletionContext,
|
context: vscode.CompletionContext,
|
||||||
): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
|
): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
|
||||||
return null;
|
const jsonNode: parser.Node | undefined = IntelliSenseUtility.parseDigitalTwinModel(document);
|
||||||
|
if (!jsonNode) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,7 @@ import * as vscode from "vscode";
|
||||||
import { Constants } from "../common/constants";
|
import { Constants } from "../common/constants";
|
||||||
import { DiagnosticMessage, DigitalTwinConstants } from "./digitalTwinConstants";
|
import { DiagnosticMessage, DigitalTwinConstants } from "./digitalTwinConstants";
|
||||||
import { ClassNode, DigitalTwinGraph, PropertyNode, ValueSchema } from "./digitalTwinGraph";
|
import { ClassNode, DigitalTwinGraph, PropertyNode, ValueSchema } from "./digitalTwinGraph";
|
||||||
import { IntelliSenseUtility } from "./intelliSenseUtility";
|
import { IntelliSenseUtility, JsonNodeType, PropertyPair } from "./intelliSenseUtility";
|
||||||
|
|
||||||
export enum JsonNodeType {
|
|
||||||
Object = "object",
|
|
||||||
Array = "array",
|
|
||||||
String = "string",
|
|
||||||
Number = "number",
|
|
||||||
Boolean = "boolean",
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PropertyPair {
|
|
||||||
name: parser.Node;
|
|
||||||
value: parser.Node;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Problem {
|
interface Problem {
|
||||||
offset: number;
|
offset: number;
|
||||||
|
@ -54,13 +41,6 @@ export class DigitalTwinDiagnosticProvider {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static parseProperty(jsonNode: parser.Node): PropertyPair | undefined {
|
|
||||||
if (!jsonNode.children || jsonNode.children.length !== 2) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return { name: jsonNode.children[0], value: jsonNode.children[1] };
|
|
||||||
}
|
|
||||||
|
|
||||||
private static getNamePropertyPair(jsonNode: parser.Node): PropertyPair | undefined {
|
private static getNamePropertyPair(jsonNode: parser.Node): PropertyPair | undefined {
|
||||||
if (jsonNode.type !== JsonNodeType.Object || !jsonNode.children || jsonNode.children.length === 0) {
|
if (jsonNode.type !== JsonNodeType.Object || !jsonNode.children || jsonNode.children.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -68,7 +48,7 @@ export class DigitalTwinDiagnosticProvider {
|
||||||
|
|
||||||
let propertyPair: PropertyPair | undefined;
|
let propertyPair: PropertyPair | undefined;
|
||||||
for (const child of jsonNode.children) {
|
for (const child of jsonNode.children) {
|
||||||
propertyPair = DigitalTwinDiagnosticProvider.parseProperty(child);
|
propertyPair = IntelliSenseUtility.parseProperty(child);
|
||||||
if (!propertyPair) {
|
if (!propertyPair) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +215,7 @@ export class DigitalTwinDiagnosticProvider {
|
||||||
let propertyPair: PropertyPair | undefined;
|
let propertyPair: PropertyPair | undefined;
|
||||||
let propertyNode: PropertyNode | undefined;
|
let propertyNode: PropertyNode | undefined;
|
||||||
for (const child of jsonNode.children) {
|
for (const child of jsonNode.children) {
|
||||||
propertyPair = DigitalTwinDiagnosticProvider.parseProperty(child);
|
propertyPair = IntelliSenseUtility.parseProperty(child);
|
||||||
if (!propertyPair) {
|
if (!propertyPair) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ export interface PropertyNode {
|
||||||
id: string;
|
id: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
isArray?: boolean;
|
isArray?: boolean;
|
||||||
|
comment?: string;
|
||||||
range?: ClassNode[];
|
range?: ClassNode[];
|
||||||
constraint?: ConstraintNode;
|
constraint?: ConstraintNode;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +57,7 @@ enum EdgeType {
|
||||||
Label = "http://www.w3.org/2000/01/rdf-schema#label",
|
Label = "http://www.w3.org/2000/01/rdf-schema#label",
|
||||||
Domain = "http://www.w3.org/2000/01/rdf-schema#domain",
|
Domain = "http://www.w3.org/2000/01/rdf-schema#domain",
|
||||||
SubClassOf = "http://www.w3.org/2000/01/rdf-schema#subClassOf",
|
SubClassOf = "http://www.w3.org/2000/01/rdf-schema#subClassOf",
|
||||||
Comment = "http://www.w3.org/2000/01/rdf-schema#comment", // Comment hasn't been used yet in DTDL
|
Comment = "http://www.w3.org/2000/01/rdf-schema#comment",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DigitalTwinGraph {
|
export class DigitalTwinGraph {
|
||||||
|
@ -73,7 +74,7 @@ export class DigitalTwinGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getClassType(classNode: ClassNode): string {
|
public static getClassType(classNode: ClassNode): string {
|
||||||
return classNode.label ? classNode.label : classNode.id;
|
return classNode.label || classNode.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getValidTypes(propertyNode: PropertyNode): string[] {
|
public static getValidTypes(propertyNode: PropertyNode): string[] {
|
||||||
|
@ -122,12 +123,14 @@ export class DigitalTwinGraph {
|
||||||
private propertyNodes: Map<string, PropertyNode>;
|
private propertyNodes: Map<string, PropertyNode>;
|
||||||
private contextNodes: Map<string, ContextNode>;
|
private contextNodes: Map<string, ContextNode>;
|
||||||
private constraintNodes: Map<string, ConstraintNode>;
|
private constraintNodes: Map<string, ConstraintNode>;
|
||||||
|
private reversedIndex: Map<string, string>;
|
||||||
private vocabulary: string;
|
private vocabulary: string;
|
||||||
private constructor() {
|
private constructor() {
|
||||||
this.classNodes = new Map<string, ClassNode>();
|
this.classNodes = new Map<string, ClassNode>();
|
||||||
this.propertyNodes = new Map<string, PropertyNode>();
|
this.propertyNodes = new Map<string, PropertyNode>();
|
||||||
this.contextNodes = new Map<string, ContextNode>();
|
this.contextNodes = new Map<string, ContextNode>();
|
||||||
this.constraintNodes = new Map<string, ConstraintNode>();
|
this.constraintNodes = new Map<string, ConstraintNode>();
|
||||||
|
this.reversedIndex = new Map<string, string>();
|
||||||
this.vocabulary = Constants.EMPTY_STRING;
|
this.vocabulary = Constants.EMPTY_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +142,10 @@ export class DigitalTwinGraph {
|
||||||
return this.propertyNodes.get(id);
|
return this.propertyNodes.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getNodeId(name: string): string {
|
||||||
|
return this.reversedIndex.get(name) || Constants.EMPTY_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
private init(context: vscode.ExtensionContext): void {
|
private init(context: vscode.ExtensionContext): void {
|
||||||
let contextJson;
|
let contextJson;
|
||||||
let constraintJson;
|
let constraintJson;
|
||||||
|
@ -161,17 +168,21 @@ export class DigitalTwinGraph {
|
||||||
const context = contextJson[DigitalTwinConstants.CONTEXT];
|
const context = contextJson[DigitalTwinConstants.CONTEXT];
|
||||||
this.vocabulary = context[DigitalTwinConstants.VOCABULARY] as string;
|
this.vocabulary = context[DigitalTwinConstants.VOCABULARY] as string;
|
||||||
|
|
||||||
|
let id: string;
|
||||||
for (const key in context) {
|
for (const key in context) {
|
||||||
if (DigitalTwinGraph.isReservedName(key)) {
|
if (DigitalTwinGraph.isReservedName(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const value = context[key];
|
const value = context[key];
|
||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
this.contextNodes.set(this.getId(value), { name: key, isArray: false });
|
id = this.getId(value);
|
||||||
|
this.contextNodes.set(id, { name: key, isArray: false });
|
||||||
} else {
|
} else {
|
||||||
const isArray: boolean = DigitalTwinGraph.isArrayType(value);
|
const isArray: boolean = DigitalTwinGraph.isArrayType(value);
|
||||||
this.contextNodes.set(this.getId(value[DigitalTwinConstants.ID] as string), { name: key, isArray });
|
id = this.getId(value[DigitalTwinConstants.ID] as string);
|
||||||
|
this.contextNodes.set(id, { name: key, isArray });
|
||||||
}
|
}
|
||||||
|
this.reversedIndex.set(key, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +226,9 @@ export class DigitalTwinGraph {
|
||||||
case EdgeType.SubClassOf:
|
case EdgeType.SubClassOf:
|
||||||
this.handleEdgeOfSubClassOf(edge);
|
this.handleEdgeOfSubClassOf(edge);
|
||||||
break;
|
break;
|
||||||
|
case EdgeType.Comment:
|
||||||
|
this.handleEdgeOfComment(edge);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,6 +338,22 @@ export class DigitalTwinGraph {
|
||||||
baseClassNode.children.push(classNode);
|
baseClassNode.children.push(classNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handle data of Comment edge
|
||||||
|
* 1. set comment of property node
|
||||||
|
* @param edge edge data
|
||||||
|
*/
|
||||||
|
private handleEdgeOfComment(edge: any): void {
|
||||||
|
const id: string = edge.SourceNode.Id as string;
|
||||||
|
const comment: string = edge.TargetNode.Value as string;
|
||||||
|
|
||||||
|
// TODO:(erichen): need to check if comment only exist in property
|
||||||
|
const propertyNode: PropertyNode | undefined = this.propertyNodes.get(id);
|
||||||
|
if (propertyNode) {
|
||||||
|
propertyNode.comment = comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ensureClassNode(id: string): ClassNode {
|
private ensureClassNode(id: string): ClassNode {
|
||||||
let classNode: ClassNode | undefined = this.classNodes.get(id);
|
let classNode: ClassNode | undefined = this.classNodes.get(id);
|
||||||
if (!classNode) {
|
if (!classNode) {
|
||||||
|
|
|
@ -1,16 +1,51 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
import * as parser from "jsonc-parser";
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
|
import { Constants } from "../common/constants";
|
||||||
|
import { DigitalTwinConstants } from "./digitalTwinConstants";
|
||||||
|
import { PropertyNode } from "./digitalTwinGraph";
|
||||||
|
import { IntelliSenseUtility, PropertyPair } from "./intelliSenseUtility";
|
||||||
|
|
||||||
export class DigitalTwinHoverProvider implements vscode.HoverProvider {
|
export class DigitalTwinHoverProvider implements vscode.HoverProvider {
|
||||||
|
private static getContent(propertyName: string): string {
|
||||||
|
if (!propertyName) {
|
||||||
|
return Constants.EMPTY_STRING;
|
||||||
|
}
|
||||||
|
switch (propertyName) {
|
||||||
|
case DigitalTwinConstants.ID:
|
||||||
|
return `An identifier for ${Constants.CHANNEL_NAME} Capability Model or interface`;
|
||||||
|
case DigitalTwinConstants.TYPE:
|
||||||
|
return `The type of ${Constants.CHANNEL_NAME} meta model object`;
|
||||||
|
case DigitalTwinConstants.CONTEXT:
|
||||||
|
return `The context for ${Constants.CHANNEL_NAME} Capability Model or interface`;
|
||||||
|
default:
|
||||||
|
const propertyNode: PropertyNode | undefined = IntelliSenseUtility.getPropertyNode(propertyName);
|
||||||
|
return propertyNode && propertyNode.comment ? propertyNode.comment : Constants.EMPTY_STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public provideHover(
|
public provideHover(
|
||||||
document: vscode.TextDocument,
|
document: vscode.TextDocument,
|
||||||
position: vscode.Position,
|
position: vscode.Position,
|
||||||
token: vscode.CancellationToken,
|
token: vscode.CancellationToken,
|
||||||
): vscode.ProviderResult<vscode.Hover> {
|
): vscode.ProviderResult<vscode.Hover> {
|
||||||
if (!document) {
|
const jsonNode: parser.Node | undefined = IntelliSenseUtility.parseDigitalTwinModel(document);
|
||||||
|
if (!jsonNode) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
const currentNode: parser.Node | undefined = parser.findNodeAtOffset(jsonNode, document.offsetAt(position));
|
||||||
|
// parent is property node
|
||||||
|
if (currentNode && currentNode.parent) {
|
||||||
|
const propertyPair: PropertyPair | undefined = IntelliSenseUtility.parseProperty(currentNode.parent);
|
||||||
|
if (propertyPair) {
|
||||||
|
const content: string = DigitalTwinHoverProvider.getContent(propertyPair.name.value as string);
|
||||||
|
if (content) {
|
||||||
|
return new vscode.Hover(content, IntelliSenseUtility.getNodeRange(document, currentNode.parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,21 @@
|
||||||
import * as parser from "jsonc-parser";
|
import * as parser from "jsonc-parser";
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { DigitalTwinConstants } from "./digitalTwinConstants";
|
import { DigitalTwinConstants } from "./digitalTwinConstants";
|
||||||
import { JsonNodeType } from "./digitalTwinDiagnosticProvider";
|
|
||||||
import { DigitalTwinGraph, PropertyNode } from "./digitalTwinGraph";
|
import { DigitalTwinGraph, PropertyNode } from "./digitalTwinGraph";
|
||||||
|
|
||||||
|
export enum JsonNodeType {
|
||||||
|
Object = "object",
|
||||||
|
Array = "array",
|
||||||
|
String = "string",
|
||||||
|
Number = "number",
|
||||||
|
Boolean = "boolean",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PropertyPair {
|
||||||
|
name: parser.Node;
|
||||||
|
value: parser.Node;
|
||||||
|
}
|
||||||
|
|
||||||
export class IntelliSenseUtility {
|
export class IntelliSenseUtility {
|
||||||
public static initGraph(context: vscode.ExtensionContext): boolean {
|
public static initGraph(context: vscode.ExtensionContext): boolean {
|
||||||
IntelliSenseUtility.graph = DigitalTwinGraph.getInstance(context);
|
IntelliSenseUtility.graph = DigitalTwinGraph.getInstance(context);
|
||||||
|
@ -40,8 +52,20 @@ export class IntelliSenseUtility {
|
||||||
return IntelliSenseUtility.getPropertyNode(DigitalTwinConstants.ENTRY_NODE);
|
return IntelliSenseUtility.getPropertyNode(DigitalTwinConstants.ENTRY_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getPropertyNode(propertyName: string): PropertyNode | undefined {
|
public static getPropertyNode(name: string): PropertyNode | undefined {
|
||||||
return IntelliSenseUtility.graph.getPropertyNode(propertyName);
|
const id: string = IntelliSenseUtility.graph.getNodeId(name) || name;
|
||||||
|
return IntelliSenseUtility.graph.getPropertyNode(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static parseProperty(jsonNode: parser.Node): PropertyPair | undefined {
|
||||||
|
if (!jsonNode.children || jsonNode.children.length !== 2) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return { name: jsonNode.children[0], value: jsonNode.children[1] };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getNodeRange(document: vscode.TextDocument, node: parser.Node): vscode.Range {
|
||||||
|
return new vscode.Range(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static graph: DigitalTwinGraph;
|
private static graph: DigitalTwinGraph;
|
||||||
|
|
|
@ -121,7 +121,7 @@ export class ModelRepositoryClient {
|
||||||
if (repoInfo.repositoryId) {
|
if (repoInfo.repositoryId) {
|
||||||
qs.repositoryId = repoInfo.repositoryId;
|
qs.repositoryId = repoInfo.repositoryId;
|
||||||
}
|
}
|
||||||
const accessToken = repoInfo.accessToken ? repoInfo.accessToken : "";
|
const accessToken = repoInfo.accessToken || Constants.EMPTY_STRING;
|
||||||
const options: request.OptionsWithUri = {
|
const options: request.OptionsWithUri = {
|
||||||
method,
|
method,
|
||||||
uri,
|
uri,
|
||||||
|
|
|
@ -83,7 +83,7 @@ export class ModelRepositoryManager {
|
||||||
accessToken: connection.generateAccessToken(),
|
accessToken: connection.generateAccessToken(),
|
||||||
};
|
};
|
||||||
// test connection by calling searchModel
|
// test connection by calling searchModel
|
||||||
await ModelRepositoryClient.searchModel(repoInfo, ModelType.Interface, "", 1, null);
|
await ModelRepositoryClient.searchModel(repoInfo, ModelType.Interface, Constants.EMPTY_STRING, 1, null);
|
||||||
if (newConnection) {
|
if (newConnection) {
|
||||||
await CredentialStore.set(Constants.MODEL_REPOSITORY_CONNECTION_KEY, connectionString);
|
await CredentialStore.set(Constants.MODEL_REPOSITORY_CONNECTION_KEY, connectionString);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ export class ModelRepositoryManager {
|
||||||
public async searchModel(
|
public async searchModel(
|
||||||
type: ModelType,
|
type: ModelType,
|
||||||
publicRepository: boolean,
|
publicRepository: boolean,
|
||||||
keyword: string = "",
|
keyword: string = Constants.EMPTY_STRING,
|
||||||
pageSize: number = Constants.DEFAULT_PAGE_SIZE,
|
pageSize: number = Constants.DEFAULT_PAGE_SIZE,
|
||||||
continuationToken: string | null = null,
|
continuationToken: string | null = null,
|
||||||
): Promise<SearchResult> {
|
): Promise<SearchResult> {
|
||||||
|
|
|
@ -68,7 +68,7 @@ export class UI {
|
||||||
}
|
}
|
||||||
items.push({ label: UIConstants.BROWSE_LABEL, description: "" });
|
items.push({ label: UIConstants.BROWSE_LABEL, description: "" });
|
||||||
const selected: vscode.QuickPickItem = await UI.showQuickPick(label, items);
|
const selected: vscode.QuickPickItem = await UI.showQuickPick(label, items);
|
||||||
return selected.description ? selected.description : await UI.showOpenDialog(label);
|
return selected.description || (await UI.showOpenDialog(label));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async showQuickPick(label: string, items: vscode.QuickPickItem[]): Promise<vscode.QuickPickItem> {
|
public static async showQuickPick(label: string, items: vscode.QuickPickItem[]): Promise<vscode.QuickPickItem> {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче