mirror of
https://github.com/openharmony/developtools_ace-ets2bundle.git
synced 2026-07-25 06:05:39 -04:00
File diff suppressed because one or more lines are too long
@@ -199,3 +199,6 @@ export const $$_NEW_VALUE: string = 'newValue';
|
|||||||
|
|
||||||
export const INTERFACE_NAME_SUFFIX:string = '_Params';
|
export const INTERFACE_NAME_SUFFIX:string = '_Params';
|
||||||
export const OBSERVED_PROPERTY_ABSTRACT:string = 'ObservedPropertyAbstract';
|
export const OBSERVED_PROPERTY_ABSTRACT:string = 'ObservedPropertyAbstract';
|
||||||
|
|
||||||
|
export const SUPERVISUAL: string = './supervisual';
|
||||||
|
export const SUPERVISUAL_SOURCEMAP_EXT: string = '.visual.js.map';
|
||||||
|
|||||||
+194
-29
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
import ts from 'typescript';
|
import ts from 'typescript';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { SourceMapGenerator } from 'source-map';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ReplaceResult,
|
ReplaceResult,
|
||||||
@@ -26,12 +28,20 @@ import {
|
|||||||
import {
|
import {
|
||||||
LogType,
|
LogType,
|
||||||
LogInfo,
|
LogInfo,
|
||||||
emitLogInfo
|
emitLogInfo,
|
||||||
|
mkDir
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { BUILD_ON } from './pre_define';
|
import {
|
||||||
|
BUILD_ON,
|
||||||
|
SUPERVISUAL,
|
||||||
|
SUPERVISUAL_SOURCEMAP_EXT
|
||||||
|
} from './pre_define';
|
||||||
import { projectConfig } from '../main.js';
|
import { projectConfig } from '../main.js';
|
||||||
import { genETS } from '../codegen/codegen_ets.js';
|
import { genETS } from '../codegen/codegen_ets.js';
|
||||||
|
|
||||||
|
const visualMap: Map<number, number> = new Map();
|
||||||
|
const slotMap: Map<number, number> = new Map();
|
||||||
|
|
||||||
function preProcess(source: string): string {
|
function preProcess(source: string): string {
|
||||||
process.env.compiler = BUILD_ON;
|
process.env.compiler = BUILD_ON;
|
||||||
if (/\.ets$/.test(this.resourcePath)) {
|
if (/\.ets$/.test(this.resourcePath)) {
|
||||||
@@ -39,7 +49,7 @@ function preProcess(source: string): string {
|
|||||||
let newContent: string = result.content;
|
let newContent: string = result.content;
|
||||||
const log: LogInfo[] = result.log.concat(validateUISyntax(source, newContent,
|
const log: LogInfo[] = result.log.concat(validateUISyntax(source, newContent,
|
||||||
this.resourcePath, this.resourceQuery));
|
this.resourcePath, this.resourceQuery));
|
||||||
newContent = parseVisual(this.resourcePath, newContent, log);
|
newContent = parseVisual(this.resourcePath, this.resourceQuery, newContent, log, source);
|
||||||
if (log.length) {
|
if (log.length) {
|
||||||
emitLogInfo(this, log);
|
emitLogInfo(this, log);
|
||||||
}
|
}
|
||||||
@@ -49,28 +59,48 @@ function preProcess(source: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseVisual(resourcePath: string, content: string, log: LogInfo[]): string {
|
function parseVisual(resourcePath: string, resourceQuery: string, content: string,
|
||||||
if (componentCollection.entryComponent && projectConfig.aceSuperVisualPath) {
|
log: LogInfo[], source: string): string {
|
||||||
const sourceFile: ts.SourceFile = ts.createSourceFile(resourcePath, content,
|
if (!componentCollection.entryComponent || !projectConfig.aceSuperVisualPath) {
|
||||||
ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
return content;
|
||||||
if (sourceFile.statements) {
|
|
||||||
sourceFile.statements.forEach(statement => {
|
|
||||||
content = parseStatement(statement, content, log, resourcePath);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return content;
|
const visualPath: string = findVisualFile(resourcePath);
|
||||||
|
if (!visualPath || !fs.existsSync(visualPath)) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
const visualContent: any = getVisualContent(visualPath, log);
|
||||||
|
if (!visualContent) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
visualMap.clear();
|
||||||
|
slotMap.clear();
|
||||||
|
const sourceFile: ts.SourceFile = ts.createSourceFile(resourcePath, content,
|
||||||
|
ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
||||||
|
let newContent: string = content;
|
||||||
|
if (sourceFile.statements) {
|
||||||
|
sourceFile.statements.forEach(statement => {
|
||||||
|
newContent = parseStatement(statement, newContent, log, visualContent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const result: ReplaceResult = sourceReplace(newContent, resourcePath);
|
||||||
|
newContent = result.content;
|
||||||
|
const resultLog: LogInfo[] = result.log.concat(validateUISyntax(source, newContent,
|
||||||
|
resourcePath, resourceQuery));
|
||||||
|
log.concat(resultLog);
|
||||||
|
if (!log.length) {
|
||||||
|
generateSourceMapForNewAndOriEtsFile(resourcePath, source);
|
||||||
|
}
|
||||||
|
return newContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseStatement(statement: ts.Statement, content: string, log: LogInfo[],
|
function parseStatement(statement: ts.Statement, content: string, log: LogInfo[],
|
||||||
resourcePath: string): string {
|
visualContent: any): string {
|
||||||
if (statement.kind === ts.SyntaxKind.ClassDeclaration &&
|
if (statement.kind === ts.SyntaxKind.ClassDeclaration &&
|
||||||
statement.name && statement.name.getText() === componentCollection.entryComponent) {
|
statement.name && statement.name.getText() === componentCollection.entryComponent) {
|
||||||
const visualPath: string = findVisualFile(resourcePath);
|
if (statement.members) {
|
||||||
if (visualPath && fs.existsSync(visualPath) && statement.members) {
|
|
||||||
statement.members.forEach(member => {
|
statement.members.forEach(member => {
|
||||||
if (member.kind && member.kind === ts.SyntaxKind.MethodDeclaration) {
|
if (member.kind && member.kind === ts.SyntaxKind.MethodDeclaration) {
|
||||||
content = parseMember(member, content, log, visualPath);
|
content = parseMember(statement, member, content, log, visualContent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -78,16 +108,13 @@ function parseStatement(statement: ts.Statement, content: string, log: LogInfo[]
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseMember(member: ts.MethodDeclaration, content: string, log: LogInfo[],
|
function parseMember(statement: ts.Statement, member: ts.MethodDeclaration, content: string,
|
||||||
visualPath: string): string {
|
log: LogInfo[], visualContent: any): string {
|
||||||
|
let newContent: string = content;
|
||||||
if (member.name && member.name.getText() === 'build') {
|
if (member.name && member.name.getText() === 'build') {
|
||||||
const buildBody: string = content.substring(member.pos, member.end);
|
const buildBody: string = member.getText();
|
||||||
if (buildBody.replace(/\ +/g, '').replace(/[\r\n]/g, '') === 'build(){}') {
|
if (buildBody.replace(/\ +/g, '').replace(/[\r\n]/g, '') === 'build(){}') {
|
||||||
const visualContent: string = getVisualContent(visualPath, log, member.pos);
|
newContent = insertVisualCode(statement, member, visualContent, newContent);
|
||||||
if (visualContent) {
|
|
||||||
content = content.replace(buildBody, '\nbuild() {\n' +
|
|
||||||
visualContent + '}\n');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
log.push({
|
log.push({
|
||||||
type: LogType.ERROR,
|
type: LogType.ERROR,
|
||||||
@@ -97,7 +124,146 @@ function parseMember(member: ts.MethodDeclaration, content: string, log: LogInfo
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return content;
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertVisualCode(statement: ts.Statement, member: ts.MethodDeclaration,
|
||||||
|
visualContent: any, content: string): string {
|
||||||
|
let newContent: string = content;
|
||||||
|
newContent = insertImport(visualContent, newContent);
|
||||||
|
newContent = insertVarAndFunc(member, visualContent, newContent, content);
|
||||||
|
newContent = insertBuild(member, visualContent, newContent, content);
|
||||||
|
newContent = insertAboutToAppear(statement, member, visualContent, newContent, content);
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertImport(visualContent: any, content: string): string {
|
||||||
|
if (!visualContent.etsImport) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
const mediaQueryImport: string = visualContent.etsImport + '\n';
|
||||||
|
const newContent: string = mediaQueryImport + content;
|
||||||
|
slotMap.set(0, mediaQueryImport.length);
|
||||||
|
visualMap.set(0, mediaQueryImport.split('\n').length - 1);
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertVarAndFunc(build: ts.MethodDeclaration, visualContent: any,
|
||||||
|
content: string, oriContent: string): string {
|
||||||
|
const visualVarAndFunc: string = (visualContent.etsVariable ?? '') +
|
||||||
|
(visualContent.etsFunction ?? '');
|
||||||
|
return visualVarAndFunc ? insertVisualCodeBeforePos(build, '\n' + visualVarAndFunc, content,
|
||||||
|
oriContent) : content;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertBuild(build: ts.MethodDeclaration, visualContent: any, content: string,
|
||||||
|
oriContent: string): string {
|
||||||
|
return visualContent.build ? insertVisualCodeAfterPos(build.body,
|
||||||
|
'\n' + visualContent.build + '\n', content, oriContent) : content;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertAboutToAppear(statement: ts.Statement, build: ts.MethodDeclaration,
|
||||||
|
visualContent: any, content: string, oriContent: string): string {
|
||||||
|
if (!visualContent.aboutToAppear) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
for (const member of statement.members) {
|
||||||
|
const hasAboutToAppear: boolean = member.kind && member.kind === ts.SyntaxKind.MethodDeclaration
|
||||||
|
&& member.name && member.name.getText() === 'aboutToAppear';
|
||||||
|
if (hasAboutToAppear) {
|
||||||
|
return insertVisualCodeAfterPos(member.body, '\n' + visualContent.aboutToAppear, content,
|
||||||
|
oriContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const aboutToAppearFunc: string = '\n aboutToAppear() {\n' + visualContent.aboutToAppear +
|
||||||
|
' }\n';
|
||||||
|
return insertVisualCodeBeforePos(build, aboutToAppearFunc, content, oriContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertVisualCodeAfterPos(member: ts.Block, visualContent: string, content: string,
|
||||||
|
oriContent: string): string {
|
||||||
|
const contentBeforePos: string = oriContent.substring(0, member.getStart() + 1);
|
||||||
|
const originEtsFileLineNumber: number = contentBeforePos.split('\n').length;
|
||||||
|
const visualLines: number = visualContent.split('\n').length - 1;
|
||||||
|
const insertedLineNumbers: number = visualMap.get(originEtsFileLineNumber);
|
||||||
|
visualMap.set(originEtsFileLineNumber, insertedLineNumbers ? insertedLineNumbers + visualLines :
|
||||||
|
visualLines);
|
||||||
|
|
||||||
|
let newPos: number = member.getStart() + 1;
|
||||||
|
for (const [key, value] of slotMap) {
|
||||||
|
if (member.getStart() >= key) {
|
||||||
|
newPos += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newContent: string = content.substring(0, newPos) + visualContent +
|
||||||
|
content.substring(newPos);
|
||||||
|
slotMap.set(member.getStart(), visualContent.length);
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertVisualCodeBeforePos(member: ts.MethodDeclaration, visualContent: string,
|
||||||
|
content: string, oriContent: string): string {
|
||||||
|
const contentBeforePos: string = oriContent.substring(0, member.pos);
|
||||||
|
const originEtsFileLineNumber: number = contentBeforePos.split('\n').length;
|
||||||
|
const visualLines: number = visualContent.split('\n').length - 1;
|
||||||
|
const insertedLineNumbers: number = visualMap.get(originEtsFileLineNumber);
|
||||||
|
visualMap.set(originEtsFileLineNumber, insertedLineNumbers ? insertedLineNumbers + visualLines :
|
||||||
|
visualLines);
|
||||||
|
let newPos: number = member.pos;
|
||||||
|
for (const [key, value] of slotMap) {
|
||||||
|
if (member.pos >= key) {
|
||||||
|
newPos += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const newContent: string = content.substring(0, newPos) + visualContent +
|
||||||
|
content.substring(newPos);
|
||||||
|
slotMap.set(member.pos, visualContent.length);
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateSourceMapForNewAndOriEtsFile(resourcePath: string, content: string) {
|
||||||
|
if (!process.env.cachePath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sourcemap: SourceMapGenerator = new SourceMapGenerator({
|
||||||
|
file: resourcePath
|
||||||
|
});
|
||||||
|
const lines: Array<string> = content.split('\n');
|
||||||
|
const originEtsFileLines: number = lines.length;
|
||||||
|
for (let l: number = 1; l <= originEtsFileLines; l++) {
|
||||||
|
let newEtsFileLineNumber: number = l;
|
||||||
|
for (const [originEtsFileLineNumber, visualLines] of visualMap) {
|
||||||
|
if (l > originEtsFileLineNumber) {
|
||||||
|
newEtsFileLineNumber += visualLines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourcemap.addMapping({
|
||||||
|
generated: {
|
||||||
|
line: newEtsFileLineNumber,
|
||||||
|
column: 0
|
||||||
|
},
|
||||||
|
source: resourcePath,
|
||||||
|
original: {
|
||||||
|
line: l,
|
||||||
|
column: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const visualMapName: string = path.parse(resourcePath).name + SUPERVISUAL_SOURCEMAP_EXT;
|
||||||
|
const visualDirPath: string = path.parse(resourcePath).dir;
|
||||||
|
const etsDirPath: string = path.parse(projectConfig.projectPath).dir;
|
||||||
|
const visualMapDirPath: string = path.resolve(process.env.cachePath, SUPERVISUAL +
|
||||||
|
visualDirPath.replace(etsDirPath, ''));
|
||||||
|
if (!(fs.existsSync(visualMapDirPath) && fs.statSync(visualMapDirPath).isDirectory())) {
|
||||||
|
mkDir(visualMapDirPath);
|
||||||
|
}
|
||||||
|
fs.writeFile(path.resolve(visualMapDirPath, visualMapName), sourcemap.toString(), (err) => {
|
||||||
|
if (err) {
|
||||||
|
return console.error('ERROR: Failed to write visual.js.map');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function findVisualFile(filePath: string): string {
|
function findVisualFile(filePath: string): string {
|
||||||
@@ -106,13 +272,12 @@ function findVisualFile(filePath: string): string {
|
|||||||
return visualPath;
|
return visualPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVisualContent(visualPath: string, log: LogInfo[], pos: number): string {
|
function getVisualContent(visualPath: string, log: LogInfo[]): any {
|
||||||
const parseContent: any = genETS(fs.readFileSync(visualPath, 'utf-8'));
|
const parseContent: any = genETS(fs.readFileSync(visualPath, 'utf-8'));
|
||||||
if (parseContent && parseContent.errorType && parseContent.errorType !== '') {
|
if (parseContent && parseContent.errorType && parseContent.errorType !== '') {
|
||||||
log.push({
|
log.push({
|
||||||
type: LogType.ERROR,
|
type: LogType.ERROR,
|
||||||
message: parseContent.message,
|
message: parseContent.message
|
||||||
pos: pos
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return parseContent ? parseContent.ets : null;
|
return parseContent ? parseContent.ets : null;
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ function copyFile(inputFile: string, outputFile: string): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mkDir(path_: string): void {
|
export function mkDir(path_: string): void {
|
||||||
const parent: string = path.join(path_, '..');
|
const parent: string = path.join(path_, '..');
|
||||||
if (!(fs.existsSync(parent) && !fs.statSync(parent).isFile())) {
|
if (!(fs.existsSync(parent) && !fs.statSync(parent).isFile())) {
|
||||||
mkDir(parent);
|
mkDir(parent);
|
||||||
|
|||||||
Reference in New Issue
Block a user