From b1dd85e5c1b5d11fdacdba2f84908385f619d4f0 Mon Sep 17 00:00:00 2001 From: yini-chen Date: Thu, 16 May 2024 15:28:20 +0800 Subject: [PATCH 1/3] feat:Code documentation has been enhanced with the Code Sample link --- src/Service.ts | 94 ++++++++++++++++++++--------------- src/extension.ts | 3 ++ src/provider/hoverProvider.ts | 74 +++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 41 deletions(-) create mode 100644 src/provider/hoverProvider.ts diff --git a/src/Service.ts b/src/Service.ts index 2e8e8e5..ca0271f 100644 --- a/src/Service.ts +++ b/src/Service.ts @@ -141,6 +141,18 @@ export class AlicloudAPIService { return {}; } + /** + * @description 根据 API 查询是否有 CodeSample + */ + async requestSamplesByAPI(product: string, version: string, api: string) { + const resStr = await fetch( + `https://api.aliyun.com/api/samples/product/${product}/version/${version}/api/${api}`, + {}, + ).then((res) => res.text()); + const res = JSON.parse(resStr); + return res?.data || []; + } + async requestEndpoints(product: string) { const resStr = await fetch( `https://api.aliyun.com/meta/v1/products/${product}/endpoints.json?language=zh-CN`, @@ -150,30 +162,31 @@ export class AlicloudAPIService { return res?.data?.endpoints || []; } - async openInCode(codeInfo:{code:string,language:string}){ - const {language, code} = codeInfo + async openInCode(codeInfo: { code: string; language: string }) { + const { language, code } = codeInfo; // 创建新的文件 - vscode.workspace.openTextDocument({ - content: code, - language: language?.toLocaleLowerCase(), - }).then(newDocument => { - vscode.window.showTextDocument(newDocument,{ - viewColumn: vscode.ViewColumn.Beside, + vscode.workspace + .openTextDocument({ + content: code, + language: language?.toLocaleLowerCase(), + }) + .then((newDocument) => { + vscode.window.showTextDocument(newDocument, { + viewColumn: vscode.ViewColumn.Beside, + }); }); - }); - return {} + return {}; } - async saveToFile(code:string){ + async saveToFile(code: string) { const uri = await vscode.window.showSaveDialog(); if (uri) { - const buf = Buffer.from(code, 'utf8'); - await vscode.workspace.fs.writeFile(uri, buf); + const buf = Buffer.from(code, "utf8"); + await vscode.workspace.fs.writeFile(uri, buf); } - return {} + return {}; } - async loadProfiles() { const configFilePath = path.join(os.homedir(), ".aliyun/config.json"); const { R_OK, W_OK } = fs.constants; @@ -188,11 +201,11 @@ export class AlicloudAPIService { } async updateLocalLanguage(lang) { - this.context.globalState.update('defaultLanguage', lang); + this.context.globalState.update("defaultLanguage", lang); } async getLocalLanguage() { - return this.context.globalState.get('defaultLanguage') + return this.context.globalState.get("defaultLanguage"); } async makeCodeRequest(requestData) { @@ -208,23 +221,22 @@ export class AlicloudAPIService { : "ak" : "ak"; const body = { - "apiName": apiMeta?.name, - "apiVersion": version, - "product": product, - "sdkType": "dara", - "params": newParamsValue || {}, - "regionId": regionId, - "endpoint": endpoint, - "credential": {type: defaultCredentialType}, - "runtimeOptions": {}, - "useCommon": false - } - const resStr = await fetch( - `https://api.aliyun.com/api/product/makeCode`, - {method: 'post', + apiName: apiMeta?.name, + apiVersion: version, + product: product, + sdkType: "dara", + params: newParamsValue || {}, + regionId: regionId, + endpoint: endpoint, + credential: { type: defaultCredentialType }, + runtimeOptions: {}, + useCommon: false, + }; + const resStr = await fetch(`https://api.aliyun.com/api/product/makeCode`, { + method: "post", body: JSON.stringify(body), - headers: {'Content-Type': 'application/json'}}, - ).then((res) => res.text()); + headers: { "Content-Type": "application/json" }, + }).then((res) => res.text()); const res = JSON.parse(resStr); return res; } @@ -247,7 +259,7 @@ export class AlicloudAPIService { : "ak" : "ak"; if (profiles?.length) { - const profile = profiles?.find(item=>item.name === profilesInfo.current) + const profile = profiles?.find((item) => item.name === profilesInfo.current); const start = Date.now(); try { data = await request({ @@ -260,7 +272,7 @@ export class AlicloudAPIService { productName: product, meta: apiMeta, bodyStyle: undefined, - credential: {type: defaultCredentialType}, + credential: { type: defaultCredentialType }, }); response = data; // 设置状态码 @@ -302,13 +314,13 @@ export class AlicloudAPIService { requestId: requestData.requestId, doc: `${product}::${version}::${apiMeta.name}`, type: "openAPIResponse", - response + response, }; - }else{ - let result = await vscode.window.showErrorMessage("请完成AK/SK配置后,再发起调用", "查看配置方法","取消"); - if (result === "查看配置方法") { - vscode.env.openExternal(vscode.Uri.parse('https://github.com/aliyun/aliyun-cli?tab=readme-ov-file#configure')); - } + } else { + let result = await vscode.window.showErrorMessage("请完成AK/SK配置后,再发起调用", "查看配置方法", "取消"); + if (result === "查看配置方法") { + vscode.env.openExternal(vscode.Uri.parse("https://github.com/aliyun/aliyun-cli?tab=readme-ov-file#configure")); + } } } diff --git a/src/extension.ts b/src/extension.ts index 844fbfb..7ebd893 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -14,6 +14,7 @@ import { AlicloudApiMetaGeneratePlugin } from "./plugins/generate"; import { getProductRequestInstance } from "./productExplorer"; import autoCompletion from "./provider/autoCompletion"; import autofix from "./provider/autofix"; +import hoverInfo from "./provider/hoverProvider"; export async function activate(context: vscode.ExtensionContext) { // if (!vscode.workspace.rootPath) { @@ -81,6 +82,8 @@ export async function activate(context: vscode.ExtensionContext) { autoCompletion(context); // 自动修复 autofix(context); + // hover提示 + hoverInfo(context); } } catch (e) { vscode.window.showErrorMessage(e.message); diff --git a/src/provider/hoverProvider.ts b/src/provider/hoverProvider.ts new file mode 100644 index 0000000..7a7ca91 --- /dev/null +++ b/src/provider/hoverProvider.ts @@ -0,0 +1,74 @@ +/** + * @author: yini-chen + * @description: hover provider + */ + +import * as vscode from "vscode"; +import { fileSel, getSpecInfoFromName } from "../utils"; +import { AlicloudAPIService, alicloudAPIMessageService } from "../Service"; +import { AlicloudApiCommands } from "../commands"; +import { getProductRequestInstance } from "../productExplorer"; + +const getKeyWord = (word: string) => { + if (/^[A-Za-z].*Request$/.test(word)) { + return word.replace("Request", ""); + } + return word; +}; + +const getProductsKeywords = (productCode: string, versions: Array): Array => { + const keywords = versions?.map((version) => { + const newVersion = version?.split("-")?.join(""); + return `${productCode}${newVersion}`.toLocaleLowerCase(); + }); + const pythonKeywords = keywords?.map((key) => { + return `${key}client`; + }); + keywords.push(productCode.toLocaleLowerCase()); + return [...keywords, ...pythonKeywords]; +}; + +class HoverProvider { + async provideHover(document: vscode.TextDocument, position: vscode.Position) { + const service = alicloudAPIMessageService; + const apis = service.pontManager.localPontSpecs + .map((pontSpec) => { + return AlicloudApiCommands.getPickItems(pontSpec); + }) + .reduce((pre, next) => pre.concat(next), []); + + const wordRange = document.getWordRangeAtPosition(position); + const word = document.getText(wordRange); + const keyWord = getKeyWord(word); + + const hoverdAPI = apis?.find((item) => item?.label?.toLocaleLowerCase() === keyWord?.toLocaleLowerCase()); + const productInstance = await getProductRequestInstance(); + const hoverdProduct = productInstance?.products?.find((item) => + getProductsKeywords(item.code, item.versions)?.includes(keyWord?.toLocaleLowerCase()), + ); + // 匹配关键字为 API 名称 + if (hoverdAPI) { + const apiName = hoverdAPI?.label; + const { product, version } = getSpecInfoFromName(hoverdAPI?.info?.split("/")[0]); + const service = new AlicloudAPIService(); + const samples = await service.requestSamplesByAPI(product, version, keyWord); + return new vscode.Hover([ + samples?.length + ? `💡 [查看更多「${apiName}」相关代码示例](https://api.aliyun.com/api/${product}/${version}/${apiName}?tab=CodeSample)` + : `💡 [查看更多「${product}」的相关代码示例](https://api.aliyun.com/api-tools/demo/${product})`, + hoverdAPI?.summary || "", + ]); + } + // 匹配关键字为产品名称 + if (hoverdProduct) { + return new vscode.Hover([ + `💡 [查看更多「${hoverdProduct?.name || hoverdProduct?.code}」的相关代码示例](https://api.aliyun.com/api-tools/demo/${hoverdProduct?.code})`, + hoverdProduct?.description || hoverdProduct?.name, + ]); + } + } +} + +export default function (context: vscode.ExtensionContext) { + context.subscriptions.push(vscode.languages.registerHoverProvider(fileSel, new HoverProvider())); +} From 8854aead472724feec09cb737d7c0953e994466d Mon Sep 17 00:00:00 2001 From: yini-chen Date: Thu, 16 May 2024 16:35:30 +0800 Subject: [PATCH 2/3] Update README --- CHANGELOG.md | 5 +++++ README.md | 6 ++++++ README.zh_CN.md | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed4076c..8d00c61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Release Notes +## 0.0.10(2024-05-16) + +- SDK code documentation has been enhanced with the Code Sample link. +- Fixed some UI issues. + ## 0.0.9(2024-04-22) - The UI was optimized and a deprecated tag was added to indicate that the API is not recommended. diff --git a/README.md b/README.md index 75f3277..53306f2 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,12 @@ Or use the keyboard shortcuts `ctrl+cmd+l` to search the API and select Insert s ![code snippets](https://img.alicdn.com/imgextra/i3/O1CN01dmGwmX1ZyVHozyKx4_!!6000000003263-1-tps-842-468.gif) +### Document enhancement + +When writing SDK code, you can get more code sample references by viewing the OpenAPI description information and additional related sample links through the code documentation. + +![Document enhancement](https://img.alicdn.com/imgextra/i3/O1CN01Yj1PrE1qwzTj3cFn8_!!6000000005561-0-tps-1562-518.jpg) + ## Feedback - Submit bug reports and feature requests on [our Github repository](https://github.com/aliyun/alibabacloud-api-vscode-toolkit/issues). diff --git a/README.zh_CN.md b/README.zh_CN.md index a57a8cc..9b1b08c 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -79,6 +79,12 @@ Default Language [zh]: zh ![code snippets](https://img.alicdn.com/imgextra/i3/O1CN01dmGwmX1ZyVHozyKx4_!!6000000003263-1-tps-842-468.gif) +### 文档增强 + +你能够在编写 SDK 代码时,通过代码文档看到 OpenAPI 的描述信息以及更多相关示例链接,来获得更多代码示例参考。 + +![Document enhancement](https://img.alicdn.com/imgextra/i3/O1CN01Yj1PrE1qwzTj3cFn8_!!6000000005561-0-tps-1562-518.jpg) + ## 反馈 - 欢迎在我们的 [Github repository](https://github.com/aliyun/alibabacloud-api-vscode-toolkit/issues) 上提交你的问题和建议。 From 59662e4c9da7024a6462e478e2848ee7909e3e51 Mon Sep 17 00:00:00 2001 From: yini-chen Date: Thu, 16 May 2024 19:43:15 +0800 Subject: [PATCH 3/3] fix conflict --- src/Service.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Service.ts b/src/Service.ts index ca0271f..e2c8b73 100644 --- a/src/Service.ts +++ b/src/Service.ts @@ -208,6 +208,27 @@ export class AlicloudAPIService { return this.context.globalState.get("defaultLanguage"); } + async getNoticeFlag() { + const globalState = this.context.globalState; + const experienceQuestionnaireKey = "questionnaireExpiration"; + const lastPromptKey = "lastPromptTime"; + // 检查上次提示的时间 + const lastPromptTime = globalState.get(lastPromptKey) as any; + const questionnaireExpiration = globalState.get(experienceQuestionnaireKey) as any; + if (!lastPromptTime || Date.now() - lastPromptTime > (questionnaireExpiration || 0) * 24 * 60 * 60 * 1000) { + return true; + } + return false; + } + + async updateQuestionnaireExpiration(days: number) { + const globalState = this.context.globalState; + const experienceQuestionnaireKey = "questionnaireExpiration"; + const lastPromptKey = "lastPromptTime"; + globalState.update(experienceQuestionnaireKey, days); + globalState.update(lastPromptKey, Date.now()); + } + async makeCodeRequest(requestData) { const { apiMeta, paramsValue, product, version, endpoint, regionId } = requestData; const newParamsValue = getFormatValues(paramsValue, apiMeta?.parameters);