Skip to content

Commit 5486caa

Browse files
Merge branch 'isolated-declarations-unity' of https://github.com/bloomberg/TypeScript into isolated-declarations-unity
2 parents f58c146 + 620cea5 commit 5486caa

65 files changed

Lines changed: 548 additions & 3422 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7220,6 +7220,10 @@
72207220
"category": "Message",
72217221
"code": 90070
72227222
},
7223+
"Annotate types of properties expando function in a namespace": {
7224+
"category": "Message",
7225+
"code": 90071
7226+
},
72237227

72247228
"Convert function to an ES2015 class": {
72257229
"category": "Message",

src/services/codefixes/fixMissingTypeAnnotationOnExports.ts

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
factory,
2727
FileTextChanges,
2828
findAncestor,
29+
FunctionDeclaration,
2930
GeneratedIdentifierFlags,
3031
getEmitScriptTarget,
3132
getSourceFileOfNode,
@@ -49,6 +50,7 @@ import {
4950
isEnumMember,
5051
isExpandoPropertyDeclaration,
5152
isExpression,
53+
isFunctionDeclaration,
5254
isFunctionExpressionOrArrowFunction,
5355
isHeritageClause,
5456
isIdentifier,
@@ -70,6 +72,7 @@ import {
7072
isValueSignatureDeclaration,
7173
isVariableDeclaration,
7274
ModifierFlags,
75+
ModifierLike,
7376
Node,
7477
NodeArray,
7578
NodeBuilderFlags,
@@ -225,6 +228,7 @@ function withChanges<T>(
225228
const scriptTarget = getEmitScriptTarget(program.getCompilerOptions());
226229
const importAdder = createImportAdder(context.sourceFile, context.program, context.preferences, context.host);
227230
const fixedNodes = new Set<Node>();
231+
const expandoPropertiesAdded = new Set<Node>();
228232

229233
const result = cb({ addFullAnnotation, addInlineAnnotation, extractAsVariable });
230234
importAdder.writeFixes(changeTracker);
@@ -235,16 +239,63 @@ function withChanges<T>(
235239

236240
function addFullAnnotation(span: TextSpan) {
237241
const nodeWithDiag = getTokenAtPosition(sourceFile, span.start);
238-
const nodeWithNoType = findNearestParentWithTypeAnnotation(nodeWithDiag) ?? findExpandoFunction(nodeWithDiag);
242+
const expandoFunction = findExpandoFunction(nodeWithDiag);
243+
if (expandoFunction) {
244+
if (isFunctionDeclaration(expandoFunction)) {
245+
return createNamespaceForExpandoProperties(expandoFunction);
246+
}
247+
return fixupForIsolatedDeclarations(expandoFunction);
248+
}
249+
const nodeWithNoType = findNearestParentWithTypeAnnotation(nodeWithDiag)
239250
if (nodeWithNoType) {
240251
return fixupForIsolatedDeclarations(nodeWithNoType);
241252
}
242253
return undefined;
243254
}
244255

256+
function createNamespaceForExpandoProperties(expandoFunc: FunctionDeclaration): DiagnosticOrDiagnosticAndArguments|undefined {
257+
if (expandoPropertiesAdded?.has(expandoFunc)) return undefined;
258+
expandoPropertiesAdded?.add(expandoFunc);
259+
const type = typeChecker.getTypeAtLocation(expandoFunc);
260+
const elements = typeChecker.getPropertiesOfType(type);
261+
if (!expandoFunc.name || elements.length === 0) return undefined;
262+
const newProperties = []
263+
for (const symbol of elements) {
264+
if (!isIdentifierText(symbol.name, program.getCompilerOptions().target)) continue;
265+
// If there's an existing variable declaration for this property - skip.
266+
if (symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration)) continue;
267+
newProperties.push(factory.createVariableStatement(
268+
[factory.createModifier(SyntaxKind.ExportKeyword)],
269+
factory.createVariableDeclarationList(
270+
[factory.createVariableDeclaration(
271+
symbol.name,
272+
/*exclamationToken*/ undefined,
273+
typeToTypeNode(typeChecker.getTypeOfSymbol(symbol), expandoFunc),
274+
/*initializer*/ undefined,
275+
)],
276+
)
277+
));
278+
}
279+
if (newProperties.length === 0) return undefined;
280+
const modifiers: ModifierLike[] = [];
281+
if (expandoFunc.modifiers?.some((modifier)=> modifier.kind === SyntaxKind.ExportKeyword)) {
282+
modifiers.push(factory.createModifier(SyntaxKind.ExportKeyword))
283+
}
284+
modifiers.push(factory.createModifier(SyntaxKind.DeclareKeyword));
285+
const namespace = factory.createModuleDeclaration(
286+
modifiers,
287+
expandoFunc.name,
288+
factory.createModuleBlock(newProperties),
289+
/*flags*/ NodeFlags.Namespace | NodeFlags.ExportContext | NodeFlags.Ambient | NodeFlags.ContextFlags,
290+
);
291+
changeTracker.insertNodeAfter(sourceFile, expandoFunc, namespace);
292+
return [Diagnostics.Annotate_types_of_properties_expando_function_in_a_namespace];
293+
}
294+
245295
function needsParenthesizedExpressionForAssertion(node: Expression) {
246296
return !isEntityNameExpression(node) && !isCallExpression(node) && !isObjectLiteralExpression(node) && !isArrayLiteralExpression(node);
247297
}
298+
248299
function createAsExpression(node: Expression, type: TypeNode) {
249300
if (needsParenthesizedExpressionForAssertion(node)) {
250301
node = factory.createParenthesizedExpression(node);
@@ -291,7 +342,7 @@ function withChanges<T>(
291342
// We can't use typeof un an unique symbol. Would result in either
292343
// const s = Symbol("") as unique symbol
293344
// const s = Symbol("") as typeof s
294-
// both of which are not cirrect
345+
// both of which are not correct
295346
if (type && type.flags & TypeFlags.UniqueESSymbol) {
296347
return undefined;
297348
}
@@ -519,8 +570,13 @@ function withChanges<T>(
519570
const properties = typeChecker.getPropertiesOfType(targetType);
520571
if (some(properties, p => p.valueDeclaration === expandoDeclaration || p.valueDeclaration === expandoDeclaration.parent)) {
521572
const fn = targetType.symbol.valueDeclaration;
522-
if (fn && isFunctionExpressionOrArrowFunction(fn) && isVariableDeclaration(fn.parent)) {
573+
if (fn) {
574+
if (isFunctionExpressionOrArrowFunction(fn) && isVariableDeclaration(fn.parent)) {
523575
return fn.parent;
576+
}
577+
if (isFunctionDeclaration(fn)) {
578+
return fn;
579+
}
524580
}
525581
}
526582
}

tests/baselines/reference/isolated-declarations/auto-fixed/diff/declarationEmitDefaultExportWithStaticAssignment.d.ts.diff

Lines changed: 0 additions & 99 deletions
This file was deleted.
Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,22 @@
1-
// [[Reason: Function declarations are not fixed]] ////
1+
// [[Reason: Cannot name internal type]] ////
22

33
//// [tests/cases/compiler/declarationEmitExpandoPropertyPrivateName.ts] ////
44

55
===================================================================
66
--- TSC declarations
77
+++ DTE declarations
8-
@@ -5,20 +5,29 @@
8+
@@ -5,8 +5,14 @@
99
}
1010
export declare function f(): I;
1111
export {};
1212
//# sourceMappingURL=a.d.ts.map
1313
+//// [b.d.ts]
1414
+export declare function q(): void;
1515
+export declare namespace q {
16-
+ var val: invalid;
16+
+ var val: I;
1717
+}
1818
+//# sourceMappingURL=b.d.ts.map
1919
/// [Errors] ////
2020

21-
b.ts(4,1): error TS4032: Property 'val' of exported interface has or is using name 'I' from private module '"a"'.
22-
+b.ts(4,1): error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
23-
24-
25-
==== a.ts (0 errors) ====
26-
interface I {}
27-
export function f(): I { return null as I; }
28-
-==== b.ts (1 errors) ====
29-
+==== b.ts (2 errors) ====
30-
import {f} from "./a";
31-
32-
export function q(): void {}
33-
q.val = f();
34-
~~~~~
35-
!!! error TS4032: Property 'val' of exported interface has or is using name 'I' from private module '"a"'.
36-
+ ~~~~~
37-
+!!! error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
38-
39-
\ No newline at end of file
21+
b.ts(5,14): error TS2304: Cannot find name 'I'.
22+
b.ts(5,14): error TS4025: Exported variable 'val' has or is using private name 'I'.

tests/baselines/reference/isolated-declarations/auto-fixed/diff/declarationEmitFunctionDuplicateNamespace.d.ts.diff

Lines changed: 0 additions & 35 deletions
This file was deleted.

tests/baselines/reference/isolated-declarations/auto-fixed/diff/declarationEmitFunctionKeywordProp.d.ts.diff

Lines changed: 0 additions & 65 deletions
This file was deleted.

0 commit comments

Comments
 (0)