Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port fixes from master into release-2.5 #18361

Merged
merged 15 commits into from
Sep 9, 2017
Merged
327 changes: 145 additions & 182 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

17 changes: 10 additions & 7 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,10 @@ namespace ts {
visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression);
}
case SyntaxKind.JSDocTypeLiteral:
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) {
visitNode(cbNode, tag);
if ((node as JSDocTypeLiteral).jsDocPropertyTags) {
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) {
visitNode(cbNode, tag);
}
}
return;
case SyntaxKind.PartiallyEmittedExpression:
Expand Down Expand Up @@ -6667,19 +6669,18 @@ namespace ts {
if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
let child: JSDocTypeTag | JSDocPropertyTag | false;
let jsdocTypeLiteral: JSDocTypeLiteral;
let alreadyHasTypeTag = false;
let childTypeTag: JSDocTypeTag;
const start = scanner.getStartPos();
while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Property))) {
if (!jsdocTypeLiteral) {
jsdocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, start);
}
if (child.kind === SyntaxKind.JSDocTypeTag) {
if (alreadyHasTypeTag) {
if (childTypeTag) {
break;
}
else {
jsdocTypeLiteral.jsDocTypeTag = child;
alreadyHasTypeTag = true;
childTypeTag = child;
}
}
else {
Expand All @@ -6693,7 +6694,9 @@ namespace ts {
if (typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType) {
jsdocTypeLiteral.isArrayType = true;
}
typedefTag.typeExpression = finishNode(jsdocTypeLiteral);
typedefTag.typeExpression = childTypeTag && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ?
childTypeTag.typeExpression :
finishNode(jsdocTypeLiteral);
}
}

Expand Down
8 changes: 3 additions & 5 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2150,7 +2150,6 @@ namespace ts {
export interface JSDocTypeLiteral extends JSDocType {
kind: SyntaxKind.JSDocTypeLiteral;
jsDocPropertyTags?: ReadonlyArray<JSDocPropertyLikeTag>;
jsDocTypeTag?: JSDocTypeTag;
/** If true, then this type literal represents an *array* of its type. */
isArrayType?: boolean;
}
Expand Down Expand Up @@ -3296,13 +3295,12 @@ namespace ts {
}

/* @internal */
export interface MappedType extends ObjectType {
export interface MappedType extends AnonymousType {
declaration: MappedTypeNode;
typeParameter?: TypeParameter;
constraintType?: Type;
templateType?: Type;
modifiersType?: Type;
mapper?: TypeMapper; // Instantiation mapper
}

export interface EvolvingArrayType extends ObjectType {
Expand Down Expand Up @@ -3412,6 +3410,8 @@ namespace ts {
/* @internal */
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
/* @internal */
canonicalSignatureCache?: Signature; // Canonical version of signature (deferred)
/* @internal */
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
/* @internal */
typePredicate?: TypePredicate;
Expand All @@ -3433,8 +3433,6 @@ namespace ts {
/* @internal */
export interface TypeMapper {
(t: TypeParameter): Type;
mappedTypes?: TypeParameter[]; // Types mapped by this mapper
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
}

export const enum InferencePriority {
Expand Down
67 changes: 62 additions & 5 deletions src/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,24 +235,39 @@ namespace ts.server {
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`;
}

interface QueuedOperation {
operationId: string;
operation: () => void;
}

class NodeTypingsInstaller implements ITypingsInstaller {
private installer: NodeChildProcess;
private installerPidReported = false;
private socket: NodeSocket;
private projectService: ProjectService;
private throttledOperations: ThrottledOperations;
private eventSender: EventSender;
private activeRequestCount = 0;
private requestQueue: QueuedOperation[] = [];
private requestMap = createMap<QueuedOperation>(); // Maps operation ID to newest requestQueue entry with that ID

// This number is essentially arbitrary. Processing more than one typings request
// at a time makes sense, but having too many in the pipe results in a hang
// (see https://github.com/nodejs/node/issues/7657).
// It would be preferable to base our limit on the amount of space left in the
// buffer, but we have yet to find a way to retrieve that value.
private static readonly maxActiveRequestCount = 10;
private static readonly requestDelayMillis = 100;


constructor(
private readonly telemetryEnabled: boolean,
private readonly logger: server.Logger,
host: ServerHost,
private readonly host: ServerHost,
eventPort: number,
readonly globalTypingsCacheLocation: string,
readonly typingSafeListLocation: string,
private readonly npmLocation: string | undefined,
private newLine: string) {
this.throttledOperations = new ThrottledOperations(host);
if (eventPort) {
const s = net.connect({ port: eventPort }, () => {
this.socket = s;
Expand Down Expand Up @@ -333,12 +348,26 @@ namespace ts.server {
this.logger.info(`Scheduling throttled operation: ${JSON.stringify(request)}`);
}
}
this.throttledOperations.schedule(project.getProjectName(), /*ms*/ 250, () => {

const operationId = project.getProjectName();
const operation = () => {
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
}
this.installer.send(request);
});
};
const queuedRequest: QueuedOperation = { operationId, operation };

if (this.activeRequestCount < NodeTypingsInstaller.maxActiveRequestCount) {
this.scheduleRequest(queuedRequest);
}
else {
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Deferring request for: ${operationId}`);
}
this.requestQueue.push(queuedRequest);
this.requestMap.set(operationId, queuedRequest);
}
}

private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
Expand Down Expand Up @@ -399,11 +428,39 @@ namespace ts.server {
return;
}

if (this.activeRequestCount > 0) {
this.activeRequestCount--;
}
else {
Debug.fail("Received too many responses");
}

while (this.requestQueue.length > 0) {
const queuedRequest = this.requestQueue.shift();
if (this.requestMap.get(queuedRequest.operationId) === queuedRequest) {
this.requestMap.delete(queuedRequest.operationId);
this.scheduleRequest(queuedRequest);
break;
}

if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Skipping defunct request for: ${queuedRequest.operationId}`);
}
}

this.projectService.updateTypingsForProject(response);
if (response.kind === ActionSet && this.socket) {
this.sendEvent(0, "setTypings", response);
}
}

private scheduleRequest(request: QueuedOperation) {
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Scheduling request for: ${request.operationId}`);
}
this.activeRequestCount++;
this.host.setTimeout(request.operation, NodeTypingsInstaller.requestDelayMillis);
}
}

class IOSession extends Session {
Expand Down
6 changes: 6 additions & 0 deletions src/server/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ namespace ts.server {
constructor(private readonly host: ServerHost) {
}

/**
* Wait `number` milliseconds and then invoke `cb`. If, while waiting, schedule
* is called again with the same `operationId`, cancel this operation in favor
* of the new one. (Note that the amount of time the canceled operation had been
* waiting does not affect the amount of time that the new operation waits.)
*/
public schedule(operationId: string, delay: number, cb: () => void) {
const pendingTimeout = this.pendingTimeouts.get(operationId);
if (pendingTimeout) {
Expand Down
3 changes: 1 addition & 2 deletions src/services/signatureHelp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,7 @@ namespace ts.SignatureHelp {
if (isTypeParameterList) {
isVariadic = false; // type parameter lists are not variadic
prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
// Use `.mapper` to ensure we get the generic type arguments even if this is an instantiated version of the signature.
const typeParameters = candidateSignature.mapper ? candidateSignature.mapper.mappedTypes : candidateSignature.typeParameters;
const typeParameters = (candidateSignature.target || candidateSignature).typeParameters;
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
const parameterParts = mapToDisplayParts(writer =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,6 @@
"kind": "JSDocTypeLiteral",
"pos": 26,
"end": 98,
"jsDocTypeTag": {
"kind": "JSDocTypeTag",
"pos": 28,
"end": 42,
"atToken": {
"kind": "AtToken",
"pos": 28,
"end": 29
},
"tagName": {
"kind": "Identifier",
"pos": 29,
"end": 33,
"escapedText": "type"
},
"typeExpression": {
"kind": "JSDocTypeExpression",
"pos": 34,
"end": 42,
"type": {
"kind": "TypeReference",
"pos": 35,
"end": 41,
"typeName": {
"kind": "Identifier",
"pos": 35,
"end": 41,
"escapedText": "Object"
}
}
}
},
"jsDocPropertyTags": [
{
"kind": "JSDocPropertyTag",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstrain
Type 'void' is not assignable to type 'string'.
tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstraintSatisfaction2.ts(38,10): error TS2345: Argument of type 'U' is not assignable to parameter of type '(x: string) => string'.
Type 'T' is not assignable to type '(x: string) => string'.
Type '() => void' is not assignable to type '(x: string) => string'.
Type 'void' is not assignable to type 'string'.


==== tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstraintSatisfaction2.ts (13 errors) ====
Expand Down Expand Up @@ -102,7 +100,5 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstrain
~
!!! error TS2345: Argument of type 'U' is not assignable to parameter of type '(x: string) => string'.
!!! error TS2345: Type 'T' is not assignable to type '(x: string) => string'.
!!! error TS2345: Type '() => void' is not assignable to type '(x: string) => string'.
!!! error TS2345: Type 'void' is not assignable to type 'string'.
}

10 changes: 10 additions & 0 deletions tests/baselines/reference/jsdocTwoLineTypedef.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//// [jsdocTwoLineTypedef.ts]
// Regression from #18301
/**
* @typedef LoadCallback
* @type {function}
*/
type LoadCallback = void;


//// [jsdocTwoLineTypedef.js]
9 changes: 9 additions & 0 deletions tests/baselines/reference/jsdocTwoLineTypedef.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
=== tests/cases/conformance/jsdoc/jsdocTwoLineTypedef.ts ===
// Regression from #18301
/**
* @typedef LoadCallback
* @type {function}
*/
type LoadCallback = void;
>LoadCallback : Symbol(LoadCallback, Decl(jsdocTwoLineTypedef.ts, 0, 0))

9 changes: 9 additions & 0 deletions tests/baselines/reference/jsdocTwoLineTypedef.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
=== tests/cases/conformance/jsdoc/jsdocTwoLineTypedef.ts ===
// Regression from #18301
/**
* @typedef LoadCallback
* @type {function}
*/
type LoadCallback = void;
>LoadCallback : void

4 changes: 2 additions & 2 deletions tests/baselines/reference/limitDeepInstantiations.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2550: Generic type instantiation is excessively deep and possibly infinite.
tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'.


Expand All @@ -7,7 +7,7 @@ tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"fals

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2550: Generic type instantiation is excessively deep and possibly infinite.
!!! error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
let f1: Foo<"true", {}>;
let f2: Foo<"false", {}>;
~~~~~~~
Expand Down
2 changes: 0 additions & 2 deletions tests/baselines/reference/promisePermutations.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ tests/cases/compiler/promisePermutations.ts(134,19): error TS2345: Argument of t
tests/cases/compiler/promisePermutations.ts(137,33): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
tests/cases/compiler/promisePermutations.ts(144,35): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
tests/cases/compiler/promisePermutations.ts(152,36): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
Type 'IPromise<string>' is not assignable to type 'Promise<number>'.
Types of property 'then' are incompatible.
Expand Down Expand Up @@ -290,7 +289,6 @@ tests/cases/compiler/promisePermutations.ts(160,21): error TS2345: Argument of t
var r10d = r10.then(testFunction, sIPromise, nIPromise); // ok
~~~~~~~~~
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
!!! error TS2345: Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
var r10e = r10.then(testFunction, nIPromise, sIPromise).then(sIPromise, sIPromise, sIPromise); // ok
var s10 = testFunction10P(x => x);
var s10a = s10.then(testFunction10, testFunction10, testFunction10); // ok
Expand Down
2 changes: 0 additions & 2 deletions tests/baselines/reference/promisePermutations2.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ tests/cases/compiler/promisePermutations2.ts(133,19): error TS2345: Argument of
tests/cases/compiler/promisePermutations2.ts(136,33): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
tests/cases/compiler/promisePermutations2.ts(143,35): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
tests/cases/compiler/promisePermutations2.ts(151,36): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
Type 'IPromise<string>' is not assignable to type 'Promise<number>'.
Types of property 'then' are incompatible.
Expand Down Expand Up @@ -289,7 +288,6 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of
var r10d = r10.then(testFunction, sIPromise, nIPromise); // error
~~~~~~~~~
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
!!! error TS2345: Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
var r10e = r10.then(testFunction, nIPromise, sIPromise).then(sIPromise, sIPromise, sIPromise); // ok
var s10 = testFunction10P(x => x);
var s10a = s10.then(testFunction10, testFunction10, testFunction10); // ok
Expand Down
2 changes: 0 additions & 2 deletions tests/baselines/reference/promisePermutations3.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ tests/cases/compiler/promisePermutations3.ts(133,19): error TS2345: Argument of
tests/cases/compiler/promisePermutations3.ts(136,33): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
tests/cases/compiler/promisePermutations3.ts(143,35): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
tests/cases/compiler/promisePermutations3.ts(151,36): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
Type 'IPromise<string>' is not assignable to type 'Promise<number>'.
Types of property 'then' are incompatible.
Expand Down Expand Up @@ -301,7 +300,6 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of
var r10d = r10.then(testFunction, sIPromise, nIPromise); // error
~~~~~~~~~
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
!!! error TS2345: Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
var r10e = r10.then(testFunction, nIPromise, sIPromise).then(sIPromise, sIPromise, sIPromise); // ok
var s10 = testFunction10P(x => x);
var s10a = s10.then(testFunction10, testFunction10, testFunction10); // ok
Expand Down
6 changes: 6 additions & 0 deletions tests/cases/conformance/jsdoc/jsdocTwoLineTypedef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Regression from #18301
/**
* @typedef LoadCallback
* @type {function}
*/
type LoadCallback = void;