• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const path = require('path');
17const fs = require('fs');
18const request = require('sync-request');
19const { checkSpelling } = require('./check_spelling');
20const { checkAPIDecorators } = require('./check_decorator');
21const { checkPermission } = require('./check_permission');
22const { checkSyscap } = require('./check_syscap');
23const { checkDeprecated } = require('./check_deprecated');
24const { checkAPINameOfHump, checkAPIFileName } = require('./check_hump');
25const { checkJSDoc } = require('./check_legality');
26const { checkNaming } = require('./check_naming');
27const { checkEventSubscription } = require('./check_event_subscription');
28const { checkAnyInAPI } = require('./check_any');
29const { hasAPINote, ApiCheckResult, requireTypescriptModule, commentNodeWhiteList, splitPath,
30  isWhiteListFile } = require('./utils');
31const ts = requireTypescriptModule();
32const result = require('../check_result.json');
33const rules = require('../code_style_rule.json');
34const { checkApiChanges } = require('./check_diff_changes');
35const whiteLists = require('../config/jsdocCheckWhiteList.json');
36
37function checkAPICodeStyle(url, isTestCase) {
38  if (fs.existsSync(url)) {
39    const mdApiFiles = getMdFiles(url, isTestCase);
40    tsTransform(mdApiFiles, checkAPICodeStyleCallback);
41  }
42}
43
44function getMdFiles(url, isTestCase) {
45  const mdFiles = [];
46  const content = fs.readFileSync(url, 'utf-8');
47  const filePathArr = content.split(/[(\r\n)\r\n]+/);
48  filePathArr.forEach(filePath => {
49    const pathElements = new Set();
50    splitPath(filePath, pathElements);
51    if (!pathElements.has('build-tools') || isTestCase) {
52      mdFiles.push(filePath);
53    }
54  })
55  return mdFiles;
56}
57
58function tsTransform(uFiles, callback) {
59  uFiles.forEach((filePath, index) => {
60    console.log(`scaning file in no ${++index}!`);
61    if (/\.d\.ts/.test(filePath) && fs.existsSync(filePath)) {
62      const content = fs.readFileSync(filePath, 'utf-8');
63      const fileName = path.basename(filePath).replace(/.d.ts/g, '.ts');
64      ts.transpileModule(content, {
65        compilerOptions: {
66          target: ts.ScriptTarget.ES2017,
67        },
68        fileName: fileName,
69        transformers: { before: [callback(filePath)] },
70      });
71    }
72  });
73}
74
75function checkAPICodeStyleCallback(fileName) {
76  return (context) => {
77    return (node) => {
78      checkAPIFileName(node, fileName);
79      checkAllNode(node, node, fileName);
80      return node;
81    };
82  };
83}
84
85function checkAllNode(node, sourcefile, fileName) {
86  if (!ts.isImportDeclaration(node) && !ts.isSourceFile(node)) {
87    // check hump naming
88    checkAPINameOfHump(node, sourcefile, fileName);
89  }
90  if (hasAPINote(node)) {
91    // check decorator
92    checkAPIDecorators(node, sourcefile, fileName);
93    // check apiNote spelling
94    checkSpelling(node, sourcefile, fileName);
95    // check syscap
96    checkSyscap(node, sourcefile, fileName);
97    // check deprecated
98    checkDeprecated(node, sourcefile, fileName);
99    // check permission
100    checkPermission(node, sourcefile, fileName);
101    // check event subscription
102    checkEventSubscription(node, sourcefile, fileName);
103
104    const uesWhiteList = !isWhiteListFile(fileName, whiteLists.JSDocCheck);
105    if (commentNodeWhiteList.includes(node.kind) && uesWhiteList) {
106      checkJSDoc(node, sourcefile, fileName, true);
107    }
108  }
109  checkAnyInAPI(node, sourcefile, fileName);
110  if (ts.isIdentifier(node)) {
111    // check variable spelling
112    checkSpelling(node, sourcefile, fileName);
113    // check naming
114    if (node.parent.parent.kind !== ts.SyntaxKind.JSDoc) {
115      checkNaming(node, sourcefile, fileName);
116    }
117  }
118  node.getChildren().forEach((item) => checkAllNode(item, sourcefile, fileName));
119}
120
121function scanEntry(url, prId, isTestCase) {
122  if (prId && prId !== 'NA') {
123    checkApiChanges(prId);
124    // scan entry
125    checkAPICodeStyle(url, isTestCase);
126  }
127  result.scanResult.push(`api_check: ${ApiCheckResult.formatCheckResult}`);
128  return result.scanResult;
129}
130exports.scanEntry = scanEntry;
131
132function reqGitApi(scanResult, prId) {
133  const administrators = new Set();
134  const SUCCESS_CODE = 200;
135  rules.administrators.forEach((administrator) => {
136    administrators.add(administrator.user);
137  });
138  if (ApiCheckResult.formatCheckResult || !prId || prId === 'NA') {
139    return scanResult;
140  }
141  const commentRequestPath = `https://gitee.com/api/v5/repos/openharmony/interface_sdk-js/pulls/${prId}/comments?page=1&per_page=100&direction=desc`;
142  const res = request('GET', commentRequestPath, {
143    headers: {
144      'Content-Type': 'application/json;charset=UFT-8',
145    },
146  });
147  if (res.statusCode !== SUCCESS_CODE) {
148    throw `The giteeAPI access failed, StatusCode:${res.statusCode}`;
149  }
150  const resBody = new TextDecoder('utf-8').decode(res.body);
151  const comments = JSON.parse(`{"resultBody": ${resBody}}`);
152  const resultBody = comments.resultBody;
153  if (!resultBody || resultBody.length === 0 || !(resultBody instanceof Array)) {
154    throw 'The format of data returned by giteeAPI is incorrect';
155  }
156  for (let i = 0; i < resultBody.length; i++) {
157    const comment = resultBody[i];
158    if (!(comment && comment.user && comment.user.id && comment.body)) {
159      continue;
160    }
161    const userId = String(comment.user.id);
162    if (userId === rules.ciId && /^代码有更新,重置PR验证状态$/.test(comment.body)) {
163      break;
164    }
165    if (administrators.has(userId) && /^approve api check$/.test(comment.body)) {
166      ApiCheckResult.formatCheckResult = true;
167      scanResult = ['api_check: true'];
168      break;
169    }
170  }
171  return scanResult;
172}
173exports.reqGitApi = reqGitApi;
174