* Copyright (c) 2021-2022 Huawei Device 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.
*/
const path = require('path');
const fs = require('fs');
const request = require('sync-request');
const { checkSpelling } = require('./check_spelling');
const { checkAPIDecorators } = require('./check_decorator');
const { checkPermission } = require('./check_permission');
const { checkSyscap } = require('./check_syscap');
const { checkDeprecated } = require('./check_deprecated');
const { checkAPINameOfHump, checkAPIFileName } = require('./check_hump');
const { checkJSDoc } = require('./check_legality');
const { checkNaming } = require('./check_naming');
const { checkEventSubscription } = require('./check_event_subscription');
const { checkAnyInAPI } = require('./check_any');
const { checkFileTagOrder } = require('./check_file_tag_order');
const { hasAPINote, ApiCheckResult, requireTypescriptModule, commentNodeWhiteList, splitPath,
isWhiteListFile } = require('./utils');
const ts = requireTypescriptModule();
const result = require('../check_result.json');
const rules = require('../code_style_rule.json');
const { checkApiChanges } = require('./check_diff_changes');
const whiteLists = require('../config/jsdocCheckWhiteList.json');
function checkAPICodeStyle(url, isTestCase) {
if (fs.existsSync(url)) {
const mdApiFiles = getMdFiles(url, isTestCase);
tsTransform(mdApiFiles, checkAPICodeStyleCallback);
}
}
function getMdFiles(url, isTestCase) {
const mdFiles = [];
const content = fs.readFileSync(url, 'utf-8');
const filePathArr = content.split(/[(\r\n)\r\n]+/);
filePathArr.forEach(filePath => {
const pathElements = new Set();
splitPath(filePath, pathElements);
if (!pathElements.has('build-tools') || isTestCase) {
mdFiles.push(filePath);
}
});
return mdFiles;
}
exports.getMdFiles = getMdFiles;
function tsTransform(uFiles, callback) {
uFiles.forEach((filePath, index) => {
console.log(`scaning file in no ${++index}!`);
if (/\.d\.ts/.test(filePath) && fs.existsSync(filePath)) {
const content = fs.readFileSync(filePath, 'utf-8');
const fileName = path.basename(filePath).replace(/.d.ts/g, '.ts');
ts.transpileModule(content, {
compilerOptions: {
target: ts.ScriptTarget.ES2017,
},
fileName: fileName,
transformers: { before: [callback(filePath)] },
});
}
});
}
function checkAPICodeStyleCallback(fileName) {
return (context) => {
return (node) => {
checkAPIFileName(node, fileName);
checkAllNode(node, node, fileName);
return node;
};
};
}
function checkAllNode(node, sourcefile, fileName) {
if (!ts.isImportDeclaration(node) && !ts.isSourceFile(node)) {
checkAPINameOfHump(node, sourcefile, fileName);
}
if (hasAPINote(node)) {
checkAPIDecorators(node, sourcefile, fileName);
checkSpelling(node, sourcefile, fileName);
checkSyscap(node, sourcefile, fileName);
checkDeprecated(node, sourcefile, fileName);
checkPermission(node, sourcefile, fileName);
checkEventSubscription(node, sourcefile, fileName);
if (ts.isSourceFile(node)) {
checkFileTagOrder(node, sourcefile, fileName);
}
const uesWhiteList = !isWhiteListFile(fileName, whiteLists.JSDocCheck);
if (commentNodeWhiteList.includes(node.kind) && uesWhiteList) {
checkJSDoc(node, sourcefile, fileName, true);
}
}
checkAnyInAPI(node, sourcefile, fileName);
if (ts.isIdentifier(node)) {
checkSpelling(node, sourcefile, fileName);
if (node.parent.parent.kind !== ts.SyntaxKind.JSDoc) {
checkNaming(node, sourcefile, fileName);
}
}
node.getChildren().forEach((item) => checkAllNode(item, sourcefile, fileName));
}
function scanEntry(url, prId, isTestCase) {
if (prId && prId !== 'NA') {
checkApiChanges(prId);
checkAPICodeStyle(url, isTestCase);
}
result.scanResult.push(`api_check: ${ApiCheckResult.formatCheckResult}`);
return result.scanResult;
}
exports.scanEntry = scanEntry;
function reqGitApi(scanResult, prId, ApiCheckResult) {
const administrators = new Set();
const SUCCESS_CODE = 200;
rules.administrators.forEach((administrator) => {
administrators.add(administrator.user);
});
if (ApiCheckResult || !prId || prId === 'NA') {
return scanResult;
}
const commentRequestPath = `https://gitee.com/api/v5/repos/openharmony/interface_sdk-js/pulls/${prId}/comments?page=1&per_page=100&direction=desc`;
const res = request('GET', commentRequestPath, {
headers: {
'Content-Type': 'application/json;charset=UFT-8',
},
});
if (res.statusCode !== SUCCESS_CODE) {
throw `The giteeAPI access failed, StatusCode:${res.statusCode}`;
}
const resBody = new TextDecoder('utf-8').decode(res.body);
const comments = JSON.parse(`{"resultBody": ${resBody}}`);
const resultBody = comments.resultBody;
if (!resultBody || resultBody.length === 0 || !(resultBody instanceof Array)) {
throw 'The format of data returned by giteeAPI is incorrect';
}
for (let i = 0; i < resultBody.length; i++) {
const comment = resultBody[i];
if (!(comment && comment.user && comment.user.id && comment.body)) {
continue;
}
const userId = String(comment.user.id);
if (userId === rules.ciId && /^代码有更新,重置PR验证状态$/.test(comment.body)) {
break;
}
if (administrators.has(userId) && /^approve api check$/.test(comment.body)) {
ApiCheckResult.formatCheckResult = true;
scanResult = ['api_check: true'];
break;
}
}
return scanResult;
}
exports.reqGitApi = reqGitApi;