diff --git a/linter-4.2/src/TypeScriptLinter.ts b/linter-4.2/src/TypeScriptLinter.ts index 5fe2f80a4120850c7178224a1ab4d59b11a2b273..8d5fc0b4201c9f1a1bf0d8d1fc9c1977ccd407c2 100644 --- a/linter-4.2/src/TypeScriptLinter.ts +++ b/linter-4.2/src/TypeScriptLinter.ts @@ -1573,6 +1573,18 @@ export class TypeScriptLinter { if ((tsIdentSym.flags & illegalValues) == 0 || !this.identiferUseInValueContext(tsIdentifier)) { return; } + + if ((tsIdentSym.flags & ts.SymbolFlags.Class) != 0) { + let ctxNode: ts.Node = tsIdentifier; + while (ts.isPropertyAccessExpression(ctxNode.parent) || ts.isQualifiedName(ctxNode.parent)) { + ctxNode = ctxNode.parent; + } + ctxNode = ctxNode.parent; + if (ts.isCallExpression(ctxNode) && this.tsUtils.hasLibraryType((ctxNode as ts.CallExpression).expression)) { + return; + } + } + if (tsIdentSym.flags & ts.SymbolFlags.ValueModule) { this.incrementCounters(tsIdentifier, FaultID.NamespaceAsObject); } else { diff --git a/linter-4.2/src/Utils.ts b/linter-4.2/src/Utils.ts index d3b9ecc0a797cbe00f548ac6fbcb5260f093169d..804e838a2c9885fbade4f3dec16c34cad99ede1c 100644 --- a/linter-4.2/src/Utils.ts +++ b/linter-4.2/src/Utils.ts @@ -1108,6 +1108,10 @@ export class TsUtils { return this.isLibrarySymbol(type.aliasSymbol ?? type.getSymbol()); } + public hasLibraryType(node: ts.Node): boolean { + return this.isLibraryType(this.tsTypeChecker.getTypeAtLocation(node)); + } + public isLibrarySymbol(sym: ts.Symbol | undefined) { if (sym && sym.declarations && sym.declarations.length > 0) { const srcFile = sym.declarations[0].getSourceFile(); diff --git a/linter-4.2/test/class_as_object.ts b/linter-4.2/test/class_as_object.ts index fb5de2dc6c48a5300ba5eeae68f52d41f3685138..7a20f0a9f4823799996892c0e7f82115642a02ef 100644 --- a/linter-4.2/test/class_as_object.ts +++ b/linter-4.2/test/class_as_object.ts @@ -13,6 +13,8 @@ * limitations under the License. */ +import { Something, SomethingFactory, SomethingBar } from "./oh_modules/ohos_factory"; + class C { static a = 5; static b = 8; @@ -58,3 +60,10 @@ class D { new D(C); type X = D; + +namespace test1 { + class SomethingFoo extends Something { } + + let x = SomethingFactory.getInstance().create(SomethingFoo).beep(); + let y = SomethingFactory.getInstance().create(SomethingBar).beep(); +} diff --git a/linter-4.2/test/class_as_object.ts.relax.json b/linter-4.2/test/class_as_object.ts.relax.json index e0222de361febc94d02a7328c833f63282938913..41ee80cd4f84d542ed57527751fcd29e2561278c 100644 --- a/linter-4.2/test/class_as_object.ts.relax.json +++ b/linter-4.2/test/class_as_object.ts.relax.json @@ -13,62 +13,62 @@ ], "nodes": [ { - "line": 25, + "line": 27, "column": 9, "problem": "ClassAsObject" }, { - "line": 26, + "line": 28, "column": 5, "problem": "ClassAsObject" }, { - "line": 27, + "line": 29, "column": 11, "problem": "ClassAsObject" }, { - "line": 28, + "line": 30, "column": 7, "problem": "ClassAsObject" }, { - "line": 36, + "line": 38, "column": 20, "problem": "TypeQuery" }, { - "line": 37, + "line": 39, "column": 6, "problem": "ClassAsObject" }, { - "line": 40, + "line": 42, "column": 10, "problem": "ClassAsObject" }, { - "line": 43, + "line": 45, "column": 20, "problem": "TypeQuery" }, { - "line": 44, + "line": 46, "column": 8, "problem": "ClassAsObject" }, { - "line": 47, + "line": 49, "column": 12, "problem": "ClassAsObject" }, { - "line": 56, + "line": 58, "column": 20, "problem": "TypeQuery" }, { - "line": 58, + "line": 60, "column": 7, "problem": "ClassAsObject" } diff --git a/linter-4.2/test/class_as_object.ts.strict.json b/linter-4.2/test/class_as_object.ts.strict.json index e0222de361febc94d02a7328c833f63282938913..41ee80cd4f84d542ed57527751fcd29e2561278c 100644 --- a/linter-4.2/test/class_as_object.ts.strict.json +++ b/linter-4.2/test/class_as_object.ts.strict.json @@ -13,62 +13,62 @@ ], "nodes": [ { - "line": 25, + "line": 27, "column": 9, "problem": "ClassAsObject" }, { - "line": 26, + "line": 28, "column": 5, "problem": "ClassAsObject" }, { - "line": 27, + "line": 29, "column": 11, "problem": "ClassAsObject" }, { - "line": 28, + "line": 30, "column": 7, "problem": "ClassAsObject" }, { - "line": 36, + "line": 38, "column": 20, "problem": "TypeQuery" }, { - "line": 37, + "line": 39, "column": 6, "problem": "ClassAsObject" }, { - "line": 40, + "line": 42, "column": 10, "problem": "ClassAsObject" }, { - "line": 43, + "line": 45, "column": 20, "problem": "TypeQuery" }, { - "line": 44, + "line": 46, "column": 8, "problem": "ClassAsObject" }, { - "line": 47, + "line": 49, "column": 12, "problem": "ClassAsObject" }, { - "line": 56, + "line": 58, "column": 20, "problem": "TypeQuery" }, { - "line": 58, + "line": 60, "column": 7, "problem": "ClassAsObject" } diff --git a/linter-4.2/test/oh_modules/ohos_factory.ts b/linter-4.2/test/oh_modules/ohos_factory.ts new file mode 100644 index 0000000000000000000000000000000000000000..506f00e625a5437b431895d9c69dd7f171ac4883 --- /dev/null +++ b/linter-4.2/test/oh_modules/ohos_factory.ts @@ -0,0 +1,11 @@ +export declare class Something { beep(): number } + +export declare class SomethingFactory { + private constructor(); + + public static getInstance(): SomethingFactory; + + public create(smth: { new(): T }): T; +} + +export declare class SomethingBar extends Something {} diff --git a/linter/src/TypeScriptLinter.ts b/linter/src/TypeScriptLinter.ts index 84cba26f7de2979d99b7372404d8780d28ab24c4..ff65347c7120f70eb2e57bfb901724110c9b93f9 100644 --- a/linter/src/TypeScriptLinter.ts +++ b/linter/src/TypeScriptLinter.ts @@ -1293,6 +1293,18 @@ export class TypeScriptLinter { if ((tsIdentSym.flags & illegalValues) == 0 || !identiferUseInValueContext(tsIdentifier)) { return; } + + if ((tsIdentSym.flags & ts.SymbolFlags.Class) != 0) { + let ctxNode: ts.Node = tsIdentifier; + while (ts.isPropertyAccessExpression(ctxNode.parent) || ts.isQualifiedName(ctxNode.parent)) { + ctxNode = ctxNode.parent; + } + ctxNode = ctxNode.parent; + if (ts.isCallExpression(ctxNode) && this.tsUtils.hasLibraryType((ctxNode as ts.CallExpression).expression)) { + return; + } + } + if (tsIdentSym.flags & ts.SymbolFlags.ValueModule) { this.incrementCounters(tsIdentifier, FaultID.NamespaceAsObject); } else { diff --git a/linter/src/utils/TsUtils.ts b/linter/src/utils/TsUtils.ts index 256819a7e133d39b5dd6b9822946ce7444452326..cfaceadae731b28a241d86279faf48bfdb6a6821 100644 --- a/linter/src/utils/TsUtils.ts +++ b/linter/src/utils/TsUtils.ts @@ -917,6 +917,10 @@ export class TsUtils { return this.isLibrarySymbol(type.aliasSymbol ?? type.getSymbol()); } + public hasLibraryType(node: ts.Node): boolean { + return this.isLibraryType(this.tsTypeChecker.getTypeAtLocation(node)); + } + public isLibrarySymbol(sym: ts.Symbol | undefined): boolean { if (sym && sym.declarations && sym.declarations.length > 0) { const srcFile = sym.declarations[0].getSourceFile(); diff --git a/linter/test/class_as_object.ts b/linter/test/class_as_object.ts index e65e7ec597c0dbe3221bc42b40159e77f4960614..6a880705660f1d26bfd2a97980bcad74e08b07c4 100644 --- a/linter/test/class_as_object.ts +++ b/linter/test/class_as_object.ts @@ -13,6 +13,8 @@ * limitations under the License. */ +import { Something, SomethingFactory, SomethingBar } from "./oh_modules/ohos_factory"; + class C { static a = 5 static b = 8 @@ -58,3 +60,10 @@ class D { new D(C) type X = D; + +namespace test1 { + class SomethingFoo extends Something { } + + let x = SomethingFactory.getInstance().create(SomethingFoo).beep(); + let y = SomethingFactory.getInstance().create(SomethingBar).beep(); +} diff --git a/linter/test/class_as_object.ts.relax.json b/linter/test/class_as_object.ts.relax.json index 9a21b256e3df1665a199f2af60b90d0eea8ed905..2d3f8a850eb3c7f3ff115a72b65b284aace1d9bf 100644 --- a/linter/test/class_as_object.ts.relax.json +++ b/linter/test/class_as_object.ts.relax.json @@ -13,62 +13,62 @@ ], "nodes": [ { - "line": 25, + "line": 27, "column": 9, "problem": "ClassAsObject" }, { - "line": 26, + "line": 28, "column": 5, "problem": "ClassAsObject" }, { - "line": 27, + "line": 29, "column": 11, "problem": "ClassAsObject" }, { - "line": 28, + "line": 30, "column": 7, "problem": "ClassAsObject" }, { - "line": 36, + "line": 38, "column": 20, "problem": "TypeQuery" }, { - "line": 37, + "line": 39, "column": 6, "problem": "ClassAsObject" }, { - "line": 40, + "line": 42, "column": 12, "problem": "ClassAsObject" }, { - "line": 43, + "line": 45, "column": 20, "problem": "TypeQuery" }, { - "line": 44, + "line": 46, "column": 8, "problem": "ClassAsObject" }, { - "line": 47, + "line": 49, "column": 14, "problem": "ClassAsObject" }, { - "line": 56, + "line": 58, "column": 22, "problem": "TypeQuery" }, { - "line": 58, + "line": 60, "column": 7, "problem": "ClassAsObject" } diff --git a/linter/test/class_as_object.ts.strict.json b/linter/test/class_as_object.ts.strict.json index 9a21b256e3df1665a199f2af60b90d0eea8ed905..2d3f8a850eb3c7f3ff115a72b65b284aace1d9bf 100644 --- a/linter/test/class_as_object.ts.strict.json +++ b/linter/test/class_as_object.ts.strict.json @@ -13,62 +13,62 @@ ], "nodes": [ { - "line": 25, + "line": 27, "column": 9, "problem": "ClassAsObject" }, { - "line": 26, + "line": 28, "column": 5, "problem": "ClassAsObject" }, { - "line": 27, + "line": 29, "column": 11, "problem": "ClassAsObject" }, { - "line": 28, + "line": 30, "column": 7, "problem": "ClassAsObject" }, { - "line": 36, + "line": 38, "column": 20, "problem": "TypeQuery" }, { - "line": 37, + "line": 39, "column": 6, "problem": "ClassAsObject" }, { - "line": 40, + "line": 42, "column": 12, "problem": "ClassAsObject" }, { - "line": 43, + "line": 45, "column": 20, "problem": "TypeQuery" }, { - "line": 44, + "line": 46, "column": 8, "problem": "ClassAsObject" }, { - "line": 47, + "line": 49, "column": 14, "problem": "ClassAsObject" }, { - "line": 56, + "line": 58, "column": 22, "problem": "TypeQuery" }, { - "line": 58, + "line": 60, "column": 7, "problem": "ClassAsObject" } diff --git a/linter/test/oh_modules/ohos_factory.ts b/linter/test/oh_modules/ohos_factory.ts new file mode 100644 index 0000000000000000000000000000000000000000..506f00e625a5437b431895d9c69dd7f171ac4883 --- /dev/null +++ b/linter/test/oh_modules/ohos_factory.ts @@ -0,0 +1,11 @@ +export declare class Something { beep(): number } + +export declare class SomethingFactory { + private constructor(); + + public static getInstance(): SomethingFactory; + + public create(smth: { new(): T }): T; +} + +export declare class SomethingBar extends Something {}