mirror of
https://github.com/openharmony/developtools_ace-ets2bundle.git
synced 2026-07-18 16:04:32 -04:00
update ets2bundle Signed-off-by: lihong <lihong67@huawei.com> Change-Id: Ia9c0229b1adac41d31004da97764063b680f9274
This commit is contained in:
@@ -54,6 +54,7 @@ function initProjectConfig(projectConfig) {
|
||||
function loadEntryObj(projectConfig) {
|
||||
initProjectConfig(projectConfig);
|
||||
setEntryFile(projectConfig);
|
||||
|
||||
if(staticPreviewPage) {
|
||||
projectConfig.entryObj['./' + staticPreviewPage] = projectConfig.projectPath + path.sep +
|
||||
staticPreviewPage + '.ets?entry';
|
||||
|
||||
@@ -28,7 +28,8 @@ import {
|
||||
import { transformLog } from './process_ui_syntax';
|
||||
import {
|
||||
dollarCollection,
|
||||
componentCollection
|
||||
componentCollection,
|
||||
moduleCollection
|
||||
} from './validate_ui_syntax';
|
||||
import { decoratorParamSet } from './process_component_member';
|
||||
import { appComponentCollection } from './process_component_build';
|
||||
@@ -78,10 +79,12 @@ export class ResultStates {
|
||||
});
|
||||
|
||||
if (!projectConfig.isPreview) {
|
||||
compiler.hooks.compilation.tap('Collect Components', compilation => {
|
||||
compilation.hooks.additionalAssets.tapAsync('Collect Components', callback => {
|
||||
compiler.hooks.compilation.tap('Collect Components And Modules', compilation => {
|
||||
compilation.hooks.additionalAssets.tapAsync('Collect Components And Modules', callback => {
|
||||
compilation.assets['./component_collection.txt'] =
|
||||
new RawSource(Array.from(appComponentCollection).join(","));
|
||||
compilation.assets['./module_collection.txt'] =
|
||||
new RawSource(moduleCollection.size === 0 ? 'NULL' : Array.from(moduleCollection).join(","));
|
||||
callback();
|
||||
});
|
||||
})
|
||||
|
||||
+419
-360
@@ -1,360 +1,419 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
export const COMPONENT_MAP: any = {
|
||||
FormComponent: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'size', 'moduleName', 'dimension', 'allowUpdate', 'visibility',
|
||||
'onAcquired', 'onError', 'onRouter'
|
||||
]
|
||||
},
|
||||
Image: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'alt', 'objectFit', 'matchTextDirection', 'fitOriginalSize', 'objectRepeat', 'renderMode', 'interpolation',
|
||||
'onComplete', 'onError', 'onFinish', 'sourceSize', 'fillColor', 'autoResize'
|
||||
]
|
||||
},
|
||||
ImageAnimator: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'images', 'state', 'duration', 'reverse', 'fixedSize', 'preDecode', 'fillMode', 'iterations', 'onStart',
|
||||
'onPause', 'onRepeat', 'onCancel', 'onFinish'
|
||||
]
|
||||
},
|
||||
Animator: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'state', 'duration', 'curve', 'delay', 'fillMode', 'iterations', 'playMode', 'motion', 'onStart',
|
||||
'onPause', 'onRepeat', 'onCancel', 'onFinish', 'onFrame'
|
||||
]
|
||||
},
|
||||
SpringProp: {
|
||||
atomic: true
|
||||
},
|
||||
SpringMotion: {
|
||||
atomic: true
|
||||
},
|
||||
FrictionMotion: {
|
||||
atomic: true
|
||||
},
|
||||
ScrollMotion: {
|
||||
atomic: true
|
||||
},
|
||||
Text: {
|
||||
children: ['Span'],
|
||||
attrs: [
|
||||
'fontColor', 'fontSize', 'fontStyle', 'fontWeight', 'textAlign', 'lineHeight', 'textOverflow', 'maxLines',
|
||||
'decoration', 'letterSpacing', 'textCase', 'baselineOffset', 'minFontSize', 'maxFontSize'
|
||||
]
|
||||
},
|
||||
TextPicker: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'defaultPickerItemHeight', 'onAccept', 'onCancel', 'onChange']
|
||||
},
|
||||
Span: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'fontColor', 'fontSize', 'fontStyle', 'fontFamily', 'fontWeight', 'decoration', 'letterSpacing', 'textCase'
|
||||
]
|
||||
},
|
||||
Button: {
|
||||
attrs: ['type', 'stateEffect', 'fontColor', 'fontSize', 'fontWeight']
|
||||
},
|
||||
Divider: {
|
||||
atomic: true,
|
||||
attrs: ['color', 'vertical', 'strokeWidth', 'lineCap']
|
||||
},
|
||||
Piece: {
|
||||
atomic: true,
|
||||
attrs: ['iconPosition']
|
||||
},
|
||||
Slider: {
|
||||
atomic: true,
|
||||
attrs: ['blockColor', 'trackColor', 'selectedColor', 'minLabel', 'maxLabel', 'showSteps', 'showTips', 'onChange']
|
||||
},
|
||||
Counter: {
|
||||
attrs: [
|
||||
'onStateChange', 'onInc',
|
||||
'onDec', 'height', 'width'
|
||||
]
|
||||
},
|
||||
Row: {
|
||||
attrs: ['alignItems']
|
||||
},
|
||||
Column: {
|
||||
attrs: ['alignItems']
|
||||
},
|
||||
Stack: {
|
||||
attrs: ['alignContent']
|
||||
},
|
||||
List: {
|
||||
children: ['ListItem', 'Section'],
|
||||
attrs: [
|
||||
'listDirection', 'scrollBar', 'edgeEffect', 'divider', 'editMode', 'cachedCount', 'chainAnimation',
|
||||
'onScroll', 'onReachStart', 'onReachEnd', 'onScrollStop', 'onItemDelete', 'onItemMove'
|
||||
]
|
||||
},
|
||||
ListItem: {
|
||||
parents: ['List'],
|
||||
single: true,
|
||||
attrs: ['sticky', 'editable']
|
||||
},
|
||||
Grid: {
|
||||
children: ['GridItem'],
|
||||
attrs: ['columnsTemplate', 'rowsTemplate', 'columnsGap', 'rowsGap', 'scrollBar', 'scrollBarWidth', 'scrollBarColor']
|
||||
},
|
||||
GridItem: {
|
||||
parents: ['Grid'],
|
||||
single: true,
|
||||
attrs: ['rowStart', 'rowEnd', 'columnStart', 'columnEnd', 'forceRebuild']
|
||||
},
|
||||
GridContainer: {
|
||||
attrs: ['columns', 'sizeType', 'gutter', 'margin']
|
||||
},
|
||||
Swiper: {
|
||||
attrs: [
|
||||
'index', 'autoPlay', 'interval', 'indicator',
|
||||
'loop', 'duration', 'vertical', 'itemSpace', 'onChange'
|
||||
]
|
||||
},
|
||||
Rating: {
|
||||
attrs: ['stars', 'stepSize', 'starStyle', 'onChange']
|
||||
},
|
||||
Calendar: {
|
||||
attrs: [
|
||||
'date', 'showLunar', 'startOfWeek', 'offDays', 'onSelectChange', 'onRequestData',
|
||||
'currentData', 'preData', 'nextData', 'needSlide', 'showHoliday', 'direction',
|
||||
'currentDayStyle', 'nonCurrentDayStyle', 'todayStyle', 'weekStyle', 'workStateStyle'
|
||||
]
|
||||
},
|
||||
Panel: {
|
||||
attrs: [
|
||||
'type', 'mode', 'dragBar', 'fullHeight',
|
||||
'halfHeight', 'miniHeight', 'show', 'onChange'
|
||||
]
|
||||
},
|
||||
Navigator: {
|
||||
single: true,
|
||||
attrs: ['target', 'type', 'params', 'active']
|
||||
},
|
||||
Sheet: {
|
||||
children: ['Section'],
|
||||
attrs: []
|
||||
},
|
||||
Section: {
|
||||
attrs: []
|
||||
},
|
||||
QRCode: {
|
||||
attrs: ['color', 'backgroundColor']
|
||||
},
|
||||
Flex: {
|
||||
attrs: []
|
||||
},
|
||||
LoadingProgress: {
|
||||
atomic: true,
|
||||
attrs: ['color']
|
||||
},
|
||||
NavigationView: {
|
||||
attrs: []
|
||||
},
|
||||
Scroll: {
|
||||
attrs: [
|
||||
'scrollable', 'onScroll', 'onScrollEdge', 'onScrollEnd', 'scrollBar', 'scrollBarColor',
|
||||
'scrollBarWidth', 'edgeEffect'
|
||||
]
|
||||
},
|
||||
Shape: {
|
||||
children: ['Rect', 'Path', 'Circle', 'Ellipse', 'Shape', 'Polyline', 'Polygon', 'Image', 'Text'],
|
||||
attrs: [
|
||||
'stroke', 'fill', 'strokeDashOffset', 'strokeLineCap',
|
||||
'strokeLineJoin', 'strokeMiterLimit', 'strokeOpacity',
|
||||
'fillOpacity', 'strokeWidth', 'antiAlias', 'strokeDashArray',
|
||||
'viewPort'
|
||||
]
|
||||
},
|
||||
Rect: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'radiusWidth', 'radiusHeight', 'radius'
|
||||
]
|
||||
},
|
||||
Path: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'commands'
|
||||
]
|
||||
},
|
||||
Circle: {
|
||||
atomic: true
|
||||
},
|
||||
Ellipse: {
|
||||
atomic: true
|
||||
},
|
||||
Camera: {
|
||||
atomic: true,
|
||||
attrs: ['devicePosition']
|
||||
},
|
||||
Tabs: {
|
||||
children: ['TabContent'],
|
||||
attrs: [
|
||||
'initialIndex', 'vertical', 'scrollable', 'barMode', 'barWidth', 'barHeight', 'animationDuration',
|
||||
'onChange'
|
||||
]
|
||||
},
|
||||
TabContent: {
|
||||
parents: ['Tabs'],
|
||||
attrs: ['tabBar']
|
||||
},
|
||||
PageTransitionEnter: {
|
||||
atomic: true,
|
||||
attrs: ['onEnter']
|
||||
},
|
||||
PageTransitionExit: {
|
||||
atomic: true,
|
||||
attrs: ['onExit']
|
||||
},
|
||||
Blank: {
|
||||
parents: ['Row', 'Column'],
|
||||
automic: true,
|
||||
attrs: ['color']
|
||||
},
|
||||
RowSplit: {
|
||||
attrs: ['resizeable']
|
||||
},
|
||||
ColumnSplit: {
|
||||
attrs: ['resizeable']
|
||||
},
|
||||
Toggle: {
|
||||
attrs: ['onChange', 'selectedColor', 'swithPointStyle']
|
||||
},
|
||||
AlertDialog: {
|
||||
attrs: ['show']
|
||||
},
|
||||
Video: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'muted', 'autoPlay', 'controls', 'loop', 'objectFit', 'onSeeking', 'onFullscreenChange',
|
||||
'onStart', 'onPause', 'onPrepared', 'onFinish', 'onSeeked', 'onUpdate', 'onError'
|
||||
]
|
||||
},
|
||||
AbilityComponent: {
|
||||
attrs: ['onReady', 'onDestroy', 'onAbilityCreated', 'onAbilityMoveToFront', 'onAbilityWillRemove']
|
||||
},
|
||||
AlphabetIndexer: {
|
||||
attrs: [
|
||||
'onSelected', 'selectedColor', 'popupColor', 'selectedBackgroundColor', 'popupBackground', 'usingPopup',
|
||||
'selectedFont', 'popupFont', 'iteamSize', 'font', 'color', 'alignStyle'
|
||||
]
|
||||
},
|
||||
Radio: {
|
||||
atomic: true,
|
||||
attrs: ['checked', 'onChange']
|
||||
},
|
||||
GeometryView: {
|
||||
atomic: true
|
||||
},
|
||||
DataPanel: {
|
||||
atomic: false,
|
||||
attrs: ['closeEffect']
|
||||
},
|
||||
Badge: {
|
||||
atomics: true,
|
||||
attrs: []
|
||||
},
|
||||
Line: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'startPoint','endPoint'
|
||||
]
|
||||
},
|
||||
Polygon: {
|
||||
atomic: true,
|
||||
attrs: ['points']
|
||||
},
|
||||
Polyline: {
|
||||
atomic: true,
|
||||
attrs: ['points']
|
||||
},
|
||||
};
|
||||
|
||||
const COMMON_ATTRS: Set<string> = new Set([
|
||||
'width', 'height', 'size', 'constraintSize', 'layoutPriority', 'layoutWeight',
|
||||
'padding', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom',
|
||||
'margin', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom',
|
||||
'border', 'borderStyle', 'borderWidth', 'borderColor', 'borderRadius',
|
||||
'backgroundColor', 'backgroundImage', 'backgroundImageSize', 'backgroundImagePosition', 'opacity', 'animation',
|
||||
'transition', 'navigationTitle', 'navigationSubTitle', 'hideNavigationBar', 'hideNavigationBackButton',
|
||||
'toolBar', 'hideToolBar', 'onClick', 'onTouch', 'onKeyEvent',
|
||||
'blur', 'backdropBlur', 'windowBlur', 'translate', 'rotate', 'scale', 'transform',
|
||||
'onAppear', 'onDisAppear', 'visibility', 'flexBasis', 'flexShrink', 'flexGrow', 'alignSelf',
|
||||
'useAlign', 'zIndex', 'sharedTransition', 'direction', 'align', 'position', 'markAnchor', 'offset',
|
||||
'enabled', 'aspectRatio', 'displayPriority', 'onDrag', 'onDragEnter', 'onDragMove', 'onDragLeave', 'onDrop',
|
||||
'overlay', 'linearGradient', 'sweepGradient', 'radialGradient', 'gridOffset', 'gridSpan', 'useSizeType',
|
||||
'motionPath', 'clip', 'shadow', 'mask', 'accessibilityGroup', 'accessibilityText', 'accessibilityDescription',
|
||||
'accessibilityImportance', 'onAccessibility'
|
||||
]);
|
||||
const TRANSITION_COMMON_ATTRS: Set<string> = new Set([
|
||||
'slide', 'translate', 'scale', 'opacity'
|
||||
]);
|
||||
export const GESTURE_ATTRS: Set<string> = new Set([
|
||||
'gesture', 'parallelGesture', 'priorityGesture'
|
||||
]);
|
||||
|
||||
export const forbiddenUseStateType: Set<string> = new Set(['Scroller', 'SwiperScroller']);
|
||||
|
||||
export const INNER_COMPONENT_NAMES: Set<string> = new Set();
|
||||
export const BUILDIN_CONTAINER_COMPONENT: Set<string> = new Set();
|
||||
export const BUILDIN_STYLE_NAMES: Set<string> = new Set([
|
||||
...COMMON_ATTRS, ...GESTURE_ATTRS, ...TRANSITION_COMMON_ATTRS
|
||||
]);
|
||||
export const AUTOMIC_COMPONENT: Set<string> = new Set();
|
||||
export const SINGLE_CHILD_COMPONENT: Set<string> = new Set();
|
||||
export const SPECIFIC_CHILD_COMPONENT: Map<string, Set<string>> = new Map();
|
||||
export const GESTURE_TYPE_NAMES: Set<string> = new Set([
|
||||
'TapGesture', 'LongPressGesture', 'PanGesture', 'PinchGesture', 'RotationGesture', 'GestureGroup'
|
||||
]);
|
||||
export const CUSTOM_BUILDER_METHOD: Set<string> = new Set();
|
||||
|
||||
export interface ExtendParamterInterfance {
|
||||
attribute: string,
|
||||
parameterCount: number
|
||||
}
|
||||
export const EXTEND_ATTRIBUTE: Map<string, Set<ExtendParamterInterfance>> = new Map();
|
||||
|
||||
(function initComponent() {
|
||||
Object.keys(COMPONENT_MAP).forEach((componentName) => {
|
||||
INNER_COMPONENT_NAMES.add(componentName);
|
||||
if (!COMPONENT_MAP[componentName].atomic) {
|
||||
BUILDIN_CONTAINER_COMPONENT.add(componentName);
|
||||
} else {
|
||||
AUTOMIC_COMPONENT.add(componentName);
|
||||
}
|
||||
if (COMPONENT_MAP[componentName].single) {
|
||||
SINGLE_CHILD_COMPONENT.add(componentName);
|
||||
}
|
||||
if (COMPONENT_MAP[componentName].children) {
|
||||
SPECIFIC_CHILD_COMPONENT.set(componentName,
|
||||
new Set([...COMPONENT_MAP[componentName].children]));
|
||||
}
|
||||
if (COMPONENT_MAP[componentName].attrs && COMPONENT_MAP[componentName].attrs.length) {
|
||||
COMPONENT_MAP[componentName].attrs.forEach((item) => {
|
||||
BUILDIN_STYLE_NAMES.add(item);
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
export const COMPONENT_MAP: any = {
|
||||
FormComponent: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'size', 'moduleName', 'dimension', 'allowUpdate', 'visibility',
|
||||
'onAcquired', 'onError', 'onRouter'
|
||||
]
|
||||
},
|
||||
Image: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'alt', 'objectFit', 'matchTextDirection', 'fitOriginalSize', 'objectRepeat', 'renderMode', 'interpolation',
|
||||
'onComplete', 'onError', 'onFinish', 'sourceSize', 'fillColor', 'autoResize'
|
||||
]
|
||||
},
|
||||
ImageAnimator: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'images', 'state', 'duration', 'reverse', 'fixedSize', 'preDecode', 'fillMode', 'iterations', 'onStart',
|
||||
'onPause', 'onRepeat', 'onCancel', 'onFinish'
|
||||
]
|
||||
},
|
||||
Animator: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'state', 'duration', 'curve', 'delay', 'fillMode', 'iterations', 'playMode', 'motion', 'onStart',
|
||||
'onPause', 'onRepeat', 'onCancel', 'onFinish', 'onFrame'
|
||||
]
|
||||
},
|
||||
Refresh: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'refreshing', 'offset', 'friction',
|
||||
'onStateChange', 'onRefreshing'
|
||||
]
|
||||
},
|
||||
SpringProp: {
|
||||
atomic: true
|
||||
},
|
||||
SpringMotion: {
|
||||
atomic: true
|
||||
},
|
||||
FrictionMotion: {
|
||||
atomic: true
|
||||
},
|
||||
ScrollMotion: {
|
||||
atomic: true
|
||||
},
|
||||
Text: {
|
||||
children: ['Span'],
|
||||
attrs: [
|
||||
'fontColor', 'fontSize', 'fontStyle', 'fontWeight', 'textAlign', 'lineHeight', 'textOverflow', 'maxLines',
|
||||
'decoration', 'letterSpacing', 'textCase', 'baselineOffset', 'minFontSize', 'maxFontSize'
|
||||
]
|
||||
},
|
||||
TextPicker: {
|
||||
atomic: true,
|
||||
attrs: ['defaultPickerItemHeight', 'onAccept', 'onCancel', 'onChange']
|
||||
},
|
||||
DatePicker: {
|
||||
atomic: true,
|
||||
attrs: ['lunar', 'onChange', 'useMilitaryTime']
|
||||
},
|
||||
Span: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'fontColor', 'fontSize', 'fontStyle', 'fontFamily', 'fontWeight', 'decoration', 'letterSpacing', 'textCase'
|
||||
]
|
||||
},
|
||||
Button: {
|
||||
attrs: ['type', 'stateEffect', 'fontColor', 'fontSize', 'fontWeight']
|
||||
},
|
||||
Divider: {
|
||||
atomic: true,
|
||||
attrs: ['color', 'vertical', 'strokeWidth', 'lineCap']
|
||||
},
|
||||
Piece: {
|
||||
atomic: true,
|
||||
attrs: ['iconPosition']
|
||||
},
|
||||
Slider: {
|
||||
atomic: true,
|
||||
attrs: ['blockColor', 'trackColor', 'selectedColor', 'minLabel','maxLabel', 'showSteps', 'showTips', 'onChange']
|
||||
},
|
||||
Counter: {
|
||||
attrs: [
|
||||
'onStateChange', 'onInc',
|
||||
'onDec', 'height', 'width'
|
||||
]
|
||||
},
|
||||
Row: {
|
||||
attrs: ['alignItems']
|
||||
},
|
||||
Column: {
|
||||
attrs: ['alignItems']
|
||||
},
|
||||
Stack: {
|
||||
attrs: ['alignContent']
|
||||
},
|
||||
List: {
|
||||
children: ['ListItem', 'Section'],
|
||||
attrs: [
|
||||
'listDirection', 'scrollBar', 'edgeEffect', 'divider', 'editMode', 'cachedCount', 'chainAnimation',
|
||||
'onScroll', 'onReachStart', 'onReachEnd', 'onScrollStop', 'onItemDelete', 'onItemMove'
|
||||
]
|
||||
},
|
||||
ListItem: {
|
||||
parents: ['List'],
|
||||
single: true,
|
||||
attrs: ['sticky', 'editable']
|
||||
},
|
||||
Grid: {
|
||||
children: ['GridItem'],
|
||||
attrs: ['columnsTemplate', 'rowsTemplate', 'columnsGap', 'rowsGap', 'scrollBar', 'scrollBarWidth', 'scrollBarColor']
|
||||
},
|
||||
GridItem: {
|
||||
parents: ['Grid'],
|
||||
single: true,
|
||||
attrs: ['rowStart', 'rowEnd', 'columnStart', 'columnEnd', 'forceRebuild']
|
||||
},
|
||||
GridContainer: {
|
||||
attrs: ['columns', 'sizeType', 'gutter', 'margin']
|
||||
},
|
||||
Hyperlink: {
|
||||
attrs: ['color']
|
||||
},
|
||||
Swiper: {
|
||||
attrs: [
|
||||
'index', 'autoPlay', 'interval', 'indicator',
|
||||
'loop', 'duration', 'vertical', 'itemSpace', 'displayMode', 'onChange'
|
||||
]
|
||||
},
|
||||
Rating: {
|
||||
attrs: ['stars', 'stepSize', 'starStyle', 'onChange']
|
||||
},
|
||||
Calendar: {
|
||||
attrs: [
|
||||
'date', 'showLunar', 'startOfWeek', 'offDays', 'onSelectChange', 'onRequestData',
|
||||
'currentData', 'preData', 'nextData', 'needSlide', 'showHoliday', 'direction',
|
||||
'currentDayStyle', 'nonCurrentDayStyle', 'todayStyle', 'weekStyle', 'workStateStyle'
|
||||
]
|
||||
},
|
||||
Panel: {
|
||||
attrs: [
|
||||
'type', 'mode', 'dragBar', 'fullHeight',
|
||||
'halfHeight', 'miniHeight', 'show', 'onChange'
|
||||
]
|
||||
},
|
||||
Navigator: {
|
||||
single: true,
|
||||
attrs: ['target', 'type', 'params', 'active']
|
||||
},
|
||||
Sheet: {
|
||||
children: ['Section'],
|
||||
attrs: []
|
||||
},
|
||||
Section: {
|
||||
attrs: []
|
||||
},
|
||||
QRCode: {
|
||||
attrs: ['color', 'backgroundColor']
|
||||
},
|
||||
Flex: {
|
||||
attrs: []
|
||||
},
|
||||
LoadingProgress: {
|
||||
atomic: true,
|
||||
attrs: ['color']
|
||||
},
|
||||
NavigationView: {
|
||||
attrs: []
|
||||
},
|
||||
Scroll: {
|
||||
attrs: [
|
||||
'scrollable', 'onScroll', 'onScrollEdge', 'onScrollEnd', 'scrollBar', 'scrollBarColor',
|
||||
'scrollBarWidth', 'edgeEffect'
|
||||
]
|
||||
},
|
||||
Shape: {
|
||||
children: ['Rect', 'Path', 'Circle', 'Ellipse', 'Shape', 'Polyline', 'Polygon', 'Image', 'Text'],
|
||||
attrs: [
|
||||
'stroke', 'fill', 'strokeDashOffset', 'strokeLineCap',
|
||||
'strokeLineJoin', 'strokeMiterLimit', 'strokeOpacity',
|
||||
'fillOpacity', 'strokeWidth', 'antiAlias', 'strokeDashArray',
|
||||
'viewPort'
|
||||
]
|
||||
},
|
||||
Progress: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'value', 'color', 'cricularStyle'
|
||||
]
|
||||
},
|
||||
Rect: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'radiusWidth', 'radiusHeight', 'radius'
|
||||
]
|
||||
},
|
||||
Path: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'commands'
|
||||
]
|
||||
},
|
||||
Circle: {
|
||||
atomic: true
|
||||
},
|
||||
Ellipse: {
|
||||
atomic: true
|
||||
},
|
||||
Camera: {
|
||||
atomic: true,
|
||||
attrs: ['devicePosition']
|
||||
},
|
||||
Tabs: {
|
||||
children: ['TabContent'],
|
||||
attrs: [
|
||||
'vertical', 'scrollable', 'barMode', 'barWidth', 'barHeight', 'animationDuration',
|
||||
'onChange'
|
||||
]
|
||||
},
|
||||
TabContent: {
|
||||
parents: ['Tabs'],
|
||||
attrs: ['tabBar']
|
||||
},
|
||||
PageTransitionEnter: {
|
||||
atomic: true,
|
||||
attrs: ['onEnter']
|
||||
},
|
||||
PageTransitionExit: {
|
||||
atomic: true,
|
||||
attrs: ['onExit']
|
||||
},
|
||||
Blank: {
|
||||
parents: ['Row', 'Column'],
|
||||
automic: true,
|
||||
attrs: ['color']
|
||||
},
|
||||
RowSplit: {
|
||||
attrs: ['resizeable']
|
||||
},
|
||||
ColumnSplit: {
|
||||
attrs: ['resizeable']
|
||||
},
|
||||
Toggle: {
|
||||
attrs: ['onChange', 'selectedColor', 'swithPointStyle']
|
||||
},
|
||||
AlertDialog: {
|
||||
attrs: ['show']
|
||||
},
|
||||
ActionSheet: {
|
||||
attrs: ['show']
|
||||
},
|
||||
Video: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'muted', 'autoPlay', 'controls', 'loop', 'objectFit', 'onSeeking', 'onFullscreenChange',
|
||||
'onStart', 'onPause', 'onPrepared', 'onFinish', 'onSeeked', 'onUpdate', 'onError'
|
||||
]
|
||||
},
|
||||
AbilityComponent: {
|
||||
attrs: ['onReady', 'onDestroy', 'onAbilityCreated', 'onAbilityMoveToFront', 'onAbilityWillRemove']
|
||||
},
|
||||
AlphabetIndexer: {
|
||||
attrs: [
|
||||
'onSelected', 'selectedColor', 'popupColor', 'selectedBackgroundColor', 'popupBackground', 'usingPopup',
|
||||
'selectedFont', 'popupFont', 'itemSize', 'font', 'color', 'alignStyle'
|
||||
]
|
||||
},
|
||||
Radio: {
|
||||
atomic: true,
|
||||
attrs: ['checked', 'onChange']
|
||||
},
|
||||
GeometryView: {
|
||||
atomic: true
|
||||
},
|
||||
DataPanel: {
|
||||
atomic: false,
|
||||
attrs: ['closeEffect']
|
||||
},
|
||||
Badge: {
|
||||
atomics: true,
|
||||
attrs: []
|
||||
},
|
||||
Line: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'startPoint','endPoint'
|
||||
]
|
||||
},
|
||||
Polygon: {
|
||||
atomic: true,
|
||||
attrs: ['points']
|
||||
},
|
||||
Polyline: {
|
||||
atomic: true,
|
||||
attrs: ['points']
|
||||
},
|
||||
Gauge: {
|
||||
atomic: true,
|
||||
attrs: ['value', 'startAngle', 'endAngle', 'colors', 'strokeWidth', 'labelTextConfig', 'labelColorConfig']
|
||||
},
|
||||
TextArea: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'placeholderColor', 'placeholderFont', 'textAlign', 'caretColor', 'correction', 'onChange'
|
||||
]
|
||||
},
|
||||
TextInput: {
|
||||
atomic: true,
|
||||
attrs: [
|
||||
'textInputType', 'placeholderColor', 'placeholderFont', 'textInputAction', 'inputFilter', 'caretColor',
|
||||
'correction', 'onEditChanged', 'onSubmit', 'onChange'
|
||||
]
|
||||
},
|
||||
Marquee: {
|
||||
atomic: true,
|
||||
attrs: ['onStart', 'onBounce', 'onFinish']
|
||||
},
|
||||
Menu: {
|
||||
children: ['Option'],
|
||||
attrs: ['show', 'showPosition'],
|
||||
},
|
||||
Option: {
|
||||
parents: ['Menu'],
|
||||
attrs: [],
|
||||
},
|
||||
};
|
||||
|
||||
const COMMON_ATTRS: Set<string> = new Set([
|
||||
'width', 'height', 'size', 'constraintSize', 'layoutPriority', 'layoutWeight',
|
||||
'padding', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom',
|
||||
'margin', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom',
|
||||
'border', 'borderStyle', 'borderWidth', 'borderColor', 'borderRadius',
|
||||
'backgroundColor', 'backgroundImage', 'backgroundImageSize', 'backgroundImagePosition', 'opacity', 'animation', 'transition',
|
||||
'navigationTitle', 'navigationSubTitle', 'hideNavigationBar', 'hideNavigationBackButton',
|
||||
'toolBar', 'hideToolBar', 'onClick', 'onTouch', 'onKeyEvent', 'onHover',
|
||||
'blur', 'backdropBlur', 'windowBlur', 'translate', 'rotate', 'scale', 'transform',
|
||||
'onAppear', 'onDisAppear', 'visibility', 'flexBasis', 'flexShrink', 'flexGrow', 'alignSelf',
|
||||
'useAlign', 'zIndex', 'sharedTransition', 'direction', 'align', 'position', 'markAnchor', 'offset',
|
||||
'enabled', 'aspectRatio', 'displayPriority', 'onDrag', 'onDragEnter', 'onDragMove', 'onDragLeave', 'onDrop',
|
||||
'overlay', 'linearGradient', 'sweepGradient', 'radialGradient', 'gridOffset', 'gridSpan', 'useSizeType',
|
||||
'motionPath', 'clip', 'shadow', 'mask', 'accessibilityGroup', 'accessibilityText', 'accessibilityDescription',
|
||||
'accessibilityImportance', 'onAccessibility', 'grayscale', 'brightness', 'contrast', 'saturate', 'geometryTransition',
|
||||
'bindPopup', 'colorBlend', 'invert', 'sepia', 'hueRotate'
|
||||
]);
|
||||
const TRANSITION_COMMON_ATTRS: Set<string> = new Set([
|
||||
'slide', 'translate', 'scale', 'opacity'
|
||||
]);
|
||||
export const GESTURE_ATTRS: Set<string> = new Set([
|
||||
'gesture', 'parallelGesture', 'priorityGesture'
|
||||
]);
|
||||
|
||||
export const forbiddenUseStateType: Set<string> = new Set(['Scroller', 'SwiperScroller']);
|
||||
|
||||
export const INNER_COMPONENT_NAMES: Set<string> = new Set();
|
||||
export const BUILDIN_CONTAINER_COMPONENT: Set<string> = new Set();
|
||||
export const BUILDIN_STYLE_NAMES: Set<string> = new Set([
|
||||
...COMMON_ATTRS, ...GESTURE_ATTRS, ...TRANSITION_COMMON_ATTRS
|
||||
]);
|
||||
export const AUTOMIC_COMPONENT: Set<string> = new Set();
|
||||
export const SINGLE_CHILD_COMPONENT: Set<string> = new Set();
|
||||
export const SPECIFIC_CHILD_COMPONENT: Map<string, Set<string>> = new Map();
|
||||
export const GESTURE_TYPE_NAMES: Set<string> = new Set([
|
||||
'TapGesture', 'LongPressGesture', 'PanGesture', 'PinchGesture', 'RotationGesture', 'GestureGroup'
|
||||
]);
|
||||
export const CUSTOM_BUILDER_METHOD: Set<string> = new Set();
|
||||
|
||||
export interface ExtendParamterInterfance {
|
||||
attribute: string,
|
||||
parameterCount: number
|
||||
}
|
||||
export const EXTEND_ATTRIBUTE: Map<string, Set<ExtendParamterInterfance>> = new Map();
|
||||
|
||||
export const JS_BIND_COMPONENTS: Set<string> = new Set([
|
||||
...GESTURE_TYPE_NAMES, 'Gesture',
|
||||
'PanGestureOption', 'CustomDialogController', 'Storage', 'Scroller', 'SwiperController',
|
||||
'TabsController', 'CalendarController', 'AbilityController', 'VideoController'
|
||||
]);
|
||||
|
||||
(function initComponent() {
|
||||
Object.keys(COMPONENT_MAP).forEach((componentName) => {
|
||||
INNER_COMPONENT_NAMES.add(componentName);
|
||||
JS_BIND_COMPONENTS.add(componentName);
|
||||
if (!COMPONENT_MAP[componentName].atomic) {
|
||||
BUILDIN_CONTAINER_COMPONENT.add(componentName);
|
||||
} else {
|
||||
AUTOMIC_COMPONENT.add(componentName);
|
||||
}
|
||||
if (COMPONENT_MAP[componentName].single) {
|
||||
SINGLE_CHILD_COMPONENT.add(componentName);
|
||||
}
|
||||
if (COMPONENT_MAP[componentName].children) {
|
||||
SPECIFIC_CHILD_COMPONENT.set(componentName,
|
||||
new Set([...COMPONENT_MAP[componentName].children]));
|
||||
}
|
||||
if (COMPONENT_MAP[componentName].attrs && COMPONENT_MAP[componentName].attrs.length) {
|
||||
COMPONENT_MAP[componentName].attrs.forEach((item) => {
|
||||
BUILDIN_STYLE_NAMES.add(item);
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
+109
-109
@@ -1,109 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 program = require('commander');
|
||||
|
||||
program.parse(process.argv);
|
||||
let name:string = 'HelloAce';
|
||||
let appID:string = 'ace.helloworld';
|
||||
let appName:string = 'HelloAce';
|
||||
if (program.args && program.args[0]) {
|
||||
name = program.args[0];
|
||||
appID = program.args[0];
|
||||
appName = program.args[0];
|
||||
}
|
||||
|
||||
const regPath: RegExp = /[`~!@#$%^&*()_+<>?:"{},./;'[\]]/im;
|
||||
|
||||
/*
|
||||
* Create sample project and files.
|
||||
* @param dist {String}
|
||||
*/
|
||||
function createProject(dist: string) {
|
||||
const dist_ = dist.trim().split('/');
|
||||
if (dist_.length > 1 || regPath.test(dist)) {
|
||||
return console.error(
|
||||
'ERROR: The project name cannot be a path nor contain any special symbol.\n' +
|
||||
"NOTE: To create the template project, run 'npm run create' in the root directory.\n" +
|
||||
"NOTE: To customize the project name, run 'npm run create <projectName>'.");
|
||||
}
|
||||
const appPath:string = dist + '/app.ets';
|
||||
const manifestPath:string = dist + '/manifest.json';
|
||||
const indexPath:string = dist + '/pages/index.ets';
|
||||
|
||||
const app:string = `export default {
|
||||
onCreate() {
|
||||
console.info('Application onCreate')
|
||||
},
|
||||
onDestroy() {
|
||||
console.info('Application onDestroy')
|
||||
},
|
||||
}`;
|
||||
|
||||
const manifest:string = `{
|
||||
"appID": "com.huawei.` + appID + `",
|
||||
"appName": "` + appName + `",
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": 1,
|
||||
"minPlatformVersion": "1.0.1",
|
||||
"pages": [
|
||||
"pages/index"
|
||||
],
|
||||
"window": {
|
||||
"designWidth": 750,
|
||||
"autoDesignWidth": false
|
||||
}
|
||||
}`;
|
||||
|
||||
const index:string = `@Entry
|
||||
@Component
|
||||
struct MyComponent {
|
||||
private value1: string = "hello world 1";
|
||||
private value2: string = "hello world 2";
|
||||
private value3: string = "hello world 3";
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text(this.value1);
|
||||
Text(this.value2);
|
||||
Text(this.value3);
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
fs.mkdir(dist + '/pages', { recursive: true }, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to create project directory.');
|
||||
}
|
||||
fs.writeFile(appPath, app, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to write app.ets.');
|
||||
}
|
||||
});
|
||||
fs.writeFile(manifestPath, manifest, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to write manifest.json.');
|
||||
}
|
||||
});
|
||||
fs.writeFile(indexPath, index, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to write index.ets.');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createProject(name);
|
||||
/*
|
||||
* Copyright (c) 2021 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 program = require('commander');
|
||||
|
||||
program.parse(process.argv);
|
||||
let name:string = 'HelloAce';
|
||||
let appID:string = 'ace.helloworld';
|
||||
let appName:string = 'HelloAce';
|
||||
if (program.args && program.args[0]) {
|
||||
name = program.args[0];
|
||||
appID = program.args[0];
|
||||
appName = program.args[0];
|
||||
}
|
||||
|
||||
const regPath: RegExp = /[`~!@#$%^&*()_+<>?:"{},./;'[\]]/im;
|
||||
|
||||
/*
|
||||
* Create sample project and files.
|
||||
* @param dist {String}
|
||||
*/
|
||||
function createProject(dist: string) {
|
||||
const dist_ = dist.trim().split('/');
|
||||
if (dist_.length > 1 || regPath.test(dist)) {
|
||||
return console.error(
|
||||
'ERROR: The project name cannot be a path nor contain any special symbol.\n' +
|
||||
"NOTE: To create the template project, run 'npm run create' in the root directory.\n" +
|
||||
"NOTE: To customize the project name, run 'npm run create <projectName>'.");
|
||||
}
|
||||
const appPath:string = dist + '/app.ets';
|
||||
const manifestPath:string = dist + '/manifest.json';
|
||||
const indexPath:string = dist + '/pages/index.ets';
|
||||
|
||||
const app:string = `export default {
|
||||
onCreate() {
|
||||
console.info('Application onCreate')
|
||||
},
|
||||
onDestroy() {
|
||||
console.info('Application onDestroy')
|
||||
},
|
||||
}`;
|
||||
|
||||
const manifest:string = `{
|
||||
"appID": "com.huawei.` + appID + `",
|
||||
"appName": "` + appName + `",
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": 1,
|
||||
"minPlatformVersion": "1.0.1",
|
||||
"pages": [
|
||||
"pages/index"
|
||||
],
|
||||
"window": {
|
||||
"designWidth": 750,
|
||||
"autoDesignWidth": false
|
||||
}
|
||||
}`;
|
||||
|
||||
const index:string = `@Entry
|
||||
@Component
|
||||
struct MyComponent {
|
||||
private value1: string = "hello world 1";
|
||||
private value2: string = "hello world 2";
|
||||
private value3: string = "hello world 3";
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text(this.value1);
|
||||
Text(this.value2);
|
||||
Text(this.value3);
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
fs.mkdir(dist + '/pages', { recursive: true }, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to create project directory.');
|
||||
}
|
||||
fs.writeFile(appPath, app, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to write app.ets.');
|
||||
}
|
||||
});
|
||||
fs.writeFile(manifestPath, manifest, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to write manifest.json.');
|
||||
}
|
||||
});
|
||||
fs.writeFile(indexPath, index, (err) => {
|
||||
if (err) {
|
||||
return console.error('ERROR: Failed to write index.ets.');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createProject(name);
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const NATIVE_MODULE: Set<string> = new Set(['app', 'router', 'curves', 'matrix4']);
|
||||
export const NATIVE_MODULE: Set<string> = new Set(
|
||||
['system.app', 'ohos.app', 'system.router', 'system.curves', 'ohos.curves', 'system.matrix4', 'ohos.matrix4']);
|
||||
export const SYSTEM_PLUGIN: string = 'system';
|
||||
export const OHOS_PLUGIN: string = 'ohos';
|
||||
|
||||
@@ -137,12 +138,22 @@ export const GESTURE_ENUM_VALUE_LOW: string = 'Low';
|
||||
export const GESTURE_ENUM_VALUE_PARALLEL: string = 'Parallel';
|
||||
|
||||
export const RESOURCE: string = '$r';
|
||||
export const RESOURCE_RAWFILE: string = '$rawfile';
|
||||
export const RESOURCE_NAME_ID: string = 'id';
|
||||
export const RESOURCE_NAME_TYPE: string = 'type';
|
||||
export const RESOURCE_NAME_PARAMS: string = 'params';
|
||||
export const RESOURCE_TYPE = {
|
||||
color: 10001,
|
||||
float: 10002,
|
||||
string: 10003,
|
||||
plural: 10004,
|
||||
media: 20000
|
||||
boolean: 10005,
|
||||
intarray: 10006,
|
||||
integer: 10007,
|
||||
pattern: 10008,
|
||||
strarray: 10009,
|
||||
media: 20000,
|
||||
rawfile: 30000
|
||||
};
|
||||
|
||||
export const WORKERS_DIR: string = 'workers';
|
||||
|
||||
+42
-38
@@ -1,38 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 {
|
||||
sourceReplace,
|
||||
validateUISyntax
|
||||
} from './validate_ui_syntax';
|
||||
import {
|
||||
LogInfo,
|
||||
emitLogInfo
|
||||
} from './utils';
|
||||
import { BUILD_ON } from './pre_define';
|
||||
|
||||
function preProcess(source: string): string {
|
||||
process.env.compiler = BUILD_ON;
|
||||
const newContent: string = sourceReplace(source);
|
||||
const log: LogInfo[] =
|
||||
validateUISyntax(source, newContent, this.resourcePath, this.resourceQuery);
|
||||
if (log.length) {
|
||||
emitLogInfo(this, log);
|
||||
}
|
||||
|
||||
return newContent;
|
||||
}
|
||||
|
||||
module.exports = preProcess;
|
||||
/*
|
||||
* Copyright (c) 2021 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 {
|
||||
sourceReplace,
|
||||
validateUISyntax,
|
||||
processSystemApi
|
||||
} from './validate_ui_syntax';
|
||||
import {
|
||||
LogInfo,
|
||||
emitLogInfo
|
||||
} from './utils';
|
||||
import { BUILD_ON } from './pre_define';
|
||||
|
||||
function preProcess(source: string): string {
|
||||
process.env.compiler = BUILD_ON;
|
||||
if (/\.ets$/.test(this.resourcePath)) {
|
||||
const newContent: string = sourceReplace(source);
|
||||
const log: LogInfo[] =
|
||||
validateUISyntax(source, newContent, this.resourcePath, this.resourceQuery);
|
||||
if (log.length) {
|
||||
emitLogInfo(this, log);
|
||||
}
|
||||
return newContent;
|
||||
} else {
|
||||
return processSystemApi(source);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = preProcess;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 path from 'path';
|
||||
|
||||
import { abilityConfig } from '../main';
|
||||
|
||||
module.exports = function processAbilityEntryFile(source: string): string {
|
||||
if (path.basename(this.resourcePath) === abilityConfig.abilityEntryFile) {
|
||||
source = source.replace(/exports\.default/, 'globalThis.exports.default');
|
||||
}
|
||||
return source;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,400 +1,400 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_BUILD_FUNCTION,
|
||||
BASE_COMPONENT_NAME,
|
||||
ATTRIBUTE_ANIMATETO,
|
||||
GLOBAL_CONTEXT,
|
||||
CREATE_CONSTRUCTOR_PARAMS,
|
||||
COMPONENT_CONSTRUCTOR_UPDATE_PARAMS,
|
||||
COMPONENT_CONSTRUCTOR_DELETE_PARAMS,
|
||||
CREATE_CONSTRUCTOR_SUBSCRIBER_MANAGER,
|
||||
ABOUT_TO_BE_DELETE_FUNCTION_ID,
|
||||
CREATE_CONSTRUCTOR_GET_FUNCTION,
|
||||
CREATE_CONSTRUCTOR_DELETE_FUNCTION,
|
||||
FOREACH_OBSERVED_OBJECT,
|
||||
FOREACH_GET_RAW_OBJECT,
|
||||
COMPONENT_BUILDER_DECORATOR,
|
||||
COMPONENT_TRANSITION_FUNCTION,
|
||||
COMPONENT_CREATE_FUNCTION,
|
||||
GEOMETRY_VIEW
|
||||
} from './pre_define';
|
||||
import {
|
||||
BUILDIN_STYLE_NAMES,
|
||||
CUSTOM_BUILDER_METHOD
|
||||
} from './component_map';
|
||||
import {
|
||||
componentCollection,
|
||||
linkCollection
|
||||
} from './validate_ui_syntax';
|
||||
import {
|
||||
addConstructor,
|
||||
getInitConstructor
|
||||
} from './process_component_constructor';
|
||||
import {
|
||||
ControllerType,
|
||||
processMemberVariableDecorators,
|
||||
UpdateResult,
|
||||
stateObjectCollection,
|
||||
curPropMap
|
||||
} from './process_component_member';
|
||||
import {
|
||||
processComponentBuild,
|
||||
processComponentBlock
|
||||
} from './process_component_build';
|
||||
import {
|
||||
LogType,
|
||||
LogInfo,
|
||||
hasDecorator
|
||||
} from './utils';
|
||||
|
||||
export function processComponentClass(node: ts.ClassDeclaration, context: ts.TransformationContext,
|
||||
log: LogInfo[], program: ts.Program): ts.ClassDeclaration {
|
||||
validateInheritClass(node, log);
|
||||
const memberNode: ts.ClassElement[] =
|
||||
processMembers(node.members, node.name, context, log, program);
|
||||
return ts.factory.updateClassDeclaration(node, undefined, node.modifiers, node.name,
|
||||
node.typeParameters, updateHeritageClauses(node), memberNode);
|
||||
}
|
||||
|
||||
type BuildCount = {
|
||||
count: number;
|
||||
}
|
||||
|
||||
function processMembers(members: ts.NodeArray<ts.ClassElement>, parentComponentName: ts.Identifier,
|
||||
context: ts.TransformationContext, log: LogInfo[], program: ts.Program): ts.ClassElement[] {
|
||||
const buildCount: BuildCount = { count: 0 };
|
||||
let ctorNode: any = getInitConstructor(members);
|
||||
const newMembers: ts.ClassElement[] = [];
|
||||
const watchMap: Map<string, ts.Node> = new Map();
|
||||
const updateParamsStatements: ts.Statement[] = [];
|
||||
const deleteParamsStatements: ts.PropertyDeclaration[] = [];
|
||||
const checkController: ControllerType =
|
||||
{ hasController: !componentCollection.customDialogs.has(parentComponentName.getText()) };
|
||||
members.forEach((item: ts.ClassElement) => {
|
||||
let updateItem: ts.ClassElement;
|
||||
if (ts.isPropertyDeclaration(item)) {
|
||||
const result: UpdateResult = processMemberVariableDecorators(parentComponentName, item,
|
||||
ctorNode, watchMap, checkController, log, program);
|
||||
if (result.isItemUpdate()) {
|
||||
updateItem = result.getProperity();
|
||||
} else {
|
||||
updateItem = item;
|
||||
}
|
||||
if (result.getVariableGet()) {
|
||||
newMembers.push(result.getVariableGet());
|
||||
}
|
||||
if (result.getVariableSet()) {
|
||||
newMembers.push(result.getVariableSet());
|
||||
}
|
||||
if (result.isCtorUpdate()) {
|
||||
ctorNode = result.getCtor();
|
||||
}
|
||||
if (result.getUpdateParams()) {
|
||||
updateParamsStatements.push(result.getUpdateParams());
|
||||
}
|
||||
if (result.isDeleteParams()) {
|
||||
deleteParamsStatements.push(item);
|
||||
}
|
||||
if (result.getControllerSet()) {
|
||||
newMembers.push(result.getControllerSet());
|
||||
}
|
||||
}
|
||||
if (ts.isMethodDeclaration(item) && item.name) {
|
||||
updateItem =
|
||||
processComponentMethod(item, parentComponentName, context, log, buildCount);
|
||||
}
|
||||
if (updateItem) {
|
||||
newMembers.push(updateItem);
|
||||
}
|
||||
});
|
||||
validateBuildMethodCount(buildCount, parentComponentName, log);
|
||||
validateHasController(parentComponentName, checkController, log);
|
||||
newMembers.unshift(addDeleteParamsFunc(deleteParamsStatements));
|
||||
newMembers.unshift(addUpdateParamsFunc(updateParamsStatements));
|
||||
newMembers.unshift(addConstructor(ctorNode, watchMap));
|
||||
return newMembers;
|
||||
}
|
||||
|
||||
function processComponentMethod(node: ts.MethodDeclaration, parentComponentName: ts.Identifier,
|
||||
context: ts.TransformationContext, log: LogInfo[], buildCount: BuildCount): ts.MethodDeclaration {
|
||||
let updateItem: ts.MethodDeclaration = node;
|
||||
const name: string = node.name.getText();
|
||||
if (name === COMPONENT_BUILD_FUNCTION) {
|
||||
buildCount.count = buildCount.count + 1;
|
||||
updateItem = processBuildMember(node, context, log);
|
||||
curPropMap.clear();
|
||||
} else if (node.body && ts.isBlock(node.body)) {
|
||||
if (name === COMPONENT_TRANSITION_FUNCTION) {
|
||||
updateItem = ts.factory.updateMethodDeclaration(node, node.decorators, node.modifiers,
|
||||
node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters,
|
||||
node.type, processComponentBlock(node.body, false, log, true));
|
||||
} else if (hasDecorator(node, COMPONENT_BUILDER_DECORATOR)) {
|
||||
CUSTOM_BUILDER_METHOD.add(name);
|
||||
updateItem = ts.factory.updateMethodDeclaration(node, undefined, node.modifiers,
|
||||
node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters,
|
||||
node.type, processComponentBlock(node.body, false, log));
|
||||
}
|
||||
}
|
||||
return ts.visitNode(updateItem, visitMethod);
|
||||
function visitMethod(node: ts.Node): ts.Node {
|
||||
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
||||
const name: string = node.expression.escapedText.toString();
|
||||
if (name === ATTRIBUTE_ANIMATETO) {
|
||||
node = processAnimateTo(node);
|
||||
}
|
||||
}
|
||||
return ts.visitEachChild(node, visitMethod, context);
|
||||
}
|
||||
}
|
||||
|
||||
function processBuildMember(node: ts.MethodDeclaration, context: ts.TransformationContext,
|
||||
log: LogInfo[]): ts.MethodDeclaration {
|
||||
if (node.parameters.length) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: `The 'build' method can not have arguments.`,
|
||||
pos: node.getStart()
|
||||
});
|
||||
}
|
||||
const buildNode: ts.MethodDeclaration = processComponentBuild(node, log);
|
||||
return ts.visitNode(buildNode, visitBuild);
|
||||
function visitBuild(node: ts.Node): ts.Node {
|
||||
if (isGeometryView(node)) {
|
||||
node = processGeometryView(node as ts.ExpressionStatement, log);
|
||||
}
|
||||
if (isProperty(node)) {
|
||||
node = createReference(node as ts.PropertyAssignment);
|
||||
}
|
||||
if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) &&
|
||||
stateObjectCollection.has(node.name.escapedText.toString()) && node.parent &&
|
||||
ts.isCallExpression(node.parent) && ts.isPropertyAccessExpression(node.parent.expression) &&
|
||||
node.parent.expression.name.escapedText.toString() !== FOREACH_GET_RAW_OBJECT) {
|
||||
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createIdentifier(FOREACH_OBSERVED_OBJECT),
|
||||
ts.factory.createIdentifier(FOREACH_GET_RAW_OBJECT)), undefined, [node]);
|
||||
}
|
||||
return ts.visitEachChild(node, visitBuild, context);
|
||||
}
|
||||
}
|
||||
|
||||
function isGeometryView(node: ts.Node): boolean {
|
||||
if (ts.isExpressionStatement(node) && ts.isCallExpression(node.expression)) {
|
||||
const call: ts.CallExpression = node.expression;
|
||||
const exp: ts.Expression = call.expression;
|
||||
const args: ts.NodeArray<ts.Expression> = call.arguments;
|
||||
if (ts.isPropertyAccessExpression(exp) && ts.isIdentifier(exp.expression) &&
|
||||
exp.expression.escapedText.toString() === GEOMETRY_VIEW && ts.isIdentifier(exp.name) &&
|
||||
exp.name.escapedText.toString() === COMPONENT_CREATE_FUNCTION && args && args.length === 1 &&
|
||||
(ts.isArrowFunction(args[0]) || ts.isFunctionExpression(args[0]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function processGeometryView(node: ts.ExpressionStatement,
|
||||
log: LogInfo[]): ts.ExpressionStatement {
|
||||
const exp: ts.CallExpression = node.expression as ts.CallExpression;
|
||||
const arg: ts.ArrowFunction | ts.FunctionExpression =
|
||||
exp.arguments[0] as ts.ArrowFunction | ts.FunctionExpression;
|
||||
return ts.factory.updateExpressionStatement(node, ts.factory.updateCallExpression(exp,
|
||||
exp.expression, undefined, [ts.factory.createArrowFunction(undefined, undefined, arg.parameters,
|
||||
undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
||||
getGeometryReaderFunctionBlock(arg, log))]));
|
||||
}
|
||||
|
||||
function getGeometryReaderFunctionBlock(node: ts.ArrowFunction | ts.FunctionExpression,
|
||||
log: LogInfo[]): ts.Block {
|
||||
let blockNode: ts.Block;
|
||||
if (ts.isBlock(node.body)) {
|
||||
blockNode = node.body;
|
||||
} else if (ts.isArrowFunction(node) && ts.isCallExpression(node.body)) {
|
||||
blockNode = ts.factory.createBlock([ts.factory.createExpressionStatement(node.body)]);
|
||||
}
|
||||
return processComponentBlock(blockNode, false, log);
|
||||
}
|
||||
|
||||
function updateHeritageClauses(node: ts.ClassDeclaration): ts.NodeArray<ts.HeritageClause> {
|
||||
const result:ts.HeritageClause[] = [];
|
||||
const heritageClause:ts.HeritageClause = ts.factory.createHeritageClause(
|
||||
ts.SyntaxKind.ExtendsKeyword,
|
||||
[ts.factory.createExpressionWithTypeArguments(
|
||||
ts.factory.createIdentifier(BASE_COMPONENT_NAME), [])]);
|
||||
|
||||
if (node.heritageClauses) {
|
||||
result.push(...node.heritageClauses);
|
||||
}
|
||||
result.push(heritageClause);
|
||||
|
||||
return ts.factory.createNodeArray(result);
|
||||
}
|
||||
|
||||
function isProperty(node: ts.Node): Boolean {
|
||||
if (node.parent && ts.isObjectLiteralExpression(node.parent) && node.parent.parent &&
|
||||
ts.isCallExpression(node.parent.parent) && ts.isPropertyAssignment(node) &&
|
||||
ts.isIdentifier(node.name)) {
|
||||
if (ts.isIdentifier(node.parent.parent.expression) &&
|
||||
!BUILDIN_STYLE_NAMES.has(node.parent.parent.expression.escapedText.toString()) &&
|
||||
componentCollection.customComponents.has(
|
||||
node.parent.parent.expression.escapedText.toString())) {
|
||||
return true;
|
||||
} else if (ts.isPropertyAccessExpression(node.parent.parent.expression) &&
|
||||
ts.isIdentifier(node.parent.parent.expression.expression) &&
|
||||
componentCollection.customComponents.has(
|
||||
node.parent.parent.expression.name.escapedText.toString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createReference(node: ts.PropertyAssignment): ts.PropertyAssignment {
|
||||
const linkParentComponent: string[] = getParentNode(node, linkCollection).slice(1);
|
||||
const propertyName: ts.Identifier = node.name as ts.Identifier;
|
||||
let initText: string;
|
||||
if (linkParentComponent && ts.isPropertyAssignment(node) && ts.isIdentifier(propertyName) &&
|
||||
linkParentComponent.includes(propertyName.escapedText.toString())) {
|
||||
const LINK_REG: RegExp = /^\$/g;
|
||||
const initExpression: ts.Expression = node.initializer;
|
||||
if (ts.isIdentifier(initExpression) &&
|
||||
initExpression.escapedText.toString().match(LINK_REG)) {
|
||||
if (linkParentComponent.includes(propertyName.escapedText.toString())) {
|
||||
initText = initExpression.escapedText.toString().replace(LINK_REG, '');
|
||||
}
|
||||
} else if (ts.isPropertyAccessExpression(initExpression) && initExpression.expression &&
|
||||
initExpression.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
||||
ts.isIdentifier(initExpression.name) &&
|
||||
initExpression.name.escapedText.toString().match(LINK_REG)) {
|
||||
if (linkParentComponent.includes(propertyName.escapedText.toString())) {
|
||||
initText = initExpression.name.escapedText.toString().replace(LINK_REG, '');
|
||||
}
|
||||
}
|
||||
if (initText) {
|
||||
node = addDoubleUnderline(node, propertyName, initText);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function addDoubleUnderline(node: ts.PropertyAssignment, propertyName: ts.Identifier,
|
||||
initText: string): ts.PropertyAssignment {
|
||||
return ts.factory.updatePropertyAssignment(node, propertyName,
|
||||
ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(`__${initText}`)));
|
||||
}
|
||||
|
||||
function getParentNode(node: ts.PropertyAssignment, collection: Map<string, Set<string>>): string[] {
|
||||
const grandparentNode: ts.NewExpression = node.parent.parent as ts.NewExpression;
|
||||
const grandparentExpression: ts.Identifier | ts.PropertyAccessExpression =
|
||||
grandparentNode.expression as ts.Identifier | ts.PropertyAccessExpression;
|
||||
let parentComponent: Set<string> = new Set();
|
||||
let grandparentName: string;
|
||||
if (ts.isIdentifier(grandparentExpression)) {
|
||||
grandparentName = grandparentExpression.escapedText.toString();
|
||||
parentComponent = collection.get(grandparentName);
|
||||
} else if (ts.isPropertyAccessExpression(grandparentExpression)) {
|
||||
grandparentName = grandparentExpression.name.escapedText.toString();
|
||||
parentComponent = collection.get(grandparentName);
|
||||
} else {
|
||||
// ignore
|
||||
}
|
||||
if (!parentComponent) {
|
||||
parentComponent = new Set();
|
||||
}
|
||||
return [grandparentName, ...parentComponent];
|
||||
}
|
||||
|
||||
function processAnimateTo(node: ts.CallExpression): ts.CallExpression {
|
||||
return ts.factory.updateCallExpression(node, ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createIdentifier(GLOBAL_CONTEXT), ts.factory.createIdentifier(ATTRIBUTE_ANIMATETO)),
|
||||
node.typeArguments, node.arguments);
|
||||
}
|
||||
|
||||
function addUpdateParamsFunc(statements: ts.Statement[]): ts.MethodDeclaration {
|
||||
return createParamsInitBlock(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS, statements);
|
||||
}
|
||||
|
||||
function addDeleteParamsFunc(statements: ts.PropertyDeclaration[]): ts.MethodDeclaration {
|
||||
const deleteStatements: ts.ExpressionStatement[] = [];
|
||||
statements.forEach((statement: ts.PropertyDeclaration) => {
|
||||
const name: ts.Identifier = statement.name as ts.Identifier;
|
||||
const paramsStatement: ts.ExpressionStatement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(`__${name.escapedText.toString()}`)),
|
||||
ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_DELETE_PARAMS)), undefined, []));
|
||||
deleteStatements.push(paramsStatement);
|
||||
});
|
||||
const defaultStatement: ts.ExpressionStatement =
|
||||
ts.factory.createExpressionStatement(ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_SUBSCRIBER_MANAGER),
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_GET_FUNCTION)), undefined, []),
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_DELETE_FUNCTION)),
|
||||
undefined, [ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createThis(), ts.factory.createIdentifier(ABOUT_TO_BE_DELETE_FUNCTION_ID)),
|
||||
undefined, [])]));
|
||||
deleteStatements.push(defaultStatement);
|
||||
const deleteParamsMethod: ts.MethodDeclaration =
|
||||
createParamsInitBlock(COMPONENT_CONSTRUCTOR_DELETE_PARAMS, deleteStatements);
|
||||
return deleteParamsMethod;
|
||||
}
|
||||
|
||||
function createParamsInitBlock(express: string, statements: ts.Statement[]): ts.MethodDeclaration {
|
||||
const methodDeclaration: ts.MethodDeclaration = ts.factory.createMethodDeclaration(undefined,
|
||||
undefined, undefined, ts.factory.createIdentifier(express), undefined, undefined,
|
||||
[ts.factory.createParameterDeclaration(undefined, undefined, undefined,
|
||||
express === COMPONENT_CONSTRUCTOR_DELETE_PARAMS ? undefined :
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_PARAMS), undefined, undefined, undefined)],
|
||||
undefined, ts.factory.createBlock(statements, true));
|
||||
return methodDeclaration;
|
||||
}
|
||||
|
||||
function validateBuildMethodCount(buildCount: BuildCount, parentComponentName: ts.Identifier,
|
||||
log: LogInfo[]): void {
|
||||
if (buildCount.count !== 1) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: `struct '${parentComponentName.getText()}' must be at least or at most one 'build' method.`,
|
||||
pos: parentComponentName.getStart()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function validateInheritClass(node: ts.ClassDeclaration, log: LogInfo[]): void {
|
||||
if (node.heritageClauses) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: '@Component should not be inherit other Classes.',
|
||||
pos: node.heritageClauses.pos
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function validateHasController(componentName: ts.Identifier, checkController: ControllerType,
|
||||
log: LogInfo[]): void {
|
||||
if (!checkController.hasController) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: '@CustomDialog component should have a property of the CustomDialogController type.',
|
||||
pos: componentName.pos
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2021 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_BUILD_FUNCTION,
|
||||
BASE_COMPONENT_NAME,
|
||||
ATTRIBUTE_ANIMATETO,
|
||||
GLOBAL_CONTEXT,
|
||||
CREATE_CONSTRUCTOR_PARAMS,
|
||||
COMPONENT_CONSTRUCTOR_UPDATE_PARAMS,
|
||||
COMPONENT_CONSTRUCTOR_DELETE_PARAMS,
|
||||
CREATE_CONSTRUCTOR_SUBSCRIBER_MANAGER,
|
||||
ABOUT_TO_BE_DELETE_FUNCTION_ID,
|
||||
CREATE_CONSTRUCTOR_GET_FUNCTION,
|
||||
CREATE_CONSTRUCTOR_DELETE_FUNCTION,
|
||||
FOREACH_OBSERVED_OBJECT,
|
||||
FOREACH_GET_RAW_OBJECT,
|
||||
COMPONENT_BUILDER_DECORATOR,
|
||||
COMPONENT_TRANSITION_FUNCTION,
|
||||
COMPONENT_CREATE_FUNCTION,
|
||||
GEOMETRY_VIEW
|
||||
} from './pre_define';
|
||||
import {
|
||||
BUILDIN_STYLE_NAMES,
|
||||
CUSTOM_BUILDER_METHOD
|
||||
} from './component_map';
|
||||
import {
|
||||
componentCollection,
|
||||
linkCollection
|
||||
} from './validate_ui_syntax';
|
||||
import {
|
||||
addConstructor,
|
||||
getInitConstructor
|
||||
} from './process_component_constructor';
|
||||
import {
|
||||
ControllerType,
|
||||
processMemberVariableDecorators,
|
||||
UpdateResult,
|
||||
stateObjectCollection,
|
||||
curPropMap
|
||||
} from './process_component_member';
|
||||
import {
|
||||
processComponentBuild,
|
||||
processComponentBlock
|
||||
} from './process_component_build';
|
||||
import {
|
||||
LogType,
|
||||
LogInfo,
|
||||
hasDecorator
|
||||
} from './utils';
|
||||
|
||||
export function processComponentClass(node: ts.ClassDeclaration, context: ts.TransformationContext,
|
||||
log: LogInfo[], program: ts.Program): ts.ClassDeclaration {
|
||||
validateInheritClass(node, log);
|
||||
const memberNode: ts.ClassElement[] =
|
||||
processMembers(node.members, node.name, context, log, program);
|
||||
return ts.factory.updateClassDeclaration(node, undefined, node.modifiers, node.name,
|
||||
node.typeParameters, updateHeritageClauses(node), memberNode);
|
||||
}
|
||||
|
||||
type BuildCount = {
|
||||
count: number;
|
||||
}
|
||||
|
||||
function processMembers(members: ts.NodeArray<ts.ClassElement>, parentComponentName: ts.Identifier,
|
||||
context: ts.TransformationContext, log: LogInfo[], program: ts.Program): ts.ClassElement[] {
|
||||
const buildCount: BuildCount = { count: 0 };
|
||||
let ctorNode: any = getInitConstructor(members);
|
||||
const newMembers: ts.ClassElement[] = [];
|
||||
const watchMap: Map<string, ts.Node> = new Map();
|
||||
const updateParamsStatements: ts.Statement[] = [];
|
||||
const deleteParamsStatements: ts.PropertyDeclaration[] = [];
|
||||
const checkController: ControllerType =
|
||||
{ hasController: !componentCollection.customDialogs.has(parentComponentName.getText()) };
|
||||
members.forEach((item: ts.ClassElement) => {
|
||||
let updateItem: ts.ClassElement;
|
||||
if (ts.isPropertyDeclaration(item)) {
|
||||
const result: UpdateResult = processMemberVariableDecorators(parentComponentName, item,
|
||||
ctorNode, watchMap, checkController, log, program);
|
||||
if (result.isItemUpdate()) {
|
||||
updateItem = result.getProperity();
|
||||
} else {
|
||||
updateItem = item;
|
||||
}
|
||||
if (result.getVariableGet()) {
|
||||
newMembers.push(result.getVariableGet());
|
||||
}
|
||||
if (result.getVariableSet()) {
|
||||
newMembers.push(result.getVariableSet());
|
||||
}
|
||||
if (result.isCtorUpdate()) {
|
||||
ctorNode = result.getCtor();
|
||||
}
|
||||
if (result.getUpdateParams()) {
|
||||
updateParamsStatements.push(result.getUpdateParams());
|
||||
}
|
||||
if (result.isDeleteParams()) {
|
||||
deleteParamsStatements.push(item);
|
||||
}
|
||||
if (result.getControllerSet()) {
|
||||
newMembers.push(result.getControllerSet());
|
||||
}
|
||||
}
|
||||
if (ts.isMethodDeclaration(item) && item.name) {
|
||||
updateItem =
|
||||
processComponentMethod(item, parentComponentName, context, log, buildCount);
|
||||
}
|
||||
if (updateItem) {
|
||||
newMembers.push(updateItem);
|
||||
}
|
||||
});
|
||||
validateBuildMethodCount(buildCount, parentComponentName, log);
|
||||
validateHasController(parentComponentName, checkController, log);
|
||||
newMembers.unshift(addDeleteParamsFunc(deleteParamsStatements));
|
||||
newMembers.unshift(addUpdateParamsFunc(updateParamsStatements));
|
||||
newMembers.unshift(addConstructor(ctorNode, watchMap));
|
||||
return newMembers;
|
||||
}
|
||||
|
||||
function processComponentMethod(node: ts.MethodDeclaration, parentComponentName: ts.Identifier,
|
||||
context: ts.TransformationContext, log: LogInfo[], buildCount: BuildCount): ts.MethodDeclaration {
|
||||
let updateItem: ts.MethodDeclaration = node;
|
||||
const name: string = node.name.getText();
|
||||
if (name === COMPONENT_BUILD_FUNCTION) {
|
||||
buildCount.count = buildCount.count + 1;
|
||||
updateItem = processBuildMember(node, context, log);
|
||||
curPropMap.clear();
|
||||
} else if (node.body && ts.isBlock(node.body)) {
|
||||
if (name === COMPONENT_TRANSITION_FUNCTION) {
|
||||
updateItem = ts.factory.updateMethodDeclaration(node, node.decorators, node.modifiers,
|
||||
node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters,
|
||||
node.type, processComponentBlock(node.body, false, log, true));
|
||||
} else if (hasDecorator(node, COMPONENT_BUILDER_DECORATOR)) {
|
||||
CUSTOM_BUILDER_METHOD.add(name);
|
||||
updateItem = ts.factory.updateMethodDeclaration(node, undefined, node.modifiers,
|
||||
node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters,
|
||||
node.type, processComponentBlock(node.body, false, log));
|
||||
}
|
||||
}
|
||||
return ts.visitNode(updateItem, visitMethod);
|
||||
function visitMethod(node: ts.Node): ts.Node {
|
||||
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
||||
const name: string = node.expression.escapedText.toString();
|
||||
if (name === ATTRIBUTE_ANIMATETO) {
|
||||
node = processAnimateTo(node);
|
||||
}
|
||||
}
|
||||
return ts.visitEachChild(node, visitMethod, context);
|
||||
}
|
||||
}
|
||||
|
||||
function processBuildMember(node: ts.MethodDeclaration, context: ts.TransformationContext,
|
||||
log: LogInfo[]): ts.MethodDeclaration {
|
||||
if (node.parameters.length) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: `The 'build' method can not have arguments.`,
|
||||
pos: node.getStart()
|
||||
});
|
||||
}
|
||||
const buildNode: ts.MethodDeclaration = processComponentBuild(node, log);
|
||||
return ts.visitNode(buildNode, visitBuild);
|
||||
function visitBuild(node: ts.Node): ts.Node {
|
||||
if (isGeometryView(node)) {
|
||||
node = processGeometryView(node as ts.ExpressionStatement, log);
|
||||
}
|
||||
if (isProperty(node)) {
|
||||
node = createReference(node as ts.PropertyAssignment);
|
||||
}
|
||||
if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name) &&
|
||||
stateObjectCollection.has(node.name.escapedText.toString()) && node.parent &&
|
||||
ts.isCallExpression(node.parent) && ts.isPropertyAccessExpression(node.parent.expression) &&
|
||||
node.parent.expression.name.escapedText.toString() !== FOREACH_GET_RAW_OBJECT) {
|
||||
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createIdentifier(FOREACH_OBSERVED_OBJECT),
|
||||
ts.factory.createIdentifier(FOREACH_GET_RAW_OBJECT)), undefined, [node]);
|
||||
}
|
||||
return ts.visitEachChild(node, visitBuild, context);
|
||||
}
|
||||
}
|
||||
|
||||
function isGeometryView(node: ts.Node): boolean {
|
||||
if (ts.isExpressionStatement(node) && ts.isCallExpression(node.expression)) {
|
||||
const call: ts.CallExpression = node.expression;
|
||||
const exp: ts.Expression = call.expression;
|
||||
const args: ts.NodeArray<ts.Expression> = call.arguments;
|
||||
if (ts.isPropertyAccessExpression(exp) && ts.isIdentifier(exp.expression) &&
|
||||
exp.expression.escapedText.toString() === GEOMETRY_VIEW && ts.isIdentifier(exp.name) &&
|
||||
exp.name.escapedText.toString() === COMPONENT_CREATE_FUNCTION && args && args.length === 1 &&
|
||||
(ts.isArrowFunction(args[0]) || ts.isFunctionExpression(args[0]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function processGeometryView(node: ts.ExpressionStatement,
|
||||
log: LogInfo[]): ts.ExpressionStatement {
|
||||
const exp: ts.CallExpression = node.expression as ts.CallExpression;
|
||||
const arg: ts.ArrowFunction | ts.FunctionExpression =
|
||||
exp.arguments[0] as ts.ArrowFunction | ts.FunctionExpression;
|
||||
return ts.factory.updateExpressionStatement(node, ts.factory.updateCallExpression(exp,
|
||||
exp.expression, undefined, [ts.factory.createArrowFunction(undefined, undefined, arg.parameters,
|
||||
undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
||||
getGeometryReaderFunctionBlock(arg, log))]));
|
||||
}
|
||||
|
||||
function getGeometryReaderFunctionBlock(node: ts.ArrowFunction | ts.FunctionExpression,
|
||||
log: LogInfo[]): ts.Block {
|
||||
let blockNode: ts.Block;
|
||||
if (ts.isBlock(node.body)) {
|
||||
blockNode = node.body;
|
||||
} else if (ts.isArrowFunction(node) && ts.isCallExpression(node.body)) {
|
||||
blockNode = ts.factory.createBlock([ts.factory.createExpressionStatement(node.body)]);
|
||||
}
|
||||
return processComponentBlock(blockNode, false, log);
|
||||
}
|
||||
|
||||
function updateHeritageClauses(node: ts.ClassDeclaration): ts.NodeArray<ts.HeritageClause> {
|
||||
const result:ts.HeritageClause[] = [];
|
||||
const heritageClause:ts.HeritageClause = ts.factory.createHeritageClause(
|
||||
ts.SyntaxKind.ExtendsKeyword,
|
||||
[ts.factory.createExpressionWithTypeArguments(
|
||||
ts.factory.createIdentifier(BASE_COMPONENT_NAME), [])]);
|
||||
|
||||
if (node.heritageClauses) {
|
||||
result.push(...node.heritageClauses);
|
||||
}
|
||||
result.push(heritageClause);
|
||||
|
||||
return ts.factory.createNodeArray(result);
|
||||
}
|
||||
|
||||
function isProperty(node: ts.Node): Boolean {
|
||||
if (node.parent && ts.isObjectLiteralExpression(node.parent) && node.parent.parent &&
|
||||
ts.isCallExpression(node.parent.parent) && ts.isPropertyAssignment(node) &&
|
||||
ts.isIdentifier(node.name)) {
|
||||
if (ts.isIdentifier(node.parent.parent.expression) &&
|
||||
!BUILDIN_STYLE_NAMES.has(node.parent.parent.expression.escapedText.toString()) &&
|
||||
componentCollection.customComponents.has(
|
||||
node.parent.parent.expression.escapedText.toString())) {
|
||||
return true;
|
||||
} else if (ts.isPropertyAccessExpression(node.parent.parent.expression) &&
|
||||
ts.isIdentifier(node.parent.parent.expression.expression) &&
|
||||
componentCollection.customComponents.has(
|
||||
node.parent.parent.expression.name.escapedText.toString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createReference(node: ts.PropertyAssignment): ts.PropertyAssignment {
|
||||
const linkParentComponent: string[] = getParentNode(node, linkCollection).slice(1);
|
||||
const propertyName: ts.Identifier = node.name as ts.Identifier;
|
||||
let initText: string;
|
||||
if (linkParentComponent && ts.isPropertyAssignment(node) && ts.isIdentifier(propertyName) &&
|
||||
linkParentComponent.includes(propertyName.escapedText.toString())) {
|
||||
const LINK_REG: RegExp = /^\$/g;
|
||||
const initExpression: ts.Expression = node.initializer;
|
||||
if (ts.isIdentifier(initExpression) &&
|
||||
initExpression.escapedText.toString().match(LINK_REG)) {
|
||||
if (linkParentComponent.includes(propertyName.escapedText.toString())) {
|
||||
initText = initExpression.escapedText.toString().replace(LINK_REG, '');
|
||||
}
|
||||
} else if (ts.isPropertyAccessExpression(initExpression) && initExpression.expression &&
|
||||
initExpression.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
||||
ts.isIdentifier(initExpression.name) &&
|
||||
initExpression.name.escapedText.toString().match(LINK_REG)) {
|
||||
if (linkParentComponent.includes(propertyName.escapedText.toString())) {
|
||||
initText = initExpression.name.escapedText.toString().replace(LINK_REG, '');
|
||||
}
|
||||
}
|
||||
if (initText) {
|
||||
node = addDoubleUnderline(node, propertyName, initText);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function addDoubleUnderline(node: ts.PropertyAssignment, propertyName: ts.Identifier,
|
||||
initText: string): ts.PropertyAssignment {
|
||||
return ts.factory.updatePropertyAssignment(node, propertyName,
|
||||
ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(`__${initText}`)));
|
||||
}
|
||||
|
||||
function getParentNode(node: ts.PropertyAssignment, collection: Map<string, Set<string>>): string[] {
|
||||
const grandparentNode: ts.NewExpression = node.parent.parent as ts.NewExpression;
|
||||
const grandparentExpression: ts.Identifier | ts.PropertyAccessExpression =
|
||||
grandparentNode.expression as ts.Identifier | ts.PropertyAccessExpression;
|
||||
let parentComponent: Set<string> = new Set();
|
||||
let grandparentName: string;
|
||||
if (ts.isIdentifier(grandparentExpression)) {
|
||||
grandparentName = grandparentExpression.escapedText.toString();
|
||||
parentComponent = collection.get(grandparentName);
|
||||
} else if (ts.isPropertyAccessExpression(grandparentExpression)) {
|
||||
grandparentName = grandparentExpression.name.escapedText.toString();
|
||||
parentComponent = collection.get(grandparentName);
|
||||
} else {
|
||||
// ignore
|
||||
}
|
||||
if (!parentComponent) {
|
||||
parentComponent = new Set();
|
||||
}
|
||||
return [grandparentName, ...parentComponent];
|
||||
}
|
||||
|
||||
function processAnimateTo(node: ts.CallExpression): ts.CallExpression {
|
||||
return ts.factory.updateCallExpression(node, ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createIdentifier(GLOBAL_CONTEXT), ts.factory.createIdentifier(ATTRIBUTE_ANIMATETO)),
|
||||
node.typeArguments, node.arguments);
|
||||
}
|
||||
|
||||
function addUpdateParamsFunc(statements: ts.Statement[]): ts.MethodDeclaration {
|
||||
return createParamsInitBlock(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS, statements);
|
||||
}
|
||||
|
||||
function addDeleteParamsFunc(statements: ts.PropertyDeclaration[]): ts.MethodDeclaration {
|
||||
const deleteStatements: ts.ExpressionStatement[] = [];
|
||||
statements.forEach((statement: ts.PropertyDeclaration) => {
|
||||
const name: ts.Identifier = statement.name as ts.Identifier;
|
||||
const paramsStatement: ts.ExpressionStatement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(`__${name.escapedText.toString()}`)),
|
||||
ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_DELETE_PARAMS)), undefined, []));
|
||||
deleteStatements.push(paramsStatement);
|
||||
});
|
||||
const defaultStatement: ts.ExpressionStatement =
|
||||
ts.factory.createExpressionStatement(ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_SUBSCRIBER_MANAGER),
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_GET_FUNCTION)), undefined, []),
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_DELETE_FUNCTION)),
|
||||
undefined, [ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createThis(), ts.factory.createIdentifier(ABOUT_TO_BE_DELETE_FUNCTION_ID)),
|
||||
undefined, [])]));
|
||||
deleteStatements.push(defaultStatement);
|
||||
const deleteParamsMethod: ts.MethodDeclaration =
|
||||
createParamsInitBlock(COMPONENT_CONSTRUCTOR_DELETE_PARAMS, deleteStatements);
|
||||
return deleteParamsMethod;
|
||||
}
|
||||
|
||||
function createParamsInitBlock(express: string, statements: ts.Statement[]): ts.MethodDeclaration {
|
||||
const methodDeclaration: ts.MethodDeclaration = ts.factory.createMethodDeclaration(undefined,
|
||||
undefined, undefined, ts.factory.createIdentifier(express), undefined, undefined,
|
||||
[ts.factory.createParameterDeclaration(undefined, undefined, undefined,
|
||||
express === COMPONENT_CONSTRUCTOR_DELETE_PARAMS ? undefined :
|
||||
ts.factory.createIdentifier(CREATE_CONSTRUCTOR_PARAMS), undefined, undefined, undefined)],
|
||||
undefined, ts.factory.createBlock(statements, true));
|
||||
return methodDeclaration;
|
||||
}
|
||||
|
||||
function validateBuildMethodCount(buildCount: BuildCount, parentComponentName: ts.Identifier,
|
||||
log: LogInfo[]): void {
|
||||
if (buildCount.count !== 1) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: `struct '${parentComponentName.getText()}' must be at least or at most one 'build' method.`,
|
||||
pos: parentComponentName.getStart()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function validateInheritClass(node: ts.ClassDeclaration, log: LogInfo[]): void {
|
||||
if (node.heritageClauses) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: '@Component should not be inherit other Classes.',
|
||||
pos: node.heritageClauses.pos
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function validateHasController(componentName: ts.Identifier, checkController: ControllerType,
|
||||
log: LogInfo[]): void {
|
||||
if (!checkController.hasController) {
|
||||
log.push({
|
||||
type: LogType.ERROR,
|
||||
message: '@CustomDialog component should have a property of the CustomDialogController type.',
|
||||
pos: componentName.pos
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_CONSTRUCTOR_ID,
|
||||
COMPONENT_CONSTRUCTOR_PARENT,
|
||||
COMPONENT_CONSTRUCTOR_PARAMS,
|
||||
COMPONENT_CONSTRUCTOR_UPDATE_PARAMS,
|
||||
COMPONENT_WATCH_FUNCTION
|
||||
} from './pre_define';
|
||||
|
||||
export function getInitConstructor(members: ts.NodeArray<ts.Node>): ts.ConstructorDeclaration {
|
||||
let ctorNode: any = members.find(item => {
|
||||
return ts.isConstructorDeclaration(item);
|
||||
});
|
||||
if (ctorNode) {
|
||||
ctorNode = updateConstructor(ctorNode, [], [], true);
|
||||
}
|
||||
return ctorNode;
|
||||
}
|
||||
|
||||
export function updateConstructor(ctorNode: ts.ConstructorDeclaration,
|
||||
para: ts.ParameterDeclaration[], addStatements: ts.Statement[],
|
||||
isSuper: boolean = false): ts.ConstructorDeclaration {
|
||||
let modifyPara: ts.ParameterDeclaration[];
|
||||
if (para && para.length) {
|
||||
modifyPara = Array.from(ctorNode.parameters);
|
||||
if (modifyPara) {
|
||||
modifyPara.push(...para);
|
||||
}
|
||||
}
|
||||
let modifyBody: ts.Statement[];
|
||||
if (addStatements && addStatements.length && ctorNode) {
|
||||
modifyBody = Array.from(ctorNode.body.statements);
|
||||
if (modifyBody) {
|
||||
if (isSuper) {
|
||||
modifyBody.unshift(...addStatements);
|
||||
} else {
|
||||
modifyBody.push(...addStatements);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ctorNode) {
|
||||
ctorNode = ts.factory.updateConstructorDeclaration(ctorNode, ctorNode.decorators,
|
||||
ctorNode.modifiers, modifyPara || ctorNode.parameters,
|
||||
ts.factory.createBlock(modifyBody || ctorNode.body.statements, true));
|
||||
}
|
||||
return ctorNode;
|
||||
}
|
||||
|
||||
export function addConstructor(ctorNode: any, watchMap: Map<string, ts.Node>)
|
||||
: ts.ConstructorDeclaration {
|
||||
const watchStatements: ts.ExpressionStatement[] = [];
|
||||
watchMap.forEach((value, key) => {
|
||||
const watchNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(COMPONENT_WATCH_FUNCTION)
|
||||
),
|
||||
undefined,
|
||||
[
|
||||
ts.factory.createStringLiteral(key),
|
||||
ts.isStringLiteral(value) ?
|
||||
ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(value.text)) : value as ts.PropertyAccessExpression
|
||||
]
|
||||
));
|
||||
watchStatements.push(watchNode);
|
||||
});
|
||||
const callSuperStatement: ts.Statement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(ts.factory.createSuper(), undefined,
|
||||
[ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID),
|
||||
ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)]));
|
||||
const updateWithValueParamsStatement: ts.Statement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createThis(), ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS)),
|
||||
undefined, [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARAMS)]));
|
||||
return updateConstructor(updateConstructor(ctorNode, [], [callSuperStatement], true), [],
|
||||
[updateWithValueParamsStatement, ...watchStatements], false);
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2021 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_CONSTRUCTOR_ID,
|
||||
COMPONENT_CONSTRUCTOR_PARENT,
|
||||
COMPONENT_CONSTRUCTOR_PARAMS,
|
||||
COMPONENT_CONSTRUCTOR_UPDATE_PARAMS,
|
||||
COMPONENT_WATCH_FUNCTION
|
||||
} from './pre_define';
|
||||
|
||||
export function getInitConstructor(members: ts.NodeArray<ts.Node>): ts.ConstructorDeclaration {
|
||||
let ctorNode: any = members.find(item => {
|
||||
return ts.isConstructorDeclaration(item);
|
||||
});
|
||||
if (ctorNode) {
|
||||
ctorNode = updateConstructor(ctorNode, [], [], true);
|
||||
}
|
||||
return ctorNode;
|
||||
}
|
||||
|
||||
export function updateConstructor(ctorNode: ts.ConstructorDeclaration,
|
||||
para: ts.ParameterDeclaration[], addStatements: ts.Statement[],
|
||||
isSuper: boolean = false): ts.ConstructorDeclaration {
|
||||
let modifyPara: ts.ParameterDeclaration[];
|
||||
if (para && para.length) {
|
||||
modifyPara = Array.from(ctorNode.parameters);
|
||||
if (modifyPara) {
|
||||
modifyPara.push(...para);
|
||||
}
|
||||
}
|
||||
let modifyBody: ts.Statement[];
|
||||
if (addStatements && addStatements.length && ctorNode) {
|
||||
modifyBody = Array.from(ctorNode.body.statements);
|
||||
if (modifyBody) {
|
||||
if (isSuper) {
|
||||
modifyBody.unshift(...addStatements);
|
||||
} else {
|
||||
modifyBody.push(...addStatements);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ctorNode) {
|
||||
ctorNode = ts.factory.updateConstructorDeclaration(ctorNode, ctorNode.decorators,
|
||||
ctorNode.modifiers, modifyPara || ctorNode.parameters,
|
||||
ts.factory.createBlock(modifyBody || ctorNode.body.statements, true));
|
||||
}
|
||||
return ctorNode;
|
||||
}
|
||||
|
||||
export function addConstructor(ctorNode: any, watchMap: Map<string, ts.Node>)
|
||||
: ts.ConstructorDeclaration {
|
||||
const watchStatements: ts.ExpressionStatement[] = [];
|
||||
watchMap.forEach((value, key) => {
|
||||
const watchNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(COMPONENT_WATCH_FUNCTION)
|
||||
),
|
||||
undefined,
|
||||
[
|
||||
ts.factory.createStringLiteral(key),
|
||||
ts.isStringLiteral(value) ?
|
||||
ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
|
||||
ts.factory.createIdentifier(value.text)) : value as ts.PropertyAccessExpression
|
||||
]
|
||||
));
|
||||
watchStatements.push(watchNode);
|
||||
});
|
||||
const callSuperStatement: ts.Statement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(ts.factory.createSuper(), undefined,
|
||||
[ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID),
|
||||
ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)]));
|
||||
const updateWithValueParamsStatement: ts.Statement = ts.factory.createExpressionStatement(
|
||||
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
||||
ts.factory.createThis(), ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS)),
|
||||
undefined, [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARAMS)]));
|
||||
return updateConstructor(updateConstructor(ctorNode, [], [callSuperStatement], true), [],
|
||||
[updateWithValueParamsStatement, ...watchStatements], false);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,6 @@
|
||||
|
||||
import { processSystemApi } from './validate_ui_syntax';
|
||||
|
||||
module.exports = function processWorker(source: string): string {
|
||||
module.exports = function processSystemModule(source: string): string {
|
||||
return processSystemApi(source);
|
||||
};
|
||||
@@ -28,7 +28,11 @@ import {
|
||||
COMPONENT_EXTEND_DECORATOR,
|
||||
RESOURCE,
|
||||
RESOURCE_TYPE,
|
||||
WORKER_OBJECT
|
||||
WORKER_OBJECT,
|
||||
RESOURCE_NAME_ID,
|
||||
RESOURCE_NAME_TYPE,
|
||||
RESOURCE_NAME_PARAMS,
|
||||
RESOURCE_RAWFILE
|
||||
} from './pre_define';
|
||||
import {
|
||||
componentInfo,
|
||||
@@ -48,19 +52,19 @@ import {
|
||||
BUILDIN_CONTAINER_COMPONENT,
|
||||
CUSTOM_BUILDER_METHOD,
|
||||
EXTEND_ATTRIBUTE,
|
||||
INNER_COMPONENT_NAMES
|
||||
JS_BIND_COMPONENTS
|
||||
} from './component_map';
|
||||
import { resources } from '../main';
|
||||
|
||||
export const transformLog: FileLog = new FileLog();
|
||||
|
||||
export function processUISyntax(program: ts.Program): Function {
|
||||
export function processUISyntax(program: ts.Program, ut = false): Function {
|
||||
return (context: ts.TransformationContext) => {
|
||||
let pagesDir: string;
|
||||
return (node: ts.SourceFile) => {
|
||||
pagesDir = path.resolve(path.dirname(node.fileName));
|
||||
if (process.env.compiler === BUILD_ON) {
|
||||
if (path.basename(node.fileName) === 'app.ets.ts') {
|
||||
if (!ut && (path.basename(node.fileName) === 'app.ets.ts' || !/\.ets\.ts$/.test(node.fileName))) {
|
||||
return node;
|
||||
}
|
||||
collectComponents(node);
|
||||
@@ -120,7 +124,7 @@ function collectComponents(node: ts.SourceFile): void {
|
||||
if (node.identifiers && node.identifiers.size) {
|
||||
// @ts-ignore
|
||||
for (let key of node.identifiers.keys()) {
|
||||
if (INNER_COMPONENT_NAMES.has(key)) {
|
||||
if (JS_BIND_COMPONENTS.has(key)) {
|
||||
appComponentCollection.add(key);
|
||||
}
|
||||
}
|
||||
@@ -129,25 +133,53 @@ function collectComponents(node: ts.SourceFile): void {
|
||||
|
||||
function isResource(node: ts.Node): boolean {
|
||||
return ts.isCallExpression(node) && ts.isIdentifier(node.expression) &&
|
||||
node.expression.escapedText.toString() === RESOURCE && node.arguments.length > 0;
|
||||
(node.expression.escapedText.toString() === RESOURCE ||
|
||||
node.expression.escapedText.toString() === RESOURCE_RAWFILE) && node.arguments.length > 0;
|
||||
}
|
||||
|
||||
function processResourceData(node: ts.CallExpression): ts.Node {
|
||||
if (ts.isStringLiteral(node.arguments[0])) {
|
||||
// @ts-ignore
|
||||
const resourceData: string[] = node.arguments[0].text.split('.');
|
||||
if (validateResourceData(resourceData, resources, node.arguments[0].getStart())) {
|
||||
const resourceType: number = RESOURCE_TYPE[resourceData[1]];
|
||||
const resourceValue: number = resources[resourceData[0]][resourceData[1]][resourceData[2]];
|
||||
const argsArr: ts.Expression[] = Array.from(node.arguments);
|
||||
argsArr.splice(0, 1, ts.factory.createNumericLiteral(resourceValue),
|
||||
ts.factory.createNumericLiteral(resourceType));
|
||||
return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, argsArr);
|
||||
if (node.expression.getText() === RESOURCE_RAWFILE) {
|
||||
return createResourceParam(0, RESOURCE_TYPE.rawfile, [node.arguments[0]]);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const resourceData: string[] = node.arguments[0].text.trim().split('.');
|
||||
if (validateResourceData(resourceData, resources, node.arguments[0].getStart())) {
|
||||
const resourceType: number = RESOURCE_TYPE[resourceData[1]];
|
||||
const resourceValue: number = resources[resourceData[0]][resourceData[1]][resourceData[2]];
|
||||
return createResourceParam(resourceValue, resourceType,
|
||||
Array.from(node.arguments).slice(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function createResourceParam(resourceValue: number, resourceType: number,argsArr: ts.Expression[]):
|
||||
ts.ObjectLiteralExpression {
|
||||
const resourceParams: ts.ObjectLiteralExpression = ts.factory.createObjectLiteralExpression(
|
||||
[
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createStringLiteral(RESOURCE_NAME_ID),
|
||||
ts.factory.createNumericLiteral(resourceValue)
|
||||
),
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createStringLiteral(RESOURCE_NAME_TYPE),
|
||||
ts.factory.createNumericLiteral(resourceType)
|
||||
),
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createIdentifier(RESOURCE_NAME_PARAMS),
|
||||
ts.factory.createArrayLiteralExpression(
|
||||
argsArr,
|
||||
false
|
||||
)
|
||||
)
|
||||
],
|
||||
false
|
||||
);
|
||||
return resourceParams;
|
||||
}
|
||||
|
||||
function validateResourceData(resourceData: string[], resources: object, pos: number): boolean {
|
||||
if (resourceData.length !== 3) {
|
||||
transformLog.errors.push({
|
||||
|
||||
@@ -1,65 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 path from 'path';
|
||||
|
||||
import { BUILD_OFF } from './pre_define';
|
||||
import {
|
||||
resetLog,
|
||||
transformLog
|
||||
} from './process_ui_syntax';
|
||||
import {
|
||||
propertyCollection,
|
||||
linkCollection
|
||||
} from './validate_ui_syntax';
|
||||
import {
|
||||
LogInfo,
|
||||
emitLogInfo,
|
||||
componentInfo
|
||||
} from './utils';
|
||||
import { resetComponentCollection } from './validate_ui_syntax';
|
||||
|
||||
module.exports = function resultProcess(source: string, map: any): string {
|
||||
process.env.compiler = BUILD_OFF;
|
||||
componentInfo.id = 0;
|
||||
propertyCollection.clear();
|
||||
linkCollection.clear();
|
||||
resetComponentCollection();
|
||||
if (transformLog && transformLog.errors.length) {
|
||||
const sourceFile: ts.SourceFile = transformLog.sourceFile;
|
||||
|
||||
const logInfos: LogInfo[] = transformLog.errors.map((item) => {
|
||||
if (item.pos) {
|
||||
const posOfNode: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(item.pos);
|
||||
item.line = posOfNode.line + 1;
|
||||
item.column = posOfNode.character + 1;
|
||||
} else {
|
||||
item.line = undefined;
|
||||
item.column = undefined;
|
||||
}
|
||||
item.fileName = sourceFile.fileName.replace(/.ts$/, '');
|
||||
return item;
|
||||
});
|
||||
emitLogInfo(this, logInfos);
|
||||
resetLog();
|
||||
}
|
||||
if (path.basename(this.resourcePath) === 'app.ets') {
|
||||
source = source.replace(/exports\.default/, 'globalThis.exports.default');
|
||||
}
|
||||
|
||||
this.callback(null, source, map);
|
||||
return;
|
||||
};
|
||||
/*
|
||||
* Copyright (c) 2021 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 path from 'path';
|
||||
|
||||
import { BUILD_OFF } from './pre_define';
|
||||
import {
|
||||
resetLog,
|
||||
transformLog
|
||||
} from './process_ui_syntax';
|
||||
import {
|
||||
propertyCollection,
|
||||
linkCollection
|
||||
} from './validate_ui_syntax';
|
||||
import {
|
||||
LogInfo,
|
||||
emitLogInfo,
|
||||
componentInfo
|
||||
} from './utils';
|
||||
import { resetComponentCollection } from './validate_ui_syntax';
|
||||
import { abilityConfig } from '../main';
|
||||
|
||||
module.exports = function resultProcess(source: string, map: any): string {
|
||||
process.env.compiler = BUILD_OFF;
|
||||
if (/\.ets$/.test(this.resourcePath)) {
|
||||
componentInfo.id = 0;
|
||||
propertyCollection.clear();
|
||||
linkCollection.clear();
|
||||
resetComponentCollection();
|
||||
if (transformLog && transformLog.errors.length) {
|
||||
const sourceFile: ts.SourceFile = transformLog.sourceFile;
|
||||
const logInfos: LogInfo[] = transformLog.errors.map((item) => {
|
||||
if (item.pos) {
|
||||
const posOfNode: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(item.pos);
|
||||
item.line = posOfNode.line + 1;
|
||||
item.column = posOfNode.character + 1;
|
||||
} else {
|
||||
item.line = undefined;
|
||||
item.column = undefined;
|
||||
}
|
||||
item.fileName = sourceFile.fileName.replace(/.ts$/, '');
|
||||
return item;
|
||||
});
|
||||
emitLogInfo(this, logInfos);
|
||||
resetLog();
|
||||
}
|
||||
}
|
||||
const resourcePath: string = path.basename(this.resourcePath);
|
||||
if (['app.ets', abilityConfig.abilityEntryFile].includes(resourcePath)) {
|
||||
source = source.replace(/exports\.default/, 'globalThis.exports.default');
|
||||
}
|
||||
|
||||
this.callback(null, source, map);
|
||||
return;
|
||||
};
|
||||
|
||||
+158
-158
@@ -1,158 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
export enum LogType {
|
||||
ERROR = 'ERROR',
|
||||
WARN = 'WARN',
|
||||
NOTE = 'NOTE'
|
||||
}
|
||||
|
||||
export interface LogInfo {
|
||||
type: LogType,
|
||||
message: string,
|
||||
pos?: number,
|
||||
line?: number,
|
||||
column?: number,
|
||||
fileName?: string
|
||||
}
|
||||
|
||||
export class FileLog {
|
||||
private _sourceFile: ts.SourceFile;
|
||||
private _errors: LogInfo[] = [];
|
||||
|
||||
public get sourceFile() {
|
||||
return this._sourceFile;
|
||||
}
|
||||
|
||||
public set sourceFile(newValue: ts.SourceFile) {
|
||||
this._sourceFile = newValue;
|
||||
}
|
||||
|
||||
public get errors() {
|
||||
return this._errors;
|
||||
}
|
||||
|
||||
public set errors(newValue: LogInfo[]) {
|
||||
this._errors = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
export function emitLogInfo(loader: any, infos: LogInfo[]) {
|
||||
if (infos && infos.length) {
|
||||
infos.forEach((item) => {
|
||||
switch (item.type) {
|
||||
case LogType.ERROR:
|
||||
loader.emitError(getMessage(loader.resourcePath, item));
|
||||
break;
|
||||
case LogType.WARN:
|
||||
loader.emitWarning(getMessage(loader.resourcePath, item));
|
||||
break;
|
||||
case LogType.NOTE:
|
||||
loader.emitWarning(getMessage(loader.resourcePath, item));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function addLog(type: LogType, message: string, pos: number, log: LogInfo[],
|
||||
sourceFile: ts.SourceFile) {
|
||||
const posOfNode: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(pos);
|
||||
log.push({
|
||||
type: type,
|
||||
message: message,
|
||||
line: posOfNode.line + 1,
|
||||
column: posOfNode.character + 1,
|
||||
fileName: sourceFile.fileName
|
||||
});
|
||||
}
|
||||
|
||||
export function getMessage(fileName: string, info: LogInfo): string {
|
||||
let messsage: string;
|
||||
if (info.line && info.column) {
|
||||
messsage = `BUILD${info.type} File: ${fileName}:${info.line}:${info.column}\n ${info.message}`;
|
||||
} else {
|
||||
messsage = `BUILD${info.type} File: ${fileName}\n ${info.message}`;
|
||||
}
|
||||
return messsage;
|
||||
}
|
||||
|
||||
class ComponentInfo {
|
||||
private _id: number = 0;
|
||||
private _componentNames: Set<string> = new Set(['ForEach']);
|
||||
public set id(id: number) {
|
||||
this._id = id;
|
||||
}
|
||||
public get id() {
|
||||
return this._id;
|
||||
}
|
||||
public set componentNames(componentNames: Set<string>) {
|
||||
this._componentNames = componentNames;
|
||||
}
|
||||
public get componentNames() {
|
||||
return this._componentNames;
|
||||
}
|
||||
}
|
||||
|
||||
export const componentInfo: ComponentInfo = new ComponentInfo();
|
||||
|
||||
export function hasDecorator(node: ts.MethodDeclaration | ts.FunctionDeclaration | ts.ClassDeclaration,
|
||||
decortorName: string): boolean {
|
||||
if (node.decorators && node.decorators.length) {
|
||||
for (let i = 0; i < node.decorators.length; i++) {
|
||||
if (node.decorators[i].getText() === decortorName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const STATEMENT_EXPECT: number = 1128;
|
||||
const SEMICOLON_EXPECT: number = 1005;
|
||||
export const IGNORE_ERROR_CODE: number[] = [STATEMENT_EXPECT, SEMICOLON_EXPECT];
|
||||
|
||||
export function readFile(dir: string, utFiles: string[]) {
|
||||
try {
|
||||
const files: string[] = fs.readdirSync(dir);
|
||||
files.forEach((element) => {
|
||||
const filePath: string = path.join(dir, element);
|
||||
const status: fs.Stats = fs.statSync(filePath);
|
||||
if (status.isDirectory()) {
|
||||
readFile(filePath, utFiles);
|
||||
} else {
|
||||
utFiles.push(filePath);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('ETS ERROR: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
export function createFunction(node: ts.Identifier, attrNode: ts.Identifier,
|
||||
argumentsArr: ts.NodeArray<ts.Expression>): ts.CallExpression {
|
||||
return ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
node,
|
||||
attrNode
|
||||
),
|
||||
undefined,
|
||||
argumentsArr && argumentsArr.length ? argumentsArr : []
|
||||
);
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2021 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 path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
export enum LogType {
|
||||
ERROR = 'ERROR',
|
||||
WARN = 'WARN',
|
||||
NOTE = 'NOTE'
|
||||
}
|
||||
|
||||
export interface LogInfo {
|
||||
type: LogType,
|
||||
message: string,
|
||||
pos?: number,
|
||||
line?: number,
|
||||
column?: number,
|
||||
fileName?: string
|
||||
}
|
||||
|
||||
export class FileLog {
|
||||
private _sourceFile: ts.SourceFile;
|
||||
private _errors: LogInfo[] = [];
|
||||
|
||||
public get sourceFile() {
|
||||
return this._sourceFile;
|
||||
}
|
||||
|
||||
public set sourceFile(newValue: ts.SourceFile) {
|
||||
this._sourceFile = newValue;
|
||||
}
|
||||
|
||||
public get errors() {
|
||||
return this._errors;
|
||||
}
|
||||
|
||||
public set errors(newValue: LogInfo[]) {
|
||||
this._errors = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
export function emitLogInfo(loader: any, infos: LogInfo[]) {
|
||||
if (infos && infos.length) {
|
||||
infos.forEach((item) => {
|
||||
switch (item.type) {
|
||||
case LogType.ERROR:
|
||||
loader.emitError(getMessage(loader.resourcePath, item));
|
||||
break;
|
||||
case LogType.WARN:
|
||||
loader.emitWarning(getMessage(loader.resourcePath, item));
|
||||
break;
|
||||
case LogType.NOTE:
|
||||
loader.emitWarning(getMessage(loader.resourcePath, item));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function addLog(type: LogType, message: string, pos: number, log: LogInfo[],
|
||||
sourceFile: ts.SourceFile) {
|
||||
const posOfNode: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(pos);
|
||||
log.push({
|
||||
type: type,
|
||||
message: message,
|
||||
line: posOfNode.line + 1,
|
||||
column: posOfNode.character + 1,
|
||||
fileName: sourceFile.fileName
|
||||
});
|
||||
}
|
||||
|
||||
export function getMessage(fileName: string, info: LogInfo): string {
|
||||
let messsage: string;
|
||||
if (info.line && info.column) {
|
||||
messsage = `BUILD${info.type} File: ${fileName}:${info.line}:${info.column}\n ${info.message}`;
|
||||
} else {
|
||||
messsage = `BUILD${info.type} File: ${fileName}\n ${info.message}`;
|
||||
}
|
||||
return messsage;
|
||||
}
|
||||
|
||||
class ComponentInfo {
|
||||
private _id: number = 0;
|
||||
private _componentNames: Set<string> = new Set(['ForEach']);
|
||||
public set id(id: number) {
|
||||
this._id = id;
|
||||
}
|
||||
public get id() {
|
||||
return this._id;
|
||||
}
|
||||
public set componentNames(componentNames: Set<string>) {
|
||||
this._componentNames = componentNames;
|
||||
}
|
||||
public get componentNames() {
|
||||
return this._componentNames;
|
||||
}
|
||||
}
|
||||
|
||||
export const componentInfo: ComponentInfo = new ComponentInfo();
|
||||
|
||||
export function hasDecorator(node: ts.MethodDeclaration | ts.FunctionDeclaration | ts.ClassDeclaration,
|
||||
decortorName: string): boolean {
|
||||
if (node.decorators && node.decorators.length) {
|
||||
for (let i = 0; i < node.decorators.length; i++) {
|
||||
if (node.decorators[i].getText() === decortorName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const STATEMENT_EXPECT: number = 1128;
|
||||
const SEMICOLON_EXPECT: number = 1005;
|
||||
export const IGNORE_ERROR_CODE: number[] = [STATEMENT_EXPECT, SEMICOLON_EXPECT];
|
||||
|
||||
export function readFile(dir: string, utFiles: string[]) {
|
||||
try {
|
||||
const files: string[] = fs.readdirSync(dir);
|
||||
files.forEach((element) => {
|
||||
const filePath: string = path.join(dir, element);
|
||||
const status: fs.Stats = fs.statSync(filePath);
|
||||
if (status.isDirectory()) {
|
||||
readFile(filePath, utFiles);
|
||||
} else {
|
||||
utFiles.push(filePath);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('ETS ERROR: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
export function createFunction(node: ts.Identifier, attrNode: ts.Identifier,
|
||||
argumentsArr: ts.NodeArray<ts.Expression>): ts.CallExpression {
|
||||
return ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
node,
|
||||
attrNode
|
||||
),
|
||||
undefined,
|
||||
argumentsArr && argumentsArr.length ? argumentsArr : []
|
||||
);
|
||||
}
|
||||
|
||||
+752
-749
File diff suppressed because it is too large
Load Diff
@@ -46,7 +46,7 @@ function expectActual(name: string, filePath: string) {
|
||||
"target": ts.ScriptTarget.ES2017
|
||||
},
|
||||
fileName: `${name}.ts`,
|
||||
transformers: { before: [processUISyntax(null)] }
|
||||
transformers: { before: [processUISyntax(null, true)] }
|
||||
});
|
||||
componentInfo.id = 0;
|
||||
componentCollection.customComponents.clear();
|
||||
|
||||
@@ -91,7 +91,8 @@ export const expectResult: string =
|
||||
if (earlierCreatedChild_2 == undefined) {
|
||||
View.create(new Child("2", this, { stateProperty: this.regularToState,
|
||||
propProperty: this.stateToProp,
|
||||
regularProperty: this.regularToRegular, linkProperty: this.__stateToLink
|
||||
regularProperty: this.regularToRegular,
|
||||
linkProperty: this.__stateToLink
|
||||
}));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -53,7 +53,7 @@ function initConfig(config) {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ets$/,
|
||||
test: /\.(ets|ts)$/,
|
||||
use: [
|
||||
{ loader: path.resolve(__dirname, 'lib/result_process.js') },
|
||||
{
|
||||
@@ -64,7 +64,7 @@ function initConfig(config) {
|
||||
configFile: path.resolve(__dirname, 'tsconfig.json'),
|
||||
getCustomTransformers(program) {
|
||||
return {
|
||||
before: [processUISyntax(program, path.join(projectPath, 'pages'))],
|
||||
before: [processUISyntax(program)],
|
||||
after: []
|
||||
};
|
||||
},
|
||||
@@ -74,26 +74,10 @@ function initConfig(config) {
|
||||
{ loader: path.resolve(__dirname, 'lib/pre_process.js') }
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{ loader: path.resolve(__dirname, 'lib/process_ability_entry_file.js') },
|
||||
{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
onlyCompileBundledFiles: true,
|
||||
configFile: path.resolve(__dirname, 'tsconfig.json'),
|
||||
}
|
||||
},
|
||||
{ loader: path.resolve(__dirname, 'lib/process_worker.js') }
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{ loader: path.resolve(__dirname, 'lib/process_worker.js') }
|
||||
{ loader: path.resolve(__dirname, 'lib/process_system_module.js') }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -102,7 +86,7 @@ function initConfig(config) {
|
||||
global: false
|
||||
},
|
||||
resolve: {
|
||||
extensions:['.ts', '.ets', '.js'],
|
||||
extensions:['.js', '.ets', '.ts'],
|
||||
modules: [
|
||||
projectPath,
|
||||
path.join(projectPath, '../../../../../'),
|
||||
|
||||
Reference in New Issue
Block a user