!3531 CodeCheck Fix: Super-large function reconstruction

Merge pull request !3531 from OneYuan/codecheck0620
This commit is contained in:
openharmony_ci 2024-06-21 08:39:58 +00:00 committed by Gitee
commit 8e39e4e1a7
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
3 changed files with 212 additions and 87 deletions

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2024 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.
*/
import ts from 'typescript';
import { COMPONENT_SENDABLE_DECORATOR } from './pre_define';
function transformOptionalMemberForSendable(node: ts.PropertyDeclaration): ts.PropertyDeclaration {
let updatedTypeNode: ts.TypeNode = node.type;
if (ts.isUnionTypeNode(updatedTypeNode)) {
if (!updatedTypeNode.types.find(type => type.kind === ts.SyntaxKind.UndefinedKeyword)) {
updatedTypeNode = ts.factory.createUnionTypeNode([
...updatedTypeNode.types,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
]);
}
} else {
updatedTypeNode = ts.factory.createUnionTypeNode([
updatedTypeNode,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
]);
}
return ts.factory.createPropertyDeclaration(
node.modifiers,
node.name,
undefined,
updatedTypeNode,
node.initializer ? node.initializer : ts.factory.createIdentifier('undefined')
);
}
function removeSendableDecorator(modifiers: ts.NodeArray<ts.ModifierLike>): ts.NodeArray<ts.ModifierLike> {
return ts.factory.createNodeArray(
modifiers.filter(decorator => {
const originalDecortor: string = decorator.getText().replace(/\(.*\)$/, '').trim();
return originalDecortor !== COMPONENT_SENDABLE_DECORATOR;
})
);
}
function updateSendableConstructor(constructor: ts.ConstructorDeclaration): ts.ConstructorDeclaration {
// Skip the overloaded signature of the constructor
if (constructor.body === undefined) {
return constructor;
}
const statementArray: ts.Statement[] = [
ts.factory.createExpressionStatement(ts.factory.createStringLiteral('use sendable')),
...constructor.body.statements
];
return ts.factory.updateConstructorDeclaration(
constructor,
constructor.modifiers,
constructor.parameters,
ts.factory.updateBlock(constructor.body, statementArray)
);
}
function addConstructorForSendableClass(members: ts.NodeArray<ts.ClassElement>): ts.NodeArray<ts.ClassElement> {
const constructor: ts.ConstructorDeclaration = ts.factory.createConstructorDeclaration(
undefined,
[],
ts.factory.createBlock(
[ts.factory.createExpressionStatement(ts.factory.createStringLiteral('use sendable'))],
true
)
);
return ts.factory.createNodeArray([constructor, ...(members || [])]);
}
export function processSendableClass(node: ts.ClassDeclaration): ts.ClassDeclaration {
let hasConstructor = false;
let updatedMembers: ts.NodeArray<ts.ClassElement> = node.members;
let updatedModifiers: ts.NodeArray<ts.ModifierLike> = removeSendableDecorator(node.modifiers);
for (const member of node.members) {
if (ts.isPropertyDeclaration(member) && member.questionToken) {
const propertyDecl: ts.PropertyDeclaration = member as ts.PropertyDeclaration;
const updatedPropertyDecl: ts.PropertyDeclaration = transformOptionalMemberForSendable(member);
updatedMembers = ts.factory.createNodeArray(
updatedMembers.map(member => (member === propertyDecl ? updatedPropertyDecl : member))
);
}
if (ts.isConstructorDeclaration(member)) {
hasConstructor = true;
const constructor: ts.ConstructorDeclaration = member as ts.ConstructorDeclaration;
updatedMembers = ts.factory.createNodeArray(
updatedMembers.map(member => (member === constructor ? updateSendableConstructor(constructor) : member))
);
}
}
if (!hasConstructor) {
updatedMembers = addConstructorForSendableClass(updatedMembers);
}
node = ts.factory.updateClassDeclaration(node, updatedModifiers, node.name, node.typeParameters,
node.heritageClauses, updatedMembers);
return node;
}

View File

