* 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 fs = require('fs');
const path = require('path');
const ExcelJS = require('exceljs');
const cm = require('comment-parser');
function requireTypescriptModule() {
const buildOption = require('./build.json');
if (buildOption.isBundle) {
return require('typescript');
}
const tsPathArray = [
path.resolve(__dirname, '../node_modules/typescript'),
path.resolve(__dirname, '../../node_modules/typescript')
];
if (fs.existsSync(tsPathArray[0])) {
return require(tsPathArray[0]);
} else if (fs.existsSync(tsPathArray[1])) {
return require(tsPathArray[1]);
}
return null;
}
exports.requireTypescriptModule = requireTypescriptModule;
const ts = requireTypescriptModule();
const commentNodeWhiteList = [
ts.SyntaxKind.PropertySignature, ts.SyntaxKind.CallSignature, ts.SyntaxKind.MethodSignature,
ts.SyntaxKind.MethodDeclaration, ts.SyntaxKind.EnumMember, ts.SyntaxKind.VariableStatement,
ts.SyntaxKind.PropertyDeclaration, ts.SyntaxKind.Constructor, ts.SyntaxKind.ModuleDeclaration,
ts.SyntaxKind.NamespaceExportDeclaration, ts.SyntaxKind.ClassDeclaration, ts.SyntaxKind.InterfaceDeclaration,
ts.SyntaxKind.EnumDeclaration, ts.SyntaxKind.Parameter, ts.SyntaxKind.TypeLiteral, ts.SyntaxKind.FunctionDeclaration,
ts.SyntaxKind.LabeledStatement, ts.SyntaxKind.TypeAliasDeclaration
];
exports.commentNodeWhiteList = commentNodeWhiteList;
const tagsArrayOfOrder = [
'namespace', 'struct', 'extends', 'implements', 'typedef', 'interface', 'permission', 'enum', 'constant', 'type',
'param', 'default', 'returns', 'readonly', 'throws', 'static', 'fires', 'syscap', 'systemapi', 'famodelonly',
'FAModelOnly', 'stagemodelonly', 'StageModelOnly', 'crossplatform', 'form', 'atomicservice', 'since', 'deprecated',
'useinstead', 'test', 'form', 'example'
];
exports.tagsArrayOfOrder = tagsArrayOfOrder;
const fileTagOrder = ['file', 'kit'];
exports.fileTagOrder = fileTagOrder;
function getAPINote(node) {
const apiLength = node.getText().length;
const apiFullLength = node.getFullText().length;
return node.getFullText().substring(0, apiFullLength - apiLength);
}
exports.getAPINote = getAPINote;
function hasAPINote(node) {
if (!node) {
return false;
}
const apiNote = getAPINote(node).replace(/[\s]/g, '');
if (apiNote && apiNote.length !== 0) {
return true;
}
return false;
}
exports.hasAPINote = hasAPINote;
function removeDir(url) {
const statObj = fs.statSync(url);
if (statObj.isDirectory()) {
let dirs = fs.readdirSync(url);
dirs = dirs.map(dir => path.join(url, dir));
for (let i = 0; i < dirs.length; i++) {
removeDir(dirs[i]);
}
fs.rmdirSync(url);
} else {
fs.unlinkSync(url);
}
}
exports.removeDir = removeDir;
function writeResultFile(resultData, outputPath, option) {
const STANDARD_INDENT = 2;
fs.writeFile(path.resolve(__dirname, outputPath), JSON.stringify(resultData, null, STANDARD_INDENT), option, err => {
if (err) {
console.error(`ERROR FOR CREATE FILE:${err}`);
} else {
console.log('API CHECK FINISH!');
}
});
}
exports.writeResultFile = writeResultFile;
function overwriteIndexOf(item, array) {
const indexArr = [];
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
indexArr.push(i);
}
}
return indexArr;
}
exports.overwriteIndexOf = overwriteIndexOf;
const ErrorType = {
UNKNOW_DECORATOR: {
id: 0,
description: 'unknow decorator',
},
MISSPELL_WORDS: {
id: 1,
description: 'misspell words',
},
NAMING_ERRORS: {
id: 2,
description: 'naming errors',
},
UNKNOW_PERMISSION: {
id: 3,
description: 'unknow permission',
},
UNKNOW_SYSCAP: {
id: 4,
description: 'unknow syscap',
},
UNKNOW_DEPRECATED: {
id: 5,
description: 'unknow deprecated',
},
WRONG_ORDER: {
id: 6,
description: 'wrong order',
},
WRONG_VALUE: {
id: 7,
description: 'wrong value',
},
WRONG_SCENE: {
id: 8,
description: 'wrong scene',
},
PARAMETER_ERRORS: {
id: 9,
description: 'wrong parameter',
},
API_PAIR_ERRORS: {
id: 10,
description: 'limited api pair errors',
},
ILLEGAL_ANY: {
id: 11,
description: 'illegal any',
},
API_CHANGE_ERRORS: {
id: 12,
description: 'api change errors',
},
};
exports.ErrorType = ErrorType;
const LogType = {
LOG_API: 'Api',
LOG_JSDOC: 'JsDoc',
LOG_FILE: 'File',
};
exports.LogType = LogType;
const ErrorLevel = {
HIGH: 3,
MIDDLE: 2,
LOW: 1,
};
exports.ErrorLevel = ErrorLevel;
const FileType = {
API: 'Api',
JSDOC: 'JsDoc',
};
exports.FileType = FileType;
const apiCheckArr = [];
exports.apiCheckArr = apiCheckArr;
const apiCheckInfoArr = [];
exports.apiCheckInfoArr = apiCheckInfoArr;
class ApiCheckResultClass {
formatCheckResult = true;
}
exports.ApiCheckResult = new ApiCheckResultClass();
async function excelApiCheckResult(apiCheckArr) {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet('Js Api', { views: [{ xSplit: 1 }] });
sheet.getRow(1).values = ['order', 'errorType', 'fileName', 'apiName', 'apiContent', 'type', 'errorInfo', 'version', 'model'];
for (let i = 1; i <= apiCheckArr.length; i++) {
const apiData = apiCheckArr[i - 1];
sheet.getRow(i + 1).values = [i, apiData.errorType, apiData.fileName, apiData.apiName, apiData.apiFullText,
apiData.type, apiData.errorInfo, apiData.version, apiData.basename];
}
const buffer = await workbook.xlsx.writeBuffer();
fs.writeFile('Js_Api.xlsx', buffer, function (err) {
if (err) {
console.error(err);
return;
}
});
return buffer;
}
exports.excelApiCheckResult = excelApiCheckResult;
function getApiInfo(node) {
const notesStr = getAPINote(node);
const apiInfo = {};
const versionArr = [];
if (notesStr !== '') {
if (/\@systemapi/g.test(notesStr)) {
apiInfo.isSystemApi = 'system api';
}
if (/\@constant/g.test(notesStr)) {
apiInfo.isConstant = true;
}
if (/\@since\s*(\d+)/g.test(notesStr)) {
notesStr.replace(/\@since\s*(\d+)/g, (versionInfo) => {
versionArr.push(versionInfo);
apiInfo.version = versionInfo.replace(/\@since/g, '').trim();
});
apiInfo.humpVersion = versionArr[0].replace(/\@since/g, '').trim();
}
if (/\@deprecated.*since\s*(\d+)/g.test(notesStr)) {
notesStr.replace(/\@deprecated.*since\s*(\d+)/g,
versionInfo => {
apiInfo.deprecated = versionInfo.replace(
/\@deprecated.*since\s*/g, '').trim();
});
}
if (/\@famodelonly/g.test(notesStr)) {
notesStr.replace(/\@famodelonly/g, modelInfo => {
apiInfo.model = modelInfo;
});
} else if (/\@stagemodelonly/g.test(notesStr)) {
notesStr.replace(/\@stagemodelonly/g, modelInfo => {
apiInfo.model = modelInfo;
});
}
if (/\@syscap\s*((\w|\.|\/|\{|\@|\}|\s)+)/g.test(notesStr)) {
notesStr.replace(/\@syscap\s*((\w|\.|\/|\{|\@|\}|\s)+)/g, sysCapInfo => {
apiInfo.sysCap = sysCapInfo.replace(/\@syscap/g, '').trim();
});
}
if (/\@permission\s*((\w|\.|\/|\{|\@|\}|\s)+)/g.test(notesStr)) {
notesStr.replace(/\@permission\s*((\w|\.|\/|\{|\@|\}|\s)+)/g,
permissionInfo => {
apiInfo.permission =
permissionInfo.replace(/\@permission/g, '').trim();
});
}
}
return apiInfo;
}
exports.getApiInfo = getApiInfo;
function getApiVersion(node) {
if (getApiInfo(node).humpVersion) {
return getApiInfo(node).humpVersion;
} else if (node.parent && !ts.isSourceFile(node.parent)) {
return getApiVersion(node.parent);
} else {
return 'NA';
}
}
exports.getApiVersion = getApiVersion;
function parseJsDoc(node) {
if (!hasAPINote(node)) {
return [];
} else {
return cm.parse(getAPINote(node));
}
}
exports.parseJsDoc = parseJsDoc;
function getDeclareValue(declareValue) {
let apiDeclareValue = '';
if (!declareValue) {
return apiDeclareValue;
}
if (ts.isFunctionTypeNode(declareValue)) {
apiDeclareValue = 'Function';
} else if (ts.isTypeLiteralNode(declareValue)) {
apiDeclareValue = 'object';
} else {
apiDeclareValue = declareValue.getText().replace(/\n|\r|\s/g, '');
}
return apiDeclareValue;
}
exports.getDeclareValue = getDeclareValue;
const systemPermissionFile = path.resolve(__dirname, '../../../../../',
'base/global/system_resources/systemres/main/module.json');
exports.systemPermissionFile = systemPermissionFile;
exports.checkOption = {
permissionContent: undefined,
};
const inheritArr = ['test', 'famodelonly', 'FAModelOnly', 'stagemodelonly', 'StageModelOnly', 'deprecated',
'systemapi'];
exports.inheritArr = inheritArr;
const ErrorValueInfo = {
ERROR_INFO_VALUE_EXTENDS: 'the [extends] tag value is incorrect. Please check if the tag value matches the inherited class name.',
ERROR_INFO_VALUE_ENUM: 'the [enum] tag type is incorrect. Please check if the tag type is { string } or { number }',
ERROR_INFO_VALUE_SINCE: 'the [since] tag value is incorrect. Please check if the tag value is a numerical value',
ERROR_INFO_RETURNS: 'the [returns] tag was used incorrectly. The returns tag should not be used when the return type is void',
ERROR_INFO_VALUE_RETURNS: 'the [returns] tag type is incorrect. Please check if the tag type is consistent with the return type',
ERROR_INFO_VALUE_USEINSTEAD: 'the [useinstead] tag value is incorrect. Please check the usage method',
ERROR_INFO_VALUE_TYPE: 'the [type] tag type is incorrect. Please check if the type matches the attribute type',
ERROR_INFO_VALUE_DEFAULT: 'the [default] tag value is incorrect. Please supplement the default value',
ERROR_INFO_VALUE_PERMISSION: 'the [permission] tag value is incorrect. Please check if the permission field has been configured or update the configuration file',
ERROR_INFO_VALUE_DEPRECATED: 'the [deprecated] tag value is incorrect. Please check the usage method',
ERROR_INFO_VALUE_SYSCAP: 'the [syscap] tag value is incorrect. Please check if the syscap field is configured',
ERROR_INFO_VALUE_NAMESPACE: 'the [namespace] tag value is incorrect. Please check if it matches the namespace name',
ERROR_INFO_VALUE_INTERFACE: 'the [interface] label value is incorrect. Please check if it matches the interface name',
ERROR_INFO_VALUE_TYPEDEF: 'the [typedef] tag value is incorrect. Please check if it matches the interface name',
ERROR_INFO_TYPE_PARAM: 'the type of the [$$] [param] tag is incorrect. Please check if it matches the type of the [$$] parameter',
ERROR_INFO_VALUE_PARAM: 'the value of the [$$] [param] tag is incorrect. Please check if it matches the [$$] parameter name',
ERROR_INFO_VALUE1_THROWS: 'the type of the [$$] [throws] tag is incorrect. Please fill in [BusinessError]',
ERROR_INFO_VALUE2_THROWS: 'the type of the [$$] [throws] tag is incorrect. Please check if the tag value is a numerical value',
ERROR_INFO_INHERIT: 'it was detected that there is an inheritable label [$$] in the current file, but there are child nodes without this label',
ERROR_ORDER: 'JSDoc label order error, please make adjustments',
ERROR_LABELNAME: 'the [$$] tag does not exist. Please use a valid JSDoc tag',
ERROR_LOST_LABEL: 'JSDoc tag validity verification failed. Please confirm if the [$$] tag is missing',
ERROR_USE: 'JSDoc label validity verification failed. The [$$] label is not allowed. Please check the label usage method.',
ERROR_MORELABEL: 'JSDoc tag validity verification failed. The [$$] [$$] tag is redundant. Please check if the tag should be deleted.',
ERROR_REPEATLABEL: 'the validity verification of the JSDoc tag failed. The [$$] tag is not allowed to be reused, please delete the extra tags',
ERROR_USE_INTERFACE: 'the validity verification of the JSDoc tag failed. The [interface] tag and [typedef] tag are not allowed to be used simultaneously. Please confirm the interface class.',
ERROR_EVENT_NAME_STRING: 'The event name should be string.',
ERROR_EVENT_NAME_NULL: 'The event name cannot be Null value.',
ERROR_EVENT_NAME_SMALL_HUMP: 'The event name should be named by small hump. (Received [\'$$\'])',
ERROR_EVENT_CALLBACK_OPTIONAL: 'The callback parameter of off function should be optional.',
ERROR_EVENT_CALLBACK_MISSING: 'The off functions of one single event should have at least one callback parameter, and the callback parameter should be the last parameter.',
ERROR_EVENT_ON_AND_OFF_PAIR: 'The on and off event subscription methods do not appear in pair.',
ILLEGAL_USE_ANY: 'Illegal [any] keyword used in the API',
ERROR_CHANGES_VERSION: 'Please check if the changed API version number is $$.',
ERROR_CHANGES_API_HISTORY_PARAM_REQUIRED_CHANGE: 'Forbid changes: Optional parameters cannot be changed to required parameters.',
ERROR_CHANGES_API_HISTORY_PARAM_RANGE_CHANGE: 'Forbid changes: Parameters type range cannot be reduced.',
ERROR_CHANGES_API_HISTORY_PARAM_WITHOUT_TYPE_CHANGE: 'Forbid changes: Parameters Parameter must be defined by type.',
ERROR_CHANGES_API_HISTORY_PARAM_TYPE_CHANGE: 'Forbid changes: Parameters type cannot be modified.',
ERROR_CHANGES_API_HISTORY_PARAM_POSITION_CHANGE: 'Forbid changes: Parameters position not be allowed to be modified.',
ERROR_CHANGES_API_NEW_REQUIRED_PARAM: 'Forbid changes: Required parameters cannot be created.',
ERROR_CHANGES_API_DELETE_PARAM: 'Forbid changes: Parameters cannot be deleted.',
ERROR_CHANGES_DEPRECATED: 'Forbid changes: The api has deprecated tag.',
ERROR_CHANGES_JSDOC_NUMBER: 'Forbid changes: API changes must add a new section of JSDoc.',
ERROR_CHANGES_JSDOC_CHANGE: 'Forbid changes: Previous JSDoc cannot be changed.',
ERROR_CHANGES_JSDOC_TRROWS: 'Forbid changes: Throws tag cannot be created.',
ERROR_CHANGES_JSDOC_PERMISSION: 'Forbid changes: Permission tag cannot be created or modified.',
ERROR_FILE_TAG_ORDER: 'File tags order is incorrect.',
ERROR_DESCRIPTION_NULL: 'description is null',
ERROR_HAS_CHINESE: 'has chinese'
};
exports.ErrorValueInfo = ErrorValueInfo;
const DIFF_INFO = {
NEW_JSDOCS_LENGTH: 1,
NEW_JSDOC_INDEX: 2,
};
exports.DIFF_INFO = DIFF_INFO;
* link error message
*/
function createErrorInfo(errorInfo, params) {
params.forEach((param) => {
errorInfo = errorInfo.replace('$$', param);
});
return errorInfo;
}
exports.createErrorInfo = createErrorInfo;
* judge if it is an API file for Arkui
*/
function isArkUIApiFile(fileName) {
if (fileName.indexOf('component\\ets\\') >= 0 || fileName.indexOf('component/ets/') >= 0) {
return true;
}
return false;
}
exports.isArkUIApiFile = isArkUIApiFile;
function isWhiteListFile(fileName, whiteList) {
for (let i = 0; i < whiteList.length; i++) {
if (path.normalize(fileName).indexOf(path.normalize(whiteList[i])) !== -1) {
return true;
}
}
return false;
}
exports.isWhiteListFile = isWhiteListFile;
function getCheckApiVersion() {
const packageJsonPath = path.join(__dirname, '../package.json');
let packageJson;
let checkApiVersion;
try {
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
packageJson = JSON.parse(packageJsonContent);
checkApiVersion = packageJson.checkApiVersion;
} catch (error) {
throw `Failed to read package.json or parse JSON content: ${error}`;
}
if (!checkApiVersion) {
throw 'Please configure the correct API version to be verified';
}
return checkApiVersion;
}
exports.getCheckApiVersion = getCheckApiVersion;
const OptionalSymbols = {
QUERY: '?',
LEFT_BRACKET: '[',
RIGHT_BRACKET: ']',
LEFT_BRACE: '{',
RIGHT_BRACE: '}',
LEFT_PARENTHESES: '(',
RIGHT_PARENTHESES: ')'
};
exports.OptionalSymbols = OptionalSymbols;
function removeDuplicateObj(array) {
const newArr = [];
const errorInfoSet = new Set();
for (const errorInfo of array) {
if (!errorInfoSet.has(JSON.stringify(errorInfo))) {
errorInfoSet.add(JSON.stringify(errorInfo));
newArr.push(errorInfo);
}
}
return newArr;
};
exports.removeDuplicateObj = removeDuplicateObj;
function checkVersionNeedCheck(node) {
const apiVersion = getApiVersion(node);
const apiCheckVersion = getCheckApiVersion();
if (parseInt(apiVersion) >= parseInt(apiCheckVersion)) {
return true;
}
return false;
}
exports.checkVersionNeedCheck = checkVersionNeedCheck;
const FUNCTION_TYPES = [ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.MethodSignature,
ts.SyntaxKind.MethodDeclaration, ts.SyntaxKind.CallSignature, ts.SyntaxKind.Constructor];
exports.FUNCTION_TYPES = FUNCTION_TYPES;
function splitPath(filePath, pathElements) {
let spliteResult = path.parse(filePath);
if (spliteResult.base !== '') {
pathElements.add(spliteResult.base);
splitPath(spliteResult.dir, pathElements);
}
}
exports.splitPath = splitPath;
function isAscending(arr) {
for (let i = 1; i < arr.length; i++) {
if (arr[i] < arr[i - 1]) {
return false;
}
}
return true;
}
exports.isAscending = isAscending;
const ruleArr = ['API_DOC_ATOMICSERVICE_01',
'API_DOC_ATOMICSERVICE_02',
'API_DOC_CONSTANT_01',
'API_DOC_CONSTANT_02',
'API_DOC_CONSTANT_03',
'API_DOC_CONSTANT_04',
'API_DOC_CROSSPLATFORM_01',
'API_DOC_CROSSPLATFORM_02',
'API_DOC_DEFAULT_01',
'API_DOC_DEFAULT_02',
'API_DOC_DEFAULT_04',
'API_DOC_DEPRECATED_01',
'API_DOC_DEPRECATED_02',
'API_DOC_DEPRECATED_03',
'API_DOC_DEPRECATED_04',
'API_DOC_ENUM_01',
'API_DOC_ENUM_02',
'API_DOC_ENUM_03',
'API_DOC_ENUM_04',
'API_DOC_ENUM_05',
'API_DOC_EXAMPLE_01',
'API_DOC_EXAMPLE_02',
'API_DOC_EXTENDS_01',
'API_DOC_EXTENDS_02',
'API_DOC_EXTENDS_03',
'API_DOC_EXTENDS_04',
'API_DOC_EXTENDS_05',
'API_DOC_FAMODELONLY_01',
'API_DOC_FAMODELONLY_02',
'API_DOC_FAMODELONLY_03',
'API_DOC_FIRES_01',
'API_DOC_FIRES_02',
'API_DOC_FORM_01',
'API_DOC_FORM_02',
'API_DOC_IMPLEMENTS_01',
'API_DOC_IMPLEMENTS_04',
'API_DOC_INTERFACE_04',
'API_DOC_INTERFACE_05',
'API_DOC_NAMESPACE_01',
'API_DOC_NAMESPACE_02',
'API_DOC_NAMESPACE_03',
'API_DOC_NAMESPACE_04',
'API_DOC_NAMESPACE_05',
'API_DOC_PARAM_01',
'API_DOC_PARAM_02',
'API_DOC_PARAM_03',
'API_DOC_PARAM_04',
'API_DOC_PARAM_05',
'API_DOC_PARAM_06',
'API_DOC_PERMISSION_02',
'API_DOC_PERMISSION_04',
'API_DOC_READONLY_01',
'API_DOC_READONLY_02',
'API_DOC_READONLY_03',
'API_DOC_RETURNS_01',
'API_DOC_RETURNS_02',
'API_DOC_RETURNS_03',
'API_DOC_RETURNS_04',
'API_DOC_RETURNS_05',
'API_DOC_RETURNS_06',
'API_DOC_SINCE_01',
'API_DOC_SINCE_02',
'API_DOC_SINCE_03',
'API_DOC_SINCE_04',
'API_DOC_STAGEMODELONLY_01',
'API_DOC_STAGEMODELONLY_02',
'API_DOC_STAGEMODELONLY_03',
'API_DOC_STATIC_01',
'API_DOC_STATIC_02',
'API_DOC_STRUCT_02',
'API_DOC_STRUCT_05',
'API_DOC_SYSCAP_02',
'API_DOC_SYSCAP_03',
'API_DOC_SYSCAP_04',
'API_DOC_SYSTEMAPI_01',
'API_DOC_SYSTEMAPI_02',
'API_DOC_SYSTEMAPI_03',
'API_DOC_TEST_01',
'API_DOC_TEST_02',
'API_DOC_TEST_03',
'API_DOC_THROWS_01',
'API_DOC_THROWS_02',
'API_DOC_THROWS_03',
'API_DOC_TYPE_01',
'API_DOC_TYPE_02',
'API_DOC_TYPE_03',
'API_DOC_TYPE_05',
'API_DOC_TYPEDEF_01',
'API_DOC_TYPEDEF_02',
'API_DOC_TYPEDEF_03',
'API_DOC_TYPEDEF_04',
'API_DOC_TYPEDEF_05',
'API_DOC_USEINSTEAD_01',
'API_DOC_USEINSTEAD_02',
'API_DOC_USEINSTEAD_03',
'API_DOC_USEINSTEAD_04',
'API_DOC_UNKNOW_DECORATOR_01',
'API_DEFINE_UNALLOWABLE_01',
'API_DEFINE_NAME_01',
'API_DEFINE_NAME_02',
'API_DEFINE_SPELLING_01',
'API_DEFINE_EVENT_01',
'API_DEFINE_EVENT_02',
'API_DEFINE_EVENT_03',
'API_DEFINE_EVENT_04',
'API_DEFINE_EVENT_05',
'API_DEFINE_EVENT_06',
'API_DEFINE_EVENT_07',
'API_DEFINE_EVENT_08',
'API_DEFINE_HUMP_01',
'API_DEFINE_HUMP_02',
'API_DEFINE_HUMP_03',
'API_DEFINE_HUMP_04',
'API_DEFINE_HUMP_05',
'API_CHANGE_INCOMPATIBLE_01',
'API_CHANGE_INCOMPATIBLE_02',
'API_CHANGE_INCOMPATIBLE_03',
'API_CHANGE_INCOMPATIBLE_04',
'API_CHANGE_INCOMPATIBLE_05',
'API_CHANGE_INCOMPATIBLE_06',
'API_CHANGE_INCOMPATIBLE_07',
'API_CHANGE_INCOMPATIBLE_08',
'API_CHANGE_INCOMPATIBLE_09',
'API_CHANGE_INCOMPATIBLE_10',
'API_CHANGE_INCOMPATIBLE_11',
'API_CHANGE_INCOMPATIBLE_12',
'API_CHANGE_INCOMPATIBLE_13',
'API_CHANGE_INCOMPATIBLE_14',
'API_CHANGE_INCOMPATIBLE_15',
'API_CHANGE_INCOMPATIBLE_16',
'API_CHANGE_INCOMPATIBLE_17',
'API_CHANGE_INCOMPATIBLE_18',
'API_CHANGE_INCOMPATIBLE_19',
'API_CHANGE_INCOMPATIBLE_20',
'API_CHANGE_INCOMPATIBLE_21',
'API_CHANGE_INCOMPATIBLE_22',
'API_CHANGE_INCOMPATIBLE_23',
'API_CHANGE_INCOMPATIBLE_24',
'API_CHANGE_INCOMPATIBLE_25',
'API_CHANGE_INCOMPATIBLE_26',
'API_CHANGE_INCOMPATIBLE_27',
'API_CHANGE_INCOMPATIBLE_28',
'API_CHANGE_INCOMPATIBLE_29',
'API_CHANGE_INCOMPATIBLE_30',
'API_CHANGE_INCOMPATIBLE_31',
'API_CHANGE_INCOMPATIBLE_33',
'API_CHANGE_INCOMPATIBLE_34',
'API_CHANGE_INCOMPATIBLE_35',
'API_CHANGE_INCOMPATIBLE_36',
'API_CHANGE_INCOMPATIBLE_37',
'API_CHANGE_INCOMPATIBLE_38',
'API_CHANGE_INCOMPATIBLE_39',
'API_CHANGE_INCOMPATIBLE_40',
'API_CHANGE_INCOMPATIBLE_41',
'API_DOC_JSDOC_04'
];
exports.ruleArr = ruleArr;