diff --git a/hdc/api_scan_IntelliJ_plugin/resources/META-INF/plugin.xml b/hdc/api_scan_IntelliJ_plugin/resources/META-INF/plugin.xml
new file mode 100644
index 0000000000000000000000000000000000000000..993be83133ce52429cdb215207b624cf2c569299
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/resources/META-INF/plugin.xml
@@ -0,0 +1,27 @@
+
+ com.kh.scan
+ API Scan
+ 1.0
+ 深圳开鸿数字产业发展有限公司
+
+
+
+ com.intellij.modules.lang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hdc/api_scan_IntelliJ_plugin/resources/images/openDisk.png b/hdc/api_scan_IntelliJ_plugin/resources/images/openDisk.png
new file mode 100644
index 0000000000000000000000000000000000000000..5956a0e538a400c7deaf41167ae5ea70348b8584
Binary files /dev/null and b/hdc/api_scan_IntelliJ_plugin/resources/images/openDisk.png differ
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/action/ScanDirAction.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/action/ScanDirAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd04c3cb07822f849a3fb19af5759b72c983dfdf
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/action/ScanDirAction.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.action;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JTextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * 编译文件夹选择框
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: select generator file path
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class ScanDirAction implements ActionListener {
+ private final JButton button;
+ private final JTextField textField;
+
+ public ScanDirAction(JButton button, JTextField textField) {
+ this.button = button;
+ this.textField = textField;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent actionEvent) {
+ if (actionEvent.getSource().equals(button)) {
+ JFileChooser fcDlg = new JFileChooser(textField.getText());
+ fcDlg.setDialogTitle("请选择扫描项目路径...");
+ fcDlg.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int returnVal = fcDlg.showOpenDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ String filepath = fcDlg.getSelectedFile().getPath();
+ textField.setText(filepath);
+ }
+ }
+ }
+}
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/action/ScanResultDirAction.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/action/ScanResultDirAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fa76065b502553fceaf9246a10afe4eadcd46ae
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/action/ScanResultDirAction.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.action;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JTextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * 脚本选择对话框
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: select compile script
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class ScanResultDirAction implements ActionListener {
+ private final JButton button;
+ private final JTextField textField;
+
+ public ScanResultDirAction(JButton button, JTextField textField) {
+ this.button = button;
+ this.textField = textField;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent actionEvent) {
+ if (actionEvent.getSource().equals(button)) {
+ JFileChooser fcDlg = new JFileChooser(textField.getText());
+ fcDlg.setDialogTitle("请选择输出结果路径...");
+ fcDlg.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int returnVal = fcDlg.showOpenDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ String filepath = fcDlg.getSelectedFile().getPath();
+ textField.setText(filepath);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialog.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d9809f0870fc29b793ff0d8ffda05c3e9831114
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialog.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2022 Guangzhou Digitalchina Information Technology Co., Ltd.
+ * All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.dialog;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.ValidationInfo;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.Action;
+import javax.swing.JComponent;
+import java.awt.Desktop;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * 主界面对话框Wrapper
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: tool conversion plug-in
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class ApiScanDialog extends DialogWrapper {
+ private static final Logger LOG = Logger.getInstance(ApiScanDialog.class);
+ private static final String TITLE = "API Scan";
+ private static final String URL = "https://gitee.com/openharmony/napi_generator/tree/master/hdc/API-Scan";
+
+ private final ApiScanDialogPane genDiag;
+
+ /**
+ * 构造函数
+ *
+ * @param project projectId
+ */
+ public ApiScanDialog(Project project) {
+ super(true);
+ this.setResizable(false);
+ setTitle(TITLE);
+ setModal(true);
+ genDiag = new ApiScanDialogPane(project);
+ init();
+ }
+
+ /**
+ * 创建视图
+ *
+ * @return 组件内容
+ */
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return genDiag.getContentPanel();
+ }
+
+
+ /**
+ * 校验数据
+ *
+ * @return 检测文本框架是否有目录。
+ */
+ @Nullable
+ @Override
+ protected ValidationInfo doValidate() {
+ return genDiag.validationInfo();
+ }
+
+ /**
+ * ok/cancel按钮
+ *
+ * @return Action[] buttos list
+ */
+ @NotNull
+ @Override
+ protected Action[] createActions() {
+ DialogWrapperExitAction exitAction = new DialogWrapperExitAction("Cancel", CANCEL_EXIT_CODE);
+ CustomOKAction okAction = new CustomOKAction();
+
+ // 设置默认的焦点按钮
+ okAction.putValue(DialogWrapper.DEFAULT_ACTION, true);
+ return new Action[]{exitAction, okAction};
+ }
+
+ @NotNull
+ @Override
+ protected Action[] createLeftSideActions() {
+ CustomHelpAction helpAction = new CustomHelpAction();
+ return new Action[]{helpAction};
+ }
+
+ /**
+ * 自定义 ok Action
+ */
+ protected class CustomOKAction extends DialogWrapperAction {
+
+ protected CustomOKAction() {
+ super("OK");
+ }
+
+ @Override
+ protected void doAction(ActionEvent actionEvent) {
+ ValidationInfo validationInfo = doValidate();
+ if (validationInfo != null) {
+ LOG.info(validationInfo.message);
+ } else {
+ if (genDiag.runFun()) {
+ close(CANCEL_EXIT_CODE);
+ }
+ }
+ }
+ }
+
+ /**
+ * 自定义 help Action
+ */
+ protected class CustomHelpAction extends DialogWrapperAction {
+
+ protected CustomHelpAction() {
+ super("Help");
+ }
+
+ @Override
+ protected void doAction(ActionEvent actionEvent) {
+ try {
+ Desktop.getDesktop().browse(new URI(URL));
+ } catch (URISyntaxException | IOException e) {
+ LOG.error("Open help error:" + e);
+ }
+ }
+ }
+}
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialogPane.form b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialogPane.form
new file mode 100644
index 0000000000000000000000000000000000000000..f71f210b759ef77562eea2772196f58d1f2362b1
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialogPane.form
@@ -0,0 +1,127 @@
+
+
+
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialogPane.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialogPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ff7261dd6d3522810ac35182457a23b941b7563
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ApiScanDialogPane.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.dialog;
+
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ValidationInfo;
+import com.kh.scan.action.ScanDirAction;
+import com.kh.scan.action.ScanResultDirAction;
+import com.kh.scan.utils.FileUtil;
+import com.kh.scan.utils.GenNotification;
+import org.apache.http.util.TextUtils;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * GenerateDialogPane生成工具主界面
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: select generate dialog
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class ApiScanDialogPane extends JDialog {
+ private static final Logger LOG = Logger.getInstance(ApiScanDialogPane.class);
+
+ private JPanel contentPane;
+ private JTextField scanDirPathTextField;
+ private JTextField outScanResultPathTextField;
+ private JButton selectScanPath;
+ private JButton outSelectPath;
+ private boolean generateSuccess = true;
+ private String sErrorMessage = "";
+ private String scanDir;
+ private String scanResultDir;
+ private final Project project;
+
+
+ /**
+ * 构造函数
+ *
+ * @param project projectId
+ */
+ public ApiScanDialogPane(Project project) {
+ this.project = project;
+ contentPane.registerKeyboardAction(actionEvent -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+ JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+ selectScanPath.addActionListener(new ScanDirAction(selectScanPath, scanDirPathTextField));
+ outSelectPath.addActionListener(new ScanResultDirAction(outSelectPath, outScanResultPathTextField));
+ }
+
+ @Override
+ public synchronized void addWindowListener(WindowListener windowListener) {
+ super.addWindowListener(windowListener);
+ new WindowAdapter() {
+ /**
+ * close dialog
+ *
+ * @param windowEvent WindowEvent
+ */
+ @Override
+ public void windowClosing(WindowEvent windowEvent) {
+ onCancel();
+ }
+ };
+ }
+
+ /**
+ * 验证文本选择框是否空。是否替换已存在的内容
+ *
+ * @return ValidationInfo 返回不符要求的信息。
+ */
+ @Nullable
+ public ValidationInfo validationInfo() {
+ String scanResultDirPath = outScanResultPathTextField.getText();
+ String scanDirPath = scanDirPathTextField.getText();
+ boolean isEmptyFile = TextUtils.isEmpty(scanDirPath) || TextUtils.isEmpty(scanResultDirPath);
+
+ ValidationInfo validationInfo = null;
+ if (isEmptyFile) {
+ String warnMsg = "扫描项目路径、结果输出路径不能为空";
+ warningMessage(warnMsg);
+ validationInfo = new ValidationInfo(warnMsg);
+ return validationInfo;
+ }
+
+ File file = new File(scanResultDirPath + "/result.xlsx");
+ if (file.exists()) {
+ ConfirmDialog confirmDialog = new ConfirmDialog("是否替换已存在的扫描结果?");
+ if (!confirmDialog.showAndGet()) {
+ validationInfo = new ValidationInfo(String.format("不替换现有扫描结果文件:%s", file));
+ return validationInfo;
+ }
+ }
+ return validationInfo;
+ }
+
+ private void onCancel() {
+ dispose();
+ }
+
+ private void warningMessage(String title) {
+ String notiContent = "请选择扫描项目路径、结果输出路径";
+ GenNotification.notifyMessage(this.project, notiContent, title, NotificationType.WARNING);
+ }
+
+ /**
+ * 执行主程序入口
+ *
+ * @return 执行状态
+ */
+ public boolean runFun() {
+ GenNotification.notifyMessage(this.project, "", "正在生成", NotificationType.INFORMATION);
+ scanDir = scanDirPathTextField.getText();
+ scanResultDir = outScanResultPathTextField.getText();
+ copyFileToTmpPath();
+ String command;
+ command = genCommand();
+ try {
+ if (!TextUtils.isEmpty(command) && callExtProcess(command)) {
+ GenNotification.notifyMessage(project, scanDirPathTextField.getText(), "提示",
+ NotificationType.INFORMATION, true);
+ return true;
+ }
+ } catch (IOException | InterruptedException ex) {
+ GenNotification.notifyMessage(project, scanDirPathTextField.getText(), "Command exec error",
+ NotificationType.ERROR);
+ LOG.error(ex);
+ }
+ return false;
+ }
+
+ /**
+ * 生成命令行指令
+ *
+ * @return 返回命令行执行内容
+ */
+ private String genCommand() {
+ String sysName = System.getProperties().getProperty("os.name").toUpperCase();
+ String tmpDirFile = System.getProperty("java.io.tmpdir");
+ String execFn;
+ execFn = "cmds/scan.py";
+ tmpDirFile += "scan.py";
+ File file = new File(tmpDirFile);
+ try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(execFn)) {
+ if (inputStream == null) {
+ throw new IOException("exec File InputStream is Null");
+ }
+ byte[] bs = inputStream.readAllBytes();
+ writeTmpFile(tmpDirFile, bs);
+ if (sysName.contains("LINUX") || sysName.contains("MAC OS")) {
+ executable(tmpDirFile);
+ }
+ } catch (IOException | InterruptedException e) {
+ GenNotification.notifyMessage(this.project, e.getMessage(), "Can not Find File:" + execFn,
+ NotificationType.ERROR);
+ LOG.error(e);
+
+ return "";
+ }
+ String command = file.toString();
+ command = "python " + command + " " + scanDir;
+ return command;
+ }
+
+ private void copyFileToTmpPath() {
+ String sysName = System.getProperties().getProperty("os.name").toUpperCase();
+ String tmpDirFile = System.getProperty("java.io.tmpdir");
+ String execFn = "cmds/scan_api.xlsx";
+ tmpDirFile += "scan_api.xlsx";
+ try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(execFn)) {
+ if (inputStream == null) {
+ throw new IOException("exec File InputStream is Null");
+ }
+ byte[] bs = inputStream.readAllBytes();
+ writeTmpFile(tmpDirFile, bs);
+ if (sysName.contains("LINUX") || sysName.contains("MAC OS")) {
+ executable(tmpDirFile);
+ }
+ } catch (IOException | InterruptedException e) {
+ GenNotification.notifyMessage(this.project, e.getMessage(), "Can not Find File:" + execFn,
+ NotificationType.ERROR);
+ LOG.error(e);
+ }
+ }
+
+ private boolean callExtProcess(String command) throws IOException, InterruptedException {
+ if (TextUtils.isEmpty(command)) {
+ GenNotification.notifyMessage(this.project, "执行命令文件为空", "空命令行提示", NotificationType.ERROR);
+ return false;
+ }
+ // 安装openpyxl依赖
+ Runtime.getRuntime().exec("pip install openpyxl");
+ String tmpDirFile = System.getProperty("java.io.tmpdir");
+ Process process = Runtime.getRuntime().exec(command, null, new File(tmpDirFile));
+ genResultLog(process);
+ StreamConsumer errConsumer = new StreamConsumer(process.getErrorStream());
+ StreamConsumer outputConsumer = new StreamConsumer(process.getInputStream());
+ errConsumer.start();
+ outputConsumer.start();
+ if (!generateSuccess) {
+ GenNotification.notifyMessage(project, sErrorMessage, "提示", NotificationType.ERROR);
+ return false;
+ }
+ errConsumer.join();
+ outputConsumer.join();
+ return true;
+ }
+
+ /**
+ * 赋值可执行文件权限。
+ *
+ * @param execFn 可执行命令
+ * @throws IOException 打开文件异常
+ * @throws InterruptedException 中断异常
+ */
+ private void executable(String execFn) throws IOException, InterruptedException {
+ callExtProcess("chmod a+x " + execFn);
+ }
+
+ /**
+ * 拷贝可执行文件到临时文件夹
+ *
+ * @param path 目标文件路径
+ * @param bs 字节内容
+ * @throws IOException exception
+ */
+ private void writeTmpFile(String path, byte[] bs) throws IOException {
+ File file = new File(path);
+ if (!file.exists()) {
+ boolean isNewFile = file.createNewFile();
+ if (!isNewFile) {
+ LOG.info("writeTmpFile createNewFile error");
+ }
+ }
+ FileOutputStream fw = new FileOutputStream(file);
+ fw.write(bs, 0, bs.length);
+ fw.close();
+ }
+
+ /**
+ * 获取生成成功结果文件。
+ *
+ * @param process 进程ID
+ */
+ private void genResultLog(Process process) {
+ BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+ String sErr;
+ String sOut;
+ sErr = getErrorResult(stdError);
+ if (TextUtils.isEmpty(sErr)) {
+ sOut = genInputLog(stdInput);
+ if (!generateIsSuccess(sOut)) {
+ sErrorMessage = sOut;
+ }
+ return;
+ }
+ generateSuccess = false;
+ sErrorMessage = sErr;
+ }
+
+ /**
+ * 获取生成失败结果文件。
+ *
+ * @param stdError error buff
+ * @return ErrorResult
+ */
+ private String getErrorResult(BufferedReader stdError) {
+ StringBuilder sErr = new StringBuilder();
+ while (true) {
+ String sTmp;
+ try {
+ if ((sTmp = stdError.readLine()) == null) {
+ break;
+ }
+ sErr.append(sTmp).append(FileUtil.getNewline());
+ } catch (IOException ioException) {
+ LOG.error(" genResultLog stdInput error" + ioException);
+ }
+ }
+ return sErr.toString();
+ }
+
+ private boolean generateIsSuccess(String sOut) {
+ generateSuccess = sOut.contains("success") || TextUtils.isEmpty(sOut);
+ return generateSuccess;
+ }
+
+ /**
+ * 获取生成文本内容。
+ *
+ * @param stdInput input buff
+ * @return 返回当前输入框内容
+ */
+ private String genInputLog(BufferedReader stdInput) {
+ StringBuilder sOut = new StringBuilder();
+ while (true) {
+ String sTmp;
+ try {
+ if ((sTmp = stdInput.readLine()) == null) {
+ break;
+ }
+ sOut.append(sTmp).append(FileUtil.getNewline());
+ } catch (IOException ioException) {
+ LOG.error(" genResultLog stdInput error" + ioException);
+ }
+ }
+ return sOut.toString();
+ }
+
+ static class StreamConsumer extends Thread {
+ InputStream is;
+
+ StreamConsumer(InputStream is) {
+ super.setName("StreamConsumer");
+ this.is = is;
+ }
+
+ @Override
+ public void run() {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+ while ((line = br.readLine()) != null) {
+ LOG.error("StreamConsumer" + line);
+ }
+ } catch (IOException ioException) {
+ LOG.error("StreamConsumer io error" + ioException);
+ }
+ }
+ }
+
+ JPanel getContentPanel() {
+ return contentPane;
+ }
+}
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDiagPane.form b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDiagPane.form
new file mode 100644
index 0000000000000000000000000000000000000000..5f38c1c861433d37e59b9eb8ac5ce02d539d762d
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDiagPane.form
@@ -0,0 +1,75 @@
+
+
+
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDiagPane.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDiagPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..013c69f8f5de7009eda9f36a32263ac27dc4eedc
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDiagPane.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.dialog;
+
+import javax.swing.JPanel;
+import javax.swing.JLabel;
+import javax.swing.JDialog;
+import javax.swing.ImageIcon;
+
+/**
+ * ConfirmDiagPane自定义确认对话框
+ * 解决ShowConfirmDiag 在Deveco里面会出现界面错位问题。
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: generator error dialog
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class ConfirmDiagPane extends JDialog {
+ private JPanel contentPane;
+ private JLabel msgLabel;
+ private JLabel iconLabel;
+
+ /**
+ * 构造函数
+ *
+ * @param sErrorMessage 错误信息
+ */
+ public ConfirmDiagPane(String sErrorMessage) {
+ msgLabel.setText(sErrorMessage);
+ iconLabel.setIcon(new ImageIcon(""));
+ }
+
+
+ JPanel getContentPanel() {
+ return contentPane;
+ }
+}
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDialog.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fb5abd1e8726c5c06387c2e0714466cffad7237
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/dialog/ConfirmDialog.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022 Guangzhou Digitalchina Information Technology Co., Ltd.
+ * All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.dialog;
+
+import com.intellij.openapi.ui.DialogWrapper;
+import org.jetbrains.annotations.Nullable;
+import javax.swing.JComponent;
+
+/**
+ * 自定义确认对话框Wrapper
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: tool conversion plug-in
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class ConfirmDialog extends DialogWrapper {
+ private final ConfirmDiagPane confirmDiagPane;
+
+ /**
+ * 构造函数
+ * @param message 弹出框信息内容
+ */
+ public ConfirmDialog(String message) {
+ super(true);
+ confirmDiagPane = new ConfirmDiagPane(message);
+ setOKButtonText("Yes");
+ setCancelButtonText("No");
+ setUndecorated(true);
+ setResizable(false);
+ init();
+ }
+
+ @Override
+ @Nullable
+ protected JComponent createCenterPanel() {
+ return confirmDiagPane.getContentPanel();
+ }
+}
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/ng/ApiScanMenu.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/ng/ApiScanMenu.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f52434e4be2fbb2d57b81169c93df832a7bf616
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/ng/ApiScanMenu.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022 Guangzhou Digitalchina Information Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.ng;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.project.Project;
+import com.kh.scan.dialog.ApiScanDialog;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 工具菜单入口
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: tool conversion plug-in
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class ApiScanMenu extends AnAction {
+
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
+ Project project = anActionEvent.getProject();
+
+ if (project == null) {
+ return;
+ }
+ ApiScanDialog wrapper = new ApiScanDialog(project);
+ wrapper.showAndGet();
+ }
+}
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/utils/FileUtil.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/utils/FileUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f077beb4bd5153f8634e21df5ab891420a049a9
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/utils/FileUtil.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.utils;
+
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import org.apache.http.util.TextUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * 文本文件工具
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: file utils
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class FileUtil {
+ private static final Logger LOG = Logger.getInstance(FileUtil.class);
+
+ private static final int COMPILE_SDK_VERSION = 5;
+
+ /**
+ * 获取换行符
+ *
+ * @return 换行符
+ */
+ public static String getNewline() {
+ return System.getProperty("line.separator");
+ }
+
+ /**
+ * check project SDK
+ *
+ * @param project projectid
+ * @param baseFile project root file
+ * @return boolean
+ */
+ public static boolean checkProjectSDK(Project project, String baseFile) {
+
+ String gradlePath = "";
+ File baseDir = new File(baseFile);
+ if (baseDir.isDirectory()) {
+ File[] childFile = baseDir.listFiles();
+ assert childFile != null;
+ for (File file : childFile) {
+ if (file.getName().equals("build.gradle") || file.getName().equals("build-profile.json5")) {
+ gradlePath = file.getPath();
+ }
+ }
+ }
+
+ Properties properties = new Properties();
+ if (TextUtils.isBlank(gradlePath)) {
+ GenNotification.notifyMessage(project, "项目结构中没有grandle配置文件。", "当前项目结构不支持",
+ NotificationType.WARNING);
+ return true;
+ }
+ try {
+ properties.load(new FileInputStream(gradlePath));
+ } catch (IOException e) {
+ GenNotification.notifyMessage(project, e.getMessage(), "提示", NotificationType.ERROR);
+ LOG.error(String.format("Can not load file :%s . %s", gradlePath, e));
+ return true;
+ }
+ String ohosSDK = properties.getProperty("compileSdkVersion");
+
+ if (ohosSDK != null && Integer.parseInt(ohosSDK) < COMPILE_SDK_VERSION) {
+ GenNotification.notifyMessage(project, "SKD版本过低,NAPI仅支持5.0及以上版本", "提示",
+ NotificationType.WARNING);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/utils/GenNotification.java b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/utils/GenNotification.java
new file mode 100644
index 0000000000000000000000000000000000000000..4239af43e630f27d36d41db67d2bc1424d853a07
--- /dev/null
+++ b/hdc/api_scan_IntelliJ_plugin/src/com/kh/scan/utils/GenNotification.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2022 Guangzhou Digitalchina Information Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.kh.scan.utils;
+
+import com.intellij.ide.actions.OpenFileAction;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationAction;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+/**
+ * 通知框
+ *
+ * @author: zhaoxudong@kaihong.com
+ * @see: tool conversion plug-in
+ * @version: v1.0.0
+ * @since 2022-10-14
+ */
+public class GenNotification {
+
+ private static final Logger LOG = Logger.getInstance(FileUtil.class);
+
+ private GenNotification() {
+ }
+
+ /**
+ * 无action 通知
+ *
+ * @param project projectId
+ * @param content 提示内容
+ * @param title 提示栏内容
+ * @param type 提示类型 Error,Waring,info
+ */
+ public static void notifyMessage(@javax.annotation.Nullable Project project, String content, String title,
+ NotificationType type) {
+ notifyMessage(project, content, title, type, false);
+ }
+
+ /**
+ * 消息通知
+ *
+ * @param project projectId
+ * @param content 提示内容
+ * @param title 提示栏内容
+ * @param type 提示类型 Error,Waring,info
+ * @param addAct 是否添加action
+ */
+ public static void notifyMessage(@javax.annotation.Nullable Project project, String content, String title,
+ NotificationType type, boolean addAct) {
+ Notification notification = new Notification("Generate.Result.Group", "Notes Message", content, type);
+ notification.setTitle(title);
+ notification.setContent(content);
+
+ if (NotificationType.ERROR.equals(type)) {
+ LOG.error(content);
+ } else if (NotificationType.WARNING.equals(type)) {
+ LOG.warn(content);
+ } else {
+ LOG.info(content);
+ }
+
+ if (addAct) {
+ notification.setContent(null);
+ addAction(project, content, notification);
+ }
+ Notifications.Bus.notify(notification, project);
+
+ }
+
+ private static void addAction(Project project, String dirPath, Notification notification) {
+ File genResultPath = new File(dirPath);
+ if (!genResultPath.exists()) {
+ LOG.info(String.format("%s not exist", genResultPath.getPath()));
+ }
+ LOG.info("generated file list log:");
+
+ File[] fa = genResultPath.listFiles();
+ for (int i = 0; i < fa.length; i++) {
+ File fs = fa[i];
+ String fileName = fs.getName();
+ boolean dissFile = !fileName.endsWith(".log") || !fileName.endsWith(".txt") || !fileName.endsWith(".ts");
+ if (!fs.isDirectory() && dissFile) {
+ String filePath = fs.getPath();
+ NotificationAction action = new NotificationAction(filePath) {
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent anActionEvent,
+ @NotNull Notification notification) {
+ OpenFileAction.openFile(filePath, project);
+ }
+ };
+ notification.addAction(action);
+ } else {
+ LOG.info(String.format("%s is Directory", fs.getPath()));
+ }
+ }
+ }
+}