@ -152,6 +152,7 @@ import {
import constantDefine from './constant_define';
import processStructComponentV2 from './process_struct_componentV2';
import createAstNodeUtils from './create_ast_node_utils';
import { processSendableClass } from './process_sendable'
export let transformLog: FileLog = new FileLog();
export let contextGlobal: ts.TransformationContext;
@ -372,7 +373,7 @@ export function processUISyntax(program: ts.Program, ut = false,
pos: node.getStart()
});
}
node = processClassSendable(node);
node = processSendableClass(node);
}
}
return ts.visitEachChild(node, processAllNodes, context);
@ -1037,92 +1038,6 @@ function processConcurrent(node: ts.FunctionDeclaration): ts.FunctionDeclaration
return node;
}
function transformQuestionToken(node: ts.PropertyDeclaration): ts.PropertyDeclaration {
let updatedTypeNode: ts.TypeNode = node.type;
if (ts.isUnionTypeNode(updatedTypeNode)) {
if (!updatedTypeNode.types.find(type => type.kind === ts.SyntaxKind.UndefinedKeyword)) {
updatedTypeNode = ts.factory.createUnionTypeNode([
...updatedTypeNode.types,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
]);
}
} else {
updatedTypeNode = ts.factory.createUnionTypeNode([
updatedTypeNode,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
]);
}
return ts.factory.createPropertyDeclaration(
node.modifiers,
node.name,
undefined,
updatedTypeNode,
node.initializer ? node.initializer : ts.factory.createIdentifier('undefined')
);
}
function processClassSendable(node: ts.ClassDeclaration): ts.ClassDeclaration {
let hasConstructor = false;
let updatedMembers: ts.NodeArray<ts.ClassElement> = node.members;
let updatedModifiers: ts.NodeArray<ts.ModifierLike> = node.modifiers;
updatedModifiers = ts.factory.createNodeArray(
updatedModifiers.filter(decorator => {
const originalDecortor: string = decorator.getText().replace(/\(.*\)$/, '').trim();
return originalDecortor !== COMPONENT_SENDABLE_DECORATOR;
})
);
for (const member of node.members) {
if (ts.isPropertyDeclaration(member) && member.questionToken) {
const propertyDecl: ts.PropertyDeclaration = member as ts.PropertyDeclaration;
const updatedPropertyDecl: ts.PropertyDeclaration = transformQuestionToken(member);
updatedMembers = ts.factory.createNodeArray(
updatedMembers.map(member => (member === propertyDecl ? updatedPropertyDecl : member))
);
}
if (ts.isConstructorDeclaration(member)) {
hasConstructor = true;
const constructor: ts.ConstructorDeclaration = member as ts.ConstructorDeclaration;
if (constructor.body !== undefined) {
const statementArray: ts.Statement[] = [
ts.factory.createExpressionStatement(ts.factory.createStringLiteral('use sendable')),
...constructor.body.statements
];
const updatedConstructor: ts.ConstructorDeclaration = ts.factory.updateConstructorDeclaration(
constructor,
constructor.modifiers,
constructor.parameters,
ts.factory.updateBlock(constructor.body, statementArray));
updatedMembers = ts.factory.createNodeArray(
updatedMembers.map(member => (member === constructor ? updatedConstructor : member))
);
}
}
}
if (!hasConstructor) {
const constructor: ts.ConstructorDeclaration = ts.factory.createConstructorDeclaration(
undefined,
[],
ts.factory.createBlock(
[ts.factory.createExpressionStatement(ts.factory.createStringLiteral('use sendable'))],
true
)
);
updatedMembers = ts.factory.createNodeArray([constructor, ...(updatedMembers || [])]);
}
node = ts.factory.updateClassDeclaration(node, updatedModifiers, node.name, node.typeParameters,
node.heritageClauses, updatedMembers);
return node;
}
export function isOriginalExtend(node: ts.Block): boolean {
let innerNode: ts.Node = node.statements[0];
if (node.statements.length === 1 && ts.isExpressionStatement(innerNode)) {

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use rollupObject 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.
*/
import { expect } from 'chai';
import mocha from 'mocha';
import * as ts from 'typescript';
import path from 'path';
import { hasDecorator } from '../../../lib/utils';
import { processSendableClass } from '../../../lib/process_sendable';
import { COMPONENT_SENDABLE_DECORATOR } from '../../../lib/pre_define';
const SENDABLE_WITHOUT_CONSTRUCTOR_CODE: string =
`
@Sendable
class sendableClass {}
`
const SENDABLE_WITHOUT_CONSTRUCTOR_CODE_EXPECT: string =
'"use strict";\n' +
'class sendableClass {\n' +
' constructor() {\n' +
' "use sendable";\n' +
' }\n' +
'}\n' +
'//# sourceMappingURL=sendableTest.js.map'
const SENDABLE_WITH_CONSTRUCTOR_CODE: string =
`
@Sendable
class sendableClass {
constructor() {}
}
`
const SENDABLE_WITH_CONSTRUCTOR_CODE_EXPECT: string =
'"use strict";\n' +
'class sendableClass {\n' +
' constructor() {\n' +
' "use sendable";\n' +
' }\n' +
'}\n' +
'//# sourceMappingURL=sendableTest.js.map'
const compilerOptions = ts.readConfigFile(
path.resolve(__dirname, '../../../tsconfig.json'), ts.sys.readFile).config.compilerOptions;
function processSendable(): Function {
return (context: ts.TransformationContext) => {
const visitor: ts.Visitor = node => {
if (ts.isClassDeclaration(node) && hasDecorator(node, COMPONENT_SENDABLE_DECORATOR)) {
return processSendableClass(node);
}
return node;
};
return (node: ts.SourceFile) => {
return ts.visitEachChild(node, visitor, context);
};
}
}
mocha.describe('process sendable class without constrcutor tests', function () {
mocha.it('process sendable decorator', function () {
const result: ts.TranspileOutput = ts.transpileModule(SENDABLE_WITHOUT_CONSTRUCTOR_CODE, {
compilerOptions: compilerOptions,
fileName: "sendableTest.ts",
transformers: { before: [ processSendable() ] }
});
console.log(result.outputText);
expect(result.outputText == SENDABLE_WITHOUT_CONSTRUCTOR_CODE_EXPECT).to.be.true;
});
})
mocha.describe('process sendable class with constrcutor tests', function () {
mocha.it('process sendable decorator', function () {
const result: ts.TranspileOutput = ts.transpileModule(SENDABLE_WITH_CONSTRUCTOR_CODE, {
compilerOptions: compilerOptions,
fileName: "sendableTest.ts",
transformers: { before: [ processSendable() ] }
});
console.log(result.outputText);
expect(result.outputText == SENDABLE_WITH_CONSTRUCTOR_CODE_EXPECT).to.be.true;
});
})