diff --git a/OAT.xml b/OAT.xml
index 3aaf1c1b76a0a76e796bdc2539766f3ea2cca931..eb7f62ab17b4eebd0baa65e29f65ef32859a0351 100644
--- a/OAT.xml
+++ b/OAT.xml
@@ -26,6 +26,7 @@
+
diff --git a/arkui-plugins/common/plugin-context.ts b/arkui-plugins/common/plugin-context.ts
index 2a07f0670001937666ed4fbf5f7a830844693efd..6396f7bf8a0b7b563369f0e5aa9579342014c308 100644
--- a/arkui-plugins/common/plugin-context.ts
+++ b/arkui-plugins/common/plugin-context.ts
@@ -101,6 +101,8 @@ export interface ProjectConfig {
resetBundleName: boolean;
allowEmptyBundleName: boolean;
moduleType: string;
+ moduleRootPath: string;
+ aceModuleJsonPath: string;
}
export type PluginHandlerFunction = () => void;
diff --git a/arkui-plugins/test/demo/localtest/build_config_template.json b/arkui-plugins/test/demo/localtest/build_config_template.json
index 64b8fdafba7bdb5d7f1d5a2d5910db0fda3d2b3b..798e9e377af5bc47874597e107678b475737eee7 100755
--- a/arkui-plugins/test/demo/localtest/build_config_template.json
+++ b/arkui-plugins/test/demo/localtest/build_config_template.json
@@ -6,11 +6,11 @@
},
"compileFiles": [
- "./demo/localtest/entry/new.ets"
+ "./demo/localtest/entry/src/main/ets/pages/new.ets"
],
"entryFiles": [
- "./demo/localtest/entry/new.ets"
+ "./demo/localtest/entry/src/main/ets/pages/new.ets"
],
"buildMode": "Debug",
@@ -43,5 +43,6 @@
"levelStr": "INFO",
"colour": "green"
},
- "isBuildConfigModified": false
+ "isBuildConfigModified": false,
+ "aceModuleJsonPath": "./demo/localtest/entry/src/main/module.json5"
}
diff --git a/arkui-plugins/test/demo/localtest/entry/index.ets b/arkui-plugins/test/demo/localtest/entry/src/main/ets/pages/index.ets
similarity index 100%
rename from arkui-plugins/test/demo/localtest/entry/index.ets
rename to arkui-plugins/test/demo/localtest/entry/src/main/ets/pages/index.ets
diff --git a/arkui-plugins/test/demo/localtest/entry/new.ets b/arkui-plugins/test/demo/localtest/entry/src/main/ets/pages/new.ets
similarity index 100%
rename from arkui-plugins/test/demo/localtest/entry/new.ets
rename to arkui-plugins/test/demo/localtest/entry/src/main/ets/pages/new.ets
diff --git a/arkui-plugins/test/demo/localtest/entry/src/main/module.json5 b/arkui-plugins/test/demo/localtest/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..f2ff2c7f12fb46a0656dd93857b72f7a1b057001
--- /dev/null
+++ b/arkui-plugins/test/demo/localtest/entry/src/main/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/arkui-plugins/test/demo/localtest/entry/src/main/resources/base/profile/main_pages.json b/arkui-plugins/test/demo/localtest/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..bc9792df11412a3f3d08a60ca4a770f9a22ae3d5
--- /dev/null
+++ b/arkui-plugins/test/demo/localtest/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,6 @@
+{
+ "src": [
+ "pages/index",
+ "pages/new"
+ ]
+}
\ No newline at end of file
diff --git a/arkui-plugins/test/localtest_config.js b/arkui-plugins/test/localtest_config.js
index 6372cbc8cfcc8b73e14d6ca0387a896aff08a9e6..00d2cfb5157e4473f7faaefc6d58dacdac16a860 100644
--- a/arkui-plugins/test/localtest_config.js
+++ b/arkui-plugins/test/localtest_config.js
@@ -31,55 +31,63 @@ const jsonFilePath = path.join(__dirname, 'demo/localtest/build_config_template.
const outJsonFilePath = path.join(__dirname, 'demo/localtest/build_config.json');
try {
- // 读取 JSON 文件内容
- const data = fs.readFileSync(jsonFilePath, 'utf8');
- const jsonData = JSON.parse(data);
- console.log(jsonData)
- // 处理 baseUrl 字段
- if (jsonData.buildSdkPath) {
- jsonData.buildSdkPath = jsonData.buildSdkPath.replace(/workspace/g, workSpace);
- }
+ // 读取 JSON 文件内容
+ const data = fs.readFileSync(jsonFilePath, 'utf8');
+ const jsonData = JSON.parse(data);
+ console.log(jsonData)
+ // 处理 baseUrl 字段
+ if (jsonData.buildSdkPath) {
+ jsonData.buildSdkPath = jsonData.buildSdkPath.replace(/workspace/g, workSpace);
+ }
- // 处理 plugins 字段
- if (jsonData.plugins.ui_plugin) {
- jsonData.plugins.ui_plugin = jsonData.plugins.ui_plugin.replace(/workspace/g, workSpace);
- }
- if (jsonData.plugins.memo_plugin) {
- jsonData.plugins.memo_plugin = jsonData.plugins.memo_plugin.replace(/workspace/g, workSpace);
- }
+ // 处理 plugins 字段
+ if (jsonData.plugins.ui_syntax_plugin) {
+ jsonData.plugins.ui_syntax_plugin = jsonData.plugins.ui_syntax_plugin.replace(/workspace/g, workSpace);
+ }
+ if (jsonData.plugins.ui_plugin) {
+ jsonData.plugins.ui_plugin = jsonData.plugins.ui_plugin.replace(/workspace/g, workSpace);
+ }
+ if (jsonData.plugins.memo_plugin) {
+ jsonData.plugins.memo_plugin = jsonData.plugins.memo_plugin.replace(/workspace/g, workSpace);
+ }
- // compileFiles
- if (jsonData.compileFiles) {
- jsonData.compileFiles = jsonData.compileFiles.map((file) => changePathToAbsPath(file));
- }
+ // compileFiles
+ if (jsonData.compileFiles) {
+ jsonData.compileFiles = jsonData.compileFiles.map((file) => changePathToAbsPath(file));
+ }
- // entryFiles
- if (jsonData.entryFiles) {
- jsonData.entryFiles = jsonData.entryFiles.map((file) => changePathToAbsPath(file));
- }
+ // entryFiles
+ if (jsonData.entryFiles) {
+ jsonData.entryFiles = jsonData.entryFiles.map((file) => changePathToAbsPath(file));
+ }
- // moduleRootPath
- if (jsonData.moduleRootPath) {
- jsonData.moduleRootPath = changePathToAbsPath(jsonData.moduleRootPath);
- }
+ // moduleRootPath
+ if (jsonData.moduleRootPath) {
+ jsonData.moduleRootPath = changePathToAbsPath(jsonData.moduleRootPath);
+ }
- // sourceRoots
- if (jsonData.sourceRoots) {
- jsonData.sourceRoots = jsonData.sourceRoots.map((file) => changePathToAbsPath(file));
- }
+ // sourceRoots
+ if (jsonData.sourceRoots) {
+ jsonData.sourceRoots = jsonData.sourceRoots.map((file) => changePathToAbsPath(file));
+ }
- // loaderOutPath
- if (jsonData.loaderOutPath) {
- jsonData.loaderOutPath = changePathToAbsPath(jsonData.loaderOutPath);
- }
+ // loaderOutPath
+ if (jsonData.loaderOutPath) {
+ jsonData.loaderOutPath = changePathToAbsPath(jsonData.loaderOutPath);
+ }
- // loaderOutPath
- if (jsonData.cachePath) {
- jsonData.cachePath = changePathToAbsPath(jsonData.cachePath);
- }
+ // loaderOutPath
+ if (jsonData.cachePath) {
+ jsonData.cachePath = changePathToAbsPath(jsonData.cachePath);
+ }
- // 将修改后的内容写回 JSON 文件
- fs.writeFileSync(outJsonFilePath, JSON.stringify(jsonData, null, 2), 'utf8');
+ // appModuleJsonPath
+ if (jsonData.aceModuleJsonPath) {
+ jsonData.aceModuleJsonPath = changePathToAbsPath(jsonData.aceModuleJsonPath);
+ }
+
+ // 将修改后的内容写回 JSON 文件
+ fs.writeFileSync(outJsonFilePath, JSON.stringify(jsonData, null, 2), 'utf8');
} catch (error) {
- console.error('处理 JSON 文件时出错:', error);
+ console.error('处理 JSON 文件时出错:', error);
}
\ No newline at end of file
diff --git a/arkui-plugins/ui-syntax-plugins/index.ts b/arkui-plugins/ui-syntax-plugins/index.ts
index 53232081ede8d769c434e28a3bbb0b038e6a304f..36167ae8cf889e7fcd918cb90e2da8c43927b5e5 100644
--- a/arkui-plugins/ui-syntax-plugins/index.ts
+++ b/arkui-plugins/ui-syntax-plugins/index.ts
@@ -24,13 +24,17 @@ export function uiSyntaxLinterTransform(): Plugins {
return {
name: 'ui-syntax-plugin',
parsed(this: PluginContext): arkts.EtsScript | undefined {
- const contextPtr = arkts.arktsGlobal.compilerContext?.peer ?? this.getContextPtr();
+ const contextPtr = this.getContextPtr() ?? arkts.arktsGlobal.compilerContext?.peer;
if (!contextPtr) {
return undefined;
}
- let program = arkts.getOrUpdateGlobalContext(contextPtr).program;
+ const program = arkts.getOrUpdateGlobalContext(contextPtr).program;
const node = program.astNode;
if (node) {
+ const projectConfig = this.getProjectConfig();
+ if (projectConfig) {
+ processor.setProjectConfig(projectConfig);
+ }
const script = new ParsedUISyntaxLinterTransformer(processor).visitor(
node,
) as arkts.EtsScript;
diff --git a/arkui-plugins/ui-syntax-plugins/processor/index.ts b/arkui-plugins/ui-syntax-plugins/processor/index.ts
index 6fdebeac52d38a28e2095e45ffc18e2c7da8fbcf..d9bb88a102c03d927e6facf7d5acee16146fa62c 100644
--- a/arkui-plugins/ui-syntax-plugins/processor/index.ts
+++ b/arkui-plugins/ui-syntax-plugins/processor/index.ts
@@ -14,76 +14,133 @@
*/
import * as arkts from '@koalaui/libarkts';
-import { UISyntaxRule, UISyntaxRuleContext } from '../rules/ui-syntax-rule';
-import { getUIComponents } from '../utils';
+import * as path from "node:path";
+import { ReportOptions, UISyntaxRule, UISyntaxRuleContext, UISyntaxRuleHandler } from '../rules/ui-syntax-rule';
+import { getUIComponents, readJSON, UISyntaxRuleComponents } from '../utils';
+import { ProjectConfig } from 'common/plugin-context';
export type UISyntaxRuleProcessor = {
+ setProjectConfig(projectConfig: ProjectConfig): void;
parsed(node: arkts.AstNode): void;
};
-export interface UISyntaxRuleComponents {
- builtInAttributes: string[];
- containerComponents: string[];
- atomicComponents: string[];
- singleChildComponents: string[];
- validParentComponent: Map;
- validChildComponent: Map;
+type ModuleConfig = {
+ module: {
+ pages: string;
+ }
}
-export function createUISyntaxRuleProcessor(
- rules: UISyntaxRule[],
-): UISyntaxRuleProcessor {
- const componentsInfo: UISyntaxRuleComponents = getUIComponents('../../components/');
- const context: UISyntaxRuleContext = {
- report(options) {
- const position = arkts.getStartPosition(options.node);
- let message: string;
- if (!options.data) {
- message = options.message;
- } else {
- message = Object.entries(options.data).reduce(
- (message, [placehoderName, placehoderValue]) => {
- return message.replace(`{{${placehoderName}}}`, placehoderValue);
- },
- options.message,
- );
- }
+type MainPages = {
+ src: string[];
+};
- let args: string[] = [];
- const kind: arkts.DiagnosticKind =
- arkts.DiagnosticKind.create(message, arkts.PluginDiagnosticType.ES2PANDA_PLUGIN_ERROR);
- if (options.fix) {
- const diagnosticInfo: arkts.DiagnosticInfo = arkts.DiagnosticInfo.create(kind, ...args);
- const suggestionInfo: arkts.SuggestionInfo =
- arkts.SuggestionInfo.create(kind, options.fix(options.node).code, ...args);
- const startPosition = arkts.getStartPosition(options.node);
- const endPosition = arkts.getEndPosition(options.node);
- const sourceRange: arkts.SourceRange = arkts.SourceRange.create(startPosition, endPosition);
- arkts.Diagnostic.logDiagnosticWithSuggestion(diagnosticInfo, suggestionInfo, sourceRange);
- } else {
- arkts.Diagnostic.logDiagnostic(kind, arkts.getStartPosition(options.node));
- }
+const BASE_RESOURCE_PATH = "src/main/resources/base";
+const ETS_PATH = "src/main/ets";
- // todo
- if (options.fix) {
- const suggestion = options.fix(options.node);
- console.log(`syntax-error: ${message}`);
- console.log(`range: (${suggestion.range[0].index()}, ${suggestion.range[0].line()}) - (${suggestion.range[1].index()}, ${suggestion.range[1].line()})`,
- `code: ${suggestion.code}`);
- } else {
- console.log(`syntax-error: ${message} (${position.index()},${position.line()})`);
- }
- },
- componentsInfo: componentsInfo
- };
+class ConcreteUISyntaxRuleContext implements UISyntaxRuleContext {
+ public componentsInfo: UISyntaxRuleComponents;
+ public projectConfig?: ProjectConfig;
+
+ constructor() {
+ this.componentsInfo = getUIComponents('../../components/');
+ }
+
+ public report(options: ReportOptions): void {
+ let message: string;
+ if (!options.data) {
+ message = options.message;
+ } else {
+ message = this.format(options.message, options.data);
+ }
- const instances = rules.map((rule) => rule.setup(context));
+ const kind: arkts.DiagnosticKind =
+ arkts.DiagnosticKind.create(message, arkts.PluginDiagnosticType.ES2PANDA_PLUGIN_ERROR);
+ if (options.fix) {
+ const diagnosticInfo: arkts.DiagnosticInfo = arkts.DiagnosticInfo.create(kind);
+ const fixSuggestion = options.fix(options.node);
+ const suggestionInfo: arkts.SuggestionInfo = arkts.SuggestionInfo.create(kind, fixSuggestion.code);
+ const [startPosition, endPosition] = fixSuggestion.range;
+ const sourceRange: arkts.SourceRange = arkts.SourceRange.create(startPosition, endPosition);
+ arkts.Diagnostic.logDiagnosticWithSuggestion(diagnosticInfo, suggestionInfo, sourceRange);
+ } else {
+ arkts.Diagnostic.logDiagnostic(kind, arkts.getStartPosition(options.node));
+ }
- return {
- parsed(node): void {
- for (const instance of instances) {
- instance.parsed?.(node);
+ // todo
+ const position = arkts.getStartPosition(options.node);
+ if (options.fix) {
+ const suggestion = options.fix(options.node);
+ console.log(`syntax-error: ${message}`);
+ console.log(`range: (${suggestion.range[0].index()}, ${suggestion.range[0].line()}) - (${suggestion.range[1].index()}, ${suggestion.range[1].line()})`,
+ `code: ${suggestion.code}`);
+ } else {
+ console.log(`syntax-error: ${message} (${position.index()},${position.line()})`);
+ }
+ }
+
+ getMainPages(): string[] {
+ if (!this.projectConfig) {
+ return [];
+ }
+ const { moduleRootPath, aceModuleJsonPath } = this.projectConfig;
+ if (!aceModuleJsonPath) {
+ throw new Error('The aceModuleJsonPath config is empty.');
+ }
+ const moduleConfig = readJSON(aceModuleJsonPath);
+ if (!moduleConfig.module || !moduleConfig.module.pages) {
+ throw new Error('Failed to read pages because the content of module.json5 is invalid.');
+ }
+ const pagesPath = moduleConfig.module.pages;
+ const matcher = /\$(?[_A-Za-z]+):(?[_A-Za-z]+)/.exec(pagesPath);
+ if (matcher && matcher.groups) {
+ const { directory, filename } = matcher.groups;
+ const mainPagesPath = path.resolve(moduleRootPath, BASE_RESOURCE_PATH, directory, `${filename}.json`);
+ const mainPages = readJSON(mainPagesPath);
+ if (!mainPages.src || !Array.isArray(mainPages.src)) {
+ throw new Error(`Failed to read pages because the content of ${filename}.json is invalid.`);
}
- },
- };
+ return mainPages.src.map(page => path.resolve(moduleRootPath, ETS_PATH, `${page}.ets`));
+ } else {
+ throw new Error('Failed to read pages from module.json5');
+ }
+ }
+
+
+ private format(content: string, placeholders: object): string {
+ return Object.entries(placeholders).reduce(
+ (content, [placehoderName, placehoderValue]) => {
+ return content.replace(`{{${placehoderName}}}`, placehoderValue);
+ },
+ content,
+ );
+ }
+}
+
+class ConcreteUISyntaxRuleProcessor implements UISyntaxRuleProcessor {
+ protected context: UISyntaxRuleContext;
+ protected handlers: UISyntaxRuleHandler[];
+
+ constructor(rules: UISyntaxRule[]) {
+ this.context = new ConcreteUISyntaxRuleContext();
+ this.handlers = rules.map(rule => {
+ return rule.setup(this.context);
+ });
+ }
+
+
+ parsed(node: arkts.AstNode): void {
+ for (const handlers of this.handlers) {
+ handlers.parsed?.(node);
+ }
+ }
+
+ setProjectConfig(projectConfig: ProjectConfig): void {
+ this.context.projectConfig = projectConfig;
+ }
+}
+
+export function createUISyntaxRuleProcessor(
+ rules: UISyntaxRule[],
+): UISyntaxRuleProcessor {
+ return new ConcreteUISyntaxRuleProcessor(rules);
}
diff --git a/arkui-plugins/ui-syntax-plugins/rules/build-root-node.ts b/arkui-plugins/ui-syntax-plugins/rules/build-root-node.ts
index 39d8bb07a0f96be914b5bcf66ba53d9ad9f3e10b..f8bbf624c6c7b8c7d35586ce0dbcf61c21496610 100644
--- a/arkui-plugins/ui-syntax-plugins/rules/build-root-node.ts
+++ b/arkui-plugins/ui-syntax-plugins/rules/build-root-node.ts
@@ -49,7 +49,7 @@ function reportvalidBuildRoot(
}
function checkBuildRootNode(node: arkts.AstNode, context: UISyntaxRuleContext): void {
- const loadedContainerComponents = context.containerComponents;
+ const loadedContainerComponents = context.componentsInfo.containerComponents;
if (!arkts.isStructDeclaration(node)) {
return;
}
@@ -92,7 +92,7 @@ function checkBuildRootNode(node: arkts.AstNode, context: UISyntaxRuleContext):
return;
}
isContainer = componentName
- ? loadedContainerComponents.has(componentName)
+ ? loadedContainerComponents.includes(componentName)
: false;
// rule2: its 'build' function can have only one root node, which must be a container component.
reportvalidBuildRoot(entryDecoratorUsage, isContainer, buildNode, context);
diff --git a/arkui-plugins/ui-syntax-plugins/rules/check-construct-private-parameter.ts b/arkui-plugins/ui-syntax-plugins/rules/check-construct-private-parameter.ts
index 6bbdbc59c666cd96be0be42ebc8fa4475e04d895..d3e4045cf2d414766fc01af7c17115dfd2dfdd34 100644
--- a/arkui-plugins/ui-syntax-plugins/rules/check-construct-private-parameter.ts
+++ b/arkui-plugins/ui-syntax-plugins/rules/check-construct-private-parameter.ts
@@ -21,13 +21,17 @@ function addProperty(item: arkts.AstNode, structName: string, privatePropertyMap
if (!arkts.isClassProperty(item) || !isPrivateClassProperty(item)) {
return;
}
+ const propertyName = getClassPropertyName(item);
+ if (!propertyName) {
+ return;
+ }
// Check if structName already exists in privateMap
if (privatePropertyMap.has(structName)) {
// If it exists, retrieve the current string[] and append the new content
- privatePropertyMap.get(structName)?.push(getClassPropertyName(item));
+ privatePropertyMap.get(structName)!.push(propertyName);
} else {
// If it doesn't exist, create a new string[] and add the content
- privatePropertyMap.set(structName, [getClassPropertyName(item)]);
+ privatePropertyMap.set(structName, [propertyName]);
}
}
diff --git a/arkui-plugins/ui-syntax-plugins/rules/check-decorated-property-type.ts b/arkui-plugins/ui-syntax-plugins/rules/check-decorated-property-type.ts
index d8f8f0dd97dafeb7a9c49fc204b50a571330d009..05563bbcc701fc5a6e215f35f29acc6ff6e446c7 100644
--- a/arkui-plugins/ui-syntax-plugins/rules/check-decorated-property-type.ts
+++ b/arkui-plugins/ui-syntax-plugins/rules/check-decorated-property-type.ts
@@ -44,8 +44,11 @@ function checkDecoratedPropertyType(
if (!arkts.isClassProperty(member)) {
return;
}
- const propertyName: string = getClassPropertyName(member);
- const propertyType: string = getClassPropertyType(member);
+ const propertyName = getClassPropertyName(member);
+ const propertyType = getClassPropertyType(member);
+ if (!propertyName || !propertyType) {
+ return;
+ }
const propertyAnnotationNames: string[] = getClassPropertyAnnotationNames(member);
const decoratorName: string | undefined =
propertyAnnotationNames.find((annotation) => annoList.includes(annotation));
@@ -61,6 +64,7 @@ function checkDecoratedPropertyType(
data: { decoratorName, propertyName, propertyType },
});
}
+
}
const rule: UISyntaxRule = {
diff --git a/arkui-plugins/ui-syntax-plugins/rules/ui-syntax-rule.ts b/arkui-plugins/ui-syntax-plugins/rules/ui-syntax-rule.ts
index f0096765c227231620fe5370ad5f17dc570f68eb..e62fa514bad275b7b4e6ed2b9d9db8ac5bd62e58 100644
--- a/arkui-plugins/ui-syntax-plugins/rules/ui-syntax-rule.ts
+++ b/arkui-plugins/ui-syntax-plugins/rules/ui-syntax-rule.ts
@@ -14,7 +14,8 @@
*/
import * as arkts from '@koalaui/libarkts';
-import { UISyntaxRuleComponents } from 'ui-syntax-plugins/processor';
+import { ProjectConfig } from 'common/plugin-context';
+import { UISyntaxRuleComponents } from 'ui-syntax-plugins/utils';
export type FixSuggestion = {
range: [start: arkts.SourcePosition, end: arkts.SourcePosition];
@@ -29,17 +30,20 @@ export type ReportOptions = {
};
export type UISyntaxRuleContext = {
- report(options: ReportOptions): void;
- configOfComponent?: Set | undefined;
+ projectConfig?: ProjectConfig;
componentsInfo: UISyntaxRuleComponents;
+ report(options: ReportOptions): void;
+ getMainPages(): string[];
};
-export type UISyntaxRuleHandler = (node: arkts.AstNode) => void;
+export type UISyntaxRulePhaseHandler = (node: arkts.AstNode) => void;
+
+export type UISyntaxRuleHandler = {
+ parsed?: UISyntaxRulePhaseHandler;
+};
export type UISyntaxRule = {
name: string;
messages: Record;
- setup(context: UISyntaxRuleContext): {
- parsed?: UISyntaxRuleHandler;
- };
+ setup(context: UISyntaxRuleContext): UISyntaxRuleHandler;
};
diff --git a/arkui-plugins/ui-syntax-plugins/utils/index.ts b/arkui-plugins/ui-syntax-plugins/utils/index.ts
index 7bd08c5250659d7f90dffc86a1f923c1061b4199..91694abaf511fec689109970c04ff22437701494 100644
--- a/arkui-plugins/ui-syntax-plugins/utils/index.ts
+++ b/arkui-plugins/ui-syntax-plugins/utils/index.ts
@@ -16,7 +16,6 @@
import * as arkts from '@koalaui/libarkts';
import * as fs from 'fs';
import * as path from 'path';
-import { UISyntaxRuleComponents } from 'ui-syntax-plugins/processor';
import { UISyntaxRuleContext } from 'ui-syntax-plugins/rules/ui-syntax-rule';
export const BUILD_NAME: string = 'build';
@@ -166,12 +165,15 @@ export function getClassAnnotationUsage(
-export function getClassPropertyName(property: arkts.ClassProperty): string {
+export function getClassPropertyName(property: arkts.ClassProperty): string | undefined {
+ if (!property.key) {
+ return undefined;
+ }
return getIdentifierName(property.key);
}
-export function getClassPropertyType(property: arkts.ClassProperty): string {
- return property.typeAnnotation.dumpSrc();
+export function getClassPropertyType(property: arkts.ClassProperty): string | undefined {
+ return property.typeAnnotation?.dumpSrc();
}
export function getClassPropertyAnnotationNames(
@@ -252,6 +254,15 @@ interface ComponentJson {
children?: string[];
}
+export interface UISyntaxRuleComponents {
+ builtInAttributes: string[];
+ containerComponents: string[];
+ atomicComponents: string[];
+ singleChildComponents: string[];
+ validParentComponent: Map;
+ validChildComponent: Map;
+}
+
export function getUIComponents(dirPath: string): UISyntaxRuleComponents {
const absolutePath = path.resolve(__dirname, dirPath);
let builtInAttributes: string[] = [];
@@ -327,4 +338,15 @@ export function isContainerComponent(context: UISyntaxRuleContext, componentName
export function isSingleChildComponent(context: UISyntaxRuleContext, componentName: string): boolean {
return context.componentsInfo.singleChildComponents.includes(componentName);
+}
+
+export function readJSON(path: string): T {
+ if (!fs.existsSync(path)) {
+ throw new Error(`Failed to read file becasue the ${path} is not exist.`);
+ }
+ const content = fs.readFileSync(path).toString();
+ if (!content) {
+ throw new Error(`Failed to read file because the file content is empty.`);
+ }
+ return JSON.parse(content) as T;
}
\ No newline at end of file