Skip to content

Commit 23a3b34

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint
2 parents c050e55 + 2a2866c commit 23a3b34

170 files changed

Lines changed: 1615 additions & 752 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/binder.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1842,7 +1842,8 @@ namespace ts {
18421842
node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord &&
18431843
node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord &&
18441844
!isIdentifierName(node) &&
1845-
!(node.flags & NodeFlags.Ambient)) {
1845+
!(node.flags & NodeFlags.Ambient) &&
1846+
!(node.flags & NodeFlags.JSDoc)) {
18461847

18471848
// Report error only if there are no parse errors in file
18481849
if (!file.parseDiagnostics.length) {

src/compiler/checker.ts

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5937,7 +5937,9 @@ namespace ts {
59375937
// Otherwise, fall back to 'any'.
59385938
else {
59395939
if (setter) {
5940-
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
5940+
if (!isPrivateWithinAmbient(setter)) {
5941+
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
5942+
}
59415943
}
59425944
else {
59435945
Debug.assert(!!getter, "there must existed getter as we are current checking either setter or getter in this function");
@@ -26273,8 +26275,9 @@ namespace ts {
2627326275

2627426276
let duplicateFunctionDeclaration = false;
2627526277
let multipleConstructorImplementation = false;
26278+
let hasNonAmbientClass = false;
2627626279
for (const current of declarations) {
26277-
const node = <SignatureDeclaration>current;
26280+
const node = <SignatureDeclaration | ClassDeclaration | ClassExpression>current;
2627826281
const inAmbientContext = node.flags & NodeFlags.Ambient;
2627926282
const inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext;
2628026283
if (inAmbientContextOrInterface) {
@@ -26288,6 +26291,10 @@ namespace ts {
2628826291
previousDeclaration = undefined;
2628926292
}
2629026293

26294+
if ((node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression) && !inAmbientContext) {
26295+
hasNonAmbientClass = true;
26296+
}
26297+
2629126298
if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.Constructor) {
2629226299
const currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
2629326300
someNodeFlags |= currentNodeFlags;
@@ -26336,6 +26343,16 @@ namespace ts {
2633626343
});
2633726344
}
2633826345

26346+
if (hasNonAmbientClass && !isConstructor && symbol.flags & SymbolFlags.Function) {
26347+
// A non-ambient class cannot be an implementation for a non-constructor function/class merge
26348+
// TODO: The below just replicates our older error from when classes and functions were
26349+
// entirely unable to merge - a more helpful message like "Class declaration cannot implement overload list"
26350+
// might be warranted. :shrug:
26351+
forEach(declarations, declaration => {
26352+
addDuplicateDeclarationError(getNameOfDeclaration(declaration) || declaration, Diagnostics.Duplicate_identifier_0, symbolName(symbol), filter(declarations, d => d !== declaration));
26353+
});
26354+
}
26355+
2633926356
// Abstract methods can't have an implementation -- in particular, they don't need one.
2634026357
if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
2634126358
!hasModifier(lastSeenNonAmbientDeclaration, ModifierFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) {
@@ -31649,7 +31666,7 @@ namespace ts {
3164931666
if (!symbol || !(symbol.flags & SymbolFlags.Function)) {
3165031667
return false;
3165131668
}
31652-
return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && isPropertyAccessExpression(p.valueDeclaration));
31669+
return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && p.valueDeclaration && isPropertyAccessExpression(p.valueDeclaration));
3165331670
}
3165431671

3165531672
function getPropertiesOfContainerFunction(node: Declaration): Symbol[] {
@@ -33043,43 +33060,39 @@ namespace ts {
3304333060
}
3304433061

3304533062
function checkGrammarAccessor(accessor: AccessorDeclaration): boolean {
33046-
const kind = accessor.kind;
33047-
if (languageVersion < ScriptTarget.ES5) {
33048-
return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
33049-
}
33050-
else if (accessor.flags & NodeFlags.Ambient) {
33051-
return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context);
33052-
}
33053-
else if (accessor.body === undefined && !hasModifier(accessor, ModifierFlags.Abstract)) {
33054-
return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
33063+
if (!(accessor.flags & NodeFlags.Ambient)) {
33064+
if (languageVersion < ScriptTarget.ES5) {
33065+
return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
33066+
}
33067+
if (accessor.body === undefined && !hasModifier(accessor, ModifierFlags.Abstract)) {
33068+
return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
33069+
}
3305533070
}
33056-
else if (accessor.body && hasModifier(accessor, ModifierFlags.Abstract)) {
33071+
if (accessor.body && hasModifier(accessor, ModifierFlags.Abstract)) {
3305733072
return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation);
3305833073
}
33059-
else if (accessor.typeParameters) {
33074+
if (accessor.typeParameters) {
3306033075
return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_have_type_parameters);
3306133076
}
33062-
else if (!doesAccessorHaveCorrectParameterCount(accessor)) {
33077+
if (!doesAccessorHaveCorrectParameterCount(accessor)) {
3306333078
return grammarErrorOnNode(accessor.name,
33064-
kind === SyntaxKind.GetAccessor ?
33079+
accessor.kind === SyntaxKind.GetAccessor ?
3306533080
Diagnostics.A_get_accessor_cannot_have_parameters :
3306633081
Diagnostics.A_set_accessor_must_have_exactly_one_parameter);
3306733082
}
33068-
else if (kind === SyntaxKind.SetAccessor) {
33083+
if (accessor.kind === SyntaxKind.SetAccessor) {
3306933084
if (accessor.type) {
3307033085
return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation);
3307133086
}
33072-
else {
33073-
const parameter = accessor.parameters[0];
33074-
if (parameter.dotDotDotToken) {
33075-
return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter);
33076-
}
33077-
else if (parameter.questionToken) {
33078-
return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter);
33079-
}
33080-
else if (parameter.initializer) {
33081-
return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer);
33082-
}
33087+
const parameter = Debug.assertDefined(getSetAccessorValueParameter(accessor), "Return value does not match parameter count assertion.");
33088+
if (parameter.dotDotDotToken) {
33089+
return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter);
33090+
}
33091+
if (parameter.questionToken) {
33092+
return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter);
33093+
}
33094+
if (parameter.initializer) {
33095+
return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer);
3308333096
}
3308433097
}
3308533098
return false;
@@ -33567,14 +33580,9 @@ namespace ts {
3356733580

3356833581
function checkGrammarStatementInAmbientContext(node: Node): boolean {
3356933582
if (node.flags & NodeFlags.Ambient) {
33570-
// An accessors is already reported about the ambient context
33571-
if (isAccessor(node.parent)) {
33572-
return getNodeLinks(node).hasReportedStatementInAmbientContext = true;
33573-
}
33574-
3357533583
// Find containing block which is either Block, ModuleBlock, SourceFile
3357633584
const links = getNodeLinks(node);
33577-
if (!links.hasReportedStatementInAmbientContext && isFunctionLike(node.parent)) {
33585+
if (!links.hasReportedStatementInAmbientContext && (isFunctionLike(node.parent) || isAccessor(node.parent))) {
3357833586
return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
3357933587
}
3358033588

src/compiler/diagnosticMessages.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,6 @@
243243
"category": "Error",
244244
"code": 1085
245245
},
246-
"An accessor cannot be declared in an ambient context.": {
247-
"category": "Error",
248-
"code": 1086
249-
},
250246
"'{0}' modifier cannot appear on a constructor declaration.": {
251247
"category": "Error",
252248
"code": 1089

src/compiler/emitter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,7 @@ namespace ts {
16081608
for (let i = 0; i < numNodes; i++) {
16091609
const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] : node;
16101610
const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile!;
1611-
const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined);
1611+
const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && hasRecordedExternalHelpers(sourceFile));
16121612
const shouldBundle = (isSourceFile(currentNode) || isUnparsedSource(currentNode)) && !isOwnFileEmit;
16131613
const helpers = isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode);
16141614
if (helpers) {

src/compiler/factory.ts

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3629,12 +3629,16 @@ namespace ts {
36293629

36303630
// Helpers
36313631

3632-
export function getHelperName(name: string) {
3632+
/**
3633+
* Gets an identifier for the name of an *unscoped* emit helper.
3634+
*/
3635+
export function getUnscopedHelperName(name: string) {
36333636
return setEmitFlags(createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode);
36343637
}
36353638

36363639
export const valuesHelper: UnscopedEmitHelper = {
36373640
name: "typescript:values",
3641+
importName: "__values",
36383642
scoped: false,
36393643
text: `
36403644
var __values = (this && this.__values) || function(o) {
@@ -3654,7 +3658,7 @@ namespace ts {
36543658
context.requestEmitHelper(valuesHelper);
36553659
return setTextRange(
36563660
createCall(
3657-
getHelperName("__values"),
3661+
getUnscopedHelperName("__values"),
36583662
/*typeArguments*/ undefined,
36593663
[expression]
36603664
),
@@ -3664,6 +3668,7 @@ namespace ts {
36643668

36653669
export const readHelper: UnscopedEmitHelper = {
36663670
name: "typescript:read",
3671+
importName: "__read",
36673672
scoped: false,
36683673
text: `
36693674
var __read = (this && this.__read) || function (o, n) {
@@ -3688,7 +3693,7 @@ namespace ts {
36883693
context.requestEmitHelper(readHelper);
36893694
return setTextRange(
36903695
createCall(
3691-
getHelperName("__read"),
3696+
getUnscopedHelperName("__read"),
36923697
/*typeArguments*/ undefined,
36933698
count !== undefined
36943699
? [iteratorRecord, createLiteral(count)]
@@ -3700,6 +3705,7 @@ namespace ts {
37003705

37013706
export const spreadHelper: UnscopedEmitHelper = {
37023707
name: "typescript:spread",
3708+
importName: "__spread",
37033709
scoped: false,
37043710
text: `
37053711
var __spread = (this && this.__spread) || function () {
@@ -3713,7 +3719,7 @@ namespace ts {
37133719
context.requestEmitHelper(spreadHelper);
37143720
return setTextRange(
37153721
createCall(
3716-
getHelperName("__spread"),
3722+
getUnscopedHelperName("__spread"),
37173723
/*typeArguments*/ undefined,
37183724
argumentList
37193725
),
@@ -3723,6 +3729,7 @@ namespace ts {
37233729

37243730
export const spreadArraysHelper: UnscopedEmitHelper = {
37253731
name: "typescript:spreadArrays",
3732+
importName: "__spreadArrays",
37263733
scoped: false,
37273734
text: `
37283735
var __spreadArrays = (this && this.__spreadArrays) || function () {
@@ -3738,7 +3745,7 @@ namespace ts {
37383745
context.requestEmitHelper(spreadArraysHelper);
37393746
return setTextRange(
37403747
createCall(
3741-
getHelperName("__spreadArrays"),
3748+
getUnscopedHelperName("__spreadArrays"),
37423749
/*typeArguments*/ undefined,
37433750
argumentList
37443751
),
@@ -4862,6 +4869,65 @@ namespace ts {
48624869
return emitNode && emitNode.externalHelpersModuleName;
48634870
}
48644871

4872+
export function hasRecordedExternalHelpers(sourceFile: SourceFile) {
4873+
const parseNode = getOriginalNode(sourceFile, isSourceFile);
4874+
const emitNode = parseNode && parseNode.emitNode;
4875+
return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers);
4876+
}
4877+
4878+
export function createExternalHelpersImportDeclarationIfNeeded(sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) {
4879+
if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) {
4880+
let namedBindings: NamedImportBindings | undefined;
4881+
const moduleKind = getEmitModuleKind(compilerOptions);
4882+
if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) {
4883+
// use named imports
4884+
const helpers = getEmitHelpers(sourceFile);
4885+
if (helpers) {
4886+
const helperNames: string[] = [];
4887+
for (const helper of helpers) {
4888+
if (!helper.scoped) {
4889+
const importName = (helper as UnscopedEmitHelper).importName;
4890+
if (importName) {
4891+
pushIfUnique(helperNames, importName);
4892+
}
4893+
}
4894+
}
4895+
if (some(helperNames)) {
4896+
helperNames.sort(compareStringsCaseSensitive);
4897+
// Alias the imports if the names are used somewhere in the file.
4898+
// NOTE: We don't need to care about global import collisions as this is a module.
4899+
namedBindings = createNamedImports(
4900+
map(helperNames, name => isFileLevelUniqueName(sourceFile, name)
4901+
? createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))
4902+
: createImportSpecifier(createIdentifier(name), getUnscopedHelperName(name))
4903+
)
4904+
);
4905+
const parseNode = getOriginalNode(sourceFile, isSourceFile);
4906+
const emitNode = getOrCreateEmitNode(parseNode);
4907+
emitNode.externalHelpers = true;
4908+
}
4909+
}
4910+
}
4911+
else {
4912+
// use a namespace import
4913+
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault);
4914+
if (externalHelpersModuleName) {
4915+
namedBindings = createNamespaceImport(externalHelpersModuleName);
4916+
}
4917+
}
4918+
if (namedBindings) {
4919+
const externalHelpersImportDeclaration = createImportDeclaration(
4920+
/*decorators*/ undefined,
4921+
/*modifiers*/ undefined,
4922+
createImportClause(/*name*/ undefined, namedBindings),
4923+
createLiteral(externalHelpersModuleNameText)
4924+
);
4925+
addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper);
4926+
return externalHelpersImportDeclaration;
4927+
}
4928+
}
4929+
}
4930+
48654931
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) {
48664932
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
48674933
const externalHelpersModuleName = getExternalHelpersModuleName(node);

0 commit comments

Comments
 (0)