107ac75b1Sopenharmony_ci/*
207ac75b1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
307ac75b1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
407ac75b1Sopenharmony_ci * you may not use this file except in compliance with the License.
507ac75b1Sopenharmony_ci * You may obtain a copy of the License at
607ac75b1Sopenharmony_ci *
707ac75b1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
807ac75b1Sopenharmony_ci *
907ac75b1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1007ac75b1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1107ac75b1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1207ac75b1Sopenharmony_ci * See the License for the specific language governing permissions and
1307ac75b1Sopenharmony_ci * limitations under the License.
1407ac75b1Sopenharmony_ci */
1507ac75b1Sopenharmony_ci
1607ac75b1Sopenharmony_ciimport ts from 'typescript';
1707ac75b1Sopenharmony_ciimport fs from 'fs';
1807ac75b1Sopenharmony_ciimport path from 'path';
1907ac75b1Sopenharmony_ciimport { SourceMapGenerator } from 'source-map';
2007ac75b1Sopenharmony_ci
2107ac75b1Sopenharmony_ciimport {
2207ac75b1Sopenharmony_ci  validateUISyntax,
2307ac75b1Sopenharmony_ci  componentCollection,
2407ac75b1Sopenharmony_ci  ReplaceResult,
2507ac75b1Sopenharmony_ci  sourceReplace
2607ac75b1Sopenharmony_ci} from './validate_ui_syntax';
2707ac75b1Sopenharmony_ciimport {
2807ac75b1Sopenharmony_ci  LogType,
2907ac75b1Sopenharmony_ci  LogInfo,
3007ac75b1Sopenharmony_ci  mkDir,
3107ac75b1Sopenharmony_ci  emitLogInfo
3207ac75b1Sopenharmony_ci} from './utils';
3307ac75b1Sopenharmony_ciimport {
3407ac75b1Sopenharmony_ci  MODULE_ETS_PATH,
3507ac75b1Sopenharmony_ci  MODULE_VISUAL_PATH,
3607ac75b1Sopenharmony_ci  SUPERVISUAL,
3707ac75b1Sopenharmony_ci  SUPERVISUAL_SOURCEMAP_EXT
3807ac75b1Sopenharmony_ci} from './pre_define';
3907ac75b1Sopenharmony_ci
4007ac75b1Sopenharmony_ciimport { projectConfig } from '../main.js';
4107ac75b1Sopenharmony_ciimport { genETS } from '../codegen/codegen_ets.js';
4207ac75b1Sopenharmony_ci
4307ac75b1Sopenharmony_ciconst visualMap: Map<number, number> = new Map();
4407ac75b1Sopenharmony_ciconst slotMap: Map<number, number> = new Map();
4507ac75b1Sopenharmony_ci
4607ac75b1Sopenharmony_ciconst red: string = '\u001b[31m';
4707ac75b1Sopenharmony_ciconst reset: string = '\u001b[39m';
4807ac75b1Sopenharmony_ci
4907ac75b1Sopenharmony_ciconst compilerOptions = ts.readConfigFile(
5007ac75b1Sopenharmony_ci  path.resolve(__dirname, '../tsconfig.json'),
5107ac75b1Sopenharmony_ci  ts.sys.readFile
5207ac75b1Sopenharmony_ci).config.compilerOptions;
5307ac75b1Sopenharmony_cicompilerOptions.sourceMap = false;
5407ac75b1Sopenharmony_ci
5507ac75b1Sopenharmony_ciexport function visualTransform(code: string, id: string, logger: any) {
5607ac75b1Sopenharmony_ci  const log: LogInfo[] = [];
5707ac75b1Sopenharmony_ci  const content: string | null = getParsedContent(code, path.normalize(id), log);
5807ac75b1Sopenharmony_ci  if (!content) {
5907ac75b1Sopenharmony_ci    return code;
6007ac75b1Sopenharmony_ci  }
6107ac75b1Sopenharmony_ci  if (log.length) {
6207ac75b1Sopenharmony_ci    emitLogInfo(logger, log, true, id);
6307ac75b1Sopenharmony_ci  }
6407ac75b1Sopenharmony_ci  generateSourceMapForNewAndOriEtsFile(path.normalize(id), code);
6507ac75b1Sopenharmony_ci  return content;
6607ac75b1Sopenharmony_ci}
6707ac75b1Sopenharmony_ci
6807ac75b1Sopenharmony_ciexport function parseVisual(resourcePath: string, resourceQuery: string, content: string,
6907ac75b1Sopenharmony_ci  log: LogInfo[], source: string): string {
7007ac75b1Sopenharmony_ci  let code: string | null = getParsedContent(content, resourcePath, log);
7107ac75b1Sopenharmony_ci  if (!code) {
7207ac75b1Sopenharmony_ci    return content;
7307ac75b1Sopenharmony_ci  }
7407ac75b1Sopenharmony_ci  const result: ReplaceResult = sourceReplace(code, resourcePath);
7507ac75b1Sopenharmony_ci  code = result.content;
7607ac75b1Sopenharmony_ci  log.concat(result.log);
7707ac75b1Sopenharmony_ci  const resultLog: LogInfo[] = validateUISyntax(source, code, resourcePath, resourceQuery);
7807ac75b1Sopenharmony_ci  log.concat(resultLog);
7907ac75b1Sopenharmony_ci  if (!log.length) {
8007ac75b1Sopenharmony_ci    generateSourceMapForNewAndOriEtsFile(resourcePath, source);
8107ac75b1Sopenharmony_ci  }
8207ac75b1Sopenharmony_ci  return code;
8307ac75b1Sopenharmony_ci}
8407ac75b1Sopenharmony_ci
8507ac75b1Sopenharmony_cifunction parseStatement(statement: ts.Statement, content: string, log: LogInfo[],
8607ac75b1Sopenharmony_ci  visualContent: any): string {
8707ac75b1Sopenharmony_ci  if (statement.kind === ts.SyntaxKind.StructDeclaration && statement.name) {
8807ac75b1Sopenharmony_ci    if (statement.members) {
8907ac75b1Sopenharmony_ci      statement.members.forEach(member => {
9007ac75b1Sopenharmony_ci        if (member.kind && member.kind === ts.SyntaxKind.MethodDeclaration) {
9107ac75b1Sopenharmony_ci          content = parseMember(statement, member, content, log, visualContent);
9207ac75b1Sopenharmony_ci        }
9307ac75b1Sopenharmony_ci      });
9407ac75b1Sopenharmony_ci    }
9507ac75b1Sopenharmony_ci  }
9607ac75b1Sopenharmony_ci  return content;
9707ac75b1Sopenharmony_ci}
9807ac75b1Sopenharmony_ci
9907ac75b1Sopenharmony_cifunction parseMember(statement: ts.Statement, member: ts.MethodDeclaration, content: string,
10007ac75b1Sopenharmony_ci  log: LogInfo[], visualContent: any): string {
10107ac75b1Sopenharmony_ci  let newContent: string = content;
10207ac75b1Sopenharmony_ci  if (member.name && member.name.getText() === 'build') {
10307ac75b1Sopenharmony_ci    const buildBody: string = member.getText();
10407ac75b1Sopenharmony_ci    if (buildBody.replace(/\ +/g, '').replace(/[\r\n]/g, '') === 'build(){}') {
10507ac75b1Sopenharmony_ci      newContent = insertVisualCode(statement, member, visualContent, newContent);
10607ac75b1Sopenharmony_ci    } else {
10707ac75b1Sopenharmony_ci      log.push({
10807ac75b1Sopenharmony_ci        type: LogType.ERROR,
10907ac75b1Sopenharmony_ci        message: `when the corresponding visual file exists,` +
11007ac75b1Sopenharmony_ci          ` the build function of the entry component must be empty.`,
11107ac75b1Sopenharmony_ci        pos: member.pos
11207ac75b1Sopenharmony_ci      });
11307ac75b1Sopenharmony_ci    }
11407ac75b1Sopenharmony_ci  }
11507ac75b1Sopenharmony_ci  return newContent;
11607ac75b1Sopenharmony_ci}
11707ac75b1Sopenharmony_ci
11807ac75b1Sopenharmony_cifunction insertVisualCode(statement: ts.Statement, member: ts.MethodDeclaration,
11907ac75b1Sopenharmony_ci  visualContent: any, content: string): string {
12007ac75b1Sopenharmony_ci  let newContent: string = content;
12107ac75b1Sopenharmony_ci  newContent = insertImport(visualContent, newContent);
12207ac75b1Sopenharmony_ci  newContent = insertVarAndFunc(member, visualContent, newContent, content);
12307ac75b1Sopenharmony_ci  newContent = insertBuild(member, visualContent, newContent, content);
12407ac75b1Sopenharmony_ci  newContent = insertAboutToAppear(statement, member, visualContent, newContent, content);
12507ac75b1Sopenharmony_ci  return newContent;
12607ac75b1Sopenharmony_ci}
12707ac75b1Sopenharmony_ci
12807ac75b1Sopenharmony_cifunction insertImport(visualContent: any, content: string): string {
12907ac75b1Sopenharmony_ci  if (!visualContent.etsImport) {
13007ac75b1Sopenharmony_ci    return content;
13107ac75b1Sopenharmony_ci  }
13207ac75b1Sopenharmony_ci  const mediaQueryImport: string = visualContent.etsImport + '\n';
13307ac75b1Sopenharmony_ci  const newContent: string = mediaQueryImport + content;
13407ac75b1Sopenharmony_ci  slotMap.set(0, mediaQueryImport.length);
13507ac75b1Sopenharmony_ci  visualMap.set(0, mediaQueryImport.split('\n').length - 1);
13607ac75b1Sopenharmony_ci  return newContent;
13707ac75b1Sopenharmony_ci}
13807ac75b1Sopenharmony_ci
13907ac75b1Sopenharmony_cifunction insertVarAndFunc(build: ts.MethodDeclaration, visualContent: any,
14007ac75b1Sopenharmony_ci  content: string, oriContent: string): string {
14107ac75b1Sopenharmony_ci  const visualVarAndFunc: string = (visualContent.etsVariable ? visualContent.etsVariable : '') +
14207ac75b1Sopenharmony_ci    (visualContent.etsFunction ? visualContent.etsFunction : '');
14307ac75b1Sopenharmony_ci  return visualVarAndFunc ? insertVisualCodeBeforePos(build, '\n' + visualVarAndFunc, content,
14407ac75b1Sopenharmony_ci    oriContent) : content;
14507ac75b1Sopenharmony_ci}
14607ac75b1Sopenharmony_ci
14707ac75b1Sopenharmony_cifunction insertBuild(build: ts.MethodDeclaration, visualContent: any, content: string,
14807ac75b1Sopenharmony_ci  oriContent: string): string {
14907ac75b1Sopenharmony_ci  return visualContent.build ? insertVisualCodeAfterPos(build.body,
15007ac75b1Sopenharmony_ci    '\n' + visualContent.build + '\n', content, oriContent) : content;
15107ac75b1Sopenharmony_ci}
15207ac75b1Sopenharmony_ci
15307ac75b1Sopenharmony_cifunction insertAboutToAppear(statement: ts.Statement, build: ts.MethodDeclaration,
15407ac75b1Sopenharmony_ci  visualContent: any, content: string, oriContent: string): string {
15507ac75b1Sopenharmony_ci  if (!visualContent.aboutToAppear) {
15607ac75b1Sopenharmony_ci    return content;
15707ac75b1Sopenharmony_ci  }
15807ac75b1Sopenharmony_ci  for (const member of statement.members) {
15907ac75b1Sopenharmony_ci    const hasAboutToAppear: boolean = member.kind && member.kind === ts.SyntaxKind.MethodDeclaration &&
16007ac75b1Sopenharmony_ci      member.name && member.name.getText() === 'aboutToAppear';
16107ac75b1Sopenharmony_ci    if (hasAboutToAppear) {
16207ac75b1Sopenharmony_ci      return insertVisualCodeAfterPos(member.body, '\n' + visualContent.aboutToAppear, content,
16307ac75b1Sopenharmony_ci        oriContent);
16407ac75b1Sopenharmony_ci    }
16507ac75b1Sopenharmony_ci  }
16607ac75b1Sopenharmony_ci
16707ac75b1Sopenharmony_ci  const aboutToAppearFunc: string = '\n  aboutToAppear() {\n' + visualContent.aboutToAppear +
16807ac75b1Sopenharmony_ci    '  }\n';
16907ac75b1Sopenharmony_ci  return insertVisualCodeBeforePos(build, aboutToAppearFunc, content, oriContent);
17007ac75b1Sopenharmony_ci}
17107ac75b1Sopenharmony_ci
17207ac75b1Sopenharmony_cifunction insertVisualCodeAfterPos(member: ts.Block, visualContent: string, content: string,
17307ac75b1Sopenharmony_ci  oriContent: string): string {
17407ac75b1Sopenharmony_ci  const contentBeforePos: string = oriContent.substring(0, member.getStart() + 1);
17507ac75b1Sopenharmony_ci  const originEtsFileLineNumber: number = contentBeforePos.split('\n').length;
17607ac75b1Sopenharmony_ci  const visualLines: number = visualContent.split('\n').length - 1;
17707ac75b1Sopenharmony_ci  const insertedLineNumbers: number = visualMap.get(originEtsFileLineNumber);
17807ac75b1Sopenharmony_ci  visualMap.set(originEtsFileLineNumber, insertedLineNumbers ? insertedLineNumbers + visualLines :
17907ac75b1Sopenharmony_ci    visualLines);
18007ac75b1Sopenharmony_ci
18107ac75b1Sopenharmony_ci  let newPos: number = member.getStart() + 1;
18207ac75b1Sopenharmony_ci  for (const [key, value] of slotMap) {
18307ac75b1Sopenharmony_ci    if (member.getStart() >= key) {
18407ac75b1Sopenharmony_ci      newPos += value;
18507ac75b1Sopenharmony_ci    }
18607ac75b1Sopenharmony_ci  }
18707ac75b1Sopenharmony_ci
18807ac75b1Sopenharmony_ci  const newContent: string = content.substring(0, newPos) + visualContent +
18907ac75b1Sopenharmony_ci    content.substring(newPos);
19007ac75b1Sopenharmony_ci  slotMap.set(member.getStart(), visualContent.length);
19107ac75b1Sopenharmony_ci  return newContent;
19207ac75b1Sopenharmony_ci}
19307ac75b1Sopenharmony_ci
19407ac75b1Sopenharmony_cifunction insertVisualCodeBeforePos(member: ts.MethodDeclaration, visualContent: string,
19507ac75b1Sopenharmony_ci  content: string, oriContent: string): string {
19607ac75b1Sopenharmony_ci  const contentBeforePos: string = oriContent.substring(0, member.pos);
19707ac75b1Sopenharmony_ci  const originEtsFileLineNumber: number = contentBeforePos.split('\n').length;
19807ac75b1Sopenharmony_ci  const visualLines: number = visualContent.split('\n').length - 1;
19907ac75b1Sopenharmony_ci  const insertedLineNumbers: number = visualMap.get(originEtsFileLineNumber);
20007ac75b1Sopenharmony_ci  visualMap.set(originEtsFileLineNumber, insertedLineNumbers ? insertedLineNumbers + visualLines :
20107ac75b1Sopenharmony_ci    visualLines);
20207ac75b1Sopenharmony_ci  let newPos: number = member.pos;
20307ac75b1Sopenharmony_ci  for (const [key, value] of slotMap) {
20407ac75b1Sopenharmony_ci    if (member.pos >= key) {
20507ac75b1Sopenharmony_ci      newPos += value;
20607ac75b1Sopenharmony_ci    }
20707ac75b1Sopenharmony_ci  }
20807ac75b1Sopenharmony_ci  const newContent: string = content.substring(0, newPos) + visualContent +
20907ac75b1Sopenharmony_ci    content.substring(newPos);
21007ac75b1Sopenharmony_ci  slotMap.set(member.pos, visualContent.length);
21107ac75b1Sopenharmony_ci  return newContent;
21207ac75b1Sopenharmony_ci}
21307ac75b1Sopenharmony_ci
21407ac75b1Sopenharmony_cifunction generateSourceMapForNewAndOriEtsFile(resourcePath: string, content: string) {
21507ac75b1Sopenharmony_ci  if (!process.env.cachePath) {
21607ac75b1Sopenharmony_ci    return;
21707ac75b1Sopenharmony_ci  }
21807ac75b1Sopenharmony_ci  const sourcemap: SourceMapGenerator = new SourceMapGenerator({
21907ac75b1Sopenharmony_ci    file: resourcePath
22007ac75b1Sopenharmony_ci  });
22107ac75b1Sopenharmony_ci  const lines: Array<string> = content.split('\n');
22207ac75b1Sopenharmony_ci  const originEtsFileLines: number = lines.length;
22307ac75b1Sopenharmony_ci  for (let l: number = 1; l <= originEtsFileLines; l++) {
22407ac75b1Sopenharmony_ci    let newEtsFileLineNumber: number = l;
22507ac75b1Sopenharmony_ci    for (const [originEtsFileLineNumber, visualLines] of visualMap) {
22607ac75b1Sopenharmony_ci      if (l > originEtsFileLineNumber) {
22707ac75b1Sopenharmony_ci        newEtsFileLineNumber += visualLines;
22807ac75b1Sopenharmony_ci      }
22907ac75b1Sopenharmony_ci    }
23007ac75b1Sopenharmony_ci    sourcemap.addMapping({
23107ac75b1Sopenharmony_ci      generated: {
23207ac75b1Sopenharmony_ci        line: newEtsFileLineNumber,
23307ac75b1Sopenharmony_ci        column: 0
23407ac75b1Sopenharmony_ci      },
23507ac75b1Sopenharmony_ci      source: resourcePath,
23607ac75b1Sopenharmony_ci      original: {
23707ac75b1Sopenharmony_ci        line: l,
23807ac75b1Sopenharmony_ci        column: 0
23907ac75b1Sopenharmony_ci      }
24007ac75b1Sopenharmony_ci    });
24107ac75b1Sopenharmony_ci  }
24207ac75b1Sopenharmony_ci  const visualMapName: string = path.parse(resourcePath).name + SUPERVISUAL_SOURCEMAP_EXT;
24307ac75b1Sopenharmony_ci  const visualDirPath: string = path.parse(resourcePath).dir;
24407ac75b1Sopenharmony_ci  const etsDirPath: string = path.parse(projectConfig.projectPath).dir;
24507ac75b1Sopenharmony_ci  let visualMapDirPath: string = path.resolve(process.env.cachePath, SUPERVISUAL +
24607ac75b1Sopenharmony_ci    visualDirPath.replace(etsDirPath, ''));
24707ac75b1Sopenharmony_ci  if (!visualDirPath.includes(etsDirPath)) {
24807ac75b1Sopenharmony_ci    const projectRootPath = getProjectRootPath();
24907ac75b1Sopenharmony_ci    visualMapDirPath = path.resolve(process.env.cachePath, SUPERVISUAL +
25007ac75b1Sopenharmony_ci      visualDirPath.replace(projectRootPath, ''));
25107ac75b1Sopenharmony_ci  }
25207ac75b1Sopenharmony_ci  if (!(fs.existsSync(visualMapDirPath) && fs.statSync(visualMapDirPath).isDirectory())) {
25307ac75b1Sopenharmony_ci    mkDir(visualMapDirPath);
25407ac75b1Sopenharmony_ci  }
25507ac75b1Sopenharmony_ci  fs.writeFile(path.resolve(visualMapDirPath, visualMapName), sourcemap.toString(), (err) => {
25607ac75b1Sopenharmony_ci    if (err) {
25707ac75b1Sopenharmony_ci      console.error(red, 'ERROR: Failed to write visual.js.map', reset);
25807ac75b1Sopenharmony_ci    }
25907ac75b1Sopenharmony_ci  });
26007ac75b1Sopenharmony_ci}
26107ac75b1Sopenharmony_ci
26207ac75b1Sopenharmony_cifunction getProjectRootPath(): string {
26307ac75b1Sopenharmony_ci  let projectRootPath = projectConfig.projectRootPath;
26407ac75b1Sopenharmony_ci  if (!projectRootPath) {
26507ac75b1Sopenharmony_ci    if (!projectConfig.aceModuleJsonPath) {
26607ac75b1Sopenharmony_ci      projectRootPath = path.resolve(projectConfig.projectPath, '../../../../../');
26707ac75b1Sopenharmony_ci    } else {
26807ac75b1Sopenharmony_ci      projectRootPath = path.resolve(projectConfig.projectPath, '../../../../');
26907ac75b1Sopenharmony_ci    }
27007ac75b1Sopenharmony_ci  }
27107ac75b1Sopenharmony_ci  return projectRootPath;
27207ac75b1Sopenharmony_ci}
27307ac75b1Sopenharmony_ci
27407ac75b1Sopenharmony_ciexport function findVisualFile(filePath: string): string {
27507ac75b1Sopenharmony_ci  if (!/\.ets$/.test(filePath)) {
27607ac75b1Sopenharmony_ci    return '';
27707ac75b1Sopenharmony_ci  }
27807ac75b1Sopenharmony_ci  let etsDirPath: string = path.parse(projectConfig.projectPath).dir;
27907ac75b1Sopenharmony_ci  let visualDirPath: string = path.parse(projectConfig.aceSuperVisualPath).dir;
28007ac75b1Sopenharmony_ci  let resolvePath = filePath.replace(projectConfig.projectPath, projectConfig.aceSuperVisualPath)
28107ac75b1Sopenharmony_ci    .replace(etsDirPath, visualDirPath).replace(/\.ets$/, '.visual');
28207ac75b1Sopenharmony_ci  if (fs.existsSync(resolvePath)) {
28307ac75b1Sopenharmony_ci    return resolvePath;
28407ac75b1Sopenharmony_ci  }
28507ac75b1Sopenharmony_ci  try {
28607ac75b1Sopenharmony_ci    const projectRootPath = getProjectRootPath();
28707ac75b1Sopenharmony_ci    let moduleName = '';
28807ac75b1Sopenharmony_ci    const relativePath = filePath.replace(projectRootPath, '');
28907ac75b1Sopenharmony_ci    const moduleNames = relativePath.split(path.sep);
29007ac75b1Sopenharmony_ci    for (let i = 0; i < moduleNames.length; ++i) {
29107ac75b1Sopenharmony_ci      if (moduleNames[i] === 'src') {
29207ac75b1Sopenharmony_ci        if (i >= moduleNames.length - 2) {
29307ac75b1Sopenharmony_ci          break;
29407ac75b1Sopenharmony_ci        }
29507ac75b1Sopenharmony_ci        const modulePath = path.join(moduleNames[i], moduleNames[i + 1], moduleNames[i + 2]);
29607ac75b1Sopenharmony_ci        if (modulePath === MODULE_ETS_PATH) {
29707ac75b1Sopenharmony_ci          break;
29807ac75b1Sopenharmony_ci        }
29907ac75b1Sopenharmony_ci      }
30007ac75b1Sopenharmony_ci      moduleName = path.join(moduleName, moduleNames[i]);
30107ac75b1Sopenharmony_ci    }
30207ac75b1Sopenharmony_ci    etsDirPath = path.join(projectRootPath, moduleName, MODULE_ETS_PATH);
30307ac75b1Sopenharmony_ci    visualDirPath = path.join(projectRootPath, moduleName, MODULE_VISUAL_PATH);
30407ac75b1Sopenharmony_ci    resolvePath = filePath.replace(etsDirPath, visualDirPath).replace(/\.ets$/, '.visual');
30507ac75b1Sopenharmony_ci    return resolvePath;
30607ac75b1Sopenharmony_ci  } catch (e) {
30707ac75b1Sopenharmony_ci    // avoid projectConfig attributes has undefined value
30807ac75b1Sopenharmony_ci    return '';
30907ac75b1Sopenharmony_ci  }
31007ac75b1Sopenharmony_ci}
31107ac75b1Sopenharmony_ci
31207ac75b1Sopenharmony_cifunction getVisualContent(visualPath: string, log: LogInfo[]): any {
31307ac75b1Sopenharmony_ci  const parseContent: any = genETS(fs.readFileSync(visualPath, 'utf-8'));
31407ac75b1Sopenharmony_ci  if (parseContent && parseContent.errorType && parseContent.errorType !== '') {
31507ac75b1Sopenharmony_ci    log.push({
31607ac75b1Sopenharmony_ci      type: LogType.ERROR,
31707ac75b1Sopenharmony_ci      message: parseContent.errorMessage
31807ac75b1Sopenharmony_ci    });
31907ac75b1Sopenharmony_ci  }
32007ac75b1Sopenharmony_ci  return parseContent ? parseContent.ets : null;
32107ac75b1Sopenharmony_ci}
32207ac75b1Sopenharmony_ci
32307ac75b1Sopenharmony_cifunction getParsedContent(code: string, id: string, log: LogInfo[]): string | null {
32407ac75b1Sopenharmony_ci  if (!projectConfig.aceSuperVisualPath ||
32507ac75b1Sopenharmony_ci    !(componentCollection.entryComponent || componentCollection.customComponents)) {
32607ac75b1Sopenharmony_ci      return null;
32707ac75b1Sopenharmony_ci  }
32807ac75b1Sopenharmony_ci  const visualPath: string = findVisualFile(id);
32907ac75b1Sopenharmony_ci  if (!visualPath || !fs.existsSync(visualPath)) {
33007ac75b1Sopenharmony_ci    return null;
33107ac75b1Sopenharmony_ci  }
33207ac75b1Sopenharmony_ci  const visualContent: any = getVisualContent(visualPath, log);
33307ac75b1Sopenharmony_ci  if (!visualContent) {
33407ac75b1Sopenharmony_ci    return null;
33507ac75b1Sopenharmony_ci  }
33607ac75b1Sopenharmony_ci  clearVisualSlotMap();
33707ac75b1Sopenharmony_ci  const sourceFile: ts.SourceFile = ts.createSourceFile(
33807ac75b1Sopenharmony_ci    id,
33907ac75b1Sopenharmony_ci    code,
34007ac75b1Sopenharmony_ci    ts.ScriptTarget.Latest,
34107ac75b1Sopenharmony_ci    true,
34207ac75b1Sopenharmony_ci    ts.ScriptKind.ETS,
34307ac75b1Sopenharmony_ci    compilerOptions
34407ac75b1Sopenharmony_ci  );
34507ac75b1Sopenharmony_ci  let content: string = code;
34607ac75b1Sopenharmony_ci  if (sourceFile.statements) {
34707ac75b1Sopenharmony_ci    sourceFile.statements.forEach(statement => {
34807ac75b1Sopenharmony_ci      content = parseStatement(statement, content, log, visualContent);
34907ac75b1Sopenharmony_ci    });
35007ac75b1Sopenharmony_ci  }
35107ac75b1Sopenharmony_ci  return content;
35207ac75b1Sopenharmony_ci}
35307ac75b1Sopenharmony_ci
35407ac75b1Sopenharmony_cifunction clearVisualSlotMap(): void {
35507ac75b1Sopenharmony_ci  visualMap.clear();
35607ac75b1Sopenharmony_ci  slotMap.clear();
35707ac75b1Sopenharmony_ci}