Merge branch 'master' into mappedTypes

# Conflicts:
#	src/compiler/checker.ts
This commit is contained in:
Anders Hejlsberg
2016-11-08 07:12:35 -08:00
39 changed files with 868 additions and 458 deletions
+36 -7
View File
@@ -1,32 +1,38 @@
Alexander <alexander@kuvaev.me># Alexander Kuvaev
AbubakerB <abubaker_bashir@hotmail.com> # Abubaker Bashir
Alexander <alexander@kuvaev.me># Alexander Kuvaev
Adam Freidin <adam.freidin@gmail.com> Adam Freidin <afreidin@adobe.com>
Adi Dahiya <adahiya@palantir.com> Adi Dahiya <adi.dahiya14@gmail.com>
Ahmad Farid <ahfarid@microsoft.com> ahmad-farid <ahfarid@microsoft.com>
Alexander Rusakov <a_s_rusakov@mail.ru>
Alex Eagle <alexeagle@google.com>
Anatoly Ressin <anatoly.ressin@icloud.com>
Anders Hejlsberg <andersh@microsoft.com> unknown <andersh@AndersX1.NOE.Nokia.com> unknown <andersh@andersh-yoga.redmond.corp.microsoft.com>
Andrej Baran <andrej.baran@gmail.com>
Andrew Z Allen <me@andrewzallen.com>
Andy Hanson <anhans@microsoft.com> Andy <anhans@microsoft.com>
Anil Anar <anilanar@hotmail.com>
Anton Tolmachev <myste@mail.ru>
Arnavion <arnavion@gmail.com> # Arnav Singh
Arthur Ozga <aozgaa@umich.edu> Arthur Ozga <t-arthoz@microsoft.com>
Arthur Ozga <aozgaa@umich.edu> Arthur Ozga <t-arthoz@microsoft.com> Arthur Ozga <aozgaa-ms@outlook.com> Arthur Ozga <aozgaa@users.noreply.github.com> Arthur Ozga <arozga@microsoft.com>
Asad Saeeduddin <masaeedu@gmail.com>
Schmavery <avery.schmavery@gmail.com> # Avery Morin
Basarat Ali Syed <basaratali@gmail.com> Basarat Syed <basaratali@gmail.com> basarat <basaratali@gmail.com>
Bill Ticehurst <billti@hotmail.com> Bill Ticehurst <billti@microsoft.com>
Ben Duffield <jebavarde@gmail.com>
Ben Mosher <me@benmosher.com>
Blake Embrey <hello@blakeembrey.com>
Bowden Kelly <wilkelly@microsoft.com>
Brett Mayen <bmayen@midnightsnacks.net>
Bryan Forbes <bryan@reigndropsfall.net>
Caitlin Potter <caitpotter88@gmail.com>
ChrisBubernak <chris.bubernak@gmail.com> unknown <chrbub@chrbub1.redmond.corp.microsoft.com> # Chris Bubernak
Christophe Vidal <kriss@krizalys.com>
Chuck Jazdzewski <chuckj@google.com>
Colby Russell <mr@colbyrussell.com>
Colin Snover <github.com@zetafleet.com>
Cyrus Najmabadi <cyrusn@microsoft.com> CyrusNajmabadi <cyrusn@microsoft.com> unknown <cyrusn@cylap.ntdev.corp.microsoft.com>
Dafrok <o.o@mug.dog> # Dafrok Zhang
Dan Corder <dev@dancorder.com>
Dan Quirk <danquirk@microsoft.com> Dan Quirk <danquirk@users.noreply.github.com> nknown <danquirk@DANQUIRK1.redmond.corp.microsoft.com>
Daniel Rosenwasser <drosen@microsoft.com> Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com> Daniel Rosenwasser <DanielRosenwasser@gmail.com> Daniel Rosenwasser <Daniel.Rosenwasser@microsoft.com> Daniel Rosenwasser <DanielRosenwasser@microsoft.com>
@@ -36,17 +42,22 @@ Denis Nedelyaev <denvned@gmail.com>
Dick van den Brink <d_vandenbrink@outlook.com> unknown <d_vandenbrink@outlook.com> unknown <d_vandenbrink@live.com>
Dirk Baeumer <dirkb@microsoft.com> Dirk Bäumer <dirkb@microsoft.com> # Dirk Bäumer
Dirk Holtwick <dirk.holtwick@gmail.com>
Dom Chen <domchen@users.noreply.github.com>
Doug Ilijev <dilijev@users.noreply.github.com>
Erik Edrosa <erik.edrosa@gmail.com>
erictsangx <erictsangx@gmail.com> # Eric Tsang
Ethan Rubio <ethanrubio@users.noreply.github.com>
Evan Martin <martine@danga.com>
Evan Sebastian <evanlhoini@gmail.com>
Eyas <eyas.sharaiha@gmail.com> # Eyas Sharaiha
Fabian Cook <faybecook@gmail.com>
falsandtru <falsandtru@users.noreply.github.com> # @falsandtru
Frank Wallis <fwallis@outlook.com>
František Žiačik <fziacik@gratex.com> František Žiačik <ziacik@gmail.com>
František Žiacik <fziacik@gratex.com> František Žiacik <ziacik@gmail.com>
Gabe Moothart <gmoothart@gmail.com>
Gabriel Isenberg <gisenberg@gmail.com>
Gilad Peleg <giladp007@gmail.com>
Godfrey Chan <godfreykfc@gmail.com>
Graeme Wicksted <graeme.wicksted@gmail.com>
Guillaume Salles <guillaume.salles@me.com>
Guy Bedford <guybedford@gmail.com> guybedford <guybedford@gmail.com>
@@ -55,6 +66,7 @@ Iain Monro <iain.monro@softwire.com>
Ingvar Stepanyan <me@rreverser.com>
impinball <impinball@gmail.com> # Isiah Meadows
Ivo Gabe de Wolff <ivogabe@ivogabe.nl>
Jakub Młokosiewicz <hckr@users.noreply.github.com>
James Whitney <james@whitney.io>
Jason Freeman <jfreeman@microsoft.com> Jason Freeman <JsonFreeman@users.noreply.github.com>
Jason Killian <jkillian@palantir.com>
@@ -69,11 +81,14 @@ Jonathan Park <jpark@daptiv.com>
Jonathan Turner <jont@microsoft.com> Jonathan Turner <probata@hotmail.com>
Jonathan Toland <toland@dnalot.com>
Jesse Schalken <me@jesseschalken.com>
Josh Abernathy <joshaber@gmail.com> joshaber <joshaber@gmail.com>
Josh Kalderimis <josh.kalderimis@gmail.com>
Josh Soref <jsoref@users.noreply.github.com>
Juan Luis Boya García <ntrrgc@gmail.com>
Julian Williams <julianjw92@gmail.com>
Herrington Darkholme <nonamesheep1@gmail.com>
Justin Bay <justin.bay@outlook.com>
Justin Johansson <thebabellion@gmail.com>
Herrington Darkholme <nonamesheep1@gmail.com> (´·?·`) <HerringtonDarkholme@users.noreply.github.com> # Herrington Darkholme
Kagami Sascha Rosylight <saschanaz@outlook.com> SaschaNaz <saschanaz@outlook.com>
Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui <yuit@users.noreply.github.com>
Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui T <yuisu@microsoft.com>
@@ -82,23 +97,29 @@ Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui <yuisu@microsoft.com>
Kanchalai Tanglertsampan <yuisu@microsoft.com> yui T <yuisu@microsoft.com>
Keith Mashinter <kmashint@yahoo.com> kmashint <kmashint@yahoo.com>
Ken Howard <ken@simplicatedweb.com>
Kevin Lang <klang2012@gmail.com>
kimamula <kenji.imamula@gmail.com> # Kenji Imamula
Kyle Kelley <rgbkrk@gmail.com>
Lorant Pinter <lorant.pinter@prezi.com>
Lucien Greathouse <me@lpghatguy.com>
Lukas Elmer <lukas.elmer@gmail.com> Lukas Elmer <lukas.elmer@renuo.ch>
Martin Vseticka <vseticka.martin@gmail.com> Martin Všeticka <vseticka.martin@gmail.com> MartyIX <vseticka.martin@gmail.com>
gcnew <gcnew@abv.bg> # Marin Marinov
vvakame <vvakame+dev@gmail.com> # Masahiro Wakame
Matt McCutchen <rmccutch@mit.edu>
Max Deepfield <maxdeepfield@absolutefreakout.com>
Micah Zoltu <micah@zoltu.net>
Michael <maykelchiche@gmail.com>
Mohamed Hegazy <mhegazy@microsoft.com>
Nathan Shively-Sanders <nathansa@microsoft.com>
Nathan Yee <ny.nathan.yee@gmail.com>
Nima Zahedi <nima.zahedee@gmail.com>
Noah Chen <nchen@palantir.com>
Noj Vek <nojvek@gmail.com>
mihailik <mihailik@gmail.com> # Oleg Mihailik
Oleksandr Chekhovskyi <oleksandr.chekhovskyi@hansoft.com>
Paul van Brenk <paul.van.brenk@microsoft.com> Paul van Brenk <paul.van.brenk@outlook.com> unknown <paul.van.brenk@microsoft.com> unknown <paul.van.brenk@microsoft.com> unknown <pvanbren@pvbvsproai.redmond.corp.microsoft.com>
Omer Sheikh <ojsheikh@gmail.com>
Oskar Segersva¨rd <oskar.segersvard@widespace.com>
pcan <piero.cangianiello@gmail.com> # Piero Cangianiello
pcbro <2bux89+dk3zspjmuh16o@sharklasers.com> # @pcbro
@@ -109,21 +130,26 @@ progre <djyayutto@gmail.com> # @progre
Prayag Verma <prayag.verma@gmail.com>
Punya Biswal <pbiswal@palantir.com>
Rado Kirov <radokirov@google.com>
Ron Buckton <rbuckton@microsoft.com> Ron Buckton <ron.buckton@microsoft.com>
Ron Buckton <rbuckton@microsoft.com> Ron Buckton <ron.buckton@microsoft.com> rbuckton <rbuckton@chronicles.org>
Rostislav Galimsky <rostgal@gmail.com>
Richard Knoll <riknoll@users.noreply.github.com> Richard Knoll <riknoll@microsoft.com>
Rowan Wyborn <rwyborn@internode.on.net>
Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com> Ryan Cavanaugh <ryan.cavanaugh@microsoft.com> Ryan Cavanaugh <ryanca@microsoft.com>
Ryohei Ikegami <iofg2100@gmail.com>
Sarangan Rajamanickam <sarajama@microsoft.com>
Sébastien Arod <sebastien.arod@gmail.com>
Sergey Shandar <sergey-shandar@users.noreply.github.com>
Sheetal Nandi <shkamat@microsoft.com>
Shengping Zhong <zhongsp@users.noreply.github.com>
shyyko.serhiy@gmail.com <shyyko.serhiy@gmail.com> # Shyyko Serhiy
Sam El-Husseini <samelh@microsoft.com>
Simon Hürlimann <simon.huerlimann@cyt.ch>
Slawomir Sadziak <slsadzia@microsoft.com>
Solal Pirelli <solal.pirelli@gmail.com>
Stan Thomas <stmsdn@norvil.net>
Stanislav Sysoev <d4rkr00t@gmail.com>
Steve Lucco <steveluc@users.noreply.github.com> steveluc <steveluc@microsoft.com>
Sudheesh Singanamalla <sudheesh1995@outlook.com>
Tarik <tarik@pushmote.com> # Tarik Ozket
Tetsuharu OHZEKI <saneyuki.snyk@gmail.com> # Tetsuharu Ohzeki
Tien Nguyen <tihoanh@microsoft.com> tien <hoanhtien@users.noreply.github.com> unknown <tihoanh@microsoft.com> #Tien Hoanhtien
@@ -133,6 +159,7 @@ Tingan Ho <tingan87@gmail.com>
togru <v3nomzxgt8@gmail.com> # togru
Tomas Grubliauskas <tgrubliauskas@gmail.com>
ToddThomson <achilles@telus.net> # Todd Thomson
Torben Fitschen <torben.fitschen@mayflower.de>
TruongSinh Tran-Nguyen <i@truongsinh.pro>
vilicvane <i@vilic.info> # Vilic Vane
Vladimir Matveev <vladima@microsoft.com> vladima <vladima@microsoft.com> v2m <desco.by@gmail.com>
@@ -140,7 +167,9 @@ Wesley Wigham <t-weswig@microsoft.com> Wesley Wigham <wwigham@gmail.com>
York Yao <plantain-00@users.noreply.github.com> york yao <yaoao12306@outlook.com> yaoyao <yaoyao12306@163.com>
Yuichi Nukiyama <oscar.wilde84@hotmail.co.jp> YuichiNukiyama <oscar.wilde84@hotmail.co.jp>
Zev Spitz <shivisi@etrog.net.il>
Zhengbo Li <zhengbli@microsoft.com> zhengbli <zhengbli@microsoft.com> Zhengbo Li <Zhengbo Li> Zhengbo Li <zhengbli@mirosoft.com> tinza123 <li.zhengbo@outlook.com> unknown <zhengbli@zhengblit430.redmond.corp.microsoft.com> Zhengbo Li <Zhengbo Li>
Zhengbo Li <zhengbli@microsoft.com> zhengbli <zhengbli@microsoft.com> Zhengbo Li <Zhengbo Li> Zhengbo Li <zhengbli@mirosoft.com> tinza123 <li.zhengbo@outlook.com> unknown <zhengbli@zhengblit430.redmond.corp.microsoft.com> Zhengbo Li <Zhengbo Li> zhengbli <zhengli@microsoft.com>
zhongsp <patrick.zhongsp@gmail.com> # Patrick Zhong
T18970237136 <T18970237136@users.noreply.github.com> # @T18970237136
JBerger <JBerger@melco.com>
JBerger <JBerger@melco.com>
bootstraponline <code@bootstraponline.com> # @bootstraponline
yortus <yortus@gmail.com> # @yortus
+31 -1
View File
@@ -5,7 +5,10 @@ TypeScript is authored by:
* Ahmad Farid
* Alex Eagle
* Alexander Kuvaev
* Alexander Rusakov
* Anatoly Ressin
* Anders Hejlsberg
* Andrej Baran
* Andrew Z Allen
* Andy Hanson
* Anil Anar
@@ -16,17 +19,21 @@ TypeScript is authored by:
* Avery Morin
* Basarat Ali Syed
* Ben Duffield
* Ben Mosher
* Bill Ticehurst
* Blake Embrey
* @bootstraponline
* Bowden Kelly
* Brett Mayen
* Bryan Forbes
* Caitlin Potter
* Chris Bubernak
* Christophe Vidal
* Chuck Jazdzewski
* Colby Russell
* Colin Snover
* Cyrus Najmabadi
* Dafrok Zhang
* Dan Corder
* Dan Quirk
* Daniel Rosenwasser
@@ -36,17 +43,22 @@ TypeScript is authored by:
* Dick van den Brink
* Dirk Bäumer
* Dirk Holtwick
* Dom Chen
* Doug Ilijev
* Eric Tsang
* Erik Edrosa
* Ethan Rubio
* Evan Martin
* Evan Sebastian
* Eyas Sharaiha
* Fabian Cook
* @falsandtru
* Frank Wallis
* František Žiačik
* František Žiacik
* Gabe Moothart
* Gabriel Isenberg
* Gilad Peleg
* Godfrey Chan
* Graeme Wicksted
* Guillaume Salles
* Guy Bedford
@@ -56,6 +68,7 @@ TypeScript is authored by:
* Ingvar Stepanyan
* Isiah Meadows
* Ivo Gabe de Wolff
* Jakub Młokosiewicz
* James Whitney
* Jason Freeman
* Jason Killian
@@ -71,30 +84,39 @@ TypeScript is authored by:
* Jonathan Park
* Jonathan Toland
* Jonathan Turner
* Josh Abernathy
* Josh Kalderimis
* Josh Soref
* Juan Luis Boya García
* Julian Williams
* Justin Bay
* Justin Johansson
* Kagami Sascha Rosylight
* Kanchalai Tanglertsampan
* Keith Mashinter
* Ken Howard
* Kenji Imamula
* Kevin Lang
* Kyle Kelley
* Lorant Pinter
* Lucien Greathouse
* Lukas Elmer
* Marin Marinov
* Martin Vseticka
* Masahiro Wakame
* Matt McCutchen
* Max Deepfield
* Micah Zoltu
* Michael
* Mohamed Hegazy
* Nathan Shively-Sanders
* Nathan Yee
* Nima Zahedi
* Noah Chen
* Noj Vek
* Oleg Mihailik
* Oleksandr Chekhovskyi
* Omer Sheikh
* Oskar Segersva¨rd
* Patrick Zhong
* Paul van Brenk
@@ -109,21 +131,27 @@ TypeScript is authored by:
* Rado Kirov
* Richard Knoll
* Ron Buckton
* Rostislav Galimsky
* Rowan Wyborn
* Ryan Cavanaugh
* Ryohei Ikegami
* Sam El-Husseini
* Sarangan Rajamanickam
* Sergey Shandar
* Sheetal Nandi
* Shengping Zhong
* Shyyko Serhiy
* Simon Hürlimann
* Slawomir Sadziak
* Solal Pirelli
* Stan Thomas
* Stanislav Sysoev
* Steve Lucco
* Sudheesh Singanamalla
* Sébastien Arod
* @T18970237136
* Tarik Ozket
* Tetsuharu Ohzeki
* Tien Hoanhtien
* Tim Perry
* Tim Viiding-Spader
@@ -131,11 +159,13 @@ TypeScript is authored by:
* Todd Thomson
* togru
* Tomas Grubliauskas
* Torben Fitschen
* TruongSinh Tran-Nguyen
* Vilic Vane
* Vladimir Matveev
* Wesley Wigham
* York Yao
* @yortus
* Yuichi Nukiyama
* Zev Spitz
* Zhengbo Li
+2
View File
@@ -171,6 +171,7 @@ var servicesSources = [
var serverCoreSources = [
"types.d.ts",
"shared.ts",
"utilities.ts",
"scriptVersionCache.ts",
"typingsCache.ts",
@@ -193,6 +194,7 @@ var cancellationTokenSources = [
var typingsInstallerSources = [
"../types.d.ts",
"../shared.ts",
"typingsInstaller.ts",
"nodeTypingsInstaller.ts"
].map(function (f) {
+66 -2
View File
@@ -560,6 +560,7 @@ namespace ts {
skipTransformFlagAggregation = true;
bindChildrenWorker(node);
skipTransformFlagAggregation = false;
subtreeTransformFlags |= node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind);
}
else {
const savedSubtreeTransformFlags = subtreeTransformFlags;
@@ -895,8 +896,8 @@ namespace ts {
const enclosingLabeledStatement = node.parent.kind === SyntaxKind.LabeledStatement
? lastOrUndefined(activeLabels)
: undefined;
// if do statement is wrapped in labeled statement then target labels for break/continue with or without
// label should be the same
// if do statement is wrapped in labeled statement then target labels for break/continue with or without
// label should be the same
const preConditionLabel = enclosingLabeledStatement ? enclosingLabeledStatement.continueTarget : createBranchLabel();
const postDoLabel = enclosingLabeledStatement ? enclosingLabeledStatement.breakTarget : createBranchLabel();
addAntecedent(preDoLabel, currentFlow);
@@ -1234,9 +1235,11 @@ namespace ts {
const postExpressionLabel = createBranchLabel();
bindCondition(node.condition, trueLabel, falseLabel);
currentFlow = finishFlowLabel(trueLabel);
bind(node.questionToken);
bind(node.whenTrue);
addAntecedent(postExpressionLabel, currentFlow);
currentFlow = finishFlowLabel(falseLabel);
bind(node.colonToken);
bind(node.whenFalse);
addAntecedent(postExpressionLabel, currentFlow);
currentFlow = finishFlowLabel(postExpressionLabel);
@@ -3208,4 +3211,65 @@ namespace ts {
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~excludeFlags;
}
/**
* Gets the transform flags to exclude when unioning the transform flags of a subtree.
*
* NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`.
* For performance reasons, `computeTransformFlagsForNode` uses local constant values rather
* than calling this function.
*/
/* @internal */
export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) {
if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) {
return TransformFlags.TypeExcludes;
}
switch (kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.ArrayLiteralExpression:
return TransformFlags.ArrayLiteralOrCallOrNewExcludes;
case SyntaxKind.ModuleDeclaration:
return TransformFlags.ModuleExcludes;
case SyntaxKind.Parameter:
return TransformFlags.ParameterExcludes;
case SyntaxKind.ArrowFunction:
return TransformFlags.ArrowFunctionExcludes;
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
return TransformFlags.FunctionExcludes;
case SyntaxKind.VariableDeclarationList:
return TransformFlags.VariableDeclarationListExcludes;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
return TransformFlags.ClassExcludes;
case SyntaxKind.Constructor:
return TransformFlags.ConstructorExcludes;
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return TransformFlags.MethodOrAccessorExcludes;
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.TypeParameter:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
return TransformFlags.TypeExcludes;
case SyntaxKind.ObjectLiteralExpression:
return TransformFlags.ObjectLiteralExcludes;
default:
return TransformFlags.NodeExcludes;
}
}
}
+25 -18
View File
@@ -2229,14 +2229,8 @@ namespace ts {
// The specified symbol flags need to be reinterpreted as type flags
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
}
else if (!(flags & TypeFormatFlags.InTypeAlias) && ((getObjectFlags(type) & ObjectFlags.Anonymous && !(<AnonymousType>type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
else if (!(flags & TypeFormatFlags.InTypeAlias) && (getObjectFlags(type) & ObjectFlags.Anonymous || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
// We emit inferred type as type-alias at the current localtion if all the following is true
// the input type is has alias symbol that is accessible
// the input type is a union, intersection or anonymous type that is fully instantiated (if not we want to keep dive into)
// e.g.: export type Bar<X, Y> = () => [X, Y];
// export type Foo<Y> = Bar<any, Y>;
// export const y = (x: Foo<string>) => 1 // we want to emit as ...x: () => [any, string])
const typeArguments = type.aliasTypeArguments;
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
}
@@ -4198,8 +4192,8 @@ namespace ts {
else {
mapper = createTypeMapper(typeParameters, typeArguments);
members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1);
callSignatures = instantiateList(source.declaredCallSignatures, mapper, instantiateSignature);
constructSignatures = instantiateList(source.declaredConstructSignatures, mapper, instantiateSignature);
callSignatures = instantiateSignatures(source.declaredCallSignatures, mapper);
constructSignatures = instantiateSignatures(source.declaredConstructSignatures, mapper);
stringIndexInfo = instantiateIndexInfo(source.declaredStringIndexInfo, mapper);
numberIndexInfo = instantiateIndexInfo(source.declaredNumberIndexInfo, mapper);
}
@@ -4266,7 +4260,7 @@ namespace ts {
for (const baseSig of baseSignatures) {
const typeParamCount = baseSig.typeParameters ? baseSig.typeParameters.length : 0;
if (typeParamCount === typeArgCount) {
const sig = typeParamCount ? getSignatureInstantiation(baseSig, typeArguments) : cloneSignature(baseSig);
const sig = typeParamCount ? createSignatureInstantiation(baseSig, typeArguments) : cloneSignature(baseSig);
sig.typeParameters = classType.localTypeParameters;
sig.resolvedReturnType = classType;
result.push(sig);
@@ -4397,8 +4391,8 @@ namespace ts {
const symbol = type.symbol;
if (type.target) {
const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false);
const callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature);
const constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature);
const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper);
const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper);
const stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.String), type.mapper);
const numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.Number), type.mapper);
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
@@ -5071,6 +5065,12 @@ namespace ts {
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature {
const instantiations = signature.instantiations || (signature.instantiations = createMap<Signature>());
const id = getTypeListId(typeArguments);
return instantiations[id] || (instantiations[id] = createSignatureInstantiation(signature, typeArguments));
}
function createSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature {
return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), /*eraseTypeParameters*/ true);
}
@@ -6155,6 +6155,14 @@ namespace ts {
return items;
}
function instantiateTypes(types: Type[], mapper: TypeMapper) {
return instantiateList(types, mapper, instantiateType);
}
function instantiateSignatures(signatures: Signature[], mapper: TypeMapper) {
return instantiateList(signatures, mapper, instantiateSignature);
}
function instantiateCached<T extends Type>(type: T, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T {
const instantiations = mapper.instantiations || (mapper.instantiations = []);
return <T>instantiations[type.id] || (instantiations[type.id] = instantiator(type, mapper));
@@ -6186,7 +6194,6 @@ namespace ts {
count == 2 ? createBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
createArrayTypeMapper(sources, targets);
mapper.mappedTypes = sources;
mapper.targetTypes = targets;
return mapper;
}
@@ -6303,7 +6310,7 @@ namespace ts {
result.target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type;
result.mapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper;
result.aliasSymbol = type.aliasSymbol;
result.aliasTypeArguments = mapper.targetTypes;
result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper);
return result;
}
@@ -6315,7 +6322,7 @@ namespace ts {
result.isOptional = type.isOptional;
result.mapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper;
result.aliasSymbol = type.aliasSymbol;
result.aliasTypeArguments = mapper.targetTypes;
result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper);
return result;
}
@@ -6413,14 +6420,14 @@ namespace ts {
return instantiateCached(type, mapper, instantiateMappedType);
}
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType));
return createTypeReference((<TypeReference>type).target, instantiateTypes((<TypeReference>type).typeArguments, mapper));
}
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*subtypeReduction*/ false, type.aliasSymbol, mapper.targetTypes);
return getUnionType(instantiateTypes((<UnionType>type).types, mapper), /*subtypeReduction*/ false, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes);
return getIntersectionType(instantiateTypes((<IntersectionType>type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
}
if (type.flags & TypeFlags.Index) {
return getIndexType(instantiateType((<IndexType>type).type, mapper));
+6 -1
View File
@@ -420,6 +420,7 @@ namespace ts {
getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(),
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
isSourceFileFromExternalLibrary,
dropDiagnosticsProducingTypeChecker
};
@@ -722,13 +723,17 @@ namespace ts {
getSourceFile: program.getSourceFile,
getSourceFileByPath: program.getSourceFileByPath,
getSourceFiles: program.getSourceFiles,
isSourceFileFromExternalLibrary: (file: SourceFile) => !!sourceFilesFoundSearchingNodeModules[file.path],
isSourceFileFromExternalLibrary,
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
isEmitBlocked,
};
}
function isSourceFileFromExternalLibrary(file: SourceFile): boolean {
return sourceFilesFoundSearchingNodeModules[file.path];
}
function getDiagnosticsProducingTypeChecker() {
return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
}
+9 -4
View File
@@ -17,7 +17,11 @@ namespace ts {
readFile(path: string, encoding?: string): string;
getFileSize?(path: string): number;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
/**
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
* use native OS file watching
*/
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
resolvePath(path: string): string;
fileExists(path: string): boolean;
@@ -439,6 +443,7 @@ namespace ts {
return filter<string>(_fs.readdirSync(path), dir => fileSystemEntryExists(combinePaths(path, dir), FileSystemEntryKind.Directory));
}
const noOpFileWatcher: FileWatcher = { close: noop };
const nodeSystem: System = {
args: process.argv.slice(2),
newLine: _os.EOL,
@@ -448,7 +453,7 @@ namespace ts {
},
readFile,
writeFile,
watchFile: (fileName, callback) => {
watchFile: (fileName, callback, pollingInterval) => {
if (useNonPollingWatchers) {
const watchedFile = watchedFileSet.addFile(fileName, callback);
return {
@@ -456,7 +461,7 @@ namespace ts {
};
}
else {
_fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged);
_fs.watchFile(fileName, { persistent: true, interval: pollingInterval || 250 }, fileChanged);
return {
close: () => _fs.unwatchFile(fileName, fileChanged)
};
@@ -475,7 +480,7 @@ namespace ts {
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
let options: any;
if (!directoryExists(directoryName)) {
return;
return noOpFileWatcher;
}
if (isNode4OrLater() && (process.platform === "win32" || process.platform === "darwin")) {
+3 -1
View File
@@ -2202,6 +2202,7 @@ namespace ts {
/* @internal */ getFileProcessingDiagnostics(): DiagnosticCollection;
/* @internal */ getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective>;
/* @internal */ isSourceFileFromExternalLibrary(file: SourceFile): boolean;
// For testing purposes only.
/* @internal */ structureIsReused?: boolean;
}
@@ -2944,6 +2945,8 @@ namespace ts {
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
/* @internal */
typePredicate?: TypePredicate;
/* @internal */
instantiations?: Map<Signature>; // Generic signature instantiation cache
}
export const enum IndexKind {
@@ -2961,7 +2964,6 @@ namespace ts {
export interface TypeMapper {
(t: TypeParameter): Type;
mappedTypes?: Type[]; // Types mapped by this mapper
targetTypes?: Type[]; // Types substituted for mapped types
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
context?: InferenceContext; // The inference context this mapper was created from.
// Only inference mappers have this set (in createInferenceMapper).
-60
View File
@@ -1270,66 +1270,6 @@ namespace ts {
return transformFlags | aggregateTransformFlagsForNode(child);
}
/**
* Gets the transform flags to exclude when unioning the transform flags of a subtree.
*
* NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`.
* For performance reasons, `computeTransformFlagsForNode` uses local constant values rather
* than calling this function.
*/
function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) {
if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) {
return TransformFlags.TypeExcludes;
}
switch (kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.ArrayLiteralExpression:
return TransformFlags.ArrayLiteralOrCallOrNewExcludes;
case SyntaxKind.ModuleDeclaration:
return TransformFlags.ModuleExcludes;
case SyntaxKind.Parameter:
return TransformFlags.ParameterExcludes;
case SyntaxKind.ArrowFunction:
return TransformFlags.ArrowFunctionExcludes;
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
return TransformFlags.FunctionExcludes;
case SyntaxKind.VariableDeclarationList:
return TransformFlags.VariableDeclarationListExcludes;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
return TransformFlags.ClassExcludes;
case SyntaxKind.Constructor:
return TransformFlags.ConstructorExcludes;
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return TransformFlags.MethodOrAccessorExcludes;
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.TypeParameter:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
return TransformFlags.TypeExcludes;
case SyntaxKind.ObjectLiteralExpression:
return TransformFlags.ObjectLiteralExcludes;
default:
return TransformFlags.NodeExcludes;
}
}
export namespace Debug {
export const failNotOptional = shouldAssert(AssertionLevel.Normal)
? (message?: string) => assert(false, message || "Node not optional.")
+17 -7
View File
@@ -44,10 +44,10 @@ namespace ts {
// NOTE: 'reusedElements' is the expected count of elements reused from the old tree to the new
// tree. It may change as we tweak the parser. If the count increases then that should always
// be a good thing. If it decreases, that's not great (less reusability), but that may be
// unavoidable. If it does decrease an investigation should be done to make sure that things
// be a good thing. If it decreases, that's not great (less reusability), but that may be
// unavoidable. If it does decrease an investigation should be done to make sure that things
// are still ok and we're still appropriately reusing most of the tree.
function compareTrees(oldText: IScriptSnapshot, newText: IScriptSnapshot, textChangeRange: TextChangeRange, expectedReusedElements: number, oldTree?: SourceFile): SourceFile {
function compareTrees(oldText: IScriptSnapshot, newText: IScriptSnapshot, textChangeRange: TextChangeRange, expectedReusedElements: number, oldTree?: SourceFile) {
oldTree = oldTree || createTree(oldText, /*version:*/ ".");
Utils.assertInvariants(oldTree, /*parent:*/ undefined);
@@ -76,7 +76,7 @@ namespace ts {
assert.equal(actualReusedCount, expectedReusedElements, actualReusedCount + " !== " + expectedReusedElements);
}
return incrementalNewTree;
return { oldTree, newTree, incrementalNewTree };
}
function reusedElements(oldNode: SourceFile, newNode: SourceFile): number {
@@ -103,7 +103,7 @@ namespace ts {
for (let i = 0; i < repeat; i++) {
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withDelete(oldText, index, 1);
const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree);
const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree;
source = newTextAndChange.text.getText(0, newTextAndChange.text.getLength());
oldTree = newTree;
@@ -116,7 +116,7 @@ namespace ts {
for (let i = 0; i < repeat; i++) {
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withInsert(oldText, index + i, toInsert.charAt(i));
const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree);
const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree;
source = newTextAndChange.text.getText(0, newTextAndChange.text.getLength());
oldTree = newTree;
@@ -639,7 +639,7 @@ module m3 { }\
});
it("Unterminated comment after keyword converted to identifier", () => {
// 'public' as a keyword should be incrementally unusable (because it has an
// 'public' as a keyword should be incrementally unusable (because it has an
// unterminated comment). When we convert it to an identifier, that shouldn't
// change anything, and we should still get the same errors.
const source = "return; a.public /*";
@@ -796,6 +796,16 @@ module m3 { }\
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4);
});
it("Reuse transformFlags of subtree during bind", () => {
const source = `class Greeter { constructor(element: HTMLElement) { } }`;
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withChange(oldText, 15, 0, "\n");
const { oldTree, incrementalNewTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1);
bindSourceFile(oldTree, {});
bindSourceFile(incrementalNewTree, {});
assert.equal(oldTree.transformFlags, incrementalNewTree.transformFlags);
});
// Simulated typing tests.
it("Type extends clause 1", () => {
+62 -19
View File
@@ -18,7 +18,6 @@ namespace ts.projectSystem {
};
export interface PostExecAction {
readonly requestKind: TI.RequestKind;
readonly success: boolean;
readonly callback: TI.RequestCompletedAction;
}
@@ -47,9 +46,14 @@ namespace ts.projectSystem {
export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller {
protected projectService: server.ProjectService;
constructor(readonly globalTypingsCacheLocation: string, throttleLimit: number, readonly installTypingHost: server.ServerHost, log?: TI.Log) {
super(globalTypingsCacheLocation, safeList.path, throttleLimit, log);
this.init();
constructor(
readonly globalTypingsCacheLocation: string,
throttleLimit: number,
installTypingHost: server.ServerHost,
readonly typesRegistry = createMap<void>(),
telemetryEnabled?: boolean,
log?: TI.Log) {
super(installTypingHost, globalTypingsCacheLocation, safeList.path, throttleLimit, telemetryEnabled, log);
}
safeFileList = safeList.path;
@@ -63,9 +67,8 @@ namespace ts.projectSystem {
}
}
checkPendingCommands(expected: TI.RequestKind[]) {
assert.equal(this.postExecActions.length, expected.length, `Expected ${expected.length} post install actions`);
this.postExecActions.forEach((act, i) => assert.equal(act.requestKind, expected[i], "Unexpected post install action"));
checkPendingCommands(expectedCount: number) {
assert.equal(this.postExecActions.length, expectedCount, `Expected ${expectedCount} post install actions`);
}
onProjectClosed() {
@@ -79,15 +82,8 @@ namespace ts.projectSystem {
return this.installTypingHost;
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
switch (requestKind) {
case TI.NpmViewRequest:
case TI.NpmInstallRequest:
break;
default:
assert.isTrue(false, `request ${requestKind} is not supported`);
}
this.addPostExecAction(requestKind, "success", cb);
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
this.addPostExecAction("success", cb);
}
sendResponse(response: server.SetTypings | server.InvalidateCachedTypings) {
@@ -99,12 +95,11 @@ namespace ts.projectSystem {
this.install(request);
}
addPostExecAction(requestKind: TI.RequestKind, stdout: string | string[], cb: TI.RequestCompletedAction) {
addPostExecAction(stdout: string | string[], cb: TI.RequestCompletedAction) {
const out = typeof stdout === "string" ? stdout : createNpmPackageJsonString(stdout);
const action: PostExecAction = {
success: !!out,
callback: cb,
requestKind
callback: cb
};
this.postExecActions.push(action);
}
@@ -1969,6 +1964,33 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({ configuredProjects: 1 });
checkProjectActualFiles(projectService.configuredProjects[0], [libES5.path, libES2015Promise.path, app.path]);
});
it("should handle non-existing directories in config file", () => {
const f = {
path: "/a/src/app.ts",
content: "let x = 1;"
};
const config = {
path: "/a/tsconfig.json",
content: JSON.stringify({
compilerOptions: {},
include: [
"src/**/*",
"notexistingfolder/*"
]
})
};
const host = createServerHost([f, config]);
const projectService = createProjectService(host);
projectService.openClientFile(f.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
projectService.closeClientFile(f.path);
projectService.checkNumberOfProjects({ configuredProjects: 0 });
projectService.openClientFile(f.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
});
});
describe("prefer typings to js", () => {
@@ -2227,6 +2249,27 @@ namespace ts.projectSystem {
assert.equal(diags.length, 0);
});
it("should property handle missing config files", () => {
const f1 = {
path: "/a/b/app.ts",
content: "let x = 1"
};
const config = {
path: "/a/b/tsconfig.json",
content: "{}"
};
const projectName = "project1";
const host = createServerHost([f1]);
const projectService = createProjectService(host);
projectService.openExternalProject({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName });
// should have one external project since config file is missing
projectService.checkNumberOfProjects({ externalProjects: 1 });
host.reloadFS([f1, config]);
projectService.openExternalProject({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName });
projectService.checkNumberOfProjects({ configuredProjects: 1 });
});
});
describe("add the missing module file for inferred project", () => {
+140 -121
View File
@@ -8,44 +8,44 @@ namespace ts.projectSystem {
interface InstallerParams {
globalTypingsCacheLocation?: string;
throttleLimit?: number;
typesRegistry?: Map<void>;
}
function createTypesRegistry(...list: string[]): Map<void> {
const map = createMap<void>();
for (const l of list) {
map[l] = undefined;
}
return map;
}
class Installer extends TestTypingsInstaller {
constructor(host: server.ServerHost, p?: InstallerParams, log?: TI.Log) {
constructor(host: server.ServerHost, p?: InstallerParams, telemetryEnabled?: boolean, log?: TI.Log) {
super(
(p && p.globalTypingsCacheLocation) || "/a/data",
(p && p.throttleLimit) || 5,
host,
(p && p.typesRegistry),
telemetryEnabled,
log);
}
installAll(expectedView: typeof TI.NpmViewRequest[], expectedInstall: typeof TI.NpmInstallRequest[]) {
this.checkPendingCommands(expectedView);
this.executePendingCommands();
this.checkPendingCommands(expectedInstall);
installAll(expectedCount: number) {
this.checkPendingCommands(expectedCount);
this.executePendingCommands();
}
}
describe("typingsInstaller", () => {
function executeCommand(self: Installer, host: TestServerHost, installedTypings: string[], typingFiles: FileOrFolder[], requestKind: TI.RequestKind, cb: TI.RequestCompletedAction): void {
switch (requestKind) {
case TI.NpmInstallRequest:
self.addPostExecAction(requestKind, installedTypings, success => {
for (const file of typingFiles) {
host.createFileOrFolder(file, /*createParentDirectory*/ true);
}
cb(success);
});
break;
case TI.NpmViewRequest:
self.addPostExecAction(requestKind, installedTypings, cb);
break;
default:
assert.isTrue(false, `unexpected request kind ${requestKind}`);
break;
function executeCommand(self: Installer, host: TestServerHost, installedTypings: string[], typingFiles: FileOrFolder[], cb: TI.RequestCompletedAction): void {
self.addPostExecAction(installedTypings, success => {
for (const file of typingFiles) {
host.createFileOrFolder(file, /*createParentDirectory*/ true);
}
}
cb(success);
});
}
describe("typingsInstaller", () => {
it("configured projects (typings installed) 1", () => {
const file1 = {
path: "/a/b/app.js",
@@ -79,12 +79,12 @@ namespace ts.projectSystem {
const host = createServerHost([file1, tsconfig, packageJson]);
const installer = new (class extends Installer {
constructor() {
super(host);
super(host, { typesRegistry: createTypesRegistry("jquery") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/jquery"];
const typingFiles = [jquery];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -95,7 +95,7 @@ namespace ts.projectSystem {
const p = projectService.configuredProjects[0];
checkProjectActualFiles(p, [file1.path]);
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
checkProjectActualFiles(p, [file1.path, jquery.path]);
@@ -123,12 +123,12 @@ namespace ts.projectSystem {
const host = createServerHost([file1, packageJson]);
const installer = new (class extends Installer {
constructor() {
super(host);
super(host, { typesRegistry: createTypesRegistry("jquery") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/jquery"];
const typingFiles = [jquery];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -139,7 +139,7 @@ namespace ts.projectSystem {
const p = projectService.inferredProjects[0];
checkProjectActualFiles(p, [file1.path]);
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { inferredProjects: 1 });
checkProjectActualFiles(p, [file1.path, jquery.path]);
@@ -167,7 +167,7 @@ namespace ts.projectSystem {
options: {},
rootFiles: [toExternalFile(file1.path)]
});
installer.checkPendingCommands([]);
installer.checkPendingCommands(/*expectedCount*/ 0);
// by default auto discovery will kick in if project contain only .js/.d.ts files
// in this case project contain only ts files - no auto discovery
projectService.checkNumberOfProjects({ externalProjects: 1 });
@@ -181,7 +181,7 @@ namespace ts.projectSystem {
const host = createServerHost([file1]);
const installer = new (class extends Installer {
constructor() {
super(host);
super(host, { typesRegistry: createTypesRegistry("jquery") });
}
enqueueInstallTypingsRequest() {
assert(false, "auto discovery should not be enabled");
@@ -196,7 +196,7 @@ namespace ts.projectSystem {
rootFiles: [toExternalFile(file1.path)],
typingOptions: { include: ["jquery"] }
});
installer.checkPendingCommands([]);
installer.checkPendingCommands(/*expectedCount*/ 0);
// by default auto discovery will kick in if project contain only .js/.d.ts files
// in this case project contain only ts files - no auto discovery even if typing options is set
projectService.checkNumberOfProjects({ externalProjects: 1 });
@@ -215,16 +215,16 @@ namespace ts.projectSystem {
let enqueueIsCalled = false;
const installer = new (class extends Installer {
constructor() {
super(host);
super(host, { typesRegistry: createTypesRegistry("jquery") });
}
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
enqueueIsCalled = true;
super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings = ["@types/jquery"];
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings = ["@types/node"];
const typingFiles = [jquery];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -234,11 +234,11 @@ namespace ts.projectSystem {
projectFileName,
options: {},
rootFiles: [toExternalFile(file1.path)],
typingOptions: { enableAutoDiscovery: true, include: ["node"] }
typingOptions: { enableAutoDiscovery: true, include: ["jquery"] }
});
assert.isTrue(enqueueIsCalled, "expected enqueueIsCalled to be true");
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
installer.installAll(/*expectedCount*/ 1);
// autoDiscovery is set in typing options - use it even if project contains only .ts files
projectService.checkNumberOfProjects({ externalProjects: 1 });
@@ -273,12 +273,12 @@ namespace ts.projectSystem {
const host = createServerHost([file1, file2, file3]);
const installer = new (class extends Installer {
constructor() {
super(host);
super(host, { typesRegistry: createTypesRegistry("lodash", "react") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings = ["@types/lodash", "@types/react"];
const typingFiles = [lodash, react];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -295,7 +295,7 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path]);
installer.installAll([TI.NpmViewRequest, TI.NpmViewRequest], [TI.NpmInstallRequest], );
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path, lodash.path, react.path]);
@@ -317,16 +317,16 @@ namespace ts.projectSystem {
let enqueueIsCalled = false;
const installer = new (class extends Installer {
constructor() {
super(host);
super(host, { typesRegistry: createTypesRegistry("jquery") });
}
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
enqueueIsCalled = true;
super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings: string[] = [];
const typingFiles: FileOrFolder[] = [];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -343,7 +343,7 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path]);
installer.checkPendingCommands([]);
installer.checkPendingCommands(/*expectedCount*/ 0);
checkNumberOfProjects(projectService, { externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path]);
@@ -396,12 +396,12 @@ namespace ts.projectSystem {
const host = createServerHost([file1, file2, file3, packageJson]);
const installer = new (class extends Installer {
constructor() {
super(host);
super(host, { typesRegistry: createTypesRegistry("jquery", "commander", "moment", "express") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings = ["@types/commander", "@types/express", "@types/jquery", "@types/moment"];
const typingFiles = [commander, express, jquery, moment];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -418,10 +418,7 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path]);
installer.installAll(
[TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest],
[TI.NpmInstallRequest]
);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path, commander.path, express.path, jquery.path, moment.path]);
@@ -475,11 +472,11 @@ namespace ts.projectSystem {
const host = createServerHost([lodashJs, commanderJs, file3, packageJson]);
const installer = new (class extends Installer {
constructor() {
super(host, { throttleLimit: 3 });
super(host, { throttleLimit: 3, typesRegistry: createTypesRegistry("commander", "express", "jquery", "moment", "lodash") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings = ["@types/commander", "@types/express", "@types/jquery", "@types/moment", "@types/lodash"];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -495,18 +492,7 @@ namespace ts.projectSystem {
const p = projectService.externalProjects[0];
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [lodashJs.path, commanderJs.path, file3.path]);
// expected 3 view requests in the queue
installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest]);
assert.equal(installer.pendingRunRequests.length, 2, "expected 2 pending requests");
// push view requests
installer.executePendingCommands();
// expected 2 remaining view requests in the queue
installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest]);
// push view requests
installer.executePendingCommands();
// expected one install request
installer.checkPendingCommands([TI.NpmInstallRequest]);
installer.checkPendingCommands(/*expectedCount*/ 1);
installer.executePendingCommands();
// expected all typings file to exist
for (const f of typingFiles) {
@@ -565,22 +551,17 @@ namespace ts.projectSystem {
const host = createServerHost([lodashJs, commanderJs, file3]);
const installer = new (class extends Installer {
constructor() {
super(host, { throttleLimit: 3 });
super(host, { throttleLimit: 1, typesRegistry: createTypesRegistry("commander", "jquery", "lodash", "cordova", "gulp", "grunt") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
if (requestKind === TI.NpmInstallRequest) {
let typingFiles: (FileOrFolder & { typings: string })[] = [];
if (args.indexOf("@types/commander") >= 0) {
typingFiles = [commander, jquery, lodash, cordova];
}
else {
typingFiles = [grunt, gulp];
}
executeCommand(this, host, typingFiles.map(f => f.typings), typingFiles, requestKind, cb);
installWorker(_requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
let typingFiles: (FileOrFolder & { typings: string })[] = [];
if (args.indexOf("@types/commander") >= 0) {
typingFiles = [commander, jquery, lodash, cordova];
}
else {
executeCommand(this, host, [], [], requestKind, cb);
typingFiles = [grunt, gulp];
}
executeCommand(this, host, typingFiles.map(f => f.typings), typingFiles, cb);
}
})();
@@ -594,8 +575,8 @@ namespace ts.projectSystem {
typingOptions: { include: ["jquery", "cordova"] }
});
installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest]);
assert.equal(installer.pendingRunRequests.length, 1, "expect one throttled request");
installer.checkPendingCommands(/*expectedCount*/ 1);
assert.equal(installer.pendingRunRequests.length, 0, "expect no throttled requests");
// Create project #2 with 2 typings
const projectFileName2 = "/a/app/test2.csproj";
@@ -605,7 +586,7 @@ namespace ts.projectSystem {
rootFiles: [toExternalFile(file3.path)],
typingOptions: { include: ["grunt", "gulp"] }
});
assert.equal(installer.pendingRunRequests.length, 3, "expect three throttled request");
assert.equal(installer.pendingRunRequests.length, 1, "expect one throttled request");
const p1 = projectService.externalProjects[0];
const p2 = projectService.externalProjects[1];
@@ -613,18 +594,14 @@ namespace ts.projectSystem {
checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path]);
checkProjectActualFiles(p2, [file3.path]);
installer.executePendingCommands();
// expected one view request from the first project and two - from the second one
installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest]);
// expected one install request from the second project
installer.checkPendingCommands(/*expectedCount*/ 1);
assert.equal(installer.pendingRunRequests.length, 0, "expected no throttled requests");
installer.executePendingCommands();
// should be two install requests from both projects
installer.checkPendingCommands([TI.NpmInstallRequest, TI.NpmInstallRequest]);
installer.executePendingCommands();
checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path, commander.path, jquery.path, lodash.path, cordova.path]);
checkProjectActualFiles(p2, [file3.path, grunt.path, gulp.path]);
});
@@ -653,12 +630,12 @@ namespace ts.projectSystem {
const host = createServerHost([app, jsconfig, jquery, jqueryPackage]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: "/tmp" });
super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/jquery"];
const typingFiles = [jqueryDTS];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -669,7 +646,7 @@ namespace ts.projectSystem {
const p = projectService.configuredProjects[0];
checkProjectActualFiles(p, [app.path]);
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
checkProjectActualFiles(p, [app.path, jqueryDTS.path]);
@@ -699,12 +676,12 @@ namespace ts.projectSystem {
const host = createServerHost([app, jsconfig, bowerJson]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: "/tmp" });
super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/jquery"];
const typingFiles = [jqueryDTS];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -715,7 +692,7 @@ namespace ts.projectSystem {
const p = projectService.configuredProjects[0];
checkProjectActualFiles(p, [app.path]);
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
checkProjectActualFiles(p, [app.path, jqueryDTS.path]);
@@ -742,23 +719,23 @@ namespace ts.projectSystem {
const host = createServerHost([f, brokenPackageJson]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath });
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/commander"];
const typingFiles = [commander];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
const service = createProjectService(host, { typingsInstaller: installer });
service.openClientFile(f.path);
installer.checkPendingCommands([]);
installer.checkPendingCommands(/*expectedCount*/ 0);
host.reloadFS([f, fixedPackageJson]);
host.triggerFileWatcherCallback(fixedPackageJson.path, /*removed*/ false);
// expected one view and one install request
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
// expected install request
installer.installAll(/*expectedCount*/ 1);
service.checkNumberOfProjects({ inferredProjects: 1 });
checkProjectActualFiles(service.inferredProjects[0], [f.path, commander.path]);
@@ -783,12 +760,12 @@ namespace ts.projectSystem {
const host = createServerHost([file]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath });
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("node", "commander") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/node", "@types/commander"];
const typingFiles = [node, commander];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
const service = createProjectService(host, { typingsInstaller: installer });
@@ -797,7 +774,7 @@ namespace ts.projectSystem {
service.checkNumberOfProjects({ inferredProjects: 1 });
checkProjectActualFiles(service.inferredProjects[0], [file.path]);
installer.installAll([TI.NpmViewRequest, TI.NpmViewRequest], [TI.NpmInstallRequest]);
installer.installAll(/*expectedCount*/1);
assert.isTrue(host.fileExists(node.path), "typings for 'node' should be created");
assert.isTrue(host.fileExists(commander.path), "typings for 'commander' should be created");
@@ -822,14 +799,10 @@ namespace ts.projectSystem {
const host = createServerHost([f1]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: "/tmp" });
super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("foo") });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
if (requestKind === TI.NpmViewRequest) {
// args should have only non-scoped packages - scoped packages are not yet supported
assert.deepEqual(args, ["foo"]);
}
executeCommand(this, host, ["foo"], [], requestKind, cb);
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
executeCommand(this, host, ["foo"], [], cb);
}
})();
const projectService = createProjectService(host, { typingsInstaller: installer });
@@ -844,7 +817,7 @@ namespace ts.projectSystem {
["foo", "foo", "foo", "@bar/router", "@bar/common", "@bar/common"]
);
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
installer.installAll(/*expectedCount*/ 1);
});
it("cached unresolved typings are not recomputed if program structure did not change", () => {
@@ -934,16 +907,16 @@ namespace ts.projectSystem {
const host = createServerHost([f1, packageJson]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: "/tmp" }, { isEnabled: () => true, writeLine: msg => messages.push(msg) });
super(host, { globalTypingsCacheLocation: "/tmp" }, /*telemetryEnabled*/ false, { isEnabled: () => true, writeLine: msg => messages.push(msg) });
}
executeRequest() {
installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) {
assert(false, "runCommand should not be invoked");
}
})();
const projectService = createProjectService(host, { typingsInstaller: installer });
projectService.openClientFile(f1.path);
installer.checkPendingCommands([]);
installer.checkPendingCommands(/*expectedCount*/ 0);
assert.isTrue(messages.indexOf("Package name '; say Hello from TypeScript! #' contains non URI safe characters") > 0, "should find package with invalid name");
});
});
@@ -978,4 +951,50 @@ namespace ts.projectSystem {
assert.deepEqual(result.newTypingNames, ["bar"]);
});
});
describe("telemetry events", () => {
it ("should be received", () => {
const f1 = {
path: "/a/app.js",
content: ""
};
const package = {
path: "/a/package.json",
content: JSON.stringify({ dependencies: { "commander": "1.0.0" } })
};
const cachePath = "/a/cache/";
const commander = {
path: cachePath + "node_modules/@types/commander/index.d.ts",
content: "export let x: number"
};
const host = createServerHost([f1, package]);
let seenTelemetryEvent = false;
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }, /*telemetryEnabled*/ true);
}
installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/commander"];
const typingFiles = [commander];
executeCommand(this, host, installedTypings, typingFiles, cb);
}
sendResponse(response: server.SetTypings | server.InvalidateCachedTypings | server.TypingsInstallEvent) {
if (response.kind === server.EventInstall) {
assert.deepEqual(response.packagesToInstall, ["@types/commander"]);
seenTelemetryEvent = true;
return;
}
super.sendResponse(response);
}
})();
const projectService = createProjectService(host, { typingsInstaller: installer });
projectService.openClientFile(f1.path);
installer.installAll(/*expectedCount*/ 1);
assert.isTrue(seenTelemetryEvent);
checkNumberOfProjects(projectService, { inferredProjects: 1 });
checkProjectActualFiles(projectService.inferredProjects[0], [f1.path, commander.path]);
});
});
}
+2 -2
View File
@@ -7586,7 +7586,7 @@ declare var IDBCursorWithValue: {
interface IDBDatabase extends EventTarget {
readonly name: string;
readonly objectStoreNames: string[];
readonly objectStoreNames: DOMStringList;
onabort: (this: this, ev: Event) => any;
onerror: (this: this, ev: ErrorEvent) => any;
version: number;
@@ -7652,7 +7652,7 @@ declare var IDBKeyRange: {
}
interface IDBObjectStore {
readonly indexNames: string[];
readonly indexNames: DOMStringList;
keyPath: string | string[];
readonly name: string;
readonly transaction: IDBTransaction;
+2 -2
View File
@@ -341,7 +341,7 @@ declare var IDBCursorWithValue: {
interface IDBDatabase extends EventTarget {
readonly name: string;
readonly objectStoreNames: string[];
readonly objectStoreNames: DOMStringList;
onabort: (this: this, ev: Event) => any;
onerror: (this: this, ev: ErrorEvent) => any;
version: number;
@@ -407,7 +407,7 @@ declare var IDBKeyRange: {
}
interface IDBObjectStore {
readonly indexNames: string[];
readonly indexNames: DOMStringList;
keyPath: string | string[];
readonly name: string;
readonly transaction: IDBTransaction;
+5 -3
View File
@@ -286,10 +286,10 @@ namespace ts.server {
return;
}
switch (response.kind) {
case "set":
case ActionSet:
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.unresolvedImports, response.typings);
break;
case "invalidate":
case ActionInvalidate:
this.typingsCache.deleteTypingsForProject(response.projectName);
break;
}
@@ -1288,7 +1288,9 @@ namespace ts.server {
for (const file of proj.rootFiles) {
const normalized = toNormalizedPath(file.fileName);
if (getBaseFileName(normalized) === "tsconfig.json") {
(tsConfigFiles || (tsConfigFiles = [])).push(normalized);
if (this.host.fileExists(normalized)) {
(tsConfigFiles || (tsConfigFiles = [])).push(normalized);
}
}
else {
rootFiles.push(file);
+5
View File
@@ -13,6 +13,7 @@ namespace ts.server {
private readonly resolveModuleName: typeof resolveModuleName;
readonly trace: (s: string) => void;
readonly realpath?: (path: string) => string;
constructor(private readonly host: ServerHost, private readonly project: Project, private readonly cancellationToken: HostCancellationToken) {
this.getCanonicalFileName = ts.createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
@@ -39,6 +40,10 @@ namespace ts.server {
}
return primaryResult;
};
if (this.host.realpath) {
this.realpath = path => this.host.realpath(path);
}
}
public startRecordingFilesWithChangedResolutions() {
+9 -3
View File
@@ -301,7 +301,7 @@ namespace ts.server {
return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles);
}
getFileNames() {
getFileNames(excludeFilesFromExternalLibraries?: boolean) {
if (!this.program) {
return [];
}
@@ -317,8 +317,14 @@ namespace ts.server {
}
return rootFiles;
}
const sourceFiles = this.program.getSourceFiles();
return sourceFiles.map(sourceFile => asNormalizedPath(sourceFile.fileName));
const result: NormalizedPath[] = [];
for (const f of this.program.getSourceFiles()) {
if (excludeFilesFromExternalLibraries && this.program.isSourceFileFromExternalLibrary(f)) {
continue;
}
result.push(asNormalizedPath(f.fileName));
}
return result;
}
getAllEmittableFiles() {
+26
View File
@@ -2057,6 +2057,32 @@ namespace ts.server.protocol {
childItems?: NavigationTree[];
}
export type TelemetryEventName = "telemetry";
export interface TelemetryEvent extends Event {
event: TelemetryEventName;
body: TelemetryEventBody;
}
export interface TelemetryEventBody {
telemetryEventName: string;
payload: any;
}
export type TypingsInstalledTelemetryEventName = "typingsInstalled";
export interface TypingsInstalledTelemetryEventBody extends TelemetryEventBody {
telemetryEventName: TypingsInstalledTelemetryEventName;
payload: TypingsInstalledTelemetryEventPayload;
}
export interface TypingsInstalledTelemetryEventPayload {
/**
* Comma separated list of installed typing packages
*/
installedPackages: string;
}
export interface NavBarResponse extends Response {
body?: NavigationBarItem[];
}
+54 -23
View File
@@ -1,4 +1,5 @@
/// <reference types="node" />
/// <reference path="shared.ts" />
/// <reference path="session.ts" />
// used in fs.writeSync
/* tslint:disable:no-null-keyword */
@@ -196,8 +197,10 @@ namespace ts.server {
private socket: NodeSocket;
private projectService: ProjectService;
private throttledOperations: ThrottledOperations;
private telemetrySender: EventSender;
constructor(
private readonly telemetryEnabled: boolean,
private readonly logger: server.Logger,
host: ServerHost,
eventPort: number,
@@ -226,15 +229,22 @@ namespace ts.server {
this.socket.write(formatMessage({ seq, type: "event", event, body }, this.logger, Buffer.byteLength, this.newLine), "utf8");
}
setTelemetrySender(telemetrySender: EventSender) {
this.telemetrySender = telemetrySender;
}
attach(projectService: ProjectService) {
this.projectService = projectService;
if (this.logger.hasLevel(LogLevel.requestTime)) {
this.logger.info("Binding...");
}
const args: string[] = ["--globalTypingsCacheLocation", this.globalTypingsCacheLocation];
const args: string[] = [Arguments.GlobalCacheLocation, this.globalTypingsCacheLocation];
if (this.telemetryEnabled) {
args.push(Arguments.EnableTelemetry);
}
if (this.logger.loggingEnabled() && this.logger.getLogFileName()) {
args.push("--logFile", combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName())), `ti-${process.pid}.log`));
args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName())), `ti-${process.pid}.log`));
}
const execArgv: string[] = [];
{
@@ -280,12 +290,25 @@ namespace ts.server {
});
}
private handleMessage(response: SetTypings | InvalidateCachedTypings) {
private handleMessage(response: SetTypings | InvalidateCachedTypings | TypingsInstallEvent) {
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Received response: ${JSON.stringify(response)}`);
}
if (response.kind === EventInstall) {
if (this.telemetrySender) {
const body: protocol.TypingsInstalledTelemetryEventBody = {
telemetryEventName: "typingsInstalled",
payload: {
installedPackages: response.packagesToInstall.join(",")
}
};
const eventName: protocol.TelemetryEventName = "telemetry";
this.telemetrySender.event(body, eventName);
}
return;
}
this.projectService.updateTypingsForProject(response);
if (response.kind == "set" && this.socket) {
if (response.kind == ActionSet && this.socket) {
this.sendEvent(0, "setTypings", response);
}
}
@@ -300,18 +323,25 @@ namespace ts.server {
useSingleInferredProject: boolean,
disableAutomaticTypingAcquisition: boolean,
globalTypingsCacheLocation: string,
telemetryEnabled: boolean,
logger: server.Logger) {
super(
host,
cancellationToken,
useSingleInferredProject,
disableAutomaticTypingAcquisition
? nullTypingsInstaller
: new NodeTypingsInstaller(logger, host, installerEventPort, globalTypingsCacheLocation, host.newLine),
Buffer.byteLength,
process.hrtime,
logger,
canUseEvents);
const typingsInstaller = disableAutomaticTypingAcquisition
? undefined
: new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, host.newLine);
super(
host,
cancellationToken,
useSingleInferredProject,
typingsInstaller || nullTypingsInstaller,
Buffer.byteLength,
process.hrtime,
logger,
canUseEvents);
if (telemetryEnabled && typingsInstaller) {
typingsInstaller.setTelemetrySender(this);
}
}
exit() {
@@ -538,17 +568,17 @@ namespace ts.server {
let eventPort: number;
{
const index = sys.args.indexOf("--eventPort");
if (index >= 0 && index < sys.args.length - 1) {
const v = parseInt(sys.args[index + 1]);
if (!isNaN(v)) {
eventPort = v;
}
const str = findArgument("--eventPort");
const v = str && parseInt(str);
if (!isNaN(v)) {
eventPort = v;
}
}
const useSingleInferredProject = sys.args.indexOf("--useSingleInferredProject") >= 0;
const disableAutomaticTypingAcquisition = sys.args.indexOf("--disableAutomaticTypingAcquisition") >= 0;
const useSingleInferredProject = hasArgument("--useSingleInferredProject");
const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition");
const telemetryEnabled = hasArgument(Arguments.EnableTelemetry);
const ioSession = new IOSession(
sys,
cancellationToken,
@@ -557,6 +587,7 @@ namespace ts.server {
useSingleInferredProject,
disableAutomaticTypingAcquisition,
getGlobalTypingsCacheLocation(),
telemetryEnabled,
logger);
process.on("uncaughtException", function (err: Error) {
ioSession.logError(err, "unknown");
+5 -1
View File
@@ -73,6 +73,10 @@ namespace ts.server {
project: Project;
}
export interface EventSender {
event(payload: any, eventName: string): void;
}
function allEditsBeforePos(edits: ts.TextChange[], pos: number) {
for (const edit of edits) {
if (textSpanEnd(edit.span) >= pos) {
@@ -165,7 +169,7 @@ namespace ts.server {
return `Content-Length: ${1 + len}\r\n\r\n${json}${newLine}`;
}
export class Session {
export class Session implements EventSender {
private readonly gcTimer: GcTimer;
protected projectService: ProjectService;
private errorTimer: any; /*NodeJS.Timer | number*/
+24
View File
@@ -0,0 +1,24 @@
/// <reference path="types.d.ts" />
namespace ts.server {
export const ActionSet: ActionSet = "action::set";
export const ActionInvalidate: ActionInvalidate = "action::invalidate";
export const EventInstall: EventInstall = "event::install";
export namespace Arguments {
export const GlobalCacheLocation = "--globalTypingsCacheLocation";
export const LogFile = "--logFile";
export const EnableTelemetry = "--enableTelemetry";
}
export function hasArgument(argumentName: string) {
return sys.args.indexOf(argumentName) >= 0;
}
export function findArgument(argumentName: string) {
const index = sys.args.indexOf(argumentName);
return index >= 0 && index < sys.args.length - 1
? sys.args[index + 1]
: undefined;
}
}
+1
View File
@@ -18,6 +18,7 @@
"files": [
"../services/shims.ts",
"../services/utilities.ts",
"shared.ts",
"utilities.ts",
"scriptVersionCache.ts",
"scriptInfo.ts",
+1
View File
@@ -15,6 +15,7 @@
"files": [
"../services/shims.ts",
"../services/utilities.ts",
"shared.ts",
"utilities.ts",
"scriptVersionCache.ts",
"scriptInfo.ts",
+19 -9
View File
@@ -41,28 +41,38 @@ declare namespace ts.server {
readonly kind: "closeProject";
}
export type SetRequest = "set";
export type InvalidateRequest = "invalidate";
export type ActionSet = "action::set";
export type ActionInvalidate = "action::invalidate";
export type EventInstall = "event::install";
export interface TypingInstallerResponse {
readonly projectName: string;
readonly kind: SetRequest | InvalidateRequest;
readonly kind: ActionSet | ActionInvalidate | EventInstall;
}
export interface SetTypings extends TypingInstallerResponse {
export interface ProjectResponse extends TypingInstallerResponse {
readonly projectName: string;
}
export interface SetTypings extends ProjectResponse {
readonly typingOptions: ts.TypingOptions;
readonly compilerOptions: ts.CompilerOptions;
readonly typings: string[];
readonly unresolvedImports: SortedReadonlyArray<string>;
readonly kind: SetRequest;
readonly kind: ActionSet;
}
export interface InvalidateCachedTypings extends TypingInstallerResponse {
readonly kind: InvalidateRequest;
export interface InvalidateCachedTypings extends ProjectResponse {
readonly kind: ActionInvalidate;
}
export interface TypingsInstallEvent extends TypingInstallerResponse {
readonly packagesToInstall: ReadonlyArray<string>;
readonly kind: EventInstall;
}
export interface InstallTypingHost extends JsTyping.TypingResolutionHost {
writeFile(path: string, content: string): void;
createDirectory(path: string): void;
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
}
}
@@ -33,42 +33,81 @@ namespace ts.server.typingsInstaller {
}
}
type HttpGet = {
(url: string, callback: (response: HttpResponse) => void): NodeJS.EventEmitter;
};
interface HttpResponse extends NodeJS.ReadableStream {
statusCode: number;
statusMessage: string;
destroy(): void;
interface TypesRegistryFile {
entries: MapLike<void>;
}
function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypingHost, log: Log): Map<void> {
if (!host.fileExists(typesRegistryFilePath)) {
if (log.isEnabled()) {
log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`);
}
return createMap<void>();
}
try {
const content = <TypesRegistryFile>JSON.parse(host.readFile(typesRegistryFilePath));
return createMap<void>(content.entries);
}
catch (e) {
if (log.isEnabled()) {
log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(<Error>e).message}, ${(<Error>e).stack}`);
}
return createMap<void>();
}
}
const TypesRegistryPackageName = "types-registry";
function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): string {
return combinePaths(normalizeSlashes(globalTypingsCacheLocation), `node_modules/${TypesRegistryPackageName}/index.json`);
}
type Exec = {
(command: string, options: { cwd: string }, callback?: (error: Error, stdout: string, stderr: string) => void): any
};
type ExecSync = {
(command: string, options: { cwd: string, stdio: "ignore" }): any
};
export class NodeTypingsInstaller extends TypingsInstaller {
private readonly exec: Exec;
private readonly httpGet: HttpGet;
private readonly npmPath: string;
readonly installTypingHost: InstallTypingHost = sys;
readonly typesRegistry: Map<void>;
constructor(globalTypingsCacheLocation: string, throttleLimit: number, log: Log) {
constructor(globalTypingsCacheLocation: string, throttleLimit: number, telemetryEnabled: boolean, log: Log) {
super(
sys,
globalTypingsCacheLocation,
toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
throttleLimit,
telemetryEnabled,
log);
if (this.log.isEnabled()) {
this.log.writeLine(`Process id: ${process.pid}`);
}
this.npmPath = getNPMLocation(process.argv[0]);
this.exec = require("child_process").exec;
this.httpGet = require("http").get;
let execSync: ExecSync;
({ exec: this.exec, execSync } = require("child_process"));
this.ensurePackageDirectoryExists(globalTypingsCacheLocation);
try {
if (this.log.isEnabled()) {
this.log.writeLine(`Updating ${TypesRegistryPackageName} npm package...`);
}
execSync(`${this.npmPath} install ${TypesRegistryPackageName}`, { cwd: globalTypingsCacheLocation, stdio: "ignore" });
}
catch (e) {
if (this.log.isEnabled()) {
this.log.writeLine(`Error updating ${TypesRegistryPackageName} package: ${(<Error>e).message}`);
}
}
this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), this.installTypingHost, this.log);
}
init() {
super.init();
listen() {
process.on("message", (req: DiscoverTypings | CloseProject) => {
switch (req.kind) {
case "discover":
@@ -90,66 +129,26 @@ namespace ts.server.typingsInstaller {
}
}
protected executeRequest(requestKind: RequestKind, requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void {
protected installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void {
if (this.log.isEnabled()) {
this.log.writeLine(`#${requestId} executing ${requestKind}, arguments'${JSON.stringify(args)}'.`);
}
switch (requestKind) {
case NpmViewRequest: {
// const command = `${self.npmPath} view @types/${typing} --silent name`;
// use http request to global npm registry instead of running npm view
Debug.assert(args.length === 1);
const url = `http://registry.npmjs.org/@types%2f${args[0]}`;
const start = Date.now();
this.httpGet(url, response => {
let ok = false;
if (this.log.isEnabled()) {
this.log.writeLine(`${requestKind} #${requestId} request to ${url}:: status code ${response.statusCode}, status message '${response.statusMessage}', took ${Date.now() - start} ms`);
}
switch (response.statusCode) {
case 200: // OK
case 301: // redirect - Moved - treat package as present
case 302: // redirect - Found - treat package as present
ok = true;
break;
}
response.destroy();
onRequestCompleted(ok);
}).on("error", (err: Error) => {
if (this.log.isEnabled()) {
this.log.writeLine(`${requestKind} #${requestId} query to npm registry failed with error ${err.message}, stack ${err.stack}`);
}
onRequestCompleted(/*success*/ false);
});
}
break;
case NpmInstallRequest: {
const command = `${this.npmPath} install ${args.join(" ")} --save-dev`;
const start = Date.now();
this.exec(command, { cwd }, (_err, stdout, stderr) => {
if (this.log.isEnabled()) {
this.log.writeLine(`${requestKind} #${requestId} took: ${Date.now() - start} ms${sys.newLine}stdout: ${stdout}${sys.newLine}stderr: ${stderr}`);
}
// treat any output on stdout as success
onRequestCompleted(!!stdout);
});
}
break;
default:
Debug.assert(false, `Unknown request kind ${requestKind}`);
this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(args)}'.`);
}
const command = `${this.npmPath} install ${args.join(" ")} --save-dev`;
const start = Date.now();
this.exec(command, { cwd }, (_err, stdout, stderr) => {
if (this.log.isEnabled()) {
this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms${sys.newLine}stdout: ${stdout}${sys.newLine}stderr: ${stderr}`);
}
// treat any output on stdout as success
onRequestCompleted(!!stdout);
});
}
}
function findArgument(argumentName: string) {
const index = sys.args.indexOf(argumentName);
return index >= 0 && index < sys.args.length - 1
? sys.args[index + 1]
: undefined;
}
const logFilePath = findArgument(server.Arguments.LogFile);
const globalTypingsCacheLocation = findArgument(server.Arguments.GlobalCacheLocation);
const telemetryEnabled = hasArgument(server.Arguments.EnableTelemetry);
const logFilePath = findArgument("--logFile");
const globalTypingsCacheLocation = findArgument("--globalTypingsCacheLocation");
const log = new FileLog(logFilePath);
if (log.isEnabled()) {
process.on("uncaughtException", (e: Error) => {
@@ -162,6 +161,6 @@ namespace ts.server.typingsInstaller {
}
process.exit(0);
});
const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, /*throttleLimit*/5, log);
installer.init();
const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, /*throttleLimit*/5, telemetryEnabled, log);
installer.listen();
}
@@ -17,6 +17,7 @@
},
"files": [
"../types.d.ts",
"../shared.ts",
"typingsInstaller.ts",
"nodeTypingsInstaller.ts"
]
+56 -81
View File
@@ -2,6 +2,7 @@
/// <reference path="../../compiler/moduleNameResolver.ts" />
/// <reference path="../../services/jsTyping.ts"/>
/// <reference path="../types.d.ts"/>
/// <reference path="../shared.ts"/>
namespace ts.server.typingsInstaller {
interface NpmConfig {
@@ -63,14 +64,8 @@ namespace ts.server.typingsInstaller {
return PackageNameValidationResult.Ok;
}
export const NpmViewRequest: "npm view" = "npm view";
export const NpmInstallRequest: "npm install" = "npm install";
export type RequestKind = typeof NpmViewRequest | typeof NpmInstallRequest;
export type RequestCompletedAction = (success: boolean) => void;
type PendingRequest = {
requestKind: RequestKind;
requestId: number;
args: string[];
cwd: string;
@@ -87,19 +82,18 @@ namespace ts.server.typingsInstaller {
private installRunCount = 1;
private inFlightRequestCount = 0;
abstract readonly installTypingHost: InstallTypingHost;
abstract readonly typesRegistry: Map<void>;
constructor(
readonly installTypingHost: InstallTypingHost,
readonly globalCachePath: string,
readonly safeListPath: Path,
readonly throttleLimit: number,
readonly telemetryEnabled: boolean,
protected readonly log = nullLog) {
if (this.log.isEnabled()) {
this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}'`);
}
}
init() {
this.processCacheLocation(this.globalCachePath);
}
@@ -224,7 +218,7 @@ namespace ts.server.typingsInstaller {
this.knownCachesSet[cacheLocation] = true;
}
private filterTypings(typingsToInstall: string[]) {
private filterAndMapToScopedName(typingsToInstall: string[]) {
if (typingsToInstall.length === 0) {
return typingsToInstall;
}
@@ -235,7 +229,14 @@ namespace ts.server.typingsInstaller {
}
const validationResult = validatePackageName(typing);
if (validationResult === PackageNameValidationResult.Ok) {
result.push(typing);
if (typing in this.typesRegistry) {
result.push(`@types/${typing}`);
}
else {
if (this.log.isEnabled()) {
this.log.writeLine(`Entry for package '${typing}' does not exist in local types registry - skipping...`);
}
}
}
else {
// add typing name to missing set so we won't process it again
@@ -267,19 +268,8 @@ namespace ts.server.typingsInstaller {
return result;
}
private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) {
if (this.log.isEnabled()) {
this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`);
}
typingsToInstall = this.filterTypings(typingsToInstall);
if (typingsToInstall.length === 0) {
if (this.log.isEnabled()) {
this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`);
}
return;
}
const npmConfigPath = combinePaths(cachePath, "package.json");
protected ensurePackageDirectoryExists(directory: string) {
const npmConfigPath = combinePaths(directory, "package.json");
if (this.log.isEnabled()) {
this.log.writeLine(`Npm config file: ${npmConfigPath}`);
}
@@ -287,23 +277,50 @@ namespace ts.server.typingsInstaller {
if (this.log.isEnabled()) {
this.log.writeLine(`Npm config file: '${npmConfigPath}' is missing, creating new one...`);
}
this.ensureDirectoryExists(cachePath, this.installTypingHost);
this.ensureDirectoryExists(directory, this.installTypingHost);
this.installTypingHost.writeFile(npmConfigPath, "{}");
}
}
private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) {
if (this.log.isEnabled()) {
this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`);
}
const scopedTypings = this.filterAndMapToScopedName(typingsToInstall);
if (scopedTypings.length === 0) {
if (this.log.isEnabled()) {
this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`);
}
return;
}
this.ensurePackageDirectoryExists(cachePath);
const requestId = this.installRunCount;
this.installRunCount++;
this.installTypingsAsync(requestId, scopedTypings, cachePath, ok => {
if (this.telemetryEnabled) {
this.sendResponse(<TypingsInstallEvent>{
kind: EventInstall,
packagesToInstall: scopedTypings
});
}
if (!ok) {
return;
}
this.runInstall(cachePath, typingsToInstall, installedTypings => {
// TODO: watch project directory
if (this.log.isEnabled()) {
this.log.writeLine(`Requested to install typings ${JSON.stringify(typingsToInstall)}, installed typings ${JSON.stringify(installedTypings)}`);
this.log.writeLine(`Requested to install typings ${JSON.stringify(scopedTypings)}, installed typings ${JSON.stringify(scopedTypings)}`);
}
const installedPackages: Map<true> = createMap<true>();
const installedTypingFiles: string[] = [];
for (const t of installedTypings) {
for (const t of scopedTypings) {
const packageName = getBaseFileName(t);
if (!packageName) {
continue;
}
installedPackages[packageName] = true;
const typingFile = typingToFileName(cachePath, packageName, this.installTypingHost);
if (!typingFile) {
continue;
@@ -316,53 +333,11 @@ namespace ts.server.typingsInstaller {
if (this.log.isEnabled()) {
this.log.writeLine(`Installed typing files ${JSON.stringify(installedTypingFiles)}`);
}
for (const toInstall of typingsToInstall) {
if (!installedPackages[toInstall]) {
if (this.log.isEnabled()) {
this.log.writeLine(`New missing typing package '${toInstall}'`);
}
this.missingTypingsSet[toInstall] = true;
}
}
this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles)));
});
}
private runInstall(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void {
const requestId = this.installRunCount;
this.installRunCount++;
let execInstallCmdCount = 0;
const filteredTypings: string[] = [];
for (const typing of typingsToInstall) {
filterExistingTypings(this, typing);
}
function filterExistingTypings(self: TypingsInstaller, typing: string) {
self.execAsync(NpmViewRequest, requestId, [typing], cachePath, ok => {
if (ok) {
filteredTypings.push(typing);
}
execInstallCmdCount++;
if (execInstallCmdCount === typingsToInstall.length) {
installFilteredTypings(self, filteredTypings);
}
});
}
function installFilteredTypings(self: TypingsInstaller, filteredTypings: string[]) {
if (filteredTypings.length === 0) {
postInstallAction([]);
return;
}
const scopedTypings = filteredTypings.map(t => "@types/" + t);
self.execAsync(NpmInstallRequest, requestId, scopedTypings, cachePath, ok => {
postInstallAction(ok ? scopedTypings : []);
});
}
}
private ensureDirectoryExists(directory: string, host: InstallTypingHost): void {
const directoryName = getDirectoryPath(directory);
if (!host.directoryExists(directoryName)) {
@@ -389,10 +364,10 @@ namespace ts.server.typingsInstaller {
this.log.writeLine(`Got FS notification for ${f}, handler is already invoked '${isInvoked}'`);
}
if (!isInvoked) {
this.sendResponse({ projectName: projectName, kind: "invalidate" });
this.sendResponse({ projectName: projectName, kind: server.ActionInvalidate });
isInvoked = true;
}
});
}, /*pollingInterval*/ 2000);
watchers.push(w);
}
this.projectWatchers[projectName] = watchers;
@@ -405,12 +380,12 @@ namespace ts.server.typingsInstaller {
compilerOptions: request.compilerOptions,
typings,
unresolvedImports: request.unresolvedImports,
kind: "set"
kind: server.ActionSet
};
}
private execAsync(requestKind: RequestKind, requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void {
this.pendingRunRequests.unshift({ requestKind, requestId, args, cwd, onRequestCompleted });
private installTypingsAsync(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void {
this.pendingRunRequests.unshift({ requestId, args, cwd, onRequestCompleted });
this.executeWithThrottling();
}
@@ -418,7 +393,7 @@ namespace ts.server.typingsInstaller {
while (this.inFlightRequestCount < this.throttleLimit && this.pendingRunRequests.length) {
this.inFlightRequestCount++;
const request = this.pendingRunRequests.pop();
this.executeRequest(request.requestKind, request.requestId, request.args, request.cwd, ok => {
this.installWorker(request.requestId, request.args, request.cwd, ok => {
this.inFlightRequestCount--;
request.onRequestCompleted(ok);
this.executeWithThrottling();
@@ -426,7 +401,7 @@ namespace ts.server.typingsInstaller {
}
}
protected abstract executeRequest(requestKind: RequestKind, requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void;
protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings): void;
protected abstract installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void;
protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | TypingsInstallEvent): void;
}
}
+3 -1
View File
@@ -1,4 +1,5 @@
/// <reference path="types.d.ts" />
/// <reference path="shared.ts" />
namespace ts.server {
export enum LogLevel {
@@ -10,6 +11,7 @@ namespace ts.server {
export const emptyArray: ReadonlyArray<any> = [];
export interface Logger {
close(): void;
hasLevel(level: LogLevel): boolean;
@@ -48,7 +50,7 @@ namespace ts.server {
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>, cachePath?: string): DiscoverTypings {
return {
projectName: project.getProjectName(),
fileNames: project.getFileNames(),
fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true),
compilerOptions: project.getCompilerOptions(),
typingOptions,
unresolvedImports,
+1 -1
View File
@@ -88,7 +88,7 @@ namespace ts.JsTyping {
exclude = typingOptions.exclude || [];
const possibleSearchDirs = map(fileNames, getDirectoryPath);
if (projectRootPath !== undefined) {
if (projectRootPath) {
possibleSearchDirs.push(projectRootPath);
}
searchDirs = deduplicate(possibleSearchDirs);
-2
View File
@@ -48,7 +48,6 @@ namespace ts {
public jsDocComments: JSDoc[];
public original: Node;
public transformFlags: TransformFlags;
public excludeTransformFlags: TransformFlags;
private _children: Node[];
constructor(kind: SyntaxKind, pos: number, end: number) {
@@ -56,7 +55,6 @@ namespace ts {
this.end = end;
this.flags = NodeFlags.None;
this.transformFlags = undefined;
this.excludeTransformFlags = undefined;
this.parent = undefined;
this.kind = kind;
}
@@ -12,4 +12,4 @@ exports.y = function (x) { return 1; };
//// [declarationEmitTypeAliasWithTypeParameters1.d.ts]
export declare type Bar<X, Y> = () => [X, Y];
export declare type Foo<Y> = Bar<any, Y>;
export declare const y: (x: () => [any, string]) => number;
export declare const y: (x: Bar<any, string>) => number;
@@ -8,15 +8,15 @@ export type Bar<X, Y> = () => [X, Y];
>Y : Y
export type Foo<Y> = Bar<any, Y>;
>Foo : () => [any, Y]
>Foo : Bar<any, Y>
>Y : Y
>Bar : Bar<X, Y>
>Y : Y
export const y = (x: Foo<string>) => 1
>y : (x: () => [any, string]) => number
>(x: Foo<string>) => 1 : (x: () => [any, string]) => number
>x : () => [any, string]
>Foo : () => [any, Y]
>y : (x: Bar<any, string>) => number
>(x: Foo<string>) => 1 : (x: Bar<any, string>) => number
>x : Bar<any, string>
>Foo : Bar<any, Y>
>1 : 1
@@ -0,0 +1,36 @@
//// [instantiatedTypeAliasDisplay.ts]
// Repros from #12066
interface X<A> {
a: A;
}
interface Y<B> {
b: B;
}
type Z<A, B> = X<A> | Y<B>;
declare function f1<A>(): Z<A, number>;
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
const x1 = f1<string>(); // Z<string, number>
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
//// [instantiatedTypeAliasDisplay.js]
// Repros from #12066
var x1 = f1(); // Z<string, number>
var x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
//// [instantiatedTypeAliasDisplay.d.ts]
interface X<A> {
a: A;
}
interface Y<B> {
b: B;
}
declare type Z<A, B> = X<A> | Y<B>;
declare function f1<A>(): Z<A, number>;
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
declare const x1: Z<string, number>;
declare const x2: Z<{}, string[]>;
@@ -0,0 +1,61 @@
=== tests/cases/compiler/instantiatedTypeAliasDisplay.ts ===
// Repros from #12066
interface X<A> {
>X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 3, 12))
a: A;
>a : Symbol(X.a, Decl(instantiatedTypeAliasDisplay.ts, 3, 16))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 3, 12))
}
interface Y<B> {
>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 5, 1))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 6, 12))
b: B;
>b : Symbol(Y.b, Decl(instantiatedTypeAliasDisplay.ts, 6, 16))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 6, 12))
}
type Z<A, B> = X<A> | Y<B>;
>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 9, 7))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 9, 9))
>X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 9, 7))
>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 5, 1))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 9, 9))
declare function f1<A>(): Z<A, number>;
>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 9, 27))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20))
>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20))
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 11, 39))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 12, 22))
>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 12, 25))
>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 12, 28))
>E : Symbol(E, Decl(instantiatedTypeAliasDisplay.ts, 12, 31))
>a : Symbol(a, Decl(instantiatedTypeAliasDisplay.ts, 12, 35))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20))
>b : Symbol(b, Decl(instantiatedTypeAliasDisplay.ts, 12, 40))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 12, 22))
>c : Symbol(c, Decl(instantiatedTypeAliasDisplay.ts, 12, 46))
>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 12, 25))
>d : Symbol(d, Decl(instantiatedTypeAliasDisplay.ts, 12, 52))
>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 12, 28))
>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20))
const x1 = f1<string>(); // Z<string, number>
>x1 : Symbol(x1, Decl(instantiatedTypeAliasDisplay.ts, 14, 5))
>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 9, 27))
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
>x2 : Symbol(x2, Decl(instantiatedTypeAliasDisplay.ts, 15, 5))
>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 11, 39))
@@ -0,0 +1,67 @@
=== tests/cases/compiler/instantiatedTypeAliasDisplay.ts ===
// Repros from #12066
interface X<A> {
>X : X<A>
>A : A
a: A;
>a : A
>A : A
}
interface Y<B> {
>Y : Y<B>
>B : B
b: B;
>b : B
>B : B
}
type Z<A, B> = X<A> | Y<B>;
>Z : Z<A, B>
>A : A
>B : B
>X : X<A>
>A : A
>Y : Y<B>
>B : B
declare function f1<A>(): Z<A, number>;
>f1 : <A>() => Z<A, number>
>A : A
>Z : Z<A, B>
>A : A
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
>f2 : <A, B, C, D, E>(a: A, b: B, c: C, d: D) => Z<A, string[]>
>A : A
>B : B
>C : C
>D : D
>E : E
>a : A
>A : A
>b : B
>B : B
>c : C
>C : C
>d : D
>D : D
>Z : Z<A, B>
>A : A
const x1 = f1<string>(); // Z<string, number>
>x1 : Z<string, number>
>f1<string>() : Z<string, number>
>f1 : <A>() => Z<A, number>
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
>x2 : Z<{}, string[]>
>f2({}, {}, {}, {}) : Z<{}, string[]>
>f2 : <A, B, C, D, E>(a: A, b: B, c: C, d: D) => Z<A, string[]>
>{} : {}
>{} : {}
>{} : {}
>{} : {}
@@ -25,8 +25,6 @@ tests/cases/compiler/promisePermutations.ts(106,19): error TS2345: Argument of t
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
tests/cases/compiler/promisePermutations.ts(109,19): error TS2345: Argument of type '(cb: <T>(a: T) => T) => IPromise<string>' is not assignable to parameter of type '(value: string) => IPromise<string>'.
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
tests/cases/compiler/promisePermutations.ts(110,19): error TS2345: Argument of type '(cb: <T>(a: T) => T) => Promise<string>' is not assignable to parameter of type '(value: string) => Promise<string>'.
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
@@ -229,8 +227,6 @@ tests/cases/compiler/promisePermutations.ts(160,21): error TS2345: Argument of t
var s7a = r7.then(testFunction7, testFunction7, testFunction7); // error
~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(cb: <T>(a: T) => T) => IPromise<string>' is not assignable to parameter of type '(value: string) => IPromise<string>'.
!!! error TS2345: Types of parameters 'cb' and 'value' are incompatible.
!!! error TS2345: Type 'string' is not assignable to type '<T>(a: T) => T'.
var s7b = r7.then(testFunction7P, testFunction7P, testFunction7P); // error
~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(cb: <T>(a: T) => T) => Promise<string>' is not assignable to parameter of type '(value: string) => Promise<string>'.
@@ -25,8 +25,6 @@ tests/cases/compiler/promisePermutations2.ts(105,19): error TS2345: Argument of
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
tests/cases/compiler/promisePermutations2.ts(108,19): error TS2345: Argument of type '(cb: <T>(a: T) => T) => IPromise<string>' is not assignable to parameter of type '(value: string) => IPromise<string>'.
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
tests/cases/compiler/promisePermutations2.ts(109,19): error TS2345: Argument of type '(cb: <T>(a: T) => T) => Promise<string>' is not assignable to parameter of type '(value: string) => Promise<string>'.
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
@@ -228,8 +226,6 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of
var s7a = r7.then(testFunction7, testFunction7, testFunction7); // error
~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(cb: <T>(a: T) => T) => IPromise<string>' is not assignable to parameter of type '(value: string) => IPromise<string>'.
!!! error TS2345: Types of parameters 'cb' and 'value' are incompatible.
!!! error TS2345: Type 'string' is not assignable to type '<T>(a: T) => T'.
var s7b = r7.then(testFunction7P, testFunction7P, testFunction7P); // error
~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(cb: <T>(a: T) => T) => Promise<string>' is not assignable to parameter of type '(value: string) => Promise<string>'.
@@ -28,8 +28,6 @@ tests/cases/compiler/promisePermutations3.ts(105,19): error TS2345: Argument of
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
tests/cases/compiler/promisePermutations3.ts(108,19): error TS2345: Argument of type '(cb: <T>(a: T) => T) => IPromise<string>' is not assignable to parameter of type '(value: string) => IPromise<string>'.
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
tests/cases/compiler/promisePermutations3.ts(109,19): error TS2345: Argument of type '(cb: <T>(a: T) => T) => Promise<string>' is not assignable to parameter of type '(value: string) => Promise<string>'.
Types of parameters 'cb' and 'value' are incompatible.
Type 'string' is not assignable to type '<T>(a: T) => T'.
@@ -240,8 +238,6 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of
var s7a = r7.then(testFunction7, testFunction7, testFunction7); // error
~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(cb: <T>(a: T) => T) => IPromise<string>' is not assignable to parameter of type '(value: string) => IPromise<string>'.
!!! error TS2345: Types of parameters 'cb' and 'value' are incompatible.
!!! error TS2345: Type 'string' is not assignable to type '<T>(a: T) => T'.
var s7b = r7.then(testFunction7P, testFunction7P, testFunction7P); // error
~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(cb: <T>(a: T) => T) => Promise<string>' is not assignable to parameter of type '(value: string) => Promise<string>'.
@@ -0,0 +1,17 @@
// @declaration: true
// Repros from #12066
interface X<A> {
a: A;
}
interface Y<B> {
b: B;
}
type Z<A, B> = X<A> | Y<B>;
declare function f1<A>(): Z<A, number>;
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
const x1 = f1<string>(); // Z<string, number>
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>