diff --git a/lib/tsc.js b/lib/tsc.js index 346999e7d6..31f8465c7f 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -44572,13 +44572,16 @@ var ts; ((_f = (ts.isLiteralImportTypeNode(location) ? location : undefined)) === null || _f === void 0 ? void 0 : _f.argument.literal); var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference, mode); + var sdkPath = compilerOptions.etsLoaderPath ? ts.resolvePath(compilerOptions.etsLoaderPath, "../..") : undefined; if (compilerOptions.needDoArkTsLinter && currentSourceFile && currentSourceFile.scriptKind === 3 && resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) { var diagnosticType = compilerOptions.isCompatibleVersion ? ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden : ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden; - error(errorNode, diagnosticType, moduleReference); + if (ts.isImportCall(location) || !allowImportSendable(sdkPath, currentSourceFile)) { + error(errorNode, diagnosticType, moduleReference); + } } var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule @@ -44713,6 +44716,11 @@ var ts; } return undefined; } + function allowImportSendable(sdkPath, currentSourceFile) { + var isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath)); + return ((isInSdkPath && currentSourceFile.isDeclarationFile) || + (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile)); + } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; var errorInfo = !ts.isExternalModuleNameRelative(moduleReference) && packageId diff --git a/lib/tsserver.js b/lib/tsserver.js index ec42c4c937..9cc33d6c38 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -53974,13 +53974,19 @@ var ts; ((_f = (ts.isLiteralImportTypeNode(location) ? location : undefined)) === null || _f === void 0 ? void 0 : _f.argument.literal); var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference, mode); + // the relative path of sdk + var sdkPath = compilerOptions.etsLoaderPath ? ts.resolvePath(compilerOptions.etsLoaderPath, "../..") : undefined; if (compilerOptions.needDoArkTsLinter && currentSourceFile && currentSourceFile.scriptKind === 3 /* ScriptKind.TS */ && resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) { var diagnosticType = compilerOptions.isCompatibleVersion ? ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden : ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden; - error(errorNode, diagnosticType, moduleReference); + if (ts.isImportCall(location) || !allowImportSendable(sdkPath, currentSourceFile)) { + // If the node is ImportCall throw error + // If currentSourceFile is not allowImportSendable (.d.ts inside sdk or .ts file when tsImportSendable is true) + error(errorNode, diagnosticType, moduleReference); + } } var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule @@ -54138,6 +54144,13 @@ var ts; } return undefined; } + function allowImportSendable(sdkPath, currentSourceFile) { + var isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath)); + // Check the file is a TypeScript file outside of the method + // currentSourceFile must be a ts file + return ((isInSdkPath && currentSourceFile.isDeclarationFile) || + (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile)); + } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; var errorInfo = !ts.isExternalModuleNameRelative(moduleReference) && packageId @@ -192891,7 +192904,7 @@ var ts; (function (ArkTSLinter_1_1) { ArkTSLinter_1_1.cookBookMsg = []; ArkTSLinter_1_1.cookBookTag = []; - for (var i = 0; i <= 164; i++) { + for (var i = 0; i <= 168; i++) { ArkTSLinter_1_1.cookBookMsg[i] = ""; } ArkTSLinter_1_1.cookBookTag[1] = "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)"; @@ -193058,6 +193071,10 @@ var ts; ArkTSLinter_1_1.cookBookTag[162] = 'Importing a module for side-effects only is not supported in shared module (arkts-no-side-effects-imports)'; ArkTSLinter_1_1.cookBookTag[163] = 'Exported object must have a Sendable data type in shared module (arkts-shared-module-exports)'; ArkTSLinter_1_1.cookBookTag[164] = '"export * from \'xxx\'" is not supported in shared module (arkts-shared-module-no-star-export)'; + ArkTSLinter_1_1.cookBookTag[165] = 'Only "Sendable" classes and "Sendable" interfaces are allowed for importing from ets into ts file (arkts-no-ts-import-ets)'; + ArkTSLinter_1_1.cookBookTag[166] = 'In ts files, "Sendable" types cannot be used in implements and extends clauses (arkts-no-ts-sendable-type-inheritance)'; + ArkTSLinter_1_1.cookBookTag[167] = 'In sdk ts files, "Sendable" class and "Sendable" interface can not be exported (arkts-no-dts-sendable-type-export)'; + ArkTSLinter_1_1.cookBookTag[168] = 'In ts files, entities from ets files can not be re-exported (arkts-no-ts-re-export-ets)'; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); /* @@ -193318,7 +193335,11 @@ var ts; FaultID[FaultID["SharedNoSideEffectImport"] = 89] = "SharedNoSideEffectImport"; FaultID[FaultID["SharedModuleExports"] = 90] = "SharedModuleExports"; FaultID[FaultID["SharedModuleNoStarExport"] = 91] = "SharedModuleNoStarExport"; - FaultID[FaultID["LAST_ID"] = 92] = "LAST_ID"; + FaultID[FaultID["NoTsImportEts"] = 92] = "NoTsImportEts"; + FaultID[FaultID["SendableTypeInheritance"] = 93] = "SendableTypeInheritance"; + FaultID[FaultID["SendableTypeExported"] = 94] = "SendableTypeExported"; + FaultID[FaultID["SendableNoTsExportEts"] = 95] = "SendableNoTsExportEts"; + FaultID[FaultID["LAST_ID"] = 96] = "LAST_ID"; })(FaultID = Problems.FaultID || (Problems.FaultID = {})); var FaultAttributes = /** @class */ (function () { function FaultAttributes(cookBookRef, migratable, severity) { @@ -193424,6 +193445,10 @@ var ts; Problems.faultsAttrs[FaultID.SharedNoSideEffectImport] = new FaultAttributes(162); Problems.faultsAttrs[FaultID.SharedModuleExports] = new FaultAttributes(163); Problems.faultsAttrs[FaultID.SharedModuleNoStarExport] = new FaultAttributes(164); + Problems.faultsAttrs[FaultID.NoTsImportEts] = new FaultAttributes(165); + Problems.faultsAttrs[FaultID.SendableTypeInheritance] = new FaultAttributes(166); + Problems.faultsAttrs[FaultID.SendableTypeExported] = new FaultAttributes(167); + Problems.faultsAttrs[FaultID.SendableNoTsExportEts] = new FaultAttributes(168); })(Problems = ArkTSLinter_1_1.Problems || (ArkTSLinter_1_1.Problems = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -194461,7 +194486,7 @@ var ts; if (!propSym || !((_a = propSym.declarations) === null || _a === void 0 ? void 0 : _a.length)) { return false; } - var propType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); + var propType = typeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); var initExpr = unwrapParenthesized(prop.initializer); if (ts.isObjectLiteralExpression(initExpr)) { if (!isObjectLiteralAssignable(propType, initExpr)) { @@ -194470,7 +194495,7 @@ var ts; } else { // Only check for structural sub-typing. - if (needToDeduceStructuralIdentity(propType, ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(initExpr), initExpr)) { + if (needToDeduceStructuralIdentity(propType, typeChecker.getTypeAtLocation(initExpr), initExpr)) { return false; } } @@ -194613,7 +194638,7 @@ var ts; } Utils.isSymbolAPI = isSymbolAPI; function isStdSymbol(symbol) { - var name = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getFullyQualifiedName(symbol); + var name = typeChecker.getFullyQualifiedName(symbol); return name === 'Symbol' && isGlobalSymbol(symbol); } Utils.isStdSymbol = isStdSymbol; @@ -194902,7 +194927,7 @@ var ts; if (ts.isArrayLiteralExpression(node) || ts.isObjectLiteralExpression(node)) { return false; } - var valueType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node); + var valueType = typeChecker.getTypeAtLocation(node); return isUnsupportedType(valueType) || isAnonymousType(valueType); } Utils.isValueAssignableToESObject = isValueAssignableToESObject; @@ -195035,7 +195060,7 @@ var ts; function isEnumStringLiteral(expr) { var symbol = trueSymbolAtLocation(expr); var isEnumMember = !!symbol && !!(symbol.flags & 8 /* ts.SymbolFlags.EnumMember */); - var type = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(expr); + var type = typeChecker.getTypeAtLocation(expr); var isStringEnumLiteral = isEnumType(type) && !!(type.flags & 128 /* ts.TypeFlags.StringLiteral */); return isEnumMember && isStringEnumLiteral; } @@ -195060,7 +195085,7 @@ var ts; if (node.parameters.length !== 1) { return false; } - var paramType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node.parameters[0]); + var paramType = typeChecker.getTypeAtLocation(node.parameters[0]); if ((paramType.flags & 8 /* ts.TypeFlags.Number */) === 0) { return false; } @@ -195137,7 +195162,7 @@ var ts; if (isConstEnum(sym)) { return true; } - return isSendableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeFromTypeNode(typeNode)); + return isSendableType(typeChecker.getTypeFromTypeNode(typeNode)); } Utils.isSendableTypeNode = isSendableTypeNode; function isSendableType(type) { @@ -195274,6 +195299,7 @@ var ts; var sym = trueSymbolAtLocation(node); return getDeclaration(sym); } + Utils.getDeclarationNode = getDeclarationNode; function isFunctionLikeDeclaration(node) { return ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node) || ts.isConstructorDeclaration(node) || @@ -195284,9 +195310,23 @@ var ts; var typeNode = decl === null || decl === void 0 ? void 0 : decl.type; return (typeNode && !isFunctionLikeDeclaration(decl)) ? isSendableTypeNode(typeNode) : - isShareableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(decl ? decl : node)); + isShareableType(typeChecker.getTypeAtLocation(decl ? decl : node)); } Utils.isShareableEntity = isShareableEntity; + function isShareableClassOrInterfaceEntity(node) { + var decl = getDeclarationNode(node); + return isSendableClassOrInterface(typeChecker.getTypeAtLocation(decl !== null && decl !== void 0 ? decl : node)); + } + Utils.isShareableClassOrInterfaceEntity = isShareableClassOrInterfaceEntity; + function isInImportWhiteList(resolvedModule) { + if (!resolvedModule.resolvedFileName || + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_LANG_D_ETS && + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_COLLECTIONS_D_ETS) { + return false; + } + return true; + } + Utils.isInImportWhiteList = isInImportWhiteList; })(Utils = ArkTSLinter_1_1.Utils || (ArkTSLinter_1_1.Utils = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -195565,6 +195605,10 @@ var ts; LinterConfig.nodeDesc[FaultID.SharedNoSideEffectImport] = 'Shared no side effect import'; LinterConfig.nodeDesc[FaultID.SharedModuleExports] = 'Shared module exports'; LinterConfig.nodeDesc[FaultID.SharedModuleNoStarExport] = 'Share module no star export'; + LinterConfig.nodeDesc[FaultID.NoTsImportEts] = 'No ts Import Ets'; + LinterConfig.nodeDesc[FaultID.SendableTypeInheritance] = 'Sendable type inheritance'; + LinterConfig.nodeDesc[FaultID.SendableTypeExported] = 'Sendable type exported'; + LinterConfig.nodeDesc[FaultID.SendableNoTsExportEts] = 'Sendable no ts export ets'; }; LinterConfig.nodeDesc = []; // The SyntaxKind enum defines additional elements at the end of the enum @@ -197735,6 +197779,327 @@ var ts; ArkTSLinter_1_1.TypeScriptLinter = TypeScriptLinter; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); +/* + * Copyright (c) 2022-2023 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. + */ +var ts; +(function (ts) { + var ArkTSLinter_1_1; + (function (ArkTSLinter_1_1) { + var FaultID = ArkTSLinter_1_1.Problems.FaultID; + var faultsAttrs = ArkTSLinter_1_1.Problems.faultsAttrs; + var Logger = ts.perfLogger; + var InteropTypescriptLinter = /** @class */ (function () { + function InteropTypescriptLinter(sourceFile, + /* private */ tsProgram, isInSdk) { + this.sourceFile = sourceFile; + this.isInSdk = isInSdk; + this.ARKTS_COLLECTIONS_ETS = '@arkts.collections'; + this.KIT_ARKTS_ETS = '@kit.ArkTS'; + this.handlersMap = new ts.Map([ + [272 /* ts.SyntaxKind.ImportDeclaration */, this.handleImportDeclaration], + [264 /* ts.SyntaxKind.InterfaceDeclaration */, this.handleInterfaceDeclaration], + [262 /* ts.SyntaxKind.ClassDeclaration */, this.handleClassDeclaration], + [212 /* ts.SyntaxKind.NewExpression */, this.handleNewExpression], + [208 /* ts.SyntaxKind.ObjectLiteralExpression */, this.handleObjectLiteralExpression], + [207 /* ts.SyntaxKind.ArrayLiteralExpression */, this.handleArrayLiteralExpression], + [233 /* ts.SyntaxKind.AsExpression */, this.handleAsExpression], + [278 /* ts.SyntaxKind.ExportDeclaration */, this.handleExportDeclaration] + ]); + InteropTypescriptLinter.tsTypeChecker = tsProgram.getLinterTypeChecker(); + this.currentErrorLine = 0; + this.currentWarningLine = 0; + } + InteropTypescriptLinter.initGlobals = function () { }; + InteropTypescriptLinter.initStatic = function () { + InteropTypescriptLinter.strictMode = true; + InteropTypescriptLinter.totalVisitedNodes = 0; + InteropTypescriptLinter.nodeCounters = []; + InteropTypescriptLinter.lineCounters = []; + InteropTypescriptLinter.totalErrorLines = 0; + InteropTypescriptLinter.totalWarningLines = 0; + InteropTypescriptLinter.errorLineNumbersString = ""; + InteropTypescriptLinter.warningLineNumbersString = ""; + for (var i = 0; i < FaultID.LAST_ID; i++) { + InteropTypescriptLinter.nodeCounters[i] = 0; + InteropTypescriptLinter.lineCounters[i] = 0; + } + InteropTypescriptLinter.problemsInfos = []; + }; + InteropTypescriptLinter.clearTsTypeChecker = function () { + InteropTypescriptLinter.tsTypeChecker = {}; + }; + InteropTypescriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { + var _a, _b; + if (autofixable === void 0) { autofixable = false; } + var _c = ArkTSLinter_1_1.Utils.getHighlightRange(node, faultId), startOffset = _c[0], endOffset = _c[1]; + var startPos = this.sourceFile.getLineAndCharacterOfPosition(startOffset); + var line = startPos.line + 1; + var character = startPos.character + 1; + InteropTypescriptLinter.nodeCounters[faultId]++; + var faultDescr = ArkTSLinter_1_1.LinterConfig.nodeDesc[faultId]; + var faultType = "unknown"; + var cookBookMsgNum = faultsAttrs[faultId] ? faultsAttrs[faultId].cookBookRef : 0; + var cookBookTg = ArkTSLinter_1_1.cookBookTag[cookBookMsgNum]; + var severity = (_b = (_a = faultsAttrs[faultId]) === null || _a === void 0 ? void 0 : _a.severity) !== null && _b !== void 0 ? _b : ArkTSLinter_1_1.Common.ProblemSeverity.ERROR; + var badNodeInfo = { + line: line, + column: character, + start: startOffset, + end: endOffset, + type: faultType, + severity: severity, + problem: FaultID[faultId], + suggest: cookBookMsgNum > 0 ? ArkTSLinter_1_1.cookBookMsg[cookBookMsgNum] : "", + rule: cookBookMsgNum > 0 && cookBookTg !== "" ? cookBookTg : faultDescr ? faultDescr : faultType, + ruleTag: cookBookMsgNum, + autofixable: autofixable, + autofix: autofix + }; + InteropTypescriptLinter.problemsInfos.push(badNodeInfo); + if (!InteropTypescriptLinter.reportDiagnostics) { + Logger.logEvent("Warning: ".concat(this.sourceFile.fileName, " (").concat(line, ", ").concat(character, "): ").concat(faultDescr ? faultDescr : faultType)); + } + InteropTypescriptLinter.lineCounters[faultId]++; + switch (faultsAttrs[faultId].severity) { + case ArkTSLinter_1_1.Common.ProblemSeverity.ERROR: { + this.currentErrorLine = line; + ++InteropTypescriptLinter.totalErrorLines; + InteropTypescriptLinter.errorLineNumbersString += line + ', '; + break; + } + case ArkTSLinter_1_1.Common.ProblemSeverity.WARNING: { + if (line === this.currentWarningLine) { + break; + } + this.currentWarningLine = line; + ++InteropTypescriptLinter.totalWarningLines; + InteropTypescriptLinter.warningLineNumbersString += line + ', '; + break; + } + } + }; + InteropTypescriptLinter.prototype.forEachNodeInSubtree = function (node, cb, stopCond) { + var _this = this; + cb.call(this, node); + if (stopCond === null || stopCond === void 0 ? void 0 : stopCond.call(this, node)) { + return; + } + ts.forEachChild(node, function (child) { + _this.forEachNodeInSubtree(child, cb, stopCond); + }); + }; + InteropTypescriptLinter.prototype.visitSourceFile = function (sf) { + var _this = this; + var callback = function (node) { + InteropTypescriptLinter.totalVisitedNodes++; + var handler = _this.handlersMap.get(node.kind); + if (handler !== undefined) { + handler.call(_this, node); + } + }; + var stopCondition = function (node) { + if (node === null || node.kind === null) { + return true; + } + if (ArkTSLinter_1_1.LinterConfig.terminalTokens.has(node.kind)) { + return true; + } + return false; + }; + this.forEachNodeInSubtree(sf, callback, stopCondition); + }; + InteropTypescriptLinter.prototype.handleImportDeclaration = function (node) { + var importDeclNode = node; + this.checkSendableClassorISendable(importDeclNode); + }; + InteropTypescriptLinter.prototype.checkSendableClassorISendable = function (node) { + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = node.moduleSpecifier; + if (!ts.isStringLiteralLike(contextSpecifier)) { + return; + } + var mode = ts.getModeForUsageLocation(currentSourceFile, contextSpecifier); + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + var importClause = node.importClause; + if (!resolvedModule) { + return; + } + if (!importClause) { + this.incrementCounters(node, FaultID.NoTsImportEts); + return; + } + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".ets" && (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".d.ets") { + return; + } + if (ArkTSLinter_1_1.Utils.isInImportWhiteList(resolvedModule)) { + return; + } + this.checkImportClause(importClause); + }; + InteropTypescriptLinter.prototype.checkImportClause = function (node) { + var _this = this; + var checkAndIncrement = function (identifier) { + if (identifier && !ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(identifier)) { + _this.incrementCounters(identifier, FaultID.NoTsImportEts); + } + }; + if (node.name) { + checkAndIncrement(node.name); + } + if (node.namedBindings) { + if (ts.isNamespaceImport(node.namedBindings)) { + this.incrementCounters(node.namedBindings, FaultID.NoTsImportEts); + } + else if (ts.isNamedImports(node.namedBindings)) { + node.namedBindings.elements.forEach(function (element) { + checkAndIncrement(element.name); + }); + } + } + }; + InteropTypescriptLinter.prototype.handleClassDeclaration = function (node) { + var tsClassDecl = node; + if (!tsClassDecl.heritageClauses) { + return; + } + for (var _i = 0, _a = tsClassDecl.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + // In ts files, sendable classes and sendable interfaces can not be extended or implemented. + InteropTypescriptLinter.prototype.checkClassOrInterfaceDeclarationHeritageClause = function (hClause) { + for (var _i = 0, _a = hClause.types; _i < _a.length; _i++) { + var tsTypeExpr = _a[_i]; + /* + * Always resolve type from 'tsTypeExpr' node, not from 'tsTypeExpr.expression' node, + * as for the latter, type checker will return incorrect type result for classes in + * 'extends' clause. Additionally, reduce reference, as mostly type checker returns + * the TypeReference type objects for classes and interfaces. + */ + var tsExprType = ArkTSLinter_1_1.Utils.reduceReference(InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsTypeExpr)); + var isSendableBaseType = ArkTSLinter_1_1.Utils.isSendableClassOrInterface(tsExprType); + if (isSendableBaseType) { + this.incrementCounters(tsTypeExpr, FaultID.SendableTypeInheritance); + } + } + }; + InteropTypescriptLinter.prototype.handleInterfaceDeclaration = function (node) { + var interfaceNode = node; + var iSymbol = ArkTSLinter_1_1.Utils.trueSymbolAtLocation(interfaceNode.name); + var iDecls = iSymbol ? iSymbol.getDeclarations() : null; + if (!iDecls) { + return; + } + if (!interfaceNode.heritageClauses) { + return; + } + for (var _i = 0, _a = interfaceNode.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + InteropTypescriptLinter.prototype.handleNewExpression = function (node) { + var tsNewExpr = node; + this.handleSendableGenericTypes(tsNewExpr); + }; + InteropTypescriptLinter.prototype.handleSendableGenericTypes = function (node) { + var type = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(node); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(type)) { + return; + } + var typeArgs = node.typeArguments; + if (!typeArgs || typeArgs.length === 0) { + return; + } + for (var _i = 0, typeArgs_6 = typeArgs; _i < typeArgs_6.length; _i++) { + var arg = typeArgs_6[_i]; + if (!ArkTSLinter_1_1.Utils.isSendableTypeNode(arg)) { + this.incrementCounters(arg, FaultID.SendableGenericTypes); + } + } + }; + InteropTypescriptLinter.prototype.handleObjectLiteralExpression = function (node) { + var objectLiteralExpr = node; + var objectLiteralType = InteropTypescriptLinter.tsTypeChecker.getContextualType(objectLiteralExpr); + if (objectLiteralType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(objectLiteralType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleArrayLiteralExpression = function (node) { + var arrayLitNode = node; + var arrayLitType = InteropTypescriptLinter.tsTypeChecker.getContextualType(arrayLitNode); + if (arrayLitType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(arrayLitType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleAsExpression = function (node) { + var tsAsExpr = node; + var targetType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.type).getNonNullableType(); + var exprType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.expression).getNonNullableType(); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(exprType) && + !ArkTSLinter_1_1.Utils.isObject(exprType) && + !ArkTSLinter_1_1.Utils.isAnyType(exprType) && + ArkTSLinter_1_1.Utils.isSendableClassOrInterface(targetType)) { + this.incrementCounters(tsAsExpr, FaultID.SendableAsExpr); + } + }; + InteropTypescriptLinter.prototype.handleExportDeclaration = function (node) { + var exportDecl = node; + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = exportDecl.moduleSpecifier; + // In ts files, re-export from .ets files is not supported. + if (contextSpecifier && ts.isStringLiteralLike(contextSpecifier)) { + var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".ets" || (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".d.ets") { + this.incrementCounters(node, FaultID.SendableNoTsExportEts); + } + return; + } + if (!this.isInSdk) { + return; + } + // In sdk .d.ts files, sendable classes and sendable interfaces can not be exported. + if (!exportDecl.exportClause) { + return; + } + if (!ts.isNamedExports(exportDecl.exportClause)) { + return; + } + for (var _i = 0, _a = exportDecl.exportClause.elements; _i < _a.length; _i++) { + var exportSpecifier = _a[_i]; + if (ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(exportSpecifier.name)) { + this.incrementCounters(exportSpecifier.name, FaultID.SendableTypeExported); + } + } + }; + InteropTypescriptLinter.prototype.lint = function () { + this.visitSourceFile(this.sourceFile); + }; + InteropTypescriptLinter.reportDiagnostics = true; + InteropTypescriptLinter.problemsInfos = []; + return InteropTypescriptLinter; + }()); + ArkTSLinter_1_1.InteropTypescriptLinter = InteropTypescriptLinter; + })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); +})(ts || (ts = {})); /* * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -197865,6 +198230,8 @@ var ts; var _a, _b; ArkTSLinter_1_1.TypeScriptLinter.errorLineNumbersString = ""; ArkTSLinter_1_1.TypeScriptLinter.warningLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.errorLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.warningLineNumbersString = ""; var diagnostics = []; ArkTSLinter_1_1.LinterConfig.initStatic(); // Retrieve list of changed files from the old program state. This needs @@ -197893,19 +198260,38 @@ var ts; var tscStrictDiagnostics = getTscDiagnostics(tscDiagnosticsLinter, srcFiles.filter(function (file) { return changedFiles.has(file.resolvedPath); })); timePrinterInstance.appendTime(ts.TimePhase.GET_TSC_DIAGNOSTICS); ArkTSLinter_1_1.TypeScriptLinter.initGlobals(); + ArkTSLinter_1_1.InteropTypescriptLinter.initGlobals(); var _loop_2 = function (fileToLint) { - ArkTSLinter_1_1.TypeScriptLinter.initStatic(); - if (ArkTSLinter_1_1.TypeScriptLinter.lintEtsOnly && fileToLint.scriptKind !== 8 /* ScriptKind.ETS */) { + if (fileToLint.scriptKind !== 8 /* ScriptKind.ETS */ && fileToLint.scriptKind !== 3 /* ScriptKind.TS */) { return "continue"; } var currentDiagnostics; if (changedFiles.has(fileToLint.resolvedPath)) { - var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); - ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); - linter.lint(); - // Get list of bad nodes from the current run. - currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; - ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + if (fileToLint.scriptKind === 8 /* ScriptKind.ETS */) { + ArkTSLinter_1_1.TypeScriptLinter.initStatic(); + var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); + linter.lint(); + // Get list of bad nodes from the current run. + currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; + ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } + else { + ArkTSLinter_1_1.InteropTypescriptLinter.initStatic(); + var isKit = ts.getBaseFileName(fileToLint.fileName).indexOf('@kit.') === 0; + var etsLoaderPath = program.getCompilerOptions().etsLoaderPath; + var isInSdk = etsLoaderPath ? ts.normalizePath(fileToLint.fileName).indexOf(ts.resolvePath(etsLoaderPath, "../..")) === 0 : false; + var isInOhModules = ts.isOHModules(fileToLint.fileName); + var tsImportSendableEnable = program.getCompilerOptions().tsImportSendableEnable; + if (isKit || isInOhModules || (!tsImportSendableEnable && !isInSdk)) { + return "continue"; + } + var InteropLinter = new ArkTSLinter_1_1.InteropTypescriptLinter(fileToLint, program, isInSdk); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.InteropTypescriptLinter.tsTypeChecker); + InteropLinter.lint(); + currentDiagnostics = []; + ArkTSLinter_1_1.InteropTypescriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } } else { // Get diagnostics from old run. @@ -197932,6 +198318,7 @@ var ts; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); + ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); ArkTSLinter_1_1.Utils.clearTrueSymbolAtLocationCache(); } diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts index 3d9af07d58..fb90c66b3f 100644 --- a/lib/tsserverlibrary.d.ts +++ b/lib/tsserverlibrary.d.ts @@ -3164,6 +3164,7 @@ declare namespace ts { packageManagerType?: string; emitNodeModulesFiles?: boolean; etsLoaderPath?: string; + tsImportSendableEnable?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } export interface EtsOptions { @@ -13144,7 +13145,11 @@ declare namespace ts { SharedNoSideEffectImport = 89, SharedModuleExports = 90, SharedModuleNoStarExport = 91, - LAST_ID = 92 + NoTsImportEts = 92, + SendableTypeInheritance = 93, + SendableTypeExported = 94, + SendableNoTsExportEts = 95, + LAST_ID = 96 } class FaultAttributes { cookBookRef: number; @@ -13341,7 +13346,10 @@ declare namespace ts { function getDecoratorsIfInSendableClass(declaration: ts.HasDecorators): readonly ts.Decorator[] | undefined; function isISendableInterface(type: ts.Type): boolean; function isSharedModule(sourceFile: ts.SourceFile): boolean; + function getDeclarationNode(node: ts.Node): ts.Declaration | undefined; function isShareableEntity(node: ts.Node): boolean; + function isShareableClassOrInterfaceEntity(node: ts.Node): boolean; + function isInImportWhiteList(resolvedModule: ResolvedModuleFull): boolean; } } } @@ -13540,6 +13548,51 @@ declare namespace ts { } } } +declare namespace ts { + namespace ArkTSLinter_1_1 { + import Autofix = Autofixer.Autofix; + class InteropTypescriptLinter { + private sourceFile; + private isInSdk; + static strictMode: boolean; + static totalVisitedNodes: number; + static nodeCounters: number[]; + static lineCounters: number[]; + static totalErrorLines: number; + static errorLineNumbersString: string; + static totalWarningLines: number; + static warningLineNumbersString: string; + static reportDiagnostics: boolean; + static problemsInfos: ProblemInfo[]; + static initGlobals(): void; + static initStatic(): void; + static tsTypeChecker: TypeChecker; + currentErrorLine: number; + currentWarningLine: number; + readonly ARKTS_COLLECTIONS_ETS = "@arkts.collections"; + readonly KIT_ARKTS_ETS = "@kit.ArkTS"; + constructor(sourceFile: SourceFile, tsProgram: Program, isInSdk: boolean); + static clearTsTypeChecker(): void; + readonly handlersMap: ESMap void>; + incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; + private forEachNodeInSubtree; + private visitSourceFile; + private handleImportDeclaration; + private checkSendableClassorISendable; + private checkImportClause; + private handleClassDeclaration; + private checkClassOrInterfaceDeclarationHeritageClause; + private handleInterfaceDeclaration; + private handleNewExpression; + private handleSendableGenericTypes; + private handleObjectLiteralExpression; + private handleArrayLiteralExpression; + private handleAsExpression; + private handleExportDeclaration; + lint(): void; + } + } +} declare namespace ts { namespace ArkTSLinter_1_1 { class TSCCompiledProgram { diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 63ae71b106..badaec4532 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -53973,13 +53973,19 @@ var ts; ((_f = (ts.isLiteralImportTypeNode(location) ? location : undefined)) === null || _f === void 0 ? void 0 : _f.argument.literal); var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference, mode); + // the relative path of sdk + var sdkPath = compilerOptions.etsLoaderPath ? ts.resolvePath(compilerOptions.etsLoaderPath, "../..") : undefined; if (compilerOptions.needDoArkTsLinter && currentSourceFile && currentSourceFile.scriptKind === 3 /* ScriptKind.TS */ && resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) { var diagnosticType = compilerOptions.isCompatibleVersion ? ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden : ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden; - error(errorNode, diagnosticType, moduleReference); + if (ts.isImportCall(location) || !allowImportSendable(sdkPath, currentSourceFile)) { + // If the node is ImportCall throw error + // If currentSourceFile is not allowImportSendable (.d.ts inside sdk or .ts file when tsImportSendable is true) + error(errorNode, diagnosticType, moduleReference); + } } var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule @@ -54137,6 +54143,13 @@ var ts; } return undefined; } + function allowImportSendable(sdkPath, currentSourceFile) { + var isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath)); + // Check the file is a TypeScript file outside of the method + // currentSourceFile must be a ts file + return ((isInSdkPath && currentSourceFile.isDeclarationFile) || + (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile)); + } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; var errorInfo = !ts.isExternalModuleNameRelative(moduleReference) && packageId @@ -192636,7 +192649,7 @@ var ts; (function (ArkTSLinter_1_1) { ArkTSLinter_1_1.cookBookMsg = []; ArkTSLinter_1_1.cookBookTag = []; - for (var i = 0; i <= 164; i++) { + for (var i = 0; i <= 168; i++) { ArkTSLinter_1_1.cookBookMsg[i] = ""; } ArkTSLinter_1_1.cookBookTag[1] = "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)"; @@ -192803,6 +192816,10 @@ var ts; ArkTSLinter_1_1.cookBookTag[162] = 'Importing a module for side-effects only is not supported in shared module (arkts-no-side-effects-imports)'; ArkTSLinter_1_1.cookBookTag[163] = 'Exported object must have a Sendable data type in shared module (arkts-shared-module-exports)'; ArkTSLinter_1_1.cookBookTag[164] = '"export * from \'xxx\'" is not supported in shared module (arkts-shared-module-no-star-export)'; + ArkTSLinter_1_1.cookBookTag[165] = 'Only "Sendable" classes and "Sendable" interfaces are allowed for importing from ets into ts file (arkts-no-ts-import-ets)'; + ArkTSLinter_1_1.cookBookTag[166] = 'In ts files, "Sendable" types cannot be used in implements and extends clauses (arkts-no-ts-sendable-type-inheritance)'; + ArkTSLinter_1_1.cookBookTag[167] = 'In sdk ts files, "Sendable" class and "Sendable" interface can not be exported (arkts-no-dts-sendable-type-export)'; + ArkTSLinter_1_1.cookBookTag[168] = 'In ts files, entities from ets files can not be re-exported (arkts-no-ts-re-export-ets)'; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); /* @@ -193063,7 +193080,11 @@ var ts; FaultID[FaultID["SharedNoSideEffectImport"] = 89] = "SharedNoSideEffectImport"; FaultID[FaultID["SharedModuleExports"] = 90] = "SharedModuleExports"; FaultID[FaultID["SharedModuleNoStarExport"] = 91] = "SharedModuleNoStarExport"; - FaultID[FaultID["LAST_ID"] = 92] = "LAST_ID"; + FaultID[FaultID["NoTsImportEts"] = 92] = "NoTsImportEts"; + FaultID[FaultID["SendableTypeInheritance"] = 93] = "SendableTypeInheritance"; + FaultID[FaultID["SendableTypeExported"] = 94] = "SendableTypeExported"; + FaultID[FaultID["SendableNoTsExportEts"] = 95] = "SendableNoTsExportEts"; + FaultID[FaultID["LAST_ID"] = 96] = "LAST_ID"; })(FaultID = Problems.FaultID || (Problems.FaultID = {})); var FaultAttributes = /** @class */ (function () { function FaultAttributes(cookBookRef, migratable, severity) { @@ -193169,6 +193190,10 @@ var ts; Problems.faultsAttrs[FaultID.SharedNoSideEffectImport] = new FaultAttributes(162); Problems.faultsAttrs[FaultID.SharedModuleExports] = new FaultAttributes(163); Problems.faultsAttrs[FaultID.SharedModuleNoStarExport] = new FaultAttributes(164); + Problems.faultsAttrs[FaultID.NoTsImportEts] = new FaultAttributes(165); + Problems.faultsAttrs[FaultID.SendableTypeInheritance] = new FaultAttributes(166); + Problems.faultsAttrs[FaultID.SendableTypeExported] = new FaultAttributes(167); + Problems.faultsAttrs[FaultID.SendableNoTsExportEts] = new FaultAttributes(168); })(Problems = ArkTSLinter_1_1.Problems || (ArkTSLinter_1_1.Problems = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -194206,7 +194231,7 @@ var ts; if (!propSym || !((_a = propSym.declarations) === null || _a === void 0 ? void 0 : _a.length)) { return false; } - var propType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); + var propType = typeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); var initExpr = unwrapParenthesized(prop.initializer); if (ts.isObjectLiteralExpression(initExpr)) { if (!isObjectLiteralAssignable(propType, initExpr)) { @@ -194215,7 +194240,7 @@ var ts; } else { // Only check for structural sub-typing. - if (needToDeduceStructuralIdentity(propType, ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(initExpr), initExpr)) { + if (needToDeduceStructuralIdentity(propType, typeChecker.getTypeAtLocation(initExpr), initExpr)) { return false; } } @@ -194358,7 +194383,7 @@ var ts; } Utils.isSymbolAPI = isSymbolAPI; function isStdSymbol(symbol) { - var name = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getFullyQualifiedName(symbol); + var name = typeChecker.getFullyQualifiedName(symbol); return name === 'Symbol' && isGlobalSymbol(symbol); } Utils.isStdSymbol = isStdSymbol; @@ -194647,7 +194672,7 @@ var ts; if (ts.isArrayLiteralExpression(node) || ts.isObjectLiteralExpression(node)) { return false; } - var valueType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node); + var valueType = typeChecker.getTypeAtLocation(node); return isUnsupportedType(valueType) || isAnonymousType(valueType); } Utils.isValueAssignableToESObject = isValueAssignableToESObject; @@ -194780,7 +194805,7 @@ var ts; function isEnumStringLiteral(expr) { var symbol = trueSymbolAtLocation(expr); var isEnumMember = !!symbol && !!(symbol.flags & 8 /* ts.SymbolFlags.EnumMember */); - var type = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(expr); + var type = typeChecker.getTypeAtLocation(expr); var isStringEnumLiteral = isEnumType(type) && !!(type.flags & 128 /* ts.TypeFlags.StringLiteral */); return isEnumMember && isStringEnumLiteral; } @@ -194805,7 +194830,7 @@ var ts; if (node.parameters.length !== 1) { return false; } - var paramType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node.parameters[0]); + var paramType = typeChecker.getTypeAtLocation(node.parameters[0]); if ((paramType.flags & 8 /* ts.TypeFlags.Number */) === 0) { return false; } @@ -194882,7 +194907,7 @@ var ts; if (isConstEnum(sym)) { return true; } - return isSendableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeFromTypeNode(typeNode)); + return isSendableType(typeChecker.getTypeFromTypeNode(typeNode)); } Utils.isSendableTypeNode = isSendableTypeNode; function isSendableType(type) { @@ -195019,6 +195044,7 @@ var ts; var sym = trueSymbolAtLocation(node); return getDeclaration(sym); } + Utils.getDeclarationNode = getDeclarationNode; function isFunctionLikeDeclaration(node) { return ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node) || ts.isConstructorDeclaration(node) || @@ -195029,9 +195055,23 @@ var ts; var typeNode = decl === null || decl === void 0 ? void 0 : decl.type; return (typeNode && !isFunctionLikeDeclaration(decl)) ? isSendableTypeNode(typeNode) : - isShareableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(decl ? decl : node)); + isShareableType(typeChecker.getTypeAtLocation(decl ? decl : node)); } Utils.isShareableEntity = isShareableEntity; + function isShareableClassOrInterfaceEntity(node) { + var decl = getDeclarationNode(node); + return isSendableClassOrInterface(typeChecker.getTypeAtLocation(decl !== null && decl !== void 0 ? decl : node)); + } + Utils.isShareableClassOrInterfaceEntity = isShareableClassOrInterfaceEntity; + function isInImportWhiteList(resolvedModule) { + if (!resolvedModule.resolvedFileName || + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_LANG_D_ETS && + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_COLLECTIONS_D_ETS) { + return false; + } + return true; + } + Utils.isInImportWhiteList = isInImportWhiteList; })(Utils = ArkTSLinter_1_1.Utils || (ArkTSLinter_1_1.Utils = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -195310,6 +195350,10 @@ var ts; LinterConfig.nodeDesc[FaultID.SharedNoSideEffectImport] = 'Shared no side effect import'; LinterConfig.nodeDesc[FaultID.SharedModuleExports] = 'Shared module exports'; LinterConfig.nodeDesc[FaultID.SharedModuleNoStarExport] = 'Share module no star export'; + LinterConfig.nodeDesc[FaultID.NoTsImportEts] = 'No ts Import Ets'; + LinterConfig.nodeDesc[FaultID.SendableTypeInheritance] = 'Sendable type inheritance'; + LinterConfig.nodeDesc[FaultID.SendableTypeExported] = 'Sendable type exported'; + LinterConfig.nodeDesc[FaultID.SendableNoTsExportEts] = 'Sendable no ts export ets'; }; LinterConfig.nodeDesc = []; // The SyntaxKind enum defines additional elements at the end of the enum @@ -197480,6 +197524,327 @@ var ts; ArkTSLinter_1_1.TypeScriptLinter = TypeScriptLinter; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); +/* + * Copyright (c) 2022-2023 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. + */ +var ts; +(function (ts) { + var ArkTSLinter_1_1; + (function (ArkTSLinter_1_1) { + var FaultID = ArkTSLinter_1_1.Problems.FaultID; + var faultsAttrs = ArkTSLinter_1_1.Problems.faultsAttrs; + var Logger = ts.perfLogger; + var InteropTypescriptLinter = /** @class */ (function () { + function InteropTypescriptLinter(sourceFile, + /* private */ tsProgram, isInSdk) { + this.sourceFile = sourceFile; + this.isInSdk = isInSdk; + this.ARKTS_COLLECTIONS_ETS = '@arkts.collections'; + this.KIT_ARKTS_ETS = '@kit.ArkTS'; + this.handlersMap = new ts.Map([ + [272 /* ts.SyntaxKind.ImportDeclaration */, this.handleImportDeclaration], + [264 /* ts.SyntaxKind.InterfaceDeclaration */, this.handleInterfaceDeclaration], + [262 /* ts.SyntaxKind.ClassDeclaration */, this.handleClassDeclaration], + [212 /* ts.SyntaxKind.NewExpression */, this.handleNewExpression], + [208 /* ts.SyntaxKind.ObjectLiteralExpression */, this.handleObjectLiteralExpression], + [207 /* ts.SyntaxKind.ArrayLiteralExpression */, this.handleArrayLiteralExpression], + [233 /* ts.SyntaxKind.AsExpression */, this.handleAsExpression], + [278 /* ts.SyntaxKind.ExportDeclaration */, this.handleExportDeclaration] + ]); + InteropTypescriptLinter.tsTypeChecker = tsProgram.getLinterTypeChecker(); + this.currentErrorLine = 0; + this.currentWarningLine = 0; + } + InteropTypescriptLinter.initGlobals = function () { }; + InteropTypescriptLinter.initStatic = function () { + InteropTypescriptLinter.strictMode = true; + InteropTypescriptLinter.totalVisitedNodes = 0; + InteropTypescriptLinter.nodeCounters = []; + InteropTypescriptLinter.lineCounters = []; + InteropTypescriptLinter.totalErrorLines = 0; + InteropTypescriptLinter.totalWarningLines = 0; + InteropTypescriptLinter.errorLineNumbersString = ""; + InteropTypescriptLinter.warningLineNumbersString = ""; + for (var i = 0; i < FaultID.LAST_ID; i++) { + InteropTypescriptLinter.nodeCounters[i] = 0; + InteropTypescriptLinter.lineCounters[i] = 0; + } + InteropTypescriptLinter.problemsInfos = []; + }; + InteropTypescriptLinter.clearTsTypeChecker = function () { + InteropTypescriptLinter.tsTypeChecker = {}; + }; + InteropTypescriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { + var _a, _b; + if (autofixable === void 0) { autofixable = false; } + var _c = ArkTSLinter_1_1.Utils.getHighlightRange(node, faultId), startOffset = _c[0], endOffset = _c[1]; + var startPos = this.sourceFile.getLineAndCharacterOfPosition(startOffset); + var line = startPos.line + 1; + var character = startPos.character + 1; + InteropTypescriptLinter.nodeCounters[faultId]++; + var faultDescr = ArkTSLinter_1_1.LinterConfig.nodeDesc[faultId]; + var faultType = "unknown"; + var cookBookMsgNum = faultsAttrs[faultId] ? faultsAttrs[faultId].cookBookRef : 0; + var cookBookTg = ArkTSLinter_1_1.cookBookTag[cookBookMsgNum]; + var severity = (_b = (_a = faultsAttrs[faultId]) === null || _a === void 0 ? void 0 : _a.severity) !== null && _b !== void 0 ? _b : ArkTSLinter_1_1.Common.ProblemSeverity.ERROR; + var badNodeInfo = { + line: line, + column: character, + start: startOffset, + end: endOffset, + type: faultType, + severity: severity, + problem: FaultID[faultId], + suggest: cookBookMsgNum > 0 ? ArkTSLinter_1_1.cookBookMsg[cookBookMsgNum] : "", + rule: cookBookMsgNum > 0 && cookBookTg !== "" ? cookBookTg : faultDescr ? faultDescr : faultType, + ruleTag: cookBookMsgNum, + autofixable: autofixable, + autofix: autofix + }; + InteropTypescriptLinter.problemsInfos.push(badNodeInfo); + if (!InteropTypescriptLinter.reportDiagnostics) { + Logger.logEvent("Warning: ".concat(this.sourceFile.fileName, " (").concat(line, ", ").concat(character, "): ").concat(faultDescr ? faultDescr : faultType)); + } + InteropTypescriptLinter.lineCounters[faultId]++; + switch (faultsAttrs[faultId].severity) { + case ArkTSLinter_1_1.Common.ProblemSeverity.ERROR: { + this.currentErrorLine = line; + ++InteropTypescriptLinter.totalErrorLines; + InteropTypescriptLinter.errorLineNumbersString += line + ', '; + break; + } + case ArkTSLinter_1_1.Common.ProblemSeverity.WARNING: { + if (line === this.currentWarningLine) { + break; + } + this.currentWarningLine = line; + ++InteropTypescriptLinter.totalWarningLines; + InteropTypescriptLinter.warningLineNumbersString += line + ', '; + break; + } + } + }; + InteropTypescriptLinter.prototype.forEachNodeInSubtree = function (node, cb, stopCond) { + var _this = this; + cb.call(this, node); + if (stopCond === null || stopCond === void 0 ? void 0 : stopCond.call(this, node)) { + return; + } + ts.forEachChild(node, function (child) { + _this.forEachNodeInSubtree(child, cb, stopCond); + }); + }; + InteropTypescriptLinter.prototype.visitSourceFile = function (sf) { + var _this = this; + var callback = function (node) { + InteropTypescriptLinter.totalVisitedNodes++; + var handler = _this.handlersMap.get(node.kind); + if (handler !== undefined) { + handler.call(_this, node); + } + }; + var stopCondition = function (node) { + if (node === null || node.kind === null) { + return true; + } + if (ArkTSLinter_1_1.LinterConfig.terminalTokens.has(node.kind)) { + return true; + } + return false; + }; + this.forEachNodeInSubtree(sf, callback, stopCondition); + }; + InteropTypescriptLinter.prototype.handleImportDeclaration = function (node) { + var importDeclNode = node; + this.checkSendableClassorISendable(importDeclNode); + }; + InteropTypescriptLinter.prototype.checkSendableClassorISendable = function (node) { + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = node.moduleSpecifier; + if (!ts.isStringLiteralLike(contextSpecifier)) { + return; + } + var mode = ts.getModeForUsageLocation(currentSourceFile, contextSpecifier); + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + var importClause = node.importClause; + if (!resolvedModule) { + return; + } + if (!importClause) { + this.incrementCounters(node, FaultID.NoTsImportEts); + return; + } + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".ets" && (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".d.ets") { + return; + } + if (ArkTSLinter_1_1.Utils.isInImportWhiteList(resolvedModule)) { + return; + } + this.checkImportClause(importClause); + }; + InteropTypescriptLinter.prototype.checkImportClause = function (node) { + var _this = this; + var checkAndIncrement = function (identifier) { + if (identifier && !ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(identifier)) { + _this.incrementCounters(identifier, FaultID.NoTsImportEts); + } + }; + if (node.name) { + checkAndIncrement(node.name); + } + if (node.namedBindings) { + if (ts.isNamespaceImport(node.namedBindings)) { + this.incrementCounters(node.namedBindings, FaultID.NoTsImportEts); + } + else if (ts.isNamedImports(node.namedBindings)) { + node.namedBindings.elements.forEach(function (element) { + checkAndIncrement(element.name); + }); + } + } + }; + InteropTypescriptLinter.prototype.handleClassDeclaration = function (node) { + var tsClassDecl = node; + if (!tsClassDecl.heritageClauses) { + return; + } + for (var _i = 0, _a = tsClassDecl.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + // In ts files, sendable classes and sendable interfaces can not be extended or implemented. + InteropTypescriptLinter.prototype.checkClassOrInterfaceDeclarationHeritageClause = function (hClause) { + for (var _i = 0, _a = hClause.types; _i < _a.length; _i++) { + var tsTypeExpr = _a[_i]; + /* + * Always resolve type from 'tsTypeExpr' node, not from 'tsTypeExpr.expression' node, + * as for the latter, type checker will return incorrect type result for classes in + * 'extends' clause. Additionally, reduce reference, as mostly type checker returns + * the TypeReference type objects for classes and interfaces. + */ + var tsExprType = ArkTSLinter_1_1.Utils.reduceReference(InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsTypeExpr)); + var isSendableBaseType = ArkTSLinter_1_1.Utils.isSendableClassOrInterface(tsExprType); + if (isSendableBaseType) { + this.incrementCounters(tsTypeExpr, FaultID.SendableTypeInheritance); + } + } + }; + InteropTypescriptLinter.prototype.handleInterfaceDeclaration = function (node) { + var interfaceNode = node; + var iSymbol = ArkTSLinter_1_1.Utils.trueSymbolAtLocation(interfaceNode.name); + var iDecls = iSymbol ? iSymbol.getDeclarations() : null; + if (!iDecls) { + return; + } + if (!interfaceNode.heritageClauses) { + return; + } + for (var _i = 0, _a = interfaceNode.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + InteropTypescriptLinter.prototype.handleNewExpression = function (node) { + var tsNewExpr = node; + this.handleSendableGenericTypes(tsNewExpr); + }; + InteropTypescriptLinter.prototype.handleSendableGenericTypes = function (node) { + var type = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(node); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(type)) { + return; + } + var typeArgs = node.typeArguments; + if (!typeArgs || typeArgs.length === 0) { + return; + } + for (var _i = 0, typeArgs_6 = typeArgs; _i < typeArgs_6.length; _i++) { + var arg = typeArgs_6[_i]; + if (!ArkTSLinter_1_1.Utils.isSendableTypeNode(arg)) { + this.incrementCounters(arg, FaultID.SendableGenericTypes); + } + } + }; + InteropTypescriptLinter.prototype.handleObjectLiteralExpression = function (node) { + var objectLiteralExpr = node; + var objectLiteralType = InteropTypescriptLinter.tsTypeChecker.getContextualType(objectLiteralExpr); + if (objectLiteralType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(objectLiteralType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleArrayLiteralExpression = function (node) { + var arrayLitNode = node; + var arrayLitType = InteropTypescriptLinter.tsTypeChecker.getContextualType(arrayLitNode); + if (arrayLitType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(arrayLitType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleAsExpression = function (node) { + var tsAsExpr = node; + var targetType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.type).getNonNullableType(); + var exprType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.expression).getNonNullableType(); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(exprType) && + !ArkTSLinter_1_1.Utils.isObject(exprType) && + !ArkTSLinter_1_1.Utils.isAnyType(exprType) && + ArkTSLinter_1_1.Utils.isSendableClassOrInterface(targetType)) { + this.incrementCounters(tsAsExpr, FaultID.SendableAsExpr); + } + }; + InteropTypescriptLinter.prototype.handleExportDeclaration = function (node) { + var exportDecl = node; + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = exportDecl.moduleSpecifier; + // In ts files, re-export from .ets files is not supported. + if (contextSpecifier && ts.isStringLiteralLike(contextSpecifier)) { + var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".ets" || (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".d.ets") { + this.incrementCounters(node, FaultID.SendableNoTsExportEts); + } + return; + } + if (!this.isInSdk) { + return; + } + // In sdk .d.ts files, sendable classes and sendable interfaces can not be exported. + if (!exportDecl.exportClause) { + return; + } + if (!ts.isNamedExports(exportDecl.exportClause)) { + return; + } + for (var _i = 0, _a = exportDecl.exportClause.elements; _i < _a.length; _i++) { + var exportSpecifier = _a[_i]; + if (ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(exportSpecifier.name)) { + this.incrementCounters(exportSpecifier.name, FaultID.SendableTypeExported); + } + } + }; + InteropTypescriptLinter.prototype.lint = function () { + this.visitSourceFile(this.sourceFile); + }; + InteropTypescriptLinter.reportDiagnostics = true; + InteropTypescriptLinter.problemsInfos = []; + return InteropTypescriptLinter; + }()); + ArkTSLinter_1_1.InteropTypescriptLinter = InteropTypescriptLinter; + })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); +})(ts || (ts = {})); /* * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -197610,6 +197975,8 @@ var ts; var _a, _b; ArkTSLinter_1_1.TypeScriptLinter.errorLineNumbersString = ""; ArkTSLinter_1_1.TypeScriptLinter.warningLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.errorLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.warningLineNumbersString = ""; var diagnostics = []; ArkTSLinter_1_1.LinterConfig.initStatic(); // Retrieve list of changed files from the old program state. This needs @@ -197638,19 +198005,38 @@ var ts; var tscStrictDiagnostics = getTscDiagnostics(tscDiagnosticsLinter, srcFiles.filter(function (file) { return changedFiles.has(file.resolvedPath); })); timePrinterInstance.appendTime(ts.TimePhase.GET_TSC_DIAGNOSTICS); ArkTSLinter_1_1.TypeScriptLinter.initGlobals(); + ArkTSLinter_1_1.InteropTypescriptLinter.initGlobals(); var _loop_2 = function (fileToLint) { - ArkTSLinter_1_1.TypeScriptLinter.initStatic(); - if (ArkTSLinter_1_1.TypeScriptLinter.lintEtsOnly && fileToLint.scriptKind !== 8 /* ScriptKind.ETS */) { + if (fileToLint.scriptKind !== 8 /* ScriptKind.ETS */ && fileToLint.scriptKind !== 3 /* ScriptKind.TS */) { return "continue"; } var currentDiagnostics; if (changedFiles.has(fileToLint.resolvedPath)) { - var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); - ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); - linter.lint(); - // Get list of bad nodes from the current run. - currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; - ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + if (fileToLint.scriptKind === 8 /* ScriptKind.ETS */) { + ArkTSLinter_1_1.TypeScriptLinter.initStatic(); + var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); + linter.lint(); + // Get list of bad nodes from the current run. + currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; + ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } + else { + ArkTSLinter_1_1.InteropTypescriptLinter.initStatic(); + var isKit = ts.getBaseFileName(fileToLint.fileName).indexOf('@kit.') === 0; + var etsLoaderPath = program.getCompilerOptions().etsLoaderPath; + var isInSdk = etsLoaderPath ? ts.normalizePath(fileToLint.fileName).indexOf(ts.resolvePath(etsLoaderPath, "../..")) === 0 : false; + var isInOhModules = ts.isOHModules(fileToLint.fileName); + var tsImportSendableEnable = program.getCompilerOptions().tsImportSendableEnable; + if (isKit || isInOhModules || (!tsImportSendableEnable && !isInSdk)) { + return "continue"; + } + var InteropLinter = new ArkTSLinter_1_1.InteropTypescriptLinter(fileToLint, program, isInSdk); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.InteropTypescriptLinter.tsTypeChecker); + InteropLinter.lint(); + currentDiagnostics = []; + ArkTSLinter_1_1.InteropTypescriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } } else { // Get diagnostics from old run. @@ -197677,6 +198063,7 @@ var ts; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); + ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); ArkTSLinter_1_1.Utils.clearTrueSymbolAtLocationCache(); } diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index ebce8b5b92..6ac9f040f0 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -3164,6 +3164,7 @@ declare namespace ts { packageManagerType?: string; emitNodeModulesFiles?: boolean; etsLoaderPath?: string; + tsImportSendableEnable?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } export interface EtsOptions { @@ -9205,7 +9206,11 @@ declare namespace ts { SharedNoSideEffectImport = 89, SharedModuleExports = 90, SharedModuleNoStarExport = 91, - LAST_ID = 92 + NoTsImportEts = 92, + SendableTypeInheritance = 93, + SendableTypeExported = 94, + SendableNoTsExportEts = 95, + LAST_ID = 96 } class FaultAttributes { cookBookRef: number; @@ -9402,7 +9407,10 @@ declare namespace ts { function getDecoratorsIfInSendableClass(declaration: ts.HasDecorators): readonly ts.Decorator[] | undefined; function isISendableInterface(type: ts.Type): boolean; function isSharedModule(sourceFile: ts.SourceFile): boolean; + function getDeclarationNode(node: ts.Node): ts.Declaration | undefined; function isShareableEntity(node: ts.Node): boolean; + function isShareableClassOrInterfaceEntity(node: ts.Node): boolean; + function isInImportWhiteList(resolvedModule: ResolvedModuleFull): boolean; } } } @@ -9601,6 +9609,51 @@ declare namespace ts { } } } +declare namespace ts { + namespace ArkTSLinter_1_1 { + import Autofix = Autofixer.Autofix; + class InteropTypescriptLinter { + private sourceFile; + private isInSdk; + static strictMode: boolean; + static totalVisitedNodes: number; + static nodeCounters: number[]; + static lineCounters: number[]; + static totalErrorLines: number; + static errorLineNumbersString: string; + static totalWarningLines: number; + static warningLineNumbersString: string; + static reportDiagnostics: boolean; + static problemsInfos: ProblemInfo[]; + static initGlobals(): void; + static initStatic(): void; + static tsTypeChecker: TypeChecker; + currentErrorLine: number; + currentWarningLine: number; + readonly ARKTS_COLLECTIONS_ETS = "@arkts.collections"; + readonly KIT_ARKTS_ETS = "@kit.ArkTS"; + constructor(sourceFile: SourceFile, tsProgram: Program, isInSdk: boolean); + static clearTsTypeChecker(): void; + readonly handlersMap: ESMap void>; + incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; + private forEachNodeInSubtree; + private visitSourceFile; + private handleImportDeclaration; + private checkSendableClassorISendable; + private checkImportClause; + private handleClassDeclaration; + private checkClassOrInterfaceDeclarationHeritageClause; + private handleInterfaceDeclaration; + private handleNewExpression; + private handleSendableGenericTypes; + private handleObjectLiteralExpression; + private handleArrayLiteralExpression; + private handleAsExpression; + private handleExportDeclaration; + lint(): void; + } + } +} declare namespace ts { namespace ArkTSLinter_1_1 { class TSCCompiledProgram { diff --git a/lib/typescript.js b/lib/typescript.js index 3cae2d262b..8b979b4e67 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -53964,13 +53964,19 @@ var ts; ((_f = (ts.isLiteralImportTypeNode(location) ? location : undefined)) === null || _f === void 0 ? void 0 : _f.argument.literal); var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference, mode); + // the relative path of sdk + var sdkPath = compilerOptions.etsLoaderPath ? ts.resolvePath(compilerOptions.etsLoaderPath, "../..") : undefined; if (compilerOptions.needDoArkTsLinter && currentSourceFile && currentSourceFile.scriptKind === 3 /* ScriptKind.TS */ && resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) { var diagnosticType = compilerOptions.isCompatibleVersion ? ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden : ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden; - error(errorNode, diagnosticType, moduleReference); + if (ts.isImportCall(location) || !allowImportSendable(sdkPath, currentSourceFile)) { + // If the node is ImportCall throw error + // If currentSourceFile is not allowImportSendable (.d.ts inside sdk or .ts file when tsImportSendable is true) + error(errorNode, diagnosticType, moduleReference); + } } var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule @@ -54128,6 +54134,13 @@ var ts; } return undefined; } + function allowImportSendable(sdkPath, currentSourceFile) { + var isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath)); + // Check the file is a TypeScript file outside of the method + // currentSourceFile must be a ts file + return ((isInSdkPath && currentSourceFile.isDeclarationFile) || + (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile)); + } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; var errorInfo = !ts.isExternalModuleNameRelative(moduleReference) && packageId @@ -181730,7 +181743,7 @@ var ts; (function (ArkTSLinter_1_1) { ArkTSLinter_1_1.cookBookMsg = []; ArkTSLinter_1_1.cookBookTag = []; - for (var i = 0; i <= 164; i++) { + for (var i = 0; i <= 168; i++) { ArkTSLinter_1_1.cookBookMsg[i] = ""; } ArkTSLinter_1_1.cookBookTag[1] = "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)"; @@ -181897,6 +181910,10 @@ var ts; ArkTSLinter_1_1.cookBookTag[162] = 'Importing a module for side-effects only is not supported in shared module (arkts-no-side-effects-imports)'; ArkTSLinter_1_1.cookBookTag[163] = 'Exported object must have a Sendable data type in shared module (arkts-shared-module-exports)'; ArkTSLinter_1_1.cookBookTag[164] = '"export * from \'xxx\'" is not supported in shared module (arkts-shared-module-no-star-export)'; + ArkTSLinter_1_1.cookBookTag[165] = 'Only "Sendable" classes and "Sendable" interfaces are allowed for importing from ets into ts file (arkts-no-ts-import-ets)'; + ArkTSLinter_1_1.cookBookTag[166] = 'In ts files, "Sendable" types cannot be used in implements and extends clauses (arkts-no-ts-sendable-type-inheritance)'; + ArkTSLinter_1_1.cookBookTag[167] = 'In sdk ts files, "Sendable" class and "Sendable" interface can not be exported (arkts-no-dts-sendable-type-export)'; + ArkTSLinter_1_1.cookBookTag[168] = 'In ts files, entities from ets files can not be re-exported (arkts-no-ts-re-export-ets)'; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); /* @@ -182157,7 +182174,11 @@ var ts; FaultID[FaultID["SharedNoSideEffectImport"] = 89] = "SharedNoSideEffectImport"; FaultID[FaultID["SharedModuleExports"] = 90] = "SharedModuleExports"; FaultID[FaultID["SharedModuleNoStarExport"] = 91] = "SharedModuleNoStarExport"; - FaultID[FaultID["LAST_ID"] = 92] = "LAST_ID"; + FaultID[FaultID["NoTsImportEts"] = 92] = "NoTsImportEts"; + FaultID[FaultID["SendableTypeInheritance"] = 93] = "SendableTypeInheritance"; + FaultID[FaultID["SendableTypeExported"] = 94] = "SendableTypeExported"; + FaultID[FaultID["SendableNoTsExportEts"] = 95] = "SendableNoTsExportEts"; + FaultID[FaultID["LAST_ID"] = 96] = "LAST_ID"; })(FaultID = Problems.FaultID || (Problems.FaultID = {})); var FaultAttributes = /** @class */ (function () { function FaultAttributes(cookBookRef, migratable, severity) { @@ -182263,6 +182284,10 @@ var ts; Problems.faultsAttrs[FaultID.SharedNoSideEffectImport] = new FaultAttributes(162); Problems.faultsAttrs[FaultID.SharedModuleExports] = new FaultAttributes(163); Problems.faultsAttrs[FaultID.SharedModuleNoStarExport] = new FaultAttributes(164); + Problems.faultsAttrs[FaultID.NoTsImportEts] = new FaultAttributes(165); + Problems.faultsAttrs[FaultID.SendableTypeInheritance] = new FaultAttributes(166); + Problems.faultsAttrs[FaultID.SendableTypeExported] = new FaultAttributes(167); + Problems.faultsAttrs[FaultID.SendableNoTsExportEts] = new FaultAttributes(168); })(Problems = ArkTSLinter_1_1.Problems || (ArkTSLinter_1_1.Problems = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -183300,7 +183325,7 @@ var ts; if (!propSym || !((_a = propSym.declarations) === null || _a === void 0 ? void 0 : _a.length)) { return false; } - var propType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); + var propType = typeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); var initExpr = unwrapParenthesized(prop.initializer); if (ts.isObjectLiteralExpression(initExpr)) { if (!isObjectLiteralAssignable(propType, initExpr)) { @@ -183309,7 +183334,7 @@ var ts; } else { // Only check for structural sub-typing. - if (needToDeduceStructuralIdentity(propType, ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(initExpr), initExpr)) { + if (needToDeduceStructuralIdentity(propType, typeChecker.getTypeAtLocation(initExpr), initExpr)) { return false; } } @@ -183452,7 +183477,7 @@ var ts; } Utils.isSymbolAPI = isSymbolAPI; function isStdSymbol(symbol) { - var name = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getFullyQualifiedName(symbol); + var name = typeChecker.getFullyQualifiedName(symbol); return name === 'Symbol' && isGlobalSymbol(symbol); } Utils.isStdSymbol = isStdSymbol; @@ -183741,7 +183766,7 @@ var ts; if (ts.isArrayLiteralExpression(node) || ts.isObjectLiteralExpression(node)) { return false; } - var valueType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node); + var valueType = typeChecker.getTypeAtLocation(node); return isUnsupportedType(valueType) || isAnonymousType(valueType); } Utils.isValueAssignableToESObject = isValueAssignableToESObject; @@ -183874,7 +183899,7 @@ var ts; function isEnumStringLiteral(expr) { var symbol = trueSymbolAtLocation(expr); var isEnumMember = !!symbol && !!(symbol.flags & 8 /* ts.SymbolFlags.EnumMember */); - var type = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(expr); + var type = typeChecker.getTypeAtLocation(expr); var isStringEnumLiteral = isEnumType(type) && !!(type.flags & 128 /* ts.TypeFlags.StringLiteral */); return isEnumMember && isStringEnumLiteral; } @@ -183899,7 +183924,7 @@ var ts; if (node.parameters.length !== 1) { return false; } - var paramType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node.parameters[0]); + var paramType = typeChecker.getTypeAtLocation(node.parameters[0]); if ((paramType.flags & 8 /* ts.TypeFlags.Number */) === 0) { return false; } @@ -183976,7 +184001,7 @@ var ts; if (isConstEnum(sym)) { return true; } - return isSendableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeFromTypeNode(typeNode)); + return isSendableType(typeChecker.getTypeFromTypeNode(typeNode)); } Utils.isSendableTypeNode = isSendableTypeNode; function isSendableType(type) { @@ -184113,6 +184138,7 @@ var ts; var sym = trueSymbolAtLocation(node); return getDeclaration(sym); } + Utils.getDeclarationNode = getDeclarationNode; function isFunctionLikeDeclaration(node) { return ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node) || ts.isConstructorDeclaration(node) || @@ -184123,9 +184149,23 @@ var ts; var typeNode = decl === null || decl === void 0 ? void 0 : decl.type; return (typeNode && !isFunctionLikeDeclaration(decl)) ? isSendableTypeNode(typeNode) : - isShareableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(decl ? decl : node)); + isShareableType(typeChecker.getTypeAtLocation(decl ? decl : node)); } Utils.isShareableEntity = isShareableEntity; + function isShareableClassOrInterfaceEntity(node) { + var decl = getDeclarationNode(node); + return isSendableClassOrInterface(typeChecker.getTypeAtLocation(decl !== null && decl !== void 0 ? decl : node)); + } + Utils.isShareableClassOrInterfaceEntity = isShareableClassOrInterfaceEntity; + function isInImportWhiteList(resolvedModule) { + if (!resolvedModule.resolvedFileName || + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_LANG_D_ETS && + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_COLLECTIONS_D_ETS) { + return false; + } + return true; + } + Utils.isInImportWhiteList = isInImportWhiteList; })(Utils = ArkTSLinter_1_1.Utils || (ArkTSLinter_1_1.Utils = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -184404,6 +184444,10 @@ var ts; LinterConfig.nodeDesc[FaultID.SharedNoSideEffectImport] = 'Shared no side effect import'; LinterConfig.nodeDesc[FaultID.SharedModuleExports] = 'Shared module exports'; LinterConfig.nodeDesc[FaultID.SharedModuleNoStarExport] = 'Share module no star export'; + LinterConfig.nodeDesc[FaultID.NoTsImportEts] = 'No ts Import Ets'; + LinterConfig.nodeDesc[FaultID.SendableTypeInheritance] = 'Sendable type inheritance'; + LinterConfig.nodeDesc[FaultID.SendableTypeExported] = 'Sendable type exported'; + LinterConfig.nodeDesc[FaultID.SendableNoTsExportEts] = 'Sendable no ts export ets'; }; LinterConfig.nodeDesc = []; // The SyntaxKind enum defines additional elements at the end of the enum @@ -186574,6 +186618,327 @@ var ts; ArkTSLinter_1_1.TypeScriptLinter = TypeScriptLinter; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); +/* + * Copyright (c) 2022-2023 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. + */ +var ts; +(function (ts) { + var ArkTSLinter_1_1; + (function (ArkTSLinter_1_1) { + var FaultID = ArkTSLinter_1_1.Problems.FaultID; + var faultsAttrs = ArkTSLinter_1_1.Problems.faultsAttrs; + var Logger = ts.perfLogger; + var InteropTypescriptLinter = /** @class */ (function () { + function InteropTypescriptLinter(sourceFile, + /* private */ tsProgram, isInSdk) { + this.sourceFile = sourceFile; + this.isInSdk = isInSdk; + this.ARKTS_COLLECTIONS_ETS = '@arkts.collections'; + this.KIT_ARKTS_ETS = '@kit.ArkTS'; + this.handlersMap = new ts.Map([ + [272 /* ts.SyntaxKind.ImportDeclaration */, this.handleImportDeclaration], + [264 /* ts.SyntaxKind.InterfaceDeclaration */, this.handleInterfaceDeclaration], + [262 /* ts.SyntaxKind.ClassDeclaration */, this.handleClassDeclaration], + [212 /* ts.SyntaxKind.NewExpression */, this.handleNewExpression], + [208 /* ts.SyntaxKind.ObjectLiteralExpression */, this.handleObjectLiteralExpression], + [207 /* ts.SyntaxKind.ArrayLiteralExpression */, this.handleArrayLiteralExpression], + [233 /* ts.SyntaxKind.AsExpression */, this.handleAsExpression], + [278 /* ts.SyntaxKind.ExportDeclaration */, this.handleExportDeclaration] + ]); + InteropTypescriptLinter.tsTypeChecker = tsProgram.getLinterTypeChecker(); + this.currentErrorLine = 0; + this.currentWarningLine = 0; + } + InteropTypescriptLinter.initGlobals = function () { }; + InteropTypescriptLinter.initStatic = function () { + InteropTypescriptLinter.strictMode = true; + InteropTypescriptLinter.totalVisitedNodes = 0; + InteropTypescriptLinter.nodeCounters = []; + InteropTypescriptLinter.lineCounters = []; + InteropTypescriptLinter.totalErrorLines = 0; + InteropTypescriptLinter.totalWarningLines = 0; + InteropTypescriptLinter.errorLineNumbersString = ""; + InteropTypescriptLinter.warningLineNumbersString = ""; + for (var i = 0; i < FaultID.LAST_ID; i++) { + InteropTypescriptLinter.nodeCounters[i] = 0; + InteropTypescriptLinter.lineCounters[i] = 0; + } + InteropTypescriptLinter.problemsInfos = []; + }; + InteropTypescriptLinter.clearTsTypeChecker = function () { + InteropTypescriptLinter.tsTypeChecker = {}; + }; + InteropTypescriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { + var _a, _b; + if (autofixable === void 0) { autofixable = false; } + var _c = ArkTSLinter_1_1.Utils.getHighlightRange(node, faultId), startOffset = _c[0], endOffset = _c[1]; + var startPos = this.sourceFile.getLineAndCharacterOfPosition(startOffset); + var line = startPos.line + 1; + var character = startPos.character + 1; + InteropTypescriptLinter.nodeCounters[faultId]++; + var faultDescr = ArkTSLinter_1_1.LinterConfig.nodeDesc[faultId]; + var faultType = "unknown"; + var cookBookMsgNum = faultsAttrs[faultId] ? faultsAttrs[faultId].cookBookRef : 0; + var cookBookTg = ArkTSLinter_1_1.cookBookTag[cookBookMsgNum]; + var severity = (_b = (_a = faultsAttrs[faultId]) === null || _a === void 0 ? void 0 : _a.severity) !== null && _b !== void 0 ? _b : ArkTSLinter_1_1.Common.ProblemSeverity.ERROR; + var badNodeInfo = { + line: line, + column: character, + start: startOffset, + end: endOffset, + type: faultType, + severity: severity, + problem: FaultID[faultId], + suggest: cookBookMsgNum > 0 ? ArkTSLinter_1_1.cookBookMsg[cookBookMsgNum] : "", + rule: cookBookMsgNum > 0 && cookBookTg !== "" ? cookBookTg : faultDescr ? faultDescr : faultType, + ruleTag: cookBookMsgNum, + autofixable: autofixable, + autofix: autofix + }; + InteropTypescriptLinter.problemsInfos.push(badNodeInfo); + if (!InteropTypescriptLinter.reportDiagnostics) { + Logger.logEvent("Warning: ".concat(this.sourceFile.fileName, " (").concat(line, ", ").concat(character, "): ").concat(faultDescr ? faultDescr : faultType)); + } + InteropTypescriptLinter.lineCounters[faultId]++; + switch (faultsAttrs[faultId].severity) { + case ArkTSLinter_1_1.Common.ProblemSeverity.ERROR: { + this.currentErrorLine = line; + ++InteropTypescriptLinter.totalErrorLines; + InteropTypescriptLinter.errorLineNumbersString += line + ', '; + break; + } + case ArkTSLinter_1_1.Common.ProblemSeverity.WARNING: { + if (line === this.currentWarningLine) { + break; + } + this.currentWarningLine = line; + ++InteropTypescriptLinter.totalWarningLines; + InteropTypescriptLinter.warningLineNumbersString += line + ', '; + break; + } + } + }; + InteropTypescriptLinter.prototype.forEachNodeInSubtree = function (node, cb, stopCond) { + var _this = this; + cb.call(this, node); + if (stopCond === null || stopCond === void 0 ? void 0 : stopCond.call(this, node)) { + return; + } + ts.forEachChild(node, function (child) { + _this.forEachNodeInSubtree(child, cb, stopCond); + }); + }; + InteropTypescriptLinter.prototype.visitSourceFile = function (sf) { + var _this = this; + var callback = function (node) { + InteropTypescriptLinter.totalVisitedNodes++; + var handler = _this.handlersMap.get(node.kind); + if (handler !== undefined) { + handler.call(_this, node); + } + }; + var stopCondition = function (node) { + if (node === null || node.kind === null) { + return true; + } + if (ArkTSLinter_1_1.LinterConfig.terminalTokens.has(node.kind)) { + return true; + } + return false; + }; + this.forEachNodeInSubtree(sf, callback, stopCondition); + }; + InteropTypescriptLinter.prototype.handleImportDeclaration = function (node) { + var importDeclNode = node; + this.checkSendableClassorISendable(importDeclNode); + }; + InteropTypescriptLinter.prototype.checkSendableClassorISendable = function (node) { + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = node.moduleSpecifier; + if (!ts.isStringLiteralLike(contextSpecifier)) { + return; + } + var mode = ts.getModeForUsageLocation(currentSourceFile, contextSpecifier); + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + var importClause = node.importClause; + if (!resolvedModule) { + return; + } + if (!importClause) { + this.incrementCounters(node, FaultID.NoTsImportEts); + return; + } + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".ets" && (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".d.ets") { + return; + } + if (ArkTSLinter_1_1.Utils.isInImportWhiteList(resolvedModule)) { + return; + } + this.checkImportClause(importClause); + }; + InteropTypescriptLinter.prototype.checkImportClause = function (node) { + var _this = this; + var checkAndIncrement = function (identifier) { + if (identifier && !ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(identifier)) { + _this.incrementCounters(identifier, FaultID.NoTsImportEts); + } + }; + if (node.name) { + checkAndIncrement(node.name); + } + if (node.namedBindings) { + if (ts.isNamespaceImport(node.namedBindings)) { + this.incrementCounters(node.namedBindings, FaultID.NoTsImportEts); + } + else if (ts.isNamedImports(node.namedBindings)) { + node.namedBindings.elements.forEach(function (element) { + checkAndIncrement(element.name); + }); + } + } + }; + InteropTypescriptLinter.prototype.handleClassDeclaration = function (node) { + var tsClassDecl = node; + if (!tsClassDecl.heritageClauses) { + return; + } + for (var _i = 0, _a = tsClassDecl.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + // In ts files, sendable classes and sendable interfaces can not be extended or implemented. + InteropTypescriptLinter.prototype.checkClassOrInterfaceDeclarationHeritageClause = function (hClause) { + for (var _i = 0, _a = hClause.types; _i < _a.length; _i++) { + var tsTypeExpr = _a[_i]; + /* + * Always resolve type from 'tsTypeExpr' node, not from 'tsTypeExpr.expression' node, + * as for the latter, type checker will return incorrect type result for classes in + * 'extends' clause. Additionally, reduce reference, as mostly type checker returns + * the TypeReference type objects for classes and interfaces. + */ + var tsExprType = ArkTSLinter_1_1.Utils.reduceReference(InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsTypeExpr)); + var isSendableBaseType = ArkTSLinter_1_1.Utils.isSendableClassOrInterface(tsExprType); + if (isSendableBaseType) { + this.incrementCounters(tsTypeExpr, FaultID.SendableTypeInheritance); + } + } + }; + InteropTypescriptLinter.prototype.handleInterfaceDeclaration = function (node) { + var interfaceNode = node; + var iSymbol = ArkTSLinter_1_1.Utils.trueSymbolAtLocation(interfaceNode.name); + var iDecls = iSymbol ? iSymbol.getDeclarations() : null; + if (!iDecls) { + return; + } + if (!interfaceNode.heritageClauses) { + return; + } + for (var _i = 0, _a = interfaceNode.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + InteropTypescriptLinter.prototype.handleNewExpression = function (node) { + var tsNewExpr = node; + this.handleSendableGenericTypes(tsNewExpr); + }; + InteropTypescriptLinter.prototype.handleSendableGenericTypes = function (node) { + var type = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(node); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(type)) { + return; + } + var typeArgs = node.typeArguments; + if (!typeArgs || typeArgs.length === 0) { + return; + } + for (var _i = 0, typeArgs_6 = typeArgs; _i < typeArgs_6.length; _i++) { + var arg = typeArgs_6[_i]; + if (!ArkTSLinter_1_1.Utils.isSendableTypeNode(arg)) { + this.incrementCounters(arg, FaultID.SendableGenericTypes); + } + } + }; + InteropTypescriptLinter.prototype.handleObjectLiteralExpression = function (node) { + var objectLiteralExpr = node; + var objectLiteralType = InteropTypescriptLinter.tsTypeChecker.getContextualType(objectLiteralExpr); + if (objectLiteralType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(objectLiteralType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleArrayLiteralExpression = function (node) { + var arrayLitNode = node; + var arrayLitType = InteropTypescriptLinter.tsTypeChecker.getContextualType(arrayLitNode); + if (arrayLitType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(arrayLitType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleAsExpression = function (node) { + var tsAsExpr = node; + var targetType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.type).getNonNullableType(); + var exprType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.expression).getNonNullableType(); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(exprType) && + !ArkTSLinter_1_1.Utils.isObject(exprType) && + !ArkTSLinter_1_1.Utils.isAnyType(exprType) && + ArkTSLinter_1_1.Utils.isSendableClassOrInterface(targetType)) { + this.incrementCounters(tsAsExpr, FaultID.SendableAsExpr); + } + }; + InteropTypescriptLinter.prototype.handleExportDeclaration = function (node) { + var exportDecl = node; + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = exportDecl.moduleSpecifier; + // In ts files, re-export from .ets files is not supported. + if (contextSpecifier && ts.isStringLiteralLike(contextSpecifier)) { + var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".ets" || (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".d.ets") { + this.incrementCounters(node, FaultID.SendableNoTsExportEts); + } + return; + } + if (!this.isInSdk) { + return; + } + // In sdk .d.ts files, sendable classes and sendable interfaces can not be exported. + if (!exportDecl.exportClause) { + return; + } + if (!ts.isNamedExports(exportDecl.exportClause)) { + return; + } + for (var _i = 0, _a = exportDecl.exportClause.elements; _i < _a.length; _i++) { + var exportSpecifier = _a[_i]; + if (ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(exportSpecifier.name)) { + this.incrementCounters(exportSpecifier.name, FaultID.SendableTypeExported); + } + } + }; + InteropTypescriptLinter.prototype.lint = function () { + this.visitSourceFile(this.sourceFile); + }; + InteropTypescriptLinter.reportDiagnostics = true; + InteropTypescriptLinter.problemsInfos = []; + return InteropTypescriptLinter; + }()); + ArkTSLinter_1_1.InteropTypescriptLinter = InteropTypescriptLinter; + })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); +})(ts || (ts = {})); /* * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -186704,6 +187069,8 @@ var ts; var _a, _b; ArkTSLinter_1_1.TypeScriptLinter.errorLineNumbersString = ""; ArkTSLinter_1_1.TypeScriptLinter.warningLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.errorLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.warningLineNumbersString = ""; var diagnostics = []; ArkTSLinter_1_1.LinterConfig.initStatic(); // Retrieve list of changed files from the old program state. This needs @@ -186732,19 +187099,38 @@ var ts; var tscStrictDiagnostics = getTscDiagnostics(tscDiagnosticsLinter, srcFiles.filter(function (file) { return changedFiles.has(file.resolvedPath); })); timePrinterInstance.appendTime(ts.TimePhase.GET_TSC_DIAGNOSTICS); ArkTSLinter_1_1.TypeScriptLinter.initGlobals(); + ArkTSLinter_1_1.InteropTypescriptLinter.initGlobals(); var _loop_2 = function (fileToLint) { - ArkTSLinter_1_1.TypeScriptLinter.initStatic(); - if (ArkTSLinter_1_1.TypeScriptLinter.lintEtsOnly && fileToLint.scriptKind !== 8 /* ScriptKind.ETS */) { + if (fileToLint.scriptKind !== 8 /* ScriptKind.ETS */ && fileToLint.scriptKind !== 3 /* ScriptKind.TS */) { return "continue"; } var currentDiagnostics; if (changedFiles.has(fileToLint.resolvedPath)) { - var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); - ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); - linter.lint(); - // Get list of bad nodes from the current run. - currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; - ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + if (fileToLint.scriptKind === 8 /* ScriptKind.ETS */) { + ArkTSLinter_1_1.TypeScriptLinter.initStatic(); + var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); + linter.lint(); + // Get list of bad nodes from the current run. + currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; + ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } + else { + ArkTSLinter_1_1.InteropTypescriptLinter.initStatic(); + var isKit = ts.getBaseFileName(fileToLint.fileName).indexOf('@kit.') === 0; + var etsLoaderPath = program.getCompilerOptions().etsLoaderPath; + var isInSdk = etsLoaderPath ? ts.normalizePath(fileToLint.fileName).indexOf(ts.resolvePath(etsLoaderPath, "../..")) === 0 : false; + var isInOhModules = ts.isOHModules(fileToLint.fileName); + var tsImportSendableEnable = program.getCompilerOptions().tsImportSendableEnable; + if (isKit || isInOhModules || (!tsImportSendableEnable && !isInSdk)) { + return "continue"; + } + var InteropLinter = new ArkTSLinter_1_1.InteropTypescriptLinter(fileToLint, program, isInSdk); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.InteropTypescriptLinter.tsTypeChecker); + InteropLinter.lint(); + currentDiagnostics = []; + ArkTSLinter_1_1.InteropTypescriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } } else { // Get diagnostics from old run. @@ -186771,6 +187157,7 @@ var ts; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); + ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); ArkTSLinter_1_1.Utils.clearTrueSymbolAtLocationCache(); } diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index 9d55094199..31140a57a6 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -3164,6 +3164,7 @@ declare namespace ts { packageManagerType?: string; emitNodeModulesFiles?: boolean; etsLoaderPath?: string; + tsImportSendableEnable?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } export interface EtsOptions { @@ -9205,7 +9206,11 @@ declare namespace ts { SharedNoSideEffectImport = 89, SharedModuleExports = 90, SharedModuleNoStarExport = 91, - LAST_ID = 92 + NoTsImportEts = 92, + SendableTypeInheritance = 93, + SendableTypeExported = 94, + SendableNoTsExportEts = 95, + LAST_ID = 96 } class FaultAttributes { cookBookRef: number; @@ -9402,7 +9407,10 @@ declare namespace ts { function getDecoratorsIfInSendableClass(declaration: ts.HasDecorators): readonly ts.Decorator[] | undefined; function isISendableInterface(type: ts.Type): boolean; function isSharedModule(sourceFile: ts.SourceFile): boolean; + function getDeclarationNode(node: ts.Node): ts.Declaration | undefined; function isShareableEntity(node: ts.Node): boolean; + function isShareableClassOrInterfaceEntity(node: ts.Node): boolean; + function isInImportWhiteList(resolvedModule: ResolvedModuleFull): boolean; } } } @@ -9601,6 +9609,51 @@ declare namespace ts { } } } +declare namespace ts { + namespace ArkTSLinter_1_1 { + import Autofix = Autofixer.Autofix; + class InteropTypescriptLinter { + private sourceFile; + private isInSdk; + static strictMode: boolean; + static totalVisitedNodes: number; + static nodeCounters: number[]; + static lineCounters: number[]; + static totalErrorLines: number; + static errorLineNumbersString: string; + static totalWarningLines: number; + static warningLineNumbersString: string; + static reportDiagnostics: boolean; + static problemsInfos: ProblemInfo[]; + static initGlobals(): void; + static initStatic(): void; + static tsTypeChecker: TypeChecker; + currentErrorLine: number; + currentWarningLine: number; + readonly ARKTS_COLLECTIONS_ETS = "@arkts.collections"; + readonly KIT_ARKTS_ETS = "@kit.ArkTS"; + constructor(sourceFile: SourceFile, tsProgram: Program, isInSdk: boolean); + static clearTsTypeChecker(): void; + readonly handlersMap: ESMap void>; + incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; + private forEachNodeInSubtree; + private visitSourceFile; + private handleImportDeclaration; + private checkSendableClassorISendable; + private checkImportClause; + private handleClassDeclaration; + private checkClassOrInterfaceDeclarationHeritageClause; + private handleInterfaceDeclaration; + private handleNewExpression; + private handleSendableGenericTypes; + private handleObjectLiteralExpression; + private handleArrayLiteralExpression; + private handleAsExpression; + private handleExportDeclaration; + lint(): void; + } + } +} declare namespace ts { namespace ArkTSLinter_1_1 { class TSCCompiledProgram { diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 636b6db7e6..7ba7c0956d 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -53964,13 +53964,19 @@ var ts; ((_f = (ts.isLiteralImportTypeNode(location) ? location : undefined)) === null || _f === void 0 ? void 0 : _f.argument.literal); var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference, mode); + // the relative path of sdk + var sdkPath = compilerOptions.etsLoaderPath ? ts.resolvePath(compilerOptions.etsLoaderPath, "../..") : undefined; if (compilerOptions.needDoArkTsLinter && currentSourceFile && currentSourceFile.scriptKind === 3 /* ScriptKind.TS */ && resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) { var diagnosticType = compilerOptions.isCompatibleVersion ? ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden : ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden; - error(errorNode, diagnosticType, moduleReference); + if (ts.isImportCall(location) || !allowImportSendable(sdkPath, currentSourceFile)) { + // If the node is ImportCall throw error + // If currentSourceFile is not allowImportSendable (.d.ts inside sdk or .ts file when tsImportSendable is true) + error(errorNode, diagnosticType, moduleReference); + } } var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule @@ -54128,6 +54134,13 @@ var ts; } return undefined; } + function allowImportSendable(sdkPath, currentSourceFile) { + var isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath)); + // Check the file is a TypeScript file outside of the method + // currentSourceFile must be a ts file + return ((isInSdkPath && currentSourceFile.isDeclarationFile) || + (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile)); + } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; var errorInfo = !ts.isExternalModuleNameRelative(moduleReference) && packageId @@ -181730,7 +181743,7 @@ var ts; (function (ArkTSLinter_1_1) { ArkTSLinter_1_1.cookBookMsg = []; ArkTSLinter_1_1.cookBookTag = []; - for (var i = 0; i <= 164; i++) { + for (var i = 0; i <= 168; i++) { ArkTSLinter_1_1.cookBookMsg[i] = ""; } ArkTSLinter_1_1.cookBookTag[1] = "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)"; @@ -181897,6 +181910,10 @@ var ts; ArkTSLinter_1_1.cookBookTag[162] = 'Importing a module for side-effects only is not supported in shared module (arkts-no-side-effects-imports)'; ArkTSLinter_1_1.cookBookTag[163] = 'Exported object must have a Sendable data type in shared module (arkts-shared-module-exports)'; ArkTSLinter_1_1.cookBookTag[164] = '"export * from \'xxx\'" is not supported in shared module (arkts-shared-module-no-star-export)'; + ArkTSLinter_1_1.cookBookTag[165] = 'Only "Sendable" classes and "Sendable" interfaces are allowed for importing from ets into ts file (arkts-no-ts-import-ets)'; + ArkTSLinter_1_1.cookBookTag[166] = 'In ts files, "Sendable" types cannot be used in implements and extends clauses (arkts-no-ts-sendable-type-inheritance)'; + ArkTSLinter_1_1.cookBookTag[167] = 'In sdk ts files, "Sendable" class and "Sendable" interface can not be exported (arkts-no-dts-sendable-type-export)'; + ArkTSLinter_1_1.cookBookTag[168] = 'In ts files, entities from ets files can not be re-exported (arkts-no-ts-re-export-ets)'; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); /* @@ -182157,7 +182174,11 @@ var ts; FaultID[FaultID["SharedNoSideEffectImport"] = 89] = "SharedNoSideEffectImport"; FaultID[FaultID["SharedModuleExports"] = 90] = "SharedModuleExports"; FaultID[FaultID["SharedModuleNoStarExport"] = 91] = "SharedModuleNoStarExport"; - FaultID[FaultID["LAST_ID"] = 92] = "LAST_ID"; + FaultID[FaultID["NoTsImportEts"] = 92] = "NoTsImportEts"; + FaultID[FaultID["SendableTypeInheritance"] = 93] = "SendableTypeInheritance"; + FaultID[FaultID["SendableTypeExported"] = 94] = "SendableTypeExported"; + FaultID[FaultID["SendableNoTsExportEts"] = 95] = "SendableNoTsExportEts"; + FaultID[FaultID["LAST_ID"] = 96] = "LAST_ID"; })(FaultID = Problems.FaultID || (Problems.FaultID = {})); var FaultAttributes = /** @class */ (function () { function FaultAttributes(cookBookRef, migratable, severity) { @@ -182263,6 +182284,10 @@ var ts; Problems.faultsAttrs[FaultID.SharedNoSideEffectImport] = new FaultAttributes(162); Problems.faultsAttrs[FaultID.SharedModuleExports] = new FaultAttributes(163); Problems.faultsAttrs[FaultID.SharedModuleNoStarExport] = new FaultAttributes(164); + Problems.faultsAttrs[FaultID.NoTsImportEts] = new FaultAttributes(165); + Problems.faultsAttrs[FaultID.SendableTypeInheritance] = new FaultAttributes(166); + Problems.faultsAttrs[FaultID.SendableTypeExported] = new FaultAttributes(167); + Problems.faultsAttrs[FaultID.SendableNoTsExportEts] = new FaultAttributes(168); })(Problems = ArkTSLinter_1_1.Problems || (ArkTSLinter_1_1.Problems = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -183300,7 +183325,7 @@ var ts; if (!propSym || !((_a = propSym.declarations) === null || _a === void 0 ? void 0 : _a.length)) { return false; } - var propType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); + var propType = typeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); var initExpr = unwrapParenthesized(prop.initializer); if (ts.isObjectLiteralExpression(initExpr)) { if (!isObjectLiteralAssignable(propType, initExpr)) { @@ -183309,7 +183334,7 @@ var ts; } else { // Only check for structural sub-typing. - if (needToDeduceStructuralIdentity(propType, ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(initExpr), initExpr)) { + if (needToDeduceStructuralIdentity(propType, typeChecker.getTypeAtLocation(initExpr), initExpr)) { return false; } } @@ -183452,7 +183477,7 @@ var ts; } Utils.isSymbolAPI = isSymbolAPI; function isStdSymbol(symbol) { - var name = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getFullyQualifiedName(symbol); + var name = typeChecker.getFullyQualifiedName(symbol); return name === 'Symbol' && isGlobalSymbol(symbol); } Utils.isStdSymbol = isStdSymbol; @@ -183741,7 +183766,7 @@ var ts; if (ts.isArrayLiteralExpression(node) || ts.isObjectLiteralExpression(node)) { return false; } - var valueType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node); + var valueType = typeChecker.getTypeAtLocation(node); return isUnsupportedType(valueType) || isAnonymousType(valueType); } Utils.isValueAssignableToESObject = isValueAssignableToESObject; @@ -183874,7 +183899,7 @@ var ts; function isEnumStringLiteral(expr) { var symbol = trueSymbolAtLocation(expr); var isEnumMember = !!symbol && !!(symbol.flags & 8 /* ts.SymbolFlags.EnumMember */); - var type = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(expr); + var type = typeChecker.getTypeAtLocation(expr); var isStringEnumLiteral = isEnumType(type) && !!(type.flags & 128 /* ts.TypeFlags.StringLiteral */); return isEnumMember && isStringEnumLiteral; } @@ -183899,7 +183924,7 @@ var ts; if (node.parameters.length !== 1) { return false; } - var paramType = ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node.parameters[0]); + var paramType = typeChecker.getTypeAtLocation(node.parameters[0]); if ((paramType.flags & 8 /* ts.TypeFlags.Number */) === 0) { return false; } @@ -183976,7 +184001,7 @@ var ts; if (isConstEnum(sym)) { return true; } - return isSendableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeFromTypeNode(typeNode)); + return isSendableType(typeChecker.getTypeFromTypeNode(typeNode)); } Utils.isSendableTypeNode = isSendableTypeNode; function isSendableType(type) { @@ -184113,6 +184138,7 @@ var ts; var sym = trueSymbolAtLocation(node); return getDeclaration(sym); } + Utils.getDeclarationNode = getDeclarationNode; function isFunctionLikeDeclaration(node) { return ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node) || ts.isConstructorDeclaration(node) || @@ -184123,9 +184149,23 @@ var ts; var typeNode = decl === null || decl === void 0 ? void 0 : decl.type; return (typeNode && !isFunctionLikeDeclaration(decl)) ? isSendableTypeNode(typeNode) : - isShareableType(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker.getTypeAtLocation(decl ? decl : node)); + isShareableType(typeChecker.getTypeAtLocation(decl ? decl : node)); } Utils.isShareableEntity = isShareableEntity; + function isShareableClassOrInterfaceEntity(node) { + var decl = getDeclarationNode(node); + return isSendableClassOrInterface(typeChecker.getTypeAtLocation(decl !== null && decl !== void 0 ? decl : node)); + } + Utils.isShareableClassOrInterfaceEntity = isShareableClassOrInterfaceEntity; + function isInImportWhiteList(resolvedModule) { + if (!resolvedModule.resolvedFileName || + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_LANG_D_ETS && + ts.getBaseFileName(resolvedModule.resolvedFileName) !== Utils.ARKTS_COLLECTIONS_D_ETS) { + return false; + } + return true; + } + Utils.isInImportWhiteList = isInImportWhiteList; })(Utils = ArkTSLinter_1_1.Utils || (ArkTSLinter_1_1.Utils = {})); })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); @@ -184404,6 +184444,10 @@ var ts; LinterConfig.nodeDesc[FaultID.SharedNoSideEffectImport] = 'Shared no side effect import'; LinterConfig.nodeDesc[FaultID.SharedModuleExports] = 'Shared module exports'; LinterConfig.nodeDesc[FaultID.SharedModuleNoStarExport] = 'Share module no star export'; + LinterConfig.nodeDesc[FaultID.NoTsImportEts] = 'No ts Import Ets'; + LinterConfig.nodeDesc[FaultID.SendableTypeInheritance] = 'Sendable type inheritance'; + LinterConfig.nodeDesc[FaultID.SendableTypeExported] = 'Sendable type exported'; + LinterConfig.nodeDesc[FaultID.SendableNoTsExportEts] = 'Sendable no ts export ets'; }; LinterConfig.nodeDesc = []; // The SyntaxKind enum defines additional elements at the end of the enum @@ -186574,6 +186618,327 @@ var ts; ArkTSLinter_1_1.TypeScriptLinter = TypeScriptLinter; })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); })(ts || (ts = {})); +/* + * Copyright (c) 2022-2023 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. + */ +var ts; +(function (ts) { + var ArkTSLinter_1_1; + (function (ArkTSLinter_1_1) { + var FaultID = ArkTSLinter_1_1.Problems.FaultID; + var faultsAttrs = ArkTSLinter_1_1.Problems.faultsAttrs; + var Logger = ts.perfLogger; + var InteropTypescriptLinter = /** @class */ (function () { + function InteropTypescriptLinter(sourceFile, + /* private */ tsProgram, isInSdk) { + this.sourceFile = sourceFile; + this.isInSdk = isInSdk; + this.ARKTS_COLLECTIONS_ETS = '@arkts.collections'; + this.KIT_ARKTS_ETS = '@kit.ArkTS'; + this.handlersMap = new ts.Map([ + [272 /* ts.SyntaxKind.ImportDeclaration */, this.handleImportDeclaration], + [264 /* ts.SyntaxKind.InterfaceDeclaration */, this.handleInterfaceDeclaration], + [262 /* ts.SyntaxKind.ClassDeclaration */, this.handleClassDeclaration], + [212 /* ts.SyntaxKind.NewExpression */, this.handleNewExpression], + [208 /* ts.SyntaxKind.ObjectLiteralExpression */, this.handleObjectLiteralExpression], + [207 /* ts.SyntaxKind.ArrayLiteralExpression */, this.handleArrayLiteralExpression], + [233 /* ts.SyntaxKind.AsExpression */, this.handleAsExpression], + [278 /* ts.SyntaxKind.ExportDeclaration */, this.handleExportDeclaration] + ]); + InteropTypescriptLinter.tsTypeChecker = tsProgram.getLinterTypeChecker(); + this.currentErrorLine = 0; + this.currentWarningLine = 0; + } + InteropTypescriptLinter.initGlobals = function () { }; + InteropTypescriptLinter.initStatic = function () { + InteropTypescriptLinter.strictMode = true; + InteropTypescriptLinter.totalVisitedNodes = 0; + InteropTypescriptLinter.nodeCounters = []; + InteropTypescriptLinter.lineCounters = []; + InteropTypescriptLinter.totalErrorLines = 0; + InteropTypescriptLinter.totalWarningLines = 0; + InteropTypescriptLinter.errorLineNumbersString = ""; + InteropTypescriptLinter.warningLineNumbersString = ""; + for (var i = 0; i < FaultID.LAST_ID; i++) { + InteropTypescriptLinter.nodeCounters[i] = 0; + InteropTypescriptLinter.lineCounters[i] = 0; + } + InteropTypescriptLinter.problemsInfos = []; + }; + InteropTypescriptLinter.clearTsTypeChecker = function () { + InteropTypescriptLinter.tsTypeChecker = {}; + }; + InteropTypescriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { + var _a, _b; + if (autofixable === void 0) { autofixable = false; } + var _c = ArkTSLinter_1_1.Utils.getHighlightRange(node, faultId), startOffset = _c[0], endOffset = _c[1]; + var startPos = this.sourceFile.getLineAndCharacterOfPosition(startOffset); + var line = startPos.line + 1; + var character = startPos.character + 1; + InteropTypescriptLinter.nodeCounters[faultId]++; + var faultDescr = ArkTSLinter_1_1.LinterConfig.nodeDesc[faultId]; + var faultType = "unknown"; + var cookBookMsgNum = faultsAttrs[faultId] ? faultsAttrs[faultId].cookBookRef : 0; + var cookBookTg = ArkTSLinter_1_1.cookBookTag[cookBookMsgNum]; + var severity = (_b = (_a = faultsAttrs[faultId]) === null || _a === void 0 ? void 0 : _a.severity) !== null && _b !== void 0 ? _b : ArkTSLinter_1_1.Common.ProblemSeverity.ERROR; + var badNodeInfo = { + line: line, + column: character, + start: startOffset, + end: endOffset, + type: faultType, + severity: severity, + problem: FaultID[faultId], + suggest: cookBookMsgNum > 0 ? ArkTSLinter_1_1.cookBookMsg[cookBookMsgNum] : "", + rule: cookBookMsgNum > 0 && cookBookTg !== "" ? cookBookTg : faultDescr ? faultDescr : faultType, + ruleTag: cookBookMsgNum, + autofixable: autofixable, + autofix: autofix + }; + InteropTypescriptLinter.problemsInfos.push(badNodeInfo); + if (!InteropTypescriptLinter.reportDiagnostics) { + Logger.logEvent("Warning: ".concat(this.sourceFile.fileName, " (").concat(line, ", ").concat(character, "): ").concat(faultDescr ? faultDescr : faultType)); + } + InteropTypescriptLinter.lineCounters[faultId]++; + switch (faultsAttrs[faultId].severity) { + case ArkTSLinter_1_1.Common.ProblemSeverity.ERROR: { + this.currentErrorLine = line; + ++InteropTypescriptLinter.totalErrorLines; + InteropTypescriptLinter.errorLineNumbersString += line + ', '; + break; + } + case ArkTSLinter_1_1.Common.ProblemSeverity.WARNING: { + if (line === this.currentWarningLine) { + break; + } + this.currentWarningLine = line; + ++InteropTypescriptLinter.totalWarningLines; + InteropTypescriptLinter.warningLineNumbersString += line + ', '; + break; + } + } + }; + InteropTypescriptLinter.prototype.forEachNodeInSubtree = function (node, cb, stopCond) { + var _this = this; + cb.call(this, node); + if (stopCond === null || stopCond === void 0 ? void 0 : stopCond.call(this, node)) { + return; + } + ts.forEachChild(node, function (child) { + _this.forEachNodeInSubtree(child, cb, stopCond); + }); + }; + InteropTypescriptLinter.prototype.visitSourceFile = function (sf) { + var _this = this; + var callback = function (node) { + InteropTypescriptLinter.totalVisitedNodes++; + var handler = _this.handlersMap.get(node.kind); + if (handler !== undefined) { + handler.call(_this, node); + } + }; + var stopCondition = function (node) { + if (node === null || node.kind === null) { + return true; + } + if (ArkTSLinter_1_1.LinterConfig.terminalTokens.has(node.kind)) { + return true; + } + return false; + }; + this.forEachNodeInSubtree(sf, callback, stopCondition); + }; + InteropTypescriptLinter.prototype.handleImportDeclaration = function (node) { + var importDeclNode = node; + this.checkSendableClassorISendable(importDeclNode); + }; + InteropTypescriptLinter.prototype.checkSendableClassorISendable = function (node) { + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = node.moduleSpecifier; + if (!ts.isStringLiteralLike(contextSpecifier)) { + return; + } + var mode = ts.getModeForUsageLocation(currentSourceFile, contextSpecifier); + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + var importClause = node.importClause; + if (!resolvedModule) { + return; + } + if (!importClause) { + this.incrementCounters(node, FaultID.NoTsImportEts); + return; + } + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".ets" && (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) !== ".d.ets") { + return; + } + if (ArkTSLinter_1_1.Utils.isInImportWhiteList(resolvedModule)) { + return; + } + this.checkImportClause(importClause); + }; + InteropTypescriptLinter.prototype.checkImportClause = function (node) { + var _this = this; + var checkAndIncrement = function (identifier) { + if (identifier && !ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(identifier)) { + _this.incrementCounters(identifier, FaultID.NoTsImportEts); + } + }; + if (node.name) { + checkAndIncrement(node.name); + } + if (node.namedBindings) { + if (ts.isNamespaceImport(node.namedBindings)) { + this.incrementCounters(node.namedBindings, FaultID.NoTsImportEts); + } + else if (ts.isNamedImports(node.namedBindings)) { + node.namedBindings.elements.forEach(function (element) { + checkAndIncrement(element.name); + }); + } + } + }; + InteropTypescriptLinter.prototype.handleClassDeclaration = function (node) { + var tsClassDecl = node; + if (!tsClassDecl.heritageClauses) { + return; + } + for (var _i = 0, _a = tsClassDecl.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + // In ts files, sendable classes and sendable interfaces can not be extended or implemented. + InteropTypescriptLinter.prototype.checkClassOrInterfaceDeclarationHeritageClause = function (hClause) { + for (var _i = 0, _a = hClause.types; _i < _a.length; _i++) { + var tsTypeExpr = _a[_i]; + /* + * Always resolve type from 'tsTypeExpr' node, not from 'tsTypeExpr.expression' node, + * as for the latter, type checker will return incorrect type result for classes in + * 'extends' clause. Additionally, reduce reference, as mostly type checker returns + * the TypeReference type objects for classes and interfaces. + */ + var tsExprType = ArkTSLinter_1_1.Utils.reduceReference(InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsTypeExpr)); + var isSendableBaseType = ArkTSLinter_1_1.Utils.isSendableClassOrInterface(tsExprType); + if (isSendableBaseType) { + this.incrementCounters(tsTypeExpr, FaultID.SendableTypeInheritance); + } + } + }; + InteropTypescriptLinter.prototype.handleInterfaceDeclaration = function (node) { + var interfaceNode = node; + var iSymbol = ArkTSLinter_1_1.Utils.trueSymbolAtLocation(interfaceNode.name); + var iDecls = iSymbol ? iSymbol.getDeclarations() : null; + if (!iDecls) { + return; + } + if (!interfaceNode.heritageClauses) { + return; + } + for (var _i = 0, _a = interfaceNode.heritageClauses; _i < _a.length; _i++) { + var hClause = _a[_i]; + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + }; + InteropTypescriptLinter.prototype.handleNewExpression = function (node) { + var tsNewExpr = node; + this.handleSendableGenericTypes(tsNewExpr); + }; + InteropTypescriptLinter.prototype.handleSendableGenericTypes = function (node) { + var type = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(node); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(type)) { + return; + } + var typeArgs = node.typeArguments; + if (!typeArgs || typeArgs.length === 0) { + return; + } + for (var _i = 0, typeArgs_6 = typeArgs; _i < typeArgs_6.length; _i++) { + var arg = typeArgs_6[_i]; + if (!ArkTSLinter_1_1.Utils.isSendableTypeNode(arg)) { + this.incrementCounters(arg, FaultID.SendableGenericTypes); + } + } + }; + InteropTypescriptLinter.prototype.handleObjectLiteralExpression = function (node) { + var objectLiteralExpr = node; + var objectLiteralType = InteropTypescriptLinter.tsTypeChecker.getContextualType(objectLiteralExpr); + if (objectLiteralType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(objectLiteralType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleArrayLiteralExpression = function (node) { + var arrayLitNode = node; + var arrayLitType = InteropTypescriptLinter.tsTypeChecker.getContextualType(arrayLitNode); + if (arrayLitType && ArkTSLinter_1_1.Utils.typeContainsSendableClassOrInterface(arrayLitType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + }; + InteropTypescriptLinter.prototype.handleAsExpression = function (node) { + var tsAsExpr = node; + var targetType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.type).getNonNullableType(); + var exprType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.expression).getNonNullableType(); + if (!ArkTSLinter_1_1.Utils.isSendableClassOrInterface(exprType) && + !ArkTSLinter_1_1.Utils.isObject(exprType) && + !ArkTSLinter_1_1.Utils.isAnyType(exprType) && + ArkTSLinter_1_1.Utils.isSendableClassOrInterface(targetType)) { + this.incrementCounters(tsAsExpr, FaultID.SendableAsExpr); + } + }; + InteropTypescriptLinter.prototype.handleExportDeclaration = function (node) { + var exportDecl = node; + var currentSourceFile = ts.getSourceFileOfNode(node); + var contextSpecifier = exportDecl.moduleSpecifier; + // In ts files, re-export from .ets files is not supported. + if (contextSpecifier && ts.isStringLiteralLike(contextSpecifier)) { + var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + var resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + if ((resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".ets" || (resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.extension) === ".d.ets") { + this.incrementCounters(node, FaultID.SendableNoTsExportEts); + } + return; + } + if (!this.isInSdk) { + return; + } + // In sdk .d.ts files, sendable classes and sendable interfaces can not be exported. + if (!exportDecl.exportClause) { + return; + } + if (!ts.isNamedExports(exportDecl.exportClause)) { + return; + } + for (var _i = 0, _a = exportDecl.exportClause.elements; _i < _a.length; _i++) { + var exportSpecifier = _a[_i]; + if (ArkTSLinter_1_1.Utils.isShareableClassOrInterfaceEntity(exportSpecifier.name)) { + this.incrementCounters(exportSpecifier.name, FaultID.SendableTypeExported); + } + } + }; + InteropTypescriptLinter.prototype.lint = function () { + this.visitSourceFile(this.sourceFile); + }; + InteropTypescriptLinter.reportDiagnostics = true; + InteropTypescriptLinter.problemsInfos = []; + return InteropTypescriptLinter; + }()); + ArkTSLinter_1_1.InteropTypescriptLinter = InteropTypescriptLinter; + })(ArkTSLinter_1_1 = ts.ArkTSLinter_1_1 || (ts.ArkTSLinter_1_1 = {})); +})(ts || (ts = {})); /* * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -186704,6 +187069,8 @@ var ts; var _a, _b; ArkTSLinter_1_1.TypeScriptLinter.errorLineNumbersString = ""; ArkTSLinter_1_1.TypeScriptLinter.warningLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.errorLineNumbersString = ""; + ArkTSLinter_1_1.InteropTypescriptLinter.warningLineNumbersString = ""; var diagnostics = []; ArkTSLinter_1_1.LinterConfig.initStatic(); // Retrieve list of changed files from the old program state. This needs @@ -186732,19 +187099,38 @@ var ts; var tscStrictDiagnostics = getTscDiagnostics(tscDiagnosticsLinter, srcFiles.filter(function (file) { return changedFiles.has(file.resolvedPath); })); timePrinterInstance.appendTime(ts.TimePhase.GET_TSC_DIAGNOSTICS); ArkTSLinter_1_1.TypeScriptLinter.initGlobals(); + ArkTSLinter_1_1.InteropTypescriptLinter.initGlobals(); var _loop_2 = function (fileToLint) { - ArkTSLinter_1_1.TypeScriptLinter.initStatic(); - if (ArkTSLinter_1_1.TypeScriptLinter.lintEtsOnly && fileToLint.scriptKind !== 8 /* ScriptKind.ETS */) { + if (fileToLint.scriptKind !== 8 /* ScriptKind.ETS */ && fileToLint.scriptKind !== 3 /* ScriptKind.TS */) { return "continue"; } var currentDiagnostics; if (changedFiles.has(fileToLint.resolvedPath)) { - var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); - ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); - linter.lint(); - // Get list of bad nodes from the current run. - currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; - ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + if (fileToLint.scriptKind === 8 /* ScriptKind.ETS */) { + ArkTSLinter_1_1.TypeScriptLinter.initStatic(); + var linter = new ArkTSLinter_1_1.TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.TypeScriptLinter.tsTypeChecker); + linter.lint(); + // Get list of bad nodes from the current run. + currentDiagnostics = (_a = tscStrictDiagnostics.get(ts.normalizePath(fileToLint.fileName))) !== null && _a !== void 0 ? _a : []; + ArkTSLinter_1_1.TypeScriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } + else { + ArkTSLinter_1_1.InteropTypescriptLinter.initStatic(); + var isKit = ts.getBaseFileName(fileToLint.fileName).indexOf('@kit.') === 0; + var etsLoaderPath = program.getCompilerOptions().etsLoaderPath; + var isInSdk = etsLoaderPath ? ts.normalizePath(fileToLint.fileName).indexOf(ts.resolvePath(etsLoaderPath, "../..")) === 0 : false; + var isInOhModules = ts.isOHModules(fileToLint.fileName); + var tsImportSendableEnable = program.getCompilerOptions().tsImportSendableEnable; + if (isKit || isInOhModules || (!tsImportSendableEnable && !isInSdk)) { + return "continue"; + } + var InteropLinter = new ArkTSLinter_1_1.InteropTypescriptLinter(fileToLint, program, isInSdk); + ArkTSLinter_1_1.Utils.setTypeChecker(ArkTSLinter_1_1.InteropTypescriptLinter.tsTypeChecker); + InteropLinter.lint(); + currentDiagnostics = []; + ArkTSLinter_1_1.InteropTypescriptLinter.problemsInfos.forEach(function (x) { return currentDiagnostics.push(translateDiag(fileToLint, x)); }); + } } else { // Get diagnostics from old run. @@ -186771,6 +187157,7 @@ var ts; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); + ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); ArkTSLinter_1_1.Utils.clearTrueSymbolAtLocationCache(); } diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 4857a556fc..3bd97d114e 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -53954,13 +53954,19 @@ var ts; ((_f = (ts.isLiteralImportTypeNode(location) ? location : undefined)) === null || _f === void 0 ? void 0 : _f.argument.literal); var mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference, mode); + // the relative path of sdk + var sdkPath = compilerOptions.etsLoaderPath ? ts.resolvePath(compilerOptions.etsLoaderPath, "../..") : undefined; if (compilerOptions.needDoArkTsLinter && currentSourceFile && currentSourceFile.scriptKind === 3 /* ScriptKind.TS */ && resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) { var diagnosticType = compilerOptions.isCompatibleVersion ? ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden : ts.Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden; - error(errorNode, diagnosticType, moduleReference); + if (ts.isImportCall(location) || !allowImportSendable(sdkPath, currentSourceFile)) { + // If the node is ImportCall throw error + // If currentSourceFile is not allowImportSendable (.d.ts inside sdk or .ts file when tsImportSendable is true) + error(errorNode, diagnosticType, moduleReference); + } } var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule @@ -54118,6 +54124,13 @@ var ts; } return undefined; } + function allowImportSendable(sdkPath, currentSourceFile) { + var isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath)); + // Check the file is a TypeScript file outside of the method + // currentSourceFile must be a ts file + return ((isInSdkPath && currentSourceFile.isDeclarationFile) || + (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile)); + } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; var errorInfo = !ts.isExternalModuleNameRelative(moduleReference) && packageId diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 45a6cc38eb..362be257b4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3745,14 +3745,19 @@ namespace ts { (isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal; const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; const resolvedModule = getResolvedModule(currentSourceFile, moduleReference, mode); - + // the relative path of sdk + const sdkPath = compilerOptions.etsLoaderPath ? resolvePath(compilerOptions.etsLoaderPath, "../..") : undefined; if (compilerOptions.needDoArkTsLinter && currentSourceFile && currentSourceFile.scriptKind === ScriptKind.TS && resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) { const diagnosticType = compilerOptions.isCompatibleVersion ? Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden : Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden; - error(errorNode, diagnosticType, moduleReference); + if (isImportCall(location) || !allowImportSendable(sdkPath, currentSourceFile)) { + // If the node is ImportCall throw error + // If currentSourceFile is not allowImportSendable (.d.ts inside sdk or .ts file when tsImportSendable is true) + error(errorNode, diagnosticType, moduleReference); + } } const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule); @@ -3924,6 +3929,16 @@ namespace ts { } return undefined; } + + function allowImportSendable(sdkPath: string | undefined, currentSourceFile: SourceFile): boolean { + const isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath)); + // Check the file is a TypeScript file outside of the method + // currentSourceFile must be a ts file + return ( + (isInSdkPath && currentSourceFile.isDeclarationFile) || + (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile) + ); + } function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void { const errorInfo = !isExternalModuleNameRelative(moduleReference) && packageId diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 98a19aa676..e5e7fc5824 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6745,6 +6745,7 @@ namespace ts { packageManagerType?: string; emitNodeModulesFiles?: boolean; etsLoaderPath?: string; + tsImportSendableEnable?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } diff --git a/src/linter/ArkTSLinter_1_1/CookBookMsg.ts b/src/linter/ArkTSLinter_1_1/CookBookMsg.ts index e7556dc5b5..fbbd0752e4 100644 --- a/src/linter/ArkTSLinter_1_1/CookBookMsg.ts +++ b/src/linter/ArkTSLinter_1_1/CookBookMsg.ts @@ -17,7 +17,7 @@ export namespace ArkTSLinter_1_1 { export const cookBookMsg: string[] = []; export const cookBookTag: string[] = []; -for (let i = 0; i <= 164; i++) { +for (let i = 0; i <= 168; i++) { cookBookMsg[ i ] = ""; } @@ -185,5 +185,9 @@ cookBookTag[161] = 'Casting "Non-sendable" data to "Sendable" type is not allowe cookBookTag[162] = 'Importing a module for side-effects only is not supported in shared module (arkts-no-side-effects-imports)'; cookBookTag[163] = 'Exported object must have a Sendable data type in shared module (arkts-shared-module-exports)'; cookBookTag[164] = '"export * from \'xxx\'" is not supported in shared module (arkts-shared-module-no-star-export)'; +cookBookTag[165] = 'Only "Sendable" classes and "Sendable" interfaces are allowed for importing from ets into ts file (arkts-no-ts-import-ets)'; +cookBookTag[166] = 'In ts files, "Sendable" types cannot be used in implements and extends clauses (arkts-no-ts-sendable-type-inheritance)'; +cookBookTag[167] = 'In sdk ts files, "Sendable" class and "Sendable" interface can not be exported (arkts-no-dts-sendable-type-export)'; +cookBookTag[168] = 'In ts files, entities from ets files can not be re-exported (arkts-no-ts-re-export-ets)'; } } \ No newline at end of file diff --git a/src/linter/ArkTSLinter_1_1/InteropTypescriptLinter.ts b/src/linter/ArkTSLinter_1_1/InteropTypescriptLinter.ts new file mode 100644 index 0000000000..66658f2245 --- /dev/null +++ b/src/linter/ArkTSLinter_1_1/InteropTypescriptLinter.ts @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2022-2023 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. + */ + +namespace ts { + export namespace ArkTSLinter_1_1 { + + import FaultID = Problems.FaultID; + import faultsAttrs = Problems.faultsAttrs; + + import Autofix = Autofixer.Autofix; + + import Logger = ts.perfLogger; + + export class InteropTypescriptLinter { + static strictMode: boolean; + static totalVisitedNodes: number; + static nodeCounters: number[]; + static lineCounters: number[]; + + static totalErrorLines: number; + static errorLineNumbersString: string; + static totalWarningLines: number; + static warningLineNumbersString: string; + static reportDiagnostics = true; + + static problemsInfos: ProblemInfo[] = []; + + public static initGlobals(): void {} + + public static initStatic(): void { + InteropTypescriptLinter.strictMode = true; + InteropTypescriptLinter.totalVisitedNodes = 0; + InteropTypescriptLinter.nodeCounters = []; + InteropTypescriptLinter.lineCounters = []; + + InteropTypescriptLinter.totalErrorLines = 0; + InteropTypescriptLinter.totalWarningLines = 0; + InteropTypescriptLinter.errorLineNumbersString = ""; + InteropTypescriptLinter.warningLineNumbersString = ""; + + for (let i = 0; i < FaultID.LAST_ID; i++) { + InteropTypescriptLinter.nodeCounters[i] = 0; + InteropTypescriptLinter.lineCounters[i] = 0; + } + + InteropTypescriptLinter.problemsInfos = []; + } + + public static tsTypeChecker: TypeChecker; + + currentErrorLine: number; + currentWarningLine: number; + readonly ARKTS_COLLECTIONS_ETS = '@arkts.collections'; + readonly KIT_ARKTS_ETS = '@kit.ArkTS'; + + constructor(private sourceFile: SourceFile, + /* private */ tsProgram: Program, + private isInSdk: boolean) { + InteropTypescriptLinter.tsTypeChecker = tsProgram.getLinterTypeChecker(); + this.currentErrorLine = 0; + this.currentWarningLine = 0; + } + + public static clearTsTypeChecker(): void { + InteropTypescriptLinter.tsTypeChecker = {} as TypeChecker; + } + + readonly handlersMap = new Map([ + [ts.SyntaxKind.ImportDeclaration, this.handleImportDeclaration], + [ts.SyntaxKind.InterfaceDeclaration, this.handleInterfaceDeclaration], + [ts.SyntaxKind.ClassDeclaration, this.handleClassDeclaration], + [ts.SyntaxKind.NewExpression, this.handleNewExpression], + [ts.SyntaxKind.ObjectLiteralExpression, this.handleObjectLiteralExpression], + [ts.SyntaxKind.ArrayLiteralExpression, this.handleArrayLiteralExpression], + [ts.SyntaxKind.AsExpression, this.handleAsExpression], + [ts.SyntaxKind.ExportDeclaration, this.handleExportDeclaration] + ]); + + public incrementCounters(node: Node | CommentRange, faultId: number, autofixable = false, autofix?: Autofix[]): void { + const [startOffset, endOffset] = Utils.getHighlightRange(node, faultId); + const startPos = this.sourceFile!.getLineAndCharacterOfPosition(startOffset); + const line = startPos.line + 1; + const character = startPos.character + 1; + + InteropTypescriptLinter.nodeCounters[faultId]++; + + const faultDescr = LinterConfig.nodeDesc[faultId]; + const faultType = "unknown"; + + const cookBookMsgNum = faultsAttrs[faultId] ? faultsAttrs[faultId].cookBookRef : 0; + const cookBookTg = cookBookTag[cookBookMsgNum]; + const severity = faultsAttrs[faultId]?.severity ?? Common.ProblemSeverity.ERROR; + const badNodeInfo: ProblemInfo = { + line: line, + column: character, + start: startOffset, + end: endOffset, + type: faultType, + severity: severity, + problem: FaultID[faultId], + suggest: cookBookMsgNum > 0 ? cookBookMsg[cookBookMsgNum] : "", + rule: cookBookMsgNum > 0 && cookBookTg !== "" ? cookBookTg : faultDescr ? faultDescr : faultType, + ruleTag: cookBookMsgNum, + autofixable: autofixable, + autofix: autofix + }; + + InteropTypescriptLinter.problemsInfos.push(badNodeInfo); + + if (!InteropTypescriptLinter.reportDiagnostics) { + Logger.logEvent( + `Warning: ${this.sourceFile.fileName} (${line}, ${character}): ${faultDescr ? faultDescr : faultType}` + ); + } + + InteropTypescriptLinter.lineCounters[faultId]++; + + switch (faultsAttrs[faultId].severity) { + case Common.ProblemSeverity.ERROR: { + this.currentErrorLine = line; + ++InteropTypescriptLinter.totalErrorLines; + InteropTypescriptLinter.errorLineNumbersString += line + ', '; + break; + } + case Common.ProblemSeverity.WARNING: { + if (line === this.currentWarningLine) { + break; + } + this.currentWarningLine = line; + ++InteropTypescriptLinter.totalWarningLines; + InteropTypescriptLinter.warningLineNumbersString += line + ', '; + break; + } + } + } + + private forEachNodeInSubtree(node: ts.Node, cb: (n: ts.Node) => void, stopCond?: (n: ts.Node) => boolean): void { + cb.call(this, node); + if (stopCond?.call(this, node)) { + return; + } + ts.forEachChild(node, (child) => { + this.forEachNodeInSubtree(child, cb, stopCond); + }); + } + + private visitSourceFile(sf: ts.SourceFile): void { + const callback = (node: ts.Node): void => { + InteropTypescriptLinter.totalVisitedNodes++; + const handler = this.handlersMap.get(node.kind); + if (handler !== undefined) { + handler.call(this, node); + } + }; + const stopCondition = (node: ts.Node): boolean => { + if (node === null || node.kind === null) { + return true; + } + if (LinterConfig.terminalTokens.has(node.kind)) { + return true; + } + return false; + }; + this.forEachNodeInSubtree(sf, callback, stopCondition); + } + + private handleImportDeclaration(node: Node): void { + const importDeclNode = node as ImportDeclaration; + this.checkSendableClassorISendable(importDeclNode); + } + + private checkSendableClassorISendable(node: ts.ImportDeclaration) { + const currentSourceFile = ts.getSourceFileOfNode(node); + const contextSpecifier = node.moduleSpecifier; + if (!isStringLiteralLike(contextSpecifier)) { + return; + } + const mode = getModeForUsageLocation(currentSourceFile, contextSpecifier); + const resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + const importClause = node.importClause; + if (!resolvedModule) { + return; + } + if (!importClause) { + this.incrementCounters(node,FaultID.NoTsImportEts); + return; + } + if (resolvedModule?.extension !== ".ets" && resolvedModule?.extension !== ".d.ets") { + return; + } + if (Utils.isInImportWhiteList(resolvedModule)) { + return; + } + + this.checkImportClause(importClause); + } + + private checkImportClause(node: ts.ImportClause) { + const checkAndIncrement = (identifier: ts.Identifier | undefined) => { + if (identifier && !Utils.isShareableClassOrInterfaceEntity(identifier)) { + this.incrementCounters(identifier, FaultID.NoTsImportEts); + } + }; + if (node.name) { + checkAndIncrement(node.name); + } + if (node.namedBindings) { + if (ts.isNamespaceImport(node.namedBindings)) { + this.incrementCounters(node.namedBindings, FaultID.NoTsImportEts); + } else if (ts.isNamedImports(node.namedBindings)) { + node.namedBindings.elements.forEach(element => { + checkAndIncrement(element.name); + }); + } + } + } + + private handleClassDeclaration(node: Node): void { + const tsClassDecl = node as ClassDeclaration; + if (!tsClassDecl.heritageClauses) { + return; + } + + for (const hClause of tsClassDecl.heritageClauses) { + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + } + + // In ts files, sendable classes and sendable interfaces can not be extended or implemented. + private checkClassOrInterfaceDeclarationHeritageClause(hClause: ts.HeritageClause): void { + for (const tsTypeExpr of hClause.types) { + + /* + * Always resolve type from 'tsTypeExpr' node, not from 'tsTypeExpr.expression' node, + * as for the latter, type checker will return incorrect type result for classes in + * 'extends' clause. Additionally, reduce reference, as mostly type checker returns + * the TypeReference type objects for classes and interfaces. + */ + const tsExprType = Utils.reduceReference(InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsTypeExpr)); + const isSendableBaseType = Utils.isSendableClassOrInterface(tsExprType); + if (isSendableBaseType) { + this.incrementCounters(tsTypeExpr, FaultID.SendableTypeInheritance); + } + } + } + + private handleInterfaceDeclaration(node: Node): void { + const interfaceNode = node as InterfaceDeclaration; + const iSymbol = Utils.trueSymbolAtLocation(interfaceNode.name); + const iDecls = iSymbol ? iSymbol.getDeclarations() : null; + if (!iDecls) { + return; + } + + if (!interfaceNode.heritageClauses) { + return; + } + + for (const hClause of interfaceNode.heritageClauses) { + if (hClause) { + this.checkClassOrInterfaceDeclarationHeritageClause(hClause); + } + } + } + + private handleNewExpression(node: Node): void { + const tsNewExpr = node as NewExpression; + this.handleSendableGenericTypes(tsNewExpr); + } + + private handleSendableGenericTypes(node: ts.NewExpression): void { + const type = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(node); + if (!Utils.isSendableClassOrInterface(type)) { + return; + } + + const typeArgs = node.typeArguments; + if (!typeArgs || typeArgs.length === 0) { + return; + } + + for (const arg of typeArgs) { + if (!Utils.isSendableTypeNode(arg)) { + this.incrementCounters(arg, FaultID.SendableGenericTypes); + } + } + } + + private handleObjectLiteralExpression(node: Node): void { + const objectLiteralExpr = node as ObjectLiteralExpression; + const objectLiteralType = InteropTypescriptLinter.tsTypeChecker.getContextualType(objectLiteralExpr); + if (objectLiteralType && Utils.typeContainsSendableClassOrInterface(objectLiteralType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + } + + private handleArrayLiteralExpression(node: Node): void { + const arrayLitNode = node as ArrayLiteralExpression; + const arrayLitType = InteropTypescriptLinter.tsTypeChecker.getContextualType(arrayLitNode); + if (arrayLitType && Utils.typeContainsSendableClassOrInterface(arrayLitType)) { + this.incrementCounters(node, FaultID.SendableObjectInitialization); + } + } + + private handleAsExpression(node: Node): void { + const tsAsExpr = node as AsExpression; + const targetType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.type).getNonNullableType(); + const exprType = InteropTypescriptLinter.tsTypeChecker.getTypeAtLocation(tsAsExpr.expression).getNonNullableType(); + + if ( + !Utils.isSendableClassOrInterface(exprType) && + !Utils.isObject(exprType) && + !Utils.isAnyType(exprType) && + Utils.isSendableClassOrInterface(targetType) + ) { + this.incrementCounters(tsAsExpr, FaultID.SendableAsExpr); + } + } + + private handleExportDeclaration(node: ts.Node): void { + const exportDecl = node as ts.ExportDeclaration; + const currentSourceFile = ts.getSourceFileOfNode(node); + const contextSpecifier = exportDecl.moduleSpecifier; + + // In ts files, re-export from .ets files is not supported. + if (contextSpecifier && isStringLiteralLike(contextSpecifier)) { + const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + const resolvedModule = ts.getResolvedModule(currentSourceFile, contextSpecifier.text, mode); + if (resolvedModule?.extension === ".ets" || resolvedModule?.extension === ".d.ets") { + this.incrementCounters(node,FaultID.SendableNoTsExportEts); + } + return; + } + + if (!this.isInSdk) { + return; + } + + // In sdk .d.ts files, sendable classes and sendable interfaces can not be exported. + if (!exportDecl.exportClause) { + return; + } + + if (!ts.isNamedExports(exportDecl.exportClause)) { + return; + } + + for (const exportSpecifier of exportDecl.exportClause.elements) { + if (Utils.isShareableClassOrInterfaceEntity(exportSpecifier.name)) { + this.incrementCounters(exportSpecifier.name, FaultID.SendableTypeExported); + } + } + } + + public lint(): void { + this.visitSourceFile(this.sourceFile); + } + } +} +} + \ No newline at end of file diff --git a/src/linter/ArkTSLinter_1_1/LinterRunner.ts b/src/linter/ArkTSLinter_1_1/LinterRunner.ts index 2dfac3a415..c7bc4cee4b 100644 --- a/src/linter/ArkTSLinter_1_1/LinterRunner.ts +++ b/src/linter/ArkTSLinter_1_1/LinterRunner.ts @@ -30,6 +30,8 @@ export function runArkTSLinter(tsBuilderProgram: BuilderProgram, srcFile?: Sourc buildInfoWriteFile?: WriteFileCallback, arkTSVersion?: string): Diagnostic[] { TypeScriptLinter.errorLineNumbersString = ""; TypeScriptLinter.warningLineNumbersString = ""; + InteropTypescriptLinter.errorLineNumbersString = ""; + InteropTypescriptLinter.warningLineNumbersString = ""; let diagnostics: Diagnostic[] = []; LinterConfig.initStatic(); @@ -65,22 +67,41 @@ export function runArkTSLinter(tsBuilderProgram: BuilderProgram, srcFile?: Sourc timePrinterInstance.appendTime(ts.TimePhase.GET_TSC_DIAGNOSTICS); TypeScriptLinter.initGlobals(); + InteropTypescriptLinter.initGlobals(); for (const fileToLint of srcFiles) { - TypeScriptLinter.initStatic(); - if (TypeScriptLinter.lintEtsOnly && fileToLint.scriptKind !== ScriptKind.ETS) { + if (fileToLint.scriptKind !== ScriptKind.ETS && fileToLint.scriptKind !== ScriptKind.TS) { continue; } let currentDiagnostics: Diagnostic[]; if (changedFiles.has(fileToLint.resolvedPath)) { - const linter = new TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); - Utils.setTypeChecker(TypeScriptLinter.tsTypeChecker); - linter.lint(); + if (fileToLint.scriptKind === ScriptKind.ETS) { + TypeScriptLinter.initStatic(); + const linter = new TypeScriptLinter(fileToLint, program, tscStrictDiagnostics); + Utils.setTypeChecker(TypeScriptLinter.tsTypeChecker); + linter.lint(); - // Get list of bad nodes from the current run. - currentDiagnostics = tscStrictDiagnostics.get(normalizePath(fileToLint.fileName)) ?? []; - TypeScriptLinter.problemsInfos.forEach((x) => currentDiagnostics.push(translateDiag(fileToLint, x))); + // Get list of bad nodes from the current run. + currentDiagnostics = tscStrictDiagnostics.get(normalizePath(fileToLint.fileName)) ?? []; + TypeScriptLinter.problemsInfos.forEach((x) => currentDiagnostics.push(translateDiag(fileToLint, x))); + } else { + InteropTypescriptLinter.initStatic(); + const isKit = ts.getBaseFileName(fileToLint.fileName).indexOf('@kit.') === 0; + const etsLoaderPath = program.getCompilerOptions().etsLoaderPath; + const isInSdk = etsLoaderPath ? normalizePath(fileToLint.fileName).indexOf(resolvePath(etsLoaderPath, "../..")) === 0 : false; + const isInOhModules = isOHModules(fileToLint.fileName); + const tsImportSendableEnable = program.getCompilerOptions().tsImportSendableEnable; + if (isKit || isInOhModules || (!tsImportSendableEnable && !isInSdk)) { + continue; + } + const InteropLinter = new InteropTypescriptLinter(fileToLint, program, isInSdk); + Utils.setTypeChecker(InteropTypescriptLinter.tsTypeChecker); + InteropLinter.lint(); + + currentDiagnostics = []; + InteropTypescriptLinter.problemsInfos.forEach((x) => currentDiagnostics.push(translateDiag(fileToLint, x))); + } } else { // Get diagnostics from old run. currentDiagnostics = (oldDiagnostics?.get(fileToLint.resolvedPath) as Diagnostic[]) ?? []; @@ -106,6 +127,7 @@ export function runArkTSLinter(tsBuilderProgram: BuilderProgram, srcFile?: Sourc // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences(): void { TypeScriptLinter.clearTsTypeChecker(); + InteropTypescriptLinter.clearTsTypeChecker(); Utils.clearTypeChecker(); Utils.clearTrueSymbolAtLocationCache(); } diff --git a/src/linter/ArkTSLinter_1_1/Problems.ts b/src/linter/ArkTSLinter_1_1/Problems.ts index b7075b7b25..ab70789aa4 100644 --- a/src/linter/ArkTSLinter_1_1/Problems.ts +++ b/src/linter/ArkTSLinter_1_1/Problems.ts @@ -41,7 +41,8 @@ export enum FaultID { SpreadOperator, LimitedStdLibApi, ErrorSuppression, StrictDiagnostic, ImportAfterStatement, EsObjectType, SendableClassInheritance, SendablePropType, SendableDefiniteAssignment, SendableGenericTypes, SendableCapturedVars, SendableClassDecorator, SendableObjectInitialization, SendableComputedPropName, SendableAsExpr, - SharedNoSideEffectImport, SharedModuleExports, SharedModuleNoStarExport, + SharedNoSideEffectImport, SharedModuleExports, SharedModuleNoStarExport, NoTsImportEts, + SendableTypeInheritance, SendableTypeExported, SendableNoTsExportEts, LAST_ID, // this should always be last enum } @@ -147,6 +148,10 @@ faultsAttrs[FaultID.SendableAsExpr] = new FaultAttributes(161); faultsAttrs[FaultID.SharedNoSideEffectImport] = new FaultAttributes(162); faultsAttrs[FaultID.SharedModuleExports] = new FaultAttributes(163); faultsAttrs[FaultID.SharedModuleNoStarExport] = new FaultAttributes(164); +faultsAttrs[FaultID.NoTsImportEts] = new FaultAttributes(165); +faultsAttrs[FaultID.SendableTypeInheritance] = new FaultAttributes(166); +faultsAttrs[FaultID.SendableTypeExported] = new FaultAttributes(167); +faultsAttrs[FaultID.SendableNoTsExportEts] = new FaultAttributes(168); } } } \ No newline at end of file diff --git a/src/linter/ArkTSLinter_1_1/TypeScriptLinterConfig.ts b/src/linter/ArkTSLinter_1_1/TypeScriptLinterConfig.ts index 228a0da340..9be1bf2e4d 100644 --- a/src/linter/ArkTSLinter_1_1/TypeScriptLinterConfig.ts +++ b/src/linter/ArkTSLinter_1_1/TypeScriptLinterConfig.ts @@ -126,6 +126,10 @@ export class LinterConfig { LinterConfig.nodeDesc[FaultID.SharedNoSideEffectImport] = 'Shared no side effect import'; LinterConfig.nodeDesc[FaultID.SharedModuleExports] = 'Shared module exports'; LinterConfig.nodeDesc[FaultID.SharedModuleNoStarExport] = 'Share module no star export'; + LinterConfig.nodeDesc[FaultID.NoTsImportEts] = 'No ts Import Ets'; + LinterConfig.nodeDesc[FaultID.SendableTypeInheritance] = 'Sendable type inheritance'; + LinterConfig.nodeDesc[FaultID.SendableTypeExported] = 'Sendable type exported'; + LinterConfig.nodeDesc[FaultID.SendableNoTsExportEts] = 'Sendable no ts export ets' } /* diff --git a/src/linter/ArkTSLinter_1_1/Utils.ts b/src/linter/ArkTSLinter_1_1/Utils.ts index cb0154887e..0de38b0637 100644 --- a/src/linter/ArkTSLinter_1_1/Utils.ts +++ b/src/linter/ArkTSLinter_1_1/Utils.ts @@ -1142,7 +1142,7 @@ function validateField(type: ts.Type, prop: ts.PropertyAssignment): boolean { return false; } - const propType = TypeScriptLinter.tsTypeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); + const propType = typeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); const initExpr = unwrapParenthesized(prop.initializer); if (ts.isObjectLiteralExpression(initExpr)) { if (!isObjectLiteralAssignable(propType, initExpr)) { @@ -1150,7 +1150,7 @@ function validateField(type: ts.Type, prop: ts.PropertyAssignment): boolean { } } else { // Only check for structural sub-typing. - if (needToDeduceStructuralIdentity(propType, TypeScriptLinter.tsTypeChecker.getTypeAtLocation(initExpr), initExpr)) { + if (needToDeduceStructuralIdentity(propType, typeChecker.getTypeAtLocation(initExpr), initExpr)) { return false; } } @@ -1305,7 +1305,7 @@ export function isSymbolAPI(symbol: Symbol): boolean { } export function isStdSymbol(symbol: ts.Symbol): boolean { - const name = TypeScriptLinter.tsTypeChecker.getFullyQualifiedName(symbol) + const name = typeChecker.getFullyQualifiedName(symbol) return name === 'Symbol' && isGlobalSymbol(symbol); } @@ -1609,7 +1609,7 @@ export function isValueAssignableToESObject(node: ts.Node): boolean { if (ts.isArrayLiteralExpression(node) || ts.isObjectLiteralExpression(node)) { return false; } - const valueType = TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node); + const valueType = typeChecker.getTypeAtLocation(node); return isUnsupportedType(valueType) || isAnonymousType(valueType) } @@ -1745,7 +1745,7 @@ export function isStdBooleanType(type: ts.Type): boolean { export function isEnumStringLiteral(expr: ts.Expression): boolean { const symbol = trueSymbolAtLocation(expr); const isEnumMember = !!symbol && !!(symbol.flags & ts.SymbolFlags.EnumMember); - const type = TypeScriptLinter.tsTypeChecker.getTypeAtLocation(expr); + const type = typeChecker.getTypeAtLocation(expr); const isStringEnumLiteral = isEnumType(type) && !!(type.flags & ts.TypeFlags.StringLiteral); return isEnumMember && isStringEnumLiteral; } @@ -1772,7 +1772,7 @@ export function isAllowedIndexSignature(node: ts.IndexSignatureDeclaration): boo return false; } - const paramType = TypeScriptLinter.tsTypeChecker.getTypeAtLocation(node.parameters[0]); + const paramType = typeChecker.getTypeAtLocation(node.parameters[0]); if ((paramType.flags & ts.TypeFlags.Number) === 0) { return false; } @@ -1861,7 +1861,7 @@ export function isSendableTypeNode(typeNode: ts.TypeNode): boolean { return true; } - return isSendableType(TypeScriptLinter.tsTypeChecker.getTypeFromTypeNode(typeNode)); + return isSendableType(typeChecker.getTypeFromTypeNode(typeNode)); } export function isSendableType(type: ts.Type): boolean { @@ -2007,7 +2007,7 @@ export function isSharedModule(sourceFile: ts.SourceFile): boolean { return false; } -function getDeclarationNode(node: ts.Node): ts.Declaration | undefined { +export function getDeclarationNode(node: ts.Node): ts.Declaration | undefined { const sym = trueSymbolAtLocation(node); return getDeclaration(sym); } @@ -2023,9 +2023,24 @@ export function isShareableEntity(node: ts.Node): boolean { const typeNode = (decl as any)?.type; return (typeNode && !isFunctionLikeDeclaration(decl!)) ? isSendableTypeNode(typeNode) : - isShareableType(TypeScriptLinter.tsTypeChecker.getTypeAtLocation(decl ? decl : node)); + isShareableType(typeChecker.getTypeAtLocation(decl ? decl : node)); } +export function isShareableClassOrInterfaceEntity(node: ts.Node): boolean { + const decl = getDeclarationNode(node); + return isSendableClassOrInterface(typeChecker.getTypeAtLocation(decl ?? node)); +} + +export function isInImportWhiteList(resolvedModule: ResolvedModuleFull): boolean { + if ( + !resolvedModule.resolvedFileName || + ts.getBaseFileName(resolvedModule.resolvedFileName) !== ARKTS_LANG_D_ETS && + ts.getBaseFileName(resolvedModule.resolvedFileName) !== ARKTS_COLLECTIONS_D_ETS + ) { + return false; + } + return true; +} } } } diff --git a/src/linter/tsconfig.json b/src/linter/tsconfig.json index 81a8823669..42629dbf00 100644 --- a/src/linter/tsconfig.json +++ b/src/linter/tsconfig.json @@ -34,6 +34,7 @@ "./ArkTSLinter_1_1/Autofixer.ts", "./ArkTSLinter_1_1/TypeScriptLinterConfig.ts", "./ArkTSLinter_1_1/TypeScriptLinter.ts", + "./ArkTSLinter_1_1/InteropTypescriptLinter.ts", "./ArkTSLinter_1_1/TSDiagnostics.ts", "./ArkTSLinter_1_1/LinterRunner.ts", "./Common/ArkTSTimePrinter.ts" diff --git a/tests/arkTSTest/ignorecase.json b/tests/arkTSTest/ignorecase.json index 57ee5acaab..b32ec65978 100644 --- a/tests/arkTSTest/ignorecase.json +++ b/tests/arkTSTest/ignorecase.json @@ -1,3 +1,27 @@ { - "ignoreCase":["testcase/arkts-shared-module-exports/@arkts.lang.d.ets"] + "ignoreCase":["testcase/arkts-shared-module-exports/@arkts.lang.d.ets", + "testcase/arkts-no-globalthis/arkts-no-globalthis-1-error/arkts-no-globalthis-1-error.ts", + "testcase/arkts-no-globalthis/arkts-no-globalthis-3-error/arkts-no-globalthis-3-error.ts", + "testcase/arkts-no-globalthis/arkts-no-globalthis-4-error/arkts-no-globalthis-4-error.ts", + "testcase/arkts-limited-esobj/arkts-limited-esobj.d.ts", + "testcase/arkts-no-aliases-by-index/arkts-no-aliases-by-index-7-error/case7.1.ts", + "testcase/arkts-no-import-assertions/path/module.ts", + "testcase/arkts-no-import-assertions/path/my-module.ts", + "testcase/arkts-no-misplaced-imports/path/module.ts", + "testcase/arkts-no-misplaced-imports/path/moduleName.ts", + "testcase/arkts-no-module-wildcards/arkts-no-module-wildcards-2-ok/math.ts", + "testcase/arkts-no-module-wildcards/arkts-no-module-wildcards-4-ok/utils.ts", + "testcase/arkts-no-module-wildcards/arkts-no-module-wildcards-5-ok/logger.ts", + "testcase/arkts-no-regexp-literals/arkts-no-regexp-literals-7-ok/case7.1.ts", + "testcase/arkts-no-ts-deps/arkts-no-ts-deps-2-ok/lib1-dependencie.ts", + "testcase/arkts-no-ts-deps/arkts-no-ts-deps-7-ok/lib1-dependencie.ts", + "testcase/arkts-no-ts-deps/arkts-no-ts-deps-7-ok/lib2-dependencie.ts", + "testcase/arkts-no-ts-deps/arkts-no-ts-deps-7-ok/lib3-dependencie.ts", + "testcase/arkts-no-ts-deps/arkts-no-ts-deps-9-ok/lib2-dependencie.ts", + "testcase/arkts-only-imported-variables/sendable_captured_variables_lib.d.ts", + "testcase/arkts-only-imported-variables/sendable_captured_variables_namespaceimport_lib.d.ts", + "testcase/arkts-no-ts-sendable-type-inheritance/@arkts.lang.d.ets", + "testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/@arkts.lang.d.ets", + "testcase/arkts-sendable-generic-types/@arkts.lang.d.ets", + "testcase/arkts-sendable-obj-init/@arkts.lang.d.ets"] } \ No newline at end of file diff --git a/tests/arkTSTest/run.js b/tests/arkTSTest/run.js index f5377f3ad5..b376abed7b 100644 --- a/tests/arkTSTest/run.js +++ b/tests/arkTSTest/run.js @@ -43,7 +43,7 @@ function getAllETSFiles(filePath) { } else { var index= currentFilePath.lastIndexOf("."); var ext = currentFilePath.substring(index+1); - if (ext == "ets"){ + if (ext == "ets" || ext == "ts"){ allFilePaths.push(currentFilePath); runComp(currentFilePath, file) } @@ -57,7 +57,8 @@ function getAllETSFiles(filePath) { function runComp(currentFilePath, file){ const result = runLinter(currentFilePath) - const jsonFile = currentFilePath.replace('ets','json') + let jsonFile = currentFilePath.replace('.ets','.json') + jsonFile = jsonFile.replace('.ts','.json') const checkfile = fs.existsSync(jsonFile); if(checkfile){ loadPares(jsonFile, result, currentFilePath, file) diff --git a/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/@arkts.lang.d.ets b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/@arkts.lang.d.ets new file mode 100644 index 0000000000..40e381dc2a --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/@arkts.lang.d.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace lang { + interface ISendable {} +} diff --git a/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/arkts-no-ts-sendable-type-inheritance.json b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/arkts-no-ts-sendable-type-inheritance.json new file mode 100644 index 0000000000..92652c4844 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/arkts-no-ts-sendable-type-inheritance.json @@ -0,0 +1,4 @@ +{ + "arktsVersion_1_0": [], + "arktsVersion_1_1": [] +} \ No newline at end of file diff --git a/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/arkts-no-ts-sendable-type-inheritance.ts b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/arkts-no-ts-sendable-type-inheritance.ts new file mode 100644 index 0000000000..4dc3380098 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/arkts-no-ts-sendable-type-inheritance.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import { A, A1, A as A2, B, B1, B as B2, C, C1, C as C2 } from './lib-dependencie' +import { I, J } from './lib-dependencie' + +interface T {} + +class D1 extends A {} +class D2 extends A1 {} +class D3 extends A2 {} +class D4 extends B {} +class D5 extends B1 {} +class D6 extends B2 {} +class D7 extends C {} +class D8 extends C1 {} +class D9 extends C2 {} + +interface I1 extends I {} +interface J1 extends J {} +interface K extends I, J, T {} diff --git a/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/lib-dependencie.ets b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/lib-dependencie.ets new file mode 100644 index 0000000000..35a7f8b491 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-no-ts-sendable-type-inheritance/lib-dependencie.ets @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { lang } from './@arkts.lang' + +@Sendable +class A {} +export { A, A as A1 } + +@Sendable +class B { + value: number = 0; +} +export { B, B as B1 } + +@Sendable +class C implements lang.ISendable { + value: number = 0 +} +export { C, C as C1 } + +export interface I extends lang.ISendable { + v: number; +} + +export interface J extends I { + u: number; +} diff --git a/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/@arkts.lang.d.ets b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/@arkts.lang.d.ets new file mode 100644 index 0000000000..40e381dc2a --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/@arkts.lang.d.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace lang { + interface ISendable {} +} diff --git a/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/arkts-sendable-as-expr-ts.json b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/arkts-sendable-as-expr-ts.json new file mode 100644 index 0000000000..92652c4844 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/arkts-sendable-as-expr-ts.json @@ -0,0 +1,4 @@ +{ + "arktsVersion_1_0": [], + "arktsVersion_1_1": [] +} \ No newline at end of file diff --git a/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/arkts-sendable-as-expr-ts.ts b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/arkts-sendable-as-expr-ts.ts new file mode 100644 index 0000000000..cc80d891bc --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/arkts-sendable-as-expr-ts.ts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import { A, A1, A as A2, B, B1, B as B2, C, C1, C as C2 } from './lib-dependencie' +import { I, J } from './lib-dependencie' + +let a1 = {} as A; +let a2 = {} as A; +let a3 = {} as A; +let b1 = { value: 0 } as B; +let b2 = { value: 0 } as B1; +let b3 = { value: 0 } as B2; +let c1 = { value: 0 } as C; +let c2 = { value: 0 } as C1; +let c3 = { value: 0 } as C2; + +let i = { v: 0 } as I; +let j = { v: 0, u: 0 } as J; + +class D {} + +function foo(d: D) {} +foo(new D() as A); +foo(new D() as A1); +foo(new D() as A2); diff --git a/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/lib-dependencie.ets b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/lib-dependencie.ets new file mode 100644 index 0000000000..6e2c5febdd --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-as-expr/arkts-sendable-as-expr-ts/lib-dependencie.ets @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { lang } from './@arkts.lang' + +@Sendable +class A {} +export { A, A as A1 } + +@Sendable +class B { + value: number = 0 +} +export { B, B as B1 } + +@Sendable +class C implements lang.ISendable { + value: number = 0 +} +export { C, C as C1 } + +export interface I extends lang.ISendable { + v: number; +} + +export interface J extends I { + u: number; +} diff --git a/tests/arkTSTest/testcase/arkts-sendable-generic-types/@arkts.lang.d.ets b/tests/arkTSTest/testcase/arkts-sendable-generic-types/@arkts.lang.d.ets new file mode 100644 index 0000000000..40e381dc2a --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-generic-types/@arkts.lang.d.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace lang { + interface ISendable {} +} diff --git a/tests/arkTSTest/testcase/arkts-sendable-generic-types/arkts-sendable-generic-types.json b/tests/arkTSTest/testcase/arkts-sendable-generic-types/arkts-sendable-generic-types.json new file mode 100644 index 0000000000..92652c4844 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-generic-types/arkts-sendable-generic-types.json @@ -0,0 +1,4 @@ +{ + "arktsVersion_1_0": [], + "arktsVersion_1_1": [] +} \ No newline at end of file diff --git a/tests/arkTSTest/testcase/arkts-sendable-generic-types/arkts-sendable-generic-types.ts b/tests/arkTSTest/testcase/arkts-sendable-generic-types/arkts-sendable-generic-types.ts new file mode 100644 index 0000000000..0208e19ae2 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-generic-types/arkts-sendable-generic-types.ts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import { A, A1, A as A2, B, B1, B as B2, C, C1, C as C2 } from './lib-dependencie' + +class D {} +interface T {} + +let a1 = new A(); +let a2 = new A1(); +let a3 = new A2(); +let a4 = new A(); +let a5 = new A1(); +let a6 = new A2(); +let a7 = new A(); +let a8 = new A1(); +let a9 = new A2(); + +let b1 = new B(); +let b2 = new B1(); +let b3 = new B2(); +let b4 = new B(); +let b5 = new B1(); +let b6 = new B2(); +let b7 = new B(); +let b8 = new B1(); +let b9 = new B2(); + +let c1 = new C(); +let c2 = new C1(); +let c3 = new C2(); +let c4 = new C(); +let c5 = new C1(); +let c6 = new C2(); +let c7 = new C(); +let c8 = new C1(); +let c9 = new C2(); diff --git a/tests/arkTSTest/testcase/arkts-sendable-generic-types/lib-dependencie.ets b/tests/arkTSTest/testcase/arkts-sendable-generic-types/lib-dependencie.ets new file mode 100644 index 0000000000..71826c0b0c --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-generic-types/lib-dependencie.ets @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { lang } from './@arkts.lang' + +@Sendable +class A {} +export { A, A as A1 } + +@Sendable +class B { + value: number = 0 +} +export { B, B as B1 } + +@Sendable +class C implements lang.ISendable { + value: number = 0 +} +export { C, C as C1 } diff --git a/tests/arkTSTest/testcase/arkts-sendable-obj-init/@arkts.lang.d.ets b/tests/arkTSTest/testcase/arkts-sendable-obj-init/@arkts.lang.d.ets new file mode 100644 index 0000000000..40e381dc2a --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-obj-init/@arkts.lang.d.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace lang { + interface ISendable {} +} diff --git a/tests/arkTSTest/testcase/arkts-sendable-obj-init/arkts-sendable-obj-init.json b/tests/arkTSTest/testcase/arkts-sendable-obj-init/arkts-sendable-obj-init.json new file mode 100644 index 0000000000..92652c4844 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-obj-init/arkts-sendable-obj-init.json @@ -0,0 +1,4 @@ +{ + "arktsVersion_1_0": [], + "arktsVersion_1_1": [] +} \ No newline at end of file diff --git a/tests/arkTSTest/testcase/arkts-sendable-obj-init/arkts-sendable-obj-init.ts b/tests/arkTSTest/testcase/arkts-sendable-obj-init/arkts-sendable-obj-init.ts new file mode 100644 index 0000000000..4f48d59257 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-obj-init/arkts-sendable-obj-init.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import { A, A1, A as A2, B, B1, B as B2, C, C1, C as C2 } from './lib-dependencie' +import { I, J } from './lib-dependencie' + +let a1: A = {}; +let a2: A1 = {}; +let a3: A2 = {}; +let b1: B = { value: 0 }; +let b2: B1 = { value: 0 }; +let b3: B2 = { value: 0 }; +let c1: C = { value: 0 }; +let c2: C1 = { value: 0 }; +let c3: C2 = { value: 0 }; + +let i = { v: 0 }; +let j = { v: 0, u: 0 }; diff --git a/tests/arkTSTest/testcase/arkts-sendable-obj-init/lib-dependencie.ets b/tests/arkTSTest/testcase/arkts-sendable-obj-init/lib-dependencie.ets new file mode 100644 index 0000000000..2a2c9a7555 --- /dev/null +++ b/tests/arkTSTest/testcase/arkts-sendable-obj-init/lib-dependencie.ets @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { lang } from './@arkts.lang' + +@Sendable +class A {} +export { A, A as A1 } + +@Sendable +class B {} +export { B, B as B1 } + +@Sendable +class C implements lang.ISendable { + value: number = 0 +} +export { C, C as C1 } + +export interface I extends lang.ISendable { + v: number; +} + +export interface J extends I { + u: number; +} diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3d9af07d58..fb90c66b3f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3164,6 +3164,7 @@ declare namespace ts { packageManagerType?: string; emitNodeModulesFiles?: boolean; etsLoaderPath?: string; + tsImportSendableEnable?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } export interface EtsOptions { @@ -13144,7 +13145,11 @@ declare namespace ts { SharedNoSideEffectImport = 89, SharedModuleExports = 90, SharedModuleNoStarExport = 91, - LAST_ID = 92 + NoTsImportEts = 92, + SendableTypeInheritance = 93, + SendableTypeExported = 94, + SendableNoTsExportEts = 95, + LAST_ID = 96 } class FaultAttributes { cookBookRef: number; @@ -13341,7 +13346,10 @@ declare namespace ts { function getDecoratorsIfInSendableClass(declaration: ts.HasDecorators): readonly ts.Decorator[] | undefined; function isISendableInterface(type: ts.Type): boolean; function isSharedModule(sourceFile: ts.SourceFile): boolean; + function getDeclarationNode(node: ts.Node): ts.Declaration | undefined; function isShareableEntity(node: ts.Node): boolean; + function isShareableClassOrInterfaceEntity(node: ts.Node): boolean; + function isInImportWhiteList(resolvedModule: ResolvedModuleFull): boolean; } } } @@ -13540,6 +13548,51 @@ declare namespace ts { } } } +declare namespace ts { + namespace ArkTSLinter_1_1 { + import Autofix = Autofixer.Autofix; + class InteropTypescriptLinter { + private sourceFile; + private isInSdk; + static strictMode: boolean; + static totalVisitedNodes: number; + static nodeCounters: number[]; + static lineCounters: number[]; + static totalErrorLines: number; + static errorLineNumbersString: string; + static totalWarningLines: number; + static warningLineNumbersString: string; + static reportDiagnostics: boolean; + static problemsInfos: ProblemInfo[]; + static initGlobals(): void; + static initStatic(): void; + static tsTypeChecker: TypeChecker; + currentErrorLine: number; + currentWarningLine: number; + readonly ARKTS_COLLECTIONS_ETS = "@arkts.collections"; + readonly KIT_ARKTS_ETS = "@kit.ArkTS"; + constructor(sourceFile: SourceFile, tsProgram: Program, isInSdk: boolean); + static clearTsTypeChecker(): void; + readonly handlersMap: ESMap void>; + incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; + private forEachNodeInSubtree; + private visitSourceFile; + private handleImportDeclaration; + private checkSendableClassorISendable; + private checkImportClause; + private handleClassDeclaration; + private checkClassOrInterfaceDeclarationHeritageClause; + private handleInterfaceDeclaration; + private handleNewExpression; + private handleSendableGenericTypes; + private handleObjectLiteralExpression; + private handleArrayLiteralExpression; + private handleAsExpression; + private handleExportDeclaration; + lint(): void; + } + } +} declare namespace ts { namespace ArkTSLinter_1_1 { class TSCCompiledProgram { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index ebce8b5b92..6ac9f040f0 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3164,6 +3164,7 @@ declare namespace ts { packageManagerType?: string; emitNodeModulesFiles?: boolean; etsLoaderPath?: string; + tsImportSendableEnable?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } export interface EtsOptions { @@ -9205,7 +9206,11 @@ declare namespace ts { SharedNoSideEffectImport = 89, SharedModuleExports = 90, SharedModuleNoStarExport = 91, - LAST_ID = 92 + NoTsImportEts = 92, + SendableTypeInheritance = 93, + SendableTypeExported = 94, + SendableNoTsExportEts = 95, + LAST_ID = 96 } class FaultAttributes { cookBookRef: number; @@ -9402,7 +9407,10 @@ declare namespace ts { function getDecoratorsIfInSendableClass(declaration: ts.HasDecorators): readonly ts.Decorator[] | undefined; function isISendableInterface(type: ts.Type): boolean; function isSharedModule(sourceFile: ts.SourceFile): boolean; + function getDeclarationNode(node: ts.Node): ts.Declaration | undefined; function isShareableEntity(node: ts.Node): boolean; + function isShareableClassOrInterfaceEntity(node: ts.Node): boolean; + function isInImportWhiteList(resolvedModule: ResolvedModuleFull): boolean; } } } @@ -9601,6 +9609,51 @@ declare namespace ts { } } } +declare namespace ts { + namespace ArkTSLinter_1_1 { + import Autofix = Autofixer.Autofix; + class InteropTypescriptLinter { + private sourceFile; + private isInSdk; + static strictMode: boolean; + static totalVisitedNodes: number; + static nodeCounters: number[]; + static lineCounters: number[]; + static totalErrorLines: number; + static errorLineNumbersString: string; + static totalWarningLines: number; + static warningLineNumbersString: string; + static reportDiagnostics: boolean; + static problemsInfos: ProblemInfo[]; + static initGlobals(): void; + static initStatic(): void; + static tsTypeChecker: TypeChecker; + currentErrorLine: number; + currentWarningLine: number; + readonly ARKTS_COLLECTIONS_ETS = "@arkts.collections"; + readonly KIT_ARKTS_ETS = "@kit.ArkTS"; + constructor(sourceFile: SourceFile, tsProgram: Program, isInSdk: boolean); + static clearTsTypeChecker(): void; + readonly handlersMap: ESMap void>; + incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; + private forEachNodeInSubtree; + private visitSourceFile; + private handleImportDeclaration; + private checkSendableClassorISendable; + private checkImportClause; + private handleClassDeclaration; + private checkClassOrInterfaceDeclarationHeritageClause; + private handleInterfaceDeclaration; + private handleNewExpression; + private handleSendableGenericTypes; + private handleObjectLiteralExpression; + private handleArrayLiteralExpression; + private handleAsExpression; + private handleExportDeclaration; + lint(): void; + } + } +} declare namespace ts { namespace ArkTSLinter_1_1 { class TSCCompiledProgram